Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

59 error handling simpler #65

Merged
merged 22 commits into from
Sep 15, 2022

Conversation

gogonzo
Copy link
Contributor

@gogonzo gogonzo commented Sep 13, 2022

closes #59 Please compare with #61

  • when eval_code fails then returns error condition of class (s3) c("quosure.error", "try-error", "error", "condition")
  • needed to register S3 method for [[.quosure.error as S4 couldn't dispatch on the quosure.error like other methods (probably it's handled internally which has priority). Class try-error needed to make validate stop. Go to shiny:::isTruthy to see when validate interrupts the reactive.
  • I'm not happy that req(<quosure.error>) in q8 doesn't return error like in q13

image


example

ui <- fluidPage(
  fluidRow(
    column(6, h1("Code")),
    column(6, h1("Output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q1_code")),
    column(6, verbatimTextOutput("q1_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q2_code")),
    column(6, verbatimTextOutput("q2_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q3_code")),
    column(6, verbatimTextOutput("q3_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q4_code")),
    column(6, verbatimTextOutput("q4_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q5_code")),
    column(6, verbatimTextOutput("q5_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q6_code")),
    column(6, verbatimTextOutput("q6_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q7_code")),
    column(6, verbatimTextOutput("q7_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q8_code")),
    column(6, verbatimTextOutput("q8_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q9_code")),
    column(6, verbatimTextOutput("q9_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q10_code")),
    column(6, verbatimTextOutput("q10_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q11_code")),
    column(6, verbatimTextOutput("q11_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q12_code")),
    column(6, verbatimTextOutput("q12_output"))
  ),
  fluidRow(
    column(6, verbatimTextOutput("q13_code")),
    column(6, verbatimTextOutput("q13_output"))
  )
)

server <- function(input, output, session) {
  q1 <- reactive({
    new_quosure() %>%
    eval_code(code = 'stop("Error message details")')
  })

  output$q1_code <- reactive(
    'q1 <- reactive(new_quosure() %>%
      eval_code(stop("Error message details")))'
  )

  output$q1_output <- renderPrint(q1())

  q2 <- reactive({
    new_quosure() %>%
      eval_code(code = "x <- 0")
  })


  output$q2_code <- reactive(
    'q2 <- reactive(new_quosure() %>%
      eval_code("x <- 0")'
  )

  output$q2_output <- renderPrint(q2())

  q3 <- reactive({
    validate(need(q1(), "q1 is not valid"))
    "hello"
  })

  output$q3_code <- reactive(
    'q3 <- reactive({
    validate(need(q1(), "q1 is not valid"))
    "hello"
    })'
  )

  output$q3_output <- renderPrint(q3())

  q4 <- reactive({
    validate(need(q2(), "q2 is not valid"))
    "hello"
  })


  output$q4_code <- reactive(
    'q4 <- reactive({
     validate(need(q2(), "q2 is not valid"))
    "hello"
    })'
  )

  output$q4_output <- renderPrint(q4())

  q5 <- reactive({
    q1()[["x"]]
  })

  # Note case q2()[["not_valid"]] handled by teal.code issue #57

  output$q5_code <- reactive(
    'q5 <- reactive(q1()[["x"]])'
  )

  output$q5_output <- renderPrint({
    q5()
  })


  q6 <- reactive({
    eval_code(q2(), "w <- y * x")
  })


  output$q6_code <- reactive(
    'q6 <- reactive(eval_code(q2(), "w <- y * x"))'
  )

  output$q6_output <- renderPrint(q6())

  q7 <- reactive({
    eval_code(q1(), "w <- 10")
  })


  output$q7_code <- reactive(
    'q7 <- reactive(eval_code(q1(), "w <- 10")'
  )

  output$q7_output <- renderPrint(q7())

  q8 <- reactive({
    req(q1())
    "hello"
  })


  output$q8_code <- reactive(
    'q8 <- reactive({
      req(q1())
      "hello"
    })'
  )

  output$q8_output <- renderPrint(q8())


  q9 <- reactive({
    join(q2(), q7()) %>% get_var("x")
  })


  output$q9_code <- reactive(
    'q9 <- reactive({
      join(q2(), q7()) %>% get_var("x")
    })'
  )

  output$q9_output <- renderPrint(q9())

  q10 <- reactive({
    join(q2(), q7()) %>% get_code()
  })


  output$q10_code <- reactive(
    'q10 <- reactive({
      join(q2(), q7()) %>% get_code()
    })'
  )

  output$q10_output <- renderPrint(q10())


  q11 <- reactive({
    new_quosure() %>%
      eval_code("x <- 0") %>%
      eval_code("y <- 0") %>%
      eval_code("w <- u * x") %>%
      eval_code("v <- x") %>%
      get_code()
  })


  output$q11_code <- reactive(
    'q11 <- reactive({
      new_quosure() %>%
      eval_code("x <- 0") %>%
      eval_code("y <- 0") %>%
      eval_code("w <- u * x") %>%
      eval_code("v <- x") %>%
      get_code()
    })'
  )

  output$q11_output <- renderPrint(q11())


  q12_a <- reactive({
    validate(need(1 > 4, "Error: 1 is less than 4"))
    new_quosure() %>% eval_code("x <- 1")
  })

  q12_b <- reactive({
    get_code(q12_a())
  })

  output$q12_code <- reactive(
    'q12_a <- reactive({
      validate(need(1 > 4, "Error: 1 is less than 4"))
      new_quosure() %>% eval_code("x <- 1")
    })

    q12_b <- reactive({
      get_code(q12_a())
    })
    '
  )

  output$q12_output <- renderPrint(q12_b())

  q13a <- reactive(stop("error in the reactive"))
  q13b <- reactive({
    req(q13a())
    "hello"
  })
  output$q13_code <- reactive(
    'q13a <- reactive(stop("error in the reactive"))
    q13b <- reactive({
      req(q13a())
      "hello"
    })
    '
  )
  output$q13_output <- renderPrint(q13b())
}

runApp(shinyApp(ui, server))

@gogonzo gogonzo added the core label Sep 13, 2022
Copy link
Contributor

@nikolas-burkoff nikolas-burkoff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor comments, I'll look in detail tomorrow

R/get_eval_details.R Outdated Show resolved Hide resolved
R/quosure-class.R Outdated Show resolved Hide resolved
R/quosure-errors.R Outdated Show resolved Hide resolved
R/quosure-get_code.R Show resolved Hide resolved
R/quosure-eval_code.R Outdated Show resolved Hide resolved
@nikolas-burkoff
Copy link
Contributor

nikolas-burkoff commented Sep 13, 2022

Would you also handle validation so that the css for validation gets used in the app compare these:

image

and you could have an S3 method for print.quosure.error to print the message out without having the <quosure.error: ...> but I sort of like that as it signposts clearly there's a problem with the quosures

@gogonzo
Copy link
Contributor Author

gogonzo commented Sep 14, 2022

and you could have an S3 method for print.quosure.error to print the message out without having the <quosure.error: ...> but I sort of like that as it signposts clearly there's a problem with the quosures

Initially I wanted quosure to return red error as it's an error and not the restricted-input-choice. I also like that it returns <quosure.error ...>. If I make quosure.error.print I'd probably just turn it red

@nikolas-burkoff
Copy link
Contributor

nikolas-burkoff commented Sep 14, 2022

So this is a little more realistic for teal at the moment buttons 1 and 2 do nothing when clicked on - I think we should change teal.widgets to output the trace / validation error when you click on them

Edit these are fixed here

library(teal.code)
library(magrittr)
library(teal.widgets)
library(shiny)

ui <- fluidPage(
  verbatim_popup_ui("rcode_1", "Show R code 1"),
  verbatim_popup_ui("rcode_2", "Show R code 2"),
  verbatim_popup_ui("rcode_3", "Show R code 3")
)

server <- function(input, output, session) {
  # invalid due to code error
  q_1 <- reactive(new_quosure() %>%
    eval_code("x <- 1") %>%
    eval_code("y <- x * w"))


  verbatim_popup_srv(
    id = "rcode_1",
    verbatim_content = reactive(get_code(q_1())),
    title = "rcode_1"
  )

  # invalid due to validate
  q_2 <- reactive({
    validate(need(1 > 4, "1 is less than 4"))
    new_quosure() %>%
      eval_code("x <- 1") %>%
      eval_code("y <- x * 1")
  })

  verbatim_popup_srv(
    id = "rcode_2",
    verbatim_content = reactive(get_code(q_2())),
    title = "rcode_2"
  )

  #valid
  q_3 <- reactive(new_quosure() %>%
    eval_code("x <- 1") %>%
    eval_code("y <- x * 1"))

  verbatim_popup_srv(
    id = "rcode_3",
    verbatim_content = reactive(get_code(q_3())),
    title = "rcode_3"
  )
}

shinyApp(ui, server)

@nikolas-burkoff nikolas-burkoff merged commit fe2af66 into teal_refactor@main Sep 15, 2022
@nikolas-burkoff nikolas-burkoff deleted the 59_error_handling_simpler branch September 15, 2022 12:22
This was linked to issues Sep 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] failing eval_code breaks the shiny app Rename quosure to qenv
2 participants