insightsengineering / teal.data

Data model for teal applications
https://insightsengineering.github.io/teal.data/
Other
8 stars 7 forks source link

[Bug]: App doesn't initialize if `teal_data` has a function that returns a function #304

Closed averissimo closed 5 months ago

averissimo commented 5 months ago

What happened?

Detected edge case when functions cannot include functions on the current main branch of teal.

library(teal)
data <- within(
  teal_data(),
  {
    add <- function(a) function(b) a + b
    iris <- iris
  }
)
datanames(data) <- c("iris")

head(data[["iris"]])
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa
cat(get_code(data))
#> add <- function(a) function(b) a + b
#> iris <- iris
class(data)
#> [1] "teal_data"
#> attr(,"package")
#> [1] "teal.data"

teal::init(
  data = data,
  modules = teal::example_module()
) |> shiny::runApp()
#> Warning in rlang::hash(list(data = data, modules = modules)) :
#>   'package:teal' may not be available when loading
#> 
#> Listening on http://127.0.0.1:4444
#> Warning in abs(pd$parent) == parent :
#>   longer object length is not a multiple of shorter object length
#> Warning: Error in if: the condition has length > 1
#>  1: shiny::runApp [/tmp/RtmpkziAl8/R.INSTALL620331194582/shiny/R/runapp.R#388]
This was first observed when creating a `teal_data_module` with a function that has a `shiny::moduleServer` ```r ssh_connect <- function(user = NULL, host = NULL, password = NULL) { if (shiny::isRunning()) { shiny::moduleServer("cred", function(input, output, session) { ssh::ssh_connect( sprintf("%s@%s", input$user, input$host), passwd = input$password ) }) } else { host <- host %||% askpass::askpass("Host") user <- user %||% askpass::askpass("Username") password <- password %||% askpass::askpass("Password") ssh::ssh_connect( sprintf("%s@%s", user, host), passwd = password ) } } data <- within( teal.data::teal_data(), { library(rlang) ssh_connect <- source iris <- iris }, source = ssh_connect ) teal.data::datanames(data) <- "iris" head(data[["iris"]]) #> Sepal.Length Sepal.Width Petal.Length Petal.Width Species #> 1 5.1 3.5 1.4 0.2 setosa #> 2 4.9 3.0 1.4 0.2 setosa #> 3 4.7 3.2 1.3 0.2 setosa #> 4 4.6 3.1 1.5 0.2 setosa #> 5 5.0 3.6 1.4 0.2 setosa #> 6 5.4 3.9 1.7 0.4 setosa cat(teal.code::get_code(data)) #> library(rlang) #> ssh_connect <- function (user = NULL, host = NULL, password = NULL) #> { #> if (shiny::isRunning()) { #> shiny::moduleServer("cred", function(input, output, session) { #> ssh::ssh_connect(sprintf("%s@%s", input$user, input$host), passwd = input$password) #> }) #> } #> else { #> host <- host %||% askpass::askpass("Host") #> user <- user %||% askpass::askpass("Username") #> password <- password %||% askpass::askpass("Password") #> ssh::ssh_connect(sprintf("%s@%s", user, host), passwd = password) #> } #> } #> iris <- iris class(data) #> [1] "teal_data" #> attr(,"package") #> [1] "teal.data" teal::init( data = data, modules = teal::example_module() ) |> shiny::runApp() #> Warning in rlang::hash(list(data = data, modules = modules)) : #> 'package:rlang' may not be available when loading #> #> Listening on http://127.0.0.1:6914 #> Warning in abs(pd$parent) == parent : #> longer object length is not a multiple of shorter object length #> Warning: Error in if: the condition has length > 1 #> 1: shiny::runApp [/tmp/RtmpkziAl8/R.INSTALL620331194582/shiny/R/runapp.R#388] ```
averissimo commented 5 months ago

Problem traced back to: https://github.com/insightsengineering/teal.data/blob/7611a115133e35d068c85b1d294866b43c4180d5/R/utils-get_code_dependency.R#L119

Parent has more than 1 index (as there are 2 nested functions) in code.

Moving issue to teal.data

m7pr commented 5 months ago

Yeah, I actually think this was an issue in teal.data

> cat(teal.data::get_code(data, datanames = 'add'))
Error in if (parent > 0) { : the condition has length > 1