When debugging functions from an external package, I often find myself copying the function to a new script to add my corrections, but I have to add a bunch of foo=extpack:::foo
at the beginning of the script for the function to access the internal function of the package.
Cloning and building the package would be a total overkill in those situations when often a single line is changed.
Is there a way to attach the package with all its internal functions?
Something like library(extpack, attach_nonexported=TRUE)
You can get all functions from a package namespace as an environment by doing e.g.:
getNamespace("ggplot2")
So you can attach them to your search path (similar to calling library
with unexported functions) by doing:
attach(getNamespace("ggplot2"))
If you prefer them in a list you can do
as.list(getNamespace("ggplot2"))
Or if you wish them to appear in the global workspace, you can do:
list2env(as.list(getNamespace("ggplot2")), globalenv())
Needless to say, you should only do this kind of thing with interactive sessions rather than when writing a package.
if you really want to simulate a library call we can create a "package:yourpkg" on the searchpath containing all functions :
magrittr::as_pipe_fn
#> Error: 'as_pipe_fn' n'est pas un objet exporté depuis 'namespace:magrittr'
magrittr:::as_pipe_fn
#> function (expr, env)
#> {
#> eval(call("function", lambda_fmls, expr), env)
#> }
#> <bytecode: 0x0000000013917228>
#> <environment: namespace:magrittr>
attach_all <- function(pkg) {
pkg <- as.character(substitute(pkg))
pkg_long <- paste0("package:", pkg)
eval(bquote(with(
setNames(list(getNamespace(pkg)), pkg_long),
attach(.(as.symbol(pkg_long)))
)))
}
attach_all(magrittr)
search()
#> [1] ".GlobalEnv" "package:magrittr" "package:stats"
#> [4] "package:graphics" "package:grDevices" "package:utils"
#> [7] "package:datasets" "package:methods" "Autoloads"
#> [10] "tools:callr" "package:base"
as_pipe_fn
#> function (expr, env)
#> {
#> eval(call("function", lambda_fmls, expr), env)
#> }
#> <bytecode: 0x0000000013917228>
#> <environment: namespace:magrittr>
Created on 2020-10-09 by the reprex package (v0.3.0)
It might make you nervous to use package:mypkg
, feel free to change this part if so, the result will be the same.
Another way would be to attach the unexported functions to a different environment so you can detach it independently if needed :
attach_unexported <- function(pkg) {
pkg <- as.character(substitute(pkg))
all_funs <- lsf.str(asNamespace(pkg))
exported <- getNamespaceExports(pkg)
unexported_funs <- setdiff(all_funs, exported)
pkg_long <- paste0(pkg, "_unexported")
eval(bquote(with(
setNames(list(mget(unexported_funs, asNamespace(pkg))), pkg_long),
attach(.(as.symbol(pkg_long)))
)))
}
attach_unexported(magrittr)
search()
#> [1] ".GlobalEnv" "magrittr_unexported" "package:stats"
#> [4] "package:graphics" "package:grDevices" "package:utils"
#> [7] "package:datasets" "package:methods" "Autoloads"
#> [10] "tools:callr" "package:base"
as_pipe_fn
#> function (expr, env)
#> {
#> eval(call("function", lambda_fmls, expr), env)
#> }
#> <bytecode: 0x0000000013a05bd0>
#> <environment: namespace:magrittr>
`%>%`
#> Error in eval(expr, envir, enclos): objet '%>%' introuvable
Created on 2020-10-09 by the reprex package (v0.3.0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With