| make_CRANtidote | R Documentation |
Sigh... CRAN will reject packages with NOTE "no visible binding for global variable" from R CMD check— not WARNING, just NOTE. This is stupid because of false-positives whenever mlocal, cq, or indeed evalq or local, are called :/. Arguing with CRAN is about as productive as trying to teach a dead fish to climb trees. So, call make_CRANtidote instead, to get a bit of code that you can paste at the end of your package's .onLoad to suppress the non-problem. Your package does not need to import mvbutils to use that code.
It works by creating a dummy for each of those variables in the namespace environment, specifically a function that causes an error (stop) with the message "CRANtidote failure". It has to be a function, since as-CRAN checks look not just for variables, but for functions. Sigh.
The dummy function should never be called, and if you see that "CRANtidote failure" error message, then the dummy has masked something important. Unwanted side-effects are unlikely, but possible: here's two examples. First, when I initially tried this with mvbutils itself, it noticed that .onAttach was mentioned directly somewhere, and helpfully tried to add that— causing failure on attach(), since R tried to run a non-function .onAttach. So .onAttach is now specifically excluded to avoid this, and will need tweaking manually in your code. There might be other special things only created/needed after .onLoad that need similar attention.
The second side-effect might be more common, but is easily fixed. Suppose you requireNamespace a package (which is OK, even according to CRAN and even if it lives in a different repo, as long as it's listed in "Suggests"), but you don't want to always refer to its members by name, e.g. otherpak::funcaroo. Of course, R says you're Supposed To do the latter, but that is not always cozza increased verbosity and decreased code clarity; and e.g. what about operators a la %dopar% in parallel? Then, just call locally_import("otherpak") instead of requireNamespace("otherpak"). It will create a local copy (an "import") of all exportees in "otherpak", by default just in the frame it is called from (so the copy disappears as soon as your code finishes). The local copies will mask any dummies created by make_CRANtidote, so things should work as you expect.
locally_import might be generally useful for packages in "Suggests", even without make_CRANtidote (if you don't care about CRAN), since it saves on precious colons— and it does eliminate the unlikely-but-logically-possible problem that a synonymous function from some completely different attached package might mask the version you are hoping to call (and without locally_import, the colonless version would only work if you attach(otherpak) anyway). You can also "import" just some selected functions.
make_CRANtidote( checkout)
locally_import( pkg, funs=getNamespaceExports( pkg), to=parent.frame())
checkout |
Result of a call to |
pkg |
name of a package, presumably listed in "Suggests" but not necessarily |
funs |
which things to "import" from |
to |
environment to create the "imports" in. The default is whatever frame |
make_CRANtidote returns a character vector of class cat, which will display nicely so that you can cut-and-paste it into your .onLoad.
locally_import returns TRUE or FALSE, like requireNamespace.
## Not run:
if( FALSE && is_very_annoying( CRAN)){ # to avoid CRAN trying to run this despite dont-run :/
test <- check.pkg( 'mypak')
make_CRANtidote( test)
# Some function defined in your own package.
# This example is complete nonsense--- its only purpose is to show syntax!
mypakfun <- function( x){
locally_import( 'doParallel') # everything from 'doParallel'
locally_import( 'otherpak', c( 'funcaroo', 'bo_diddley')) # just those 2
# Look mum no double-colons
thrub <- funcaroo( x %dopar% y)
return( bo_diddley( thrub))
}
}
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.