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

Duplicated decorators during an edge case of named and unnamed decorators #835

Merged
merged 9 commits into from
Feb 7, 2025

Conversation

m7pr
Copy link
Contributor

@m7pr m7pr commented Jan 28, 2025

@llrs-roche llrs-roche self-assigned this Jan 29, 2025
R/utils.R Outdated Show resolved Hide resolved
Copy link
Contributor

@llrs-roche llrs-roche left a comment

Choose a reason for hiding this comment

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

I can also reproduce the CI checks failures about the vignettes.
Check the linter message and Dawid comment.

R/utils.R Outdated Show resolved Hide resolved
@m7pr
Copy link
Contributor Author

m7pr commented Jan 31, 2025

Alrighty, for now I allowed only to pass either all named, or all unnamed decorators

Code
pkgload::load_all(".")
data <- teal_data()
data <- within(data, {
  require(nestcolor)
  CO2 <- CO2
  factors <- names(Filter(isTRUE, vapply(CO2, is.factor, logical(1L))))
  CO2[factors] <- lapply(CO2[factors], as.character)
})

static_decorator <- teal_transform_module(
  label = "Static decorator",
  server = function(id, data) {
    moduleServer(id, function(input, output, session) {
      reactive({
        req(data())
        within(data(), {
          plot <- plot +
            ggplot2::ggtitle("This is title") +
            ggplot2::xlab("x axis")
        })
      })
    })
  }
)

interactive_decorator <- teal_transform_module(
  label = "Interactive decorator",
  ui = function(id) {
    ns <- NS(id)
    div(
      textInput(ns("x_axis_title"), "X axis title", value = "x axis")
    )
  },
  server = function(id, data) {
    moduleServer(id, function(input, output, session) {
      reactive({
        req(data())
        within(data(),
               {
                 plot <- plot +
                   ggplot2::ggtitle("This is title") +
                   ggplot2::xlab(my_title)
               },
               my_title = input$x_axis_title
        )
      })
    })
  }
)

app <- init(
  data = data,
  modules = tm_g_bivariate(
    x = data_extract_spec(
      dataname = "CO2",
      select = select_spec(
        label = "Select variable:",
        choices = variable_choices(data[["CO2"]]),
        selected = "conc",
        fixed = FALSE
      )
    ),
    y = data_extract_spec(
      dataname = "CO2",
      select = select_spec(
        label = "Select variable:",
        choices = variable_choices(data[["CO2"]]),
        selected = "uptake",
        multiple = FALSE,
        fixed = FALSE
      )
    ),
    row_facet = data_extract_spec(
      dataname = "CO2",
      select = select_spec(
        label = "Select variable:",
        choices = variable_choices(data[["CO2"]]),
        selected = "Type",
        fixed = FALSE
      )
    ),
    col_facet = data_extract_spec(
      dataname = "CO2",
      select = select_spec(
        label = "Select variable:",
        choices = variable_choices(data[["CO2"]]),
        selected = "Treatment",
        fixed = FALSE
      )
    ),
    # decorators = list() # SHOULD BE OK
    # decorators = list(plot = static_decorator, default = interactive_decorator) # SHOULD BE OK
    # decorators = list(static_decorator, interactive_decorator) # SHOULD BE OK
    # decorators = list(plot = static_decorator, interactive_decorator) # SHOULD THROWN AN ERROR
  )
)

shinyApp(app$ui, app$server)

Copy link
Contributor

github-actions bot commented Jan 31, 2025

Unit Tests Summary

  1 files   22 suites   13m 2s ⏱️
145 tests 107 ✅ 38 💤 0 ❌
475 runs  437 ✅ 38 💤 0 ❌

Results for commit 67d76ed.

♻️ This comment has been updated with latest results.

Copy link
Contributor

github-actions bot commented Jan 31, 2025

Unit Test Performance Difference

Test Suite $Status$ Time on main $±Time$ $±Tests$ $±Skipped$ $±Failures$ $±Errors$
examples 💚 $5.24$ $-4.66$ $-1$ $+38$ $0$ $0$
shinytest2-tm_a_pca 💚 $118.90$ $-2.24$ $0$ $0$ $0$ $0$
shinytest2-tm_a_regression 💚 $53.87$ $-1.49$ $0$ $0$ $0$ $0$
shinytest2-tm_front_page 💚 $21.70$ $-1.15$ $0$ $0$ $0$ $0$
shinytest2-tm_g_association 💚 $33.18$ $-1.88$ $0$ $0$ $0$ $0$
shinytest2-tm_g_bivariate 💚 $75.94$ $-1.78$ $0$ $0$ $0$ $0$
shinytest2-tm_outliers 💚 $112.28$ $-1.12$ $0$ $0$ $0$ $0$
Additional test case details
Test Suite $Status$ Time on main $±Time$ Test Case
examples 💚 $1.71$ $-1.63$ example_add_facet_labels.Rd

Results for commit 8bf03fb

♻️ This comment has been updated with latest results.

Copy link
Contributor

@llrs-roche llrs-roche left a comment

Choose a reason for hiding this comment

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

I like the decision to only allow named or unnamed decorators.

  • decorators = list()

    No problem ✅

  • decorators = list(plot = static_decorator, default = interactive_decorator)

    I don't see the default interactive decorator having any effect. This makes sense but there is no message that the named one will be used instead. This confused me initially. Could you add a message/warning so that users know what is happening on that case? Or alternative patch the documentation?

image

⁉️

  • decorators = list(static_decorator, interactive_decorator)
    The interactive decorator worked well, but again no notification of what happened with the static_decorator. I would prefer to have some documentation or a clear message of what is happening here. ⁉️

  • decorators = list(plot = static_decorator, interactive_decorator)
    Throws an error (not a warning) ✅

  • decorators = list(plot = static_decorator, plot = interactive_decorator)
    This example also throws the same error "All decorators should either be named or unnamed" but here the duplicated decorator are named so the message is not informative. Could the users get a more informative message? ❌

@m7pr
Copy link
Contributor Author

m7pr commented Feb 3, 2025

@llrs-roche funny things.

I don't see the default interactive decorator having any effect. This makes sense but there is no message that the named one will be used instead. This confused me initially. Could you add a message/warning so that users know what is happening on that case? Or alternative patch the documentation?

Both of them are used, but both of them edit the same thing.

static_decorator is applied after interactive_decorator
they both edit ggplot2::xlab("x axis").

interactive_decorator uses input to edit xlab but then static_decorator overwrites with ggplot2::xlab("x axis").

If you remove ggplot2::xlab("x axis") from static_decorator, you can see that changes from interactive_decorator are actually visible:

image
Code
pkgload::load_all(".")
data <- teal_data()
data <- within(data, {
  require(nestcolor)
  CO2 <- CO2
  factors <- names(Filter(isTRUE, vapply(CO2, is.factor, logical(1L))))
  CO2[factors] <- lapply(CO2[factors], as.character)
})

static_decorator <- teal_transform_module(
  label = "Static decorator",
  server = function(id, data) {
    moduleServer(id, function(input, output, session) {
      reactive({
        req(data())
        within(data(), {
          plot <- plot +
            ggplot2::ggtitle("This is title")
        })
      })
    })
  }
)

interactive_decorator <- teal_transform_module(
  label = "Interactive decorator",
  ui = function(id) {
    ns <- NS(id)
    div(
      textInput(ns("x_axis_title"), "X axis title", value = "x axis")
    )
  },
  server = function(id, data) {
    moduleServer(id, function(input, output, session) {
      reactive({
        req(data())
        within(data(),
               {
                 plot <- plot +
                   ggplot2::ggtitle("This is title") +
                   ggplot2::xlab(my_title)
               },
               my_title = input$x_axis_title
        )
      })
    })
  }
)

app <- init(
  data = data,
  modules = tm_g_bivariate(
    x = data_extract_spec(
      dataname = "CO2",
      select = select_spec(
        label = "Select variable:",
        choices = variable_choices(data[["CO2"]]),
        selected = "conc",
        fixed = FALSE
      )
    ),
    y = data_extract_spec(
      dataname = "CO2",
      select = select_spec(
        label = "Select variable:",
        choices = variable_choices(data[["CO2"]]),
        selected = "uptake",
        multiple = FALSE,
        fixed = FALSE
      )
    ),
    row_facet = data_extract_spec(
      dataname = "CO2",
      select = select_spec(
        label = "Select variable:",
        choices = variable_choices(data[["CO2"]]),
        selected = "Type",
        fixed = FALSE
      )
    ),
    col_facet = data_extract_spec(
      dataname = "CO2",
      select = select_spec(
        label = "Select variable:",
        choices = variable_choices(data[["CO2"]]),
        selected = "Treatment",
        fixed = FALSE
      )
    ),
    # decorators = list() # SHOULD BE OK
    # decorators = list(plot = static_decorator, default = interactive_decorator) # SHOULD BE OK
    # decorators = list(static_decorator, interactive_decorator) # SHOULD BE OK
    decorators = list(plot = static_decorator, default = interactive_decorator) # SHOULD THROWN A WARNING
  )
)

shinyApp(app$ui, app$server)

@m7pr
Copy link
Contributor Author

m7pr commented Feb 3, 2025

decorators = list(plot = static_decorator, plot = interactive_decorator)
This example also throws the same error "All decorators should either be named or unnamed" but here the duplicated decorator are named so the message is not informative. Could the users get a more informative message? ❌

I think we can work on this. Thanks for double checking

@m7pr
Copy link
Contributor Author

m7pr commented Feb 6, 2025

Hey @llrs-roche when non-unique names are passed to decorators, function will throw a warning from assert_decorators. I allowed such case to pass through normalize_decorators. Check last commit.

Now user will see

Error in tm_g_bivariate(x = data_extract_spec(dataname = "CO2", select = select_spec(label = "Select variable:",  : 
  Assertion on 'decorators' failed: Non-unique names in decorators.
Called from: mstop("Assertion on '%s' failed: %s.", var.name, res, call. = sys.call(-2L))

I will push the same to tmc

Copy link
Contributor

@llrs-roche llrs-roche left a comment

Choose a reason for hiding this comment

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

Looks good and the corner case was handled elegantly. 👍

@m7pr m7pr merged commit 1c92f2a into main Feb 7, 2025
26 checks passed
@m7pr m7pr deleted the 1316_duplicates@main branch February 7, 2025 08:00
@github-actions github-actions bot locked and limited conversation to collaborators Feb 7, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants