Skip to content

Commit

Permalink
datanames in vignettes (#239)
Browse files Browse the repository at this point in the history
concise cods
  • Loading branch information
gogonzo authored Jan 7, 2025
1 parent b385638 commit 8c05112
Show file tree
Hide file tree
Showing 17 changed files with 353 additions and 311 deletions.
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ repos:
name: Regenerate package documentation
additional_dependencies:
- checkmate
- cli
- grDevices
- lifecycle
- methods
Expand Down
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ Depends:
R (>= 4.0)
Imports:
checkmate (>= 2.1.0),
cli (>= 3.4.0),
grDevices,
lifecycle (>= 0.2.0),
rlang (>= 1.1.0),
stats,
utils
Suggests:
cli (>= 3.4.0),
knitr (>= 1.42),
rmarkdown (>= 2.23),
shiny (>= 1.6.0),
Expand All @@ -45,7 +45,7 @@ VignetteBuilder:
rmarkdown
RdMacros:
lifecycle
Config/Needs/verdepcheck: mllg/checkmate, r-lib/lifecycle, r-lib/rlang,
Config/Needs/verdepcheck: mllg/checkmate, r-lib/cli, r-lib/lifecycle, r-lib/rlang,
r-lib/cli, yihui/knitr, rstudio/rmarkdown, rstudio/shiny,
r-lib/testthat, r-lib/withr
Config/Needs/website: insightsengineering/nesttemplate
Expand Down
38 changes: 24 additions & 14 deletions R/qenv-constructor.R
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
#' Code tracking with `qenv` object
#' Instantiates a `qenv` environment
#'
#' @description
#' `r badge("stable")`
#'
#' Create a `qenv` object and evaluate code in it to track code history.
#'
#' @param names (`character`) for `x[names]`, names of objects included in `qenv` to subset. Names not present in `qenv`
#' are skipped. For `get_code` `r lifecycle::badge("experimental")` vector of object names to return the code for.
#' For more details see the "Extracting dataset-specific code" section.
#' Instantiates a `qenv` environment.
#'
#' @details
#'
#' `qenv()` instantiates a `qenv` with an empty environment.
#' Any changes must be made by evaluating code in it with `eval_code` or `within`, thereby ensuring reproducibility.
#' `qenv` class has following characteristics:
#'
#' - It inherits from the environment and methods such as [`$`], [get()], [ls()], [as.list()],
#' [parent.env()] work out of the box.
#' - `qenv` is a locked environment, and data modification is only possible through the [eval_code()]
#' and [within.qenv()] functions.
#' - It stores metadata about the code used to create the data (see [get_code()]).
#' - It supports slicing (see [`subset-qenv`])
#' - It is immutable which means that each code evaluation does not modify the original `qenv`
#' environment directly. See the following code:
#'
#' ```
#' q1 <- qenv()
#' q2 <- eval_code(q1, "a <- 1")
#' identical(q1, q2) # FALSE
#' ```
#'
#' @name qenv
#'
#' @return `qenv` returns a `qenv` object.
#' @return `qenv` environment.
#'
#' @seealso [`base::within()`], [`get_var()`], [`get_env()`], [`get_warnings()`], [`join()`], [`concat()`]
#' @seealso [eval_code()], [get_var()], [`subset-qenv`], [get_env()],[get_warnings()], [join()], [concat()]
#' @examples
#' # create empty qenv
#' qenv()
#'
#' q <- qenv()
#' q2 <- within(q, a <- 1)
#' ls(q2)
#' q2$a
#' @export
qenv <- function() {
methods::new("qenv")
Expand Down
5 changes: 2 additions & 3 deletions R/qenv-eval_code.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#' Evaluate code in `qenv`
#'
#' @details
#'
#' `eval_code()` evaluates given code in the `qenv` environment and appends it to the `code` slot.
#' Thus, if the `qenv` had been instantiated empty, contents of the environment are always a result of the stored code.
#'
Expand All @@ -10,7 +11,7 @@
#' `expression` being a result of `parse(keep.source = TRUE)`.
#'
#' @return
#' `eval_code` returns a `qenv` object with `expr` evaluated or `qenv.error` if evaluation fails.
#' `qenv` environment with `code/expr` evaluated or `qenv.error` if evaluation fails.
#'
#' @examples
#' # evaluate code in qenv
Expand All @@ -20,8 +21,6 @@
#' q <- eval_code(q, quote(library(checkmate)))
#' q <- eval_code(q, expression(assert_number(a)))
#'
#' @name eval_code
#' @rdname qenv
#' @aliases eval_code,qenv,character-method
#' @aliases eval_code,qenv,language-method
#' @aliases eval_code,qenv,expression-method
Expand Down
15 changes: 8 additions & 7 deletions R/qenv-extract.R
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
#' Subsets `qenv`
#'
#' @section Subsetting:
#' `x[names]` subsets objects in `qenv` environment and limit the code to the necessary needed to build limited objects.
#' `...` passes parameters to further methods.
#' @description
#' Subsets [`qenv`] environment and limits the code to the necessary needed to build limited objects.
#'
#' @param x (`qenv`)
#' @param names (`character`) names of objects included in [`qenv`] to subset. Names not present in [`qenv`]
#' are skipped.
#' @param ... internal usage, please ignore.
#'
#' @examples
#' @name subset-qenv
#'
#' # Subsetting
#' @examples
#' q <- qenv()
#' q <- eval_code(q, "a <- 1;b<-2")
#' q["a"]
#' q[c("a", "b")]
#'
#' @rdname qenv
#'
#' @export
`[.qenv` <- function(x, names, ...) {
checkmate::assert_character(names, any.missing = FALSE)
Expand Down
40 changes: 8 additions & 32 deletions R/qenv-get_code.R
Original file line number Diff line number Diff line change
@@ -1,39 +1,17 @@
#' @name qenv-inheritted
#' @rdname qenv
#'
#' @details
#'
#' `x[[name]]`, `x$name` and `get(name, x)` are generic \R operators to access the objects in the environment.
#' See [`[[`] for more details.
#' `names(x)` calls on the `qenv` object and will list all objects in the environment.
#'
#' @return `[[`, `$` and `get` return the value of the object named `name` in the `qenv` object.
#' @return `names` return a character vector of all the names of the objects in the `qenv` object.
#' @return `ls` return a character vector of the names of the objects in the `qenv` object.
#' It will only show the objects that are not named with a dot prefix, unless
#' the `all.names = TRUE`, which will show all objects.
#'
#' @examples
#' # Extract objects from qenv
#' q[["a"]]
#' q$a
#'
#' # list objects in qenv
#' names(q)
NULL

#' Get code from `qenv`
#'
#' @details
#' `get_code()` retrieves the code stored in the `qenv`. `...` passes arguments to methods.
#' @description
#' Retrieves the code stored in the `qenv`.
#'
#' @param object (`qenv`)
#' @param deparse (`logical(1)`) flag specifying whether to return code as `character` or `expression`.
#' @param ... see `Details`
#'
#' @param ... internal usage, please ignore.
#' @param names (`character`) `r lifecycle::badge("experimental")` vector of object names to return the code for.
#' For more details see the "Extracting dataset-specific code" section.
#'
#' @section Extracting dataset-specific code:
#' When `names` for `get_code` is specified, the code returned will be limited to the lines needed to _create_
#'
#' `get_code(object, names)` limits the returned code to contain only those lines needed to _create_
#' the requested objects. The code stored in the `qenv` is analyzed statically to determine
#' which lines the objects of interest depend upon. The analysis works well when objects are created
#' with standard infix assignment operators (see `?assignOps`) but it can fail in some situations.
Expand Down Expand Up @@ -98,7 +76,7 @@ NULL
#' - creating and evaluating language objects, _e.g._ `eval(<call>)`
#'
#' @return
#' `get_code` returns the traced code in the form specified by `deparse`.
#' The code used in the `qenv` in the form specified by `deparse`.
#'
#' @examples
#' # retrieve code
Expand All @@ -114,8 +92,6 @@ NULL
#' q <- eval_code(q, code = c("a <- 1", "b <- 2"))
#' get_code(q, names = "a")
#'
#' @name get_code
#' @rdname qenv
#' @aliases get_code,qenv-method
#' @aliases get_code,qenv.error-method
#'
Expand Down
7 changes: 3 additions & 4 deletions R/qenv-get_var.R
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#' Get object from `qenv`
#'
#' @description
#' `r lifecycle::badge("deprecated")` by native \R operators/functions:
#' `x[[name]]`, `x$name` or [get()].
#' `r lifecycle::badge("deprecated")`
#' Instead of [get_var()] use native \R operators/functions:
#' `x[[name]]`, `x$name` or [get()]:
#'
#' Retrieve variables from the `qenv` environment.
#'
Expand All @@ -17,8 +18,6 @@
#' q2 <- eval_code(q1, code = "b <- a")
#' get_var(q2, "b")
#'
#' @name get_var
#' @rdname get_var
#' @aliases get_var,qenv,character-method
#' @aliases get_var,qenv.error,ANY-method
#'
Expand Down
33 changes: 32 additions & 1 deletion R/qenv-show.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,36 @@
#' @importFrom methods show
#' @export
setMethod("show", "qenv", function(object) {
rlang::env_print(object@.xData)
env <- get_env(object)
header <- cli::col_blue(sprintf("<environment: %s>", rlang::env_label(env)))
parent <- sprintf("Parent: <environment: %s>", rlang::env_label(rlang::env_parent(env)))
cat(cli::style_bold(header), "\U1F512", "\n")
cat(parent, "\n")

shown <- ls(object)
if (length(shown > 0L)) cat(cli::style_bold("Bindings:\n"))
lapply(shown, function(x) {
cat(
sprintf(
"- %s: [%s]\n",
deparse(rlang::sym(x), backtick = TRUE),
class(object[[x]])[1]
)
)
})

hidden <- setdiff(ls(object, all.names = TRUE), shown)
lapply(hidden, function(x) {
cat(
cli::style_blurred(
sprintf(
"- %s: [%s]\n",
deparse(rlang::sym(x), backtick = TRUE),
class(object[[x]])[1]
)
)
)
})

invisible(object)
})
18 changes: 6 additions & 12 deletions R/qenv-within.R
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
#' Evaluate Expression in `qenv`
#'
#' @details
#' `within()` is a convenience function for evaluating inline code inside the environment of a `qenv`.
#' It is a method for the `base` generic that wraps `eval_code` to provide a simplified way of passing code.
#' `within` accepts only inline expressions (both simple and compound) and allows for injecting values into `expr`
#' through the `...` argument:
#' as `name:value` pairs are passed to `...`, `name` in `expr` will be replaced with `value`.
#' `within()` is a convenience method that wraps `eval_code` to provide a simplified way of passing expression.
#' `within` accepts only inline expressions (both simple and compound) and allows to substitute `expr`
#' with `...` named argument values.
#'
#' @section Using language objects with `within`:
#' Passing language objects to `expr` is generally not intended but can be achieved with `do.call`.
#' Only single `expression`s will work and substitution is not available. See examples.
#'
#' @param data (`qenv`)
#' @param expr (`expression`) to evaluate. Must be inline code, see `Using language objects...`
#' @param ... see `Details`
#'
#' @return
#' `within` returns a `qenv` object with `expr` evaluated or `qenv.error` if evaluation fails.
#' @param ... named argument value will substitute a symbol in the `expr` matched by the name.
#' For practical usage see Examples section below.
#'
#' @examples
#' # evaluate code using within
Expand Down Expand Up @@ -49,7 +43,7 @@
#' within(q, exprlist) # fails
#' do.call(within, list(q, do.call(c, exprlist)))
#'
#' @rdname qenv
#' @rdname eval_code
#'
#' @export
#'
Expand Down
1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ reference:
- join
- qenv
- show,qenv-method
- subset-qenv
- within.qenv
88 changes: 88 additions & 0 deletions man/eval_code.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8c05112

Please sign in to comment.