Skip to content

Conversation

@maelle
Copy link
Member

@maelle maelle commented Aug 20, 2025

Fix #546

Example usage: EMODnet/emodnet.wfs#193

@@ -0,0 +1,7 @@
#' @rdname vcr-example
Copy link
Member Author

Choose a reason for hiding this comment

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

I'd like to add an actual test but am not sure how to.

#' @return Nothing: called for file system side effects.
#' @export
#'
use_vcr_examples <- function(path = ".") {
Copy link
Member Author

Choose a reason for hiding this comment

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

@maelle maelle requested review from hadley and sckott and removed request for hadley August 20, 2025 09:49
@@ -1,8 +1,12 @@
#' Use cassettes in examples
#'
#' @description
Copy link
Member Author

Choose a reason for hiding this comment

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

In this file it'd be useful to describe how to run the examples. devtools::run_examples()? Use example()? Run the code by opening the Rd file? Which reminds me of posit-dev/positron#1734

Choose a reason for hiding this comment

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

Yes! I ended up running my examples line by line, which was a little tedious.

}

#' @export
roxy_tag_rd.roxy_tag_examplesVCR <- function(x, base_path, env) {
Copy link
Member Author

Choose a reason for hiding this comment

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

@maelle
Copy link
Member Author

maelle commented Aug 20, 2025

I wonder how useful this would actually be, given that there might be other boilerplate code anyway: in ellmer an option is set and unset, in @drmowinckels' package a function is called to fake authentication.

Could one somehow use @examples with a code chunk like in a vignette, with "eval" (=examplesIf) and "cassette" options for instance? And a knitr hook would allow having the right boilerplate code with dontshow.

Could one also store some boilerplate for all examples in a central place, like a general setup chunk for all examples, that could set local options for instance?
Or for that should package maintainers write their own @examples tag overwriting the roxygen2 one?

I might be overthinking this. 😅

R/roxygen.R Outdated
Comment on lines 1 to 2
#' @importFrom roxygen2 roxy_tag_parse
#' @importFrom roxygen2 roxy_tag_rd
Copy link
Member

Choose a reason for hiding this comment

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

I think you could drop these and switch from @exporting the method to @S3method registering it so you don't need to import roxygen2.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

I made a new try, I hope I got it right. Thanks for the link!

@maelle maelle requested a review from hadley August 22, 2025 14:23
@sckott
Copy link
Collaborator

sckott commented Aug 25, 2025

Thanks @maelle !!

I imagine users won't want to write their own @examples tag, so from that perspective there's motivation for it here.

How fragile do you think these code changes are in this PR? That is, adding it here means we need to maintain it moving forward, and I'm curious if these kinds of additions to roxygen2 get broken with new roxygen2 versions? Asking because I'm not familiar with roxygen2 from the dev side.

So what is the usage flow like? Someone adds the @examplesVCR tag to an example block and then what? Do they have to run local_cassette or similar with the path the example will use and run the code line by line? Running line by line is how it currently works so that's the same behavior.

@maelle
Copy link
Member Author

maelle commented Aug 26, 2025

@sckott

I imagine users won't want to write their own @examples tag, so from that perspective there's motivation for it here.

Maybe they would, if that were better documented/easier? But yes, not vcr's concern.

How fragile do you think these code changes are in this PR? That is, adding it here means we need to maintain it moving forward, and I'm curious if these kinds of additions to roxygen2 get broken with new roxygen2 versions? Asking because I'm not familiar with roxygen2 from the dev side.

Well with @hadley as a reviewer hopefully we're adding the tag correctly so that it won't be fragile. 😅 There are other packages out there building upon roxygen2's infrastructure, like @mpadge's srr https://github.com/ropensci-review-tools/srr (which is far more complex than what we're doing in this PR!).

So what is the usage flow like? Someone adds the @examplesVCR tag to an example block and then what? Do they have to run local_cassette or similar with the path the example will use and run the code line by line? Running line by line is how it currently works so that's the same behavior.

Instead of using @examples the package author would use @examplesVCR. To create the cassette I opened the Rd file and ran the code that was in there which honestly wasn't ideal as noted in #548 (comment). I'd like us to document this better. devtools::run_examples(start = "<path>") might be the solution, but it run all examples starting from the path, not only the example from the path.

@hadley
Copy link
Member

hadley commented Aug 27, 2025

@maelle it's so sweet and naive that you think I have any idea how adding new roxygen2 tags works 😆

@maelle
Copy link
Member Author

maelle commented Aug 27, 2025

I simply expect you as a roxygen2 maintainer to not break this precious tag in the future 🥺

@mpadge
Copy link
Member

mpadge commented Aug 28, 2025

This is cool people! Just one note that from all attempts at roxygen2 adaptation and expansion that I could find, there seems to be a general approach that roxy_tag_parse() functions are used for the single roxygen2 function call to whatever form of parsing you are implementing- so in your case, roxygen2::tag_examples(x), while the mechanics generally live in roclet_process(), and not within roxy_tag_parse(). I think that'd just mean putting this code:

vcr/R/roxygen.R

Lines 8 to 25 in 35f3a67

lines <- unlist(strsplit(x$raw, "\r?\n"))
cassette_name <- trimws(lines[1])
package_name <- roxygen2::roxy_meta_get("current_package")
x$raw <- paste(
c(
sprintf(
"\\dontshow{vcr::insert_example_cassette('%s', package = '%s')}",
cassette_name,
package_name
),
lines[-1],
"\\dontshow{vcr::eject_cassette()}"
),
collapse = "\n"
)
x$value <- ""

into roclet_process instead. That code is quite clearly processing and not parsing,

One day somebody here will get around to writing the long-awaiting roxygen2 extension manual, and when that happens, it should and will definitely suggest that parsing is strictly for parsing only, and processing is for everything else. Moreover, processing is also general, and can be applied directly to all tags associated with a given roclet, while parsing is applied to the specified tag only. Any future generalisation to other vcr tags from current form would thus require directly copying and repating the roclet_parse code, whereas defining in roclet_process defines a general engine that can be applied at any later stage to all vcr roclet tags, as well as the single one you're implementing here.

@maelle
Copy link
Member Author

maelle commented Sep 1, 2025

Sort of related: r-lib/roxygen2#1697 where I had asked "could one define a whole new tag in a package without importing roxygen2?" 😅

@maelle
Copy link
Member Author

maelle commented Sep 1, 2025

@mpadge I'm sorry but I didn't understand.

I thought you meant moving the body of roxy_tag_parse.roxy_tag_examplesVCR() to roclet_process.roclet_examplesVCR() which didn't work.

Any chance you could do a PR to this PR? 😅 Thanks in advance.

@sckott
Copy link
Collaborator

sckott commented Oct 16, 2025

@maelle What's the next step in this PR?

@maelle
Copy link
Member Author

maelle commented Oct 23, 2025

@sckott

  • Maybe @mpadge can make a PR to the PR to improve this, but if not I guess we could still move forward.
  • I am not sure how to add a test.

I'm also still wondering how we could help with more complicated setup code for examples #548 (comment) but that might be beyond the scope of both this PR and vcr. 😸

@mpadge
Copy link
Member

mpadge commented Oct 27, 2025

Maybe @mpadge can make a PR to the PR to improve this, but if not I guess we could still move forward.

I did a detailed comparison of this PR with srr, and think you've actually got the best structure here, with roxy_tag_parse.roxy_tag_examplesVCR, contrary to what I said above. So all good there.

I am not sure how to add a test.

PR #551 hopefully helps. It adds a modified version of the pkg skeleton used to test srr.

@sckott
Copy link
Collaborator

sckott commented Nov 4, 2025

thanks @mpadge ! Sorry for delay on this, i'll take a look at the PR

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.

roxygen2 tag

6 participants