Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

malcolmbarrett
Copy link
Contributor

…and bump rlang requirement

Prework

PR

This PR modifies assert_package() to use rlang::check_installed() which is a recent, very ergonomic package check that offers to install the package(s) for you. It's also vectorized. This did require a small bump in the required rlang version, as it's a new feature.

On my machine, for instance, I now get this message with tar_watch():

tar_watch()
ℹ The `bs4Dash` and `shinyWidgets` packages are required.
x Would you like to install them?

1: Yes
2: No

@wlandau
Copy link
Member

wlandau commented Feb 27, 2021

I do like the menu, and I appreciate how much pain it takes away from the user. However, check_installed() throws an error of class c("rlang_error", "error", "condition") instead of the desired c("condition_validate", "condition_targets", "error", "condition"). Custom assertions like assert_package() generate custom error objects:

error_validate <- function(...) {
structure(
list(message = paste0(..., collapse = ""), call = NULL),
class = c("condition_validate", "condition_targets", "error", "condition")
)
}

These custom error classes help targets and its tests distinguish among different kinds of errors and help keep the infrastructure working. If you can figure out how to combine the best of both worlds, I will accept the PR.

@wlandau
Copy link
Member

wlandau commented Feb 27, 2021

Assuming we solve that, please add check_installed to the @importFrom statement in R/tar_package.R.

#' @importFrom rlang as_function as_quosure enquo quo quo_squash sym

@malcolmbarrett
Copy link
Contributor Author

malcolmbarrett commented Feb 27, 2021

Ah, I see! For my own interest, can you point me to a spot where targets is checking such classed conditions? I have a growing interest in them after seeing some cool use cases.

Anyway, I did a simple catch of the error, replaced it with throw_validate(), then imported check_installed(). Let me know how it looks!

@wlandau
Copy link
Member

wlandau commented Feb 27, 2021

I tested this out, and check_installed() makes it so easy to install missing packages without any interruption. I think the PR will be ready to merge after a couple of minor details are resolved (see my inline comments). Thanks for the contribution.

For my own interest, can you point me to a spot where targets is checking such classed conditions? I have a growing interest in them after seeing some cool use cases.

I mostly use it for tests, as you may have seen with expect_error(..., class = "condition_validate"). It may be possible to define nice print methods for these kinds of errors, though I have not done so yet. On rare occasions, I also use it to divert control flow without having to worry about where I am in the call stack. This is useful in high-performance computing situations where we run targets locally until we find a target that requires a remote worker:

throw_prelocal("requires workers")

targets/R/class_clustermq.R

Lines 199 to 205 in 1e4dfe1

tryCatch(
self$produce_prelocal()$run(),
condition_prelocal = function(e) NULL
)
if (self$scheduler$queue$is_nonempty()) {
self$run_clustermq()
}

@malcolmbarrett
Copy link
Contributor Author

Yes, it's a much more pleasant approach! I was happy to find it. For context, we're now using targets as our default project structure, but we also use renv by default. Sometimes renv doesn't have a package cached that you otherwise have on your machine, so this workflow is much smoother. We use an explicit, DESCRIPTION-based approach to renv package management, and usethis::use_package() runs check_installed() when adding a pkg to that file. It was such an improvement to my workflow that I thought I just had to try to get it in targets for the rest of my workflow 😁

Thanks also for the example! That's interesting and exactly the sort of use case I think is compelling.

Anyway, all updated. Let me know if there's anything else

@wlandau wlandau merged commit 77e1581 into ropensci:main Feb 27, 2021
@wlandau
Copy link
Member

wlandau commented Feb 27, 2021

Looks great, thanks again.

FWIW, targets has a tar_renv() function that detects many of the package requirements of a pipeline and writes a _packages.R file that renv can detect automatically. (Though it does not create or modify a DESCRIPTION file.)

@malcolmbarrett
Copy link
Contributor Author

Awesome, thanks! I didn't know about tar_renv(); I'll take a closer look. While it may not be useful for our team workflow, I am developing some teaching material about using targets + renv that uses the default (implicit) renv detection, so it will probably be a great thing to have handy!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants