Code in R package: find out *which* package/namespace it is in - r

Is there a way code in an R package can find out which package or namespace it belongs to?
Background: I find I have common code between packages that just differs in the package name. One common example is tests/testthat.R:
library(testthat)
library(ShiftedExcitation)
test_check("ShiftedExcitation")
If the code could find out to which package or namespace it belongs, I could avoid a number of places where the package name is now given.
Right now I define a hidden variable that contains the package name, say
.PKG <- "ShiftedExcitation"
and then use something along the lines of *
library(testthat)
library(.PKG, character.only = TRUE)
test_check(.PKG)
but I'm curious whether a more elegant solution exists.
* I did not get this working so far as testthat.R is evaluated outside the package namespace. It does work for defining a unittest function inside the package code, though.

Approaching an answer:
#MartinMorgan's hint to use topenv () is quite close. But it turns out that while running unit tests with testthat, testthat is before the package namespace in the search path.
So this is the current state:
.findmyname <- function() {
pkgs <- .packages ()
if (pkgs [1] == "testthat")
pkgs [2]
else
pkgs [1]
}
This function finds the name of the package in question both from within the package and in tests/testthat.R. (Of course, any .findmyname () defined within the package is not known in tests/testthat.R before the library call...)

Related

Function imported from dependency not found, requires library(dependency)

I am trying to create an R package that uses functions from another package (gamlss.tr).
The function I need from the dependency is gamlss.dist::TF (gamlss.dist is loaded alongside gamlss.tr), but it is referenced in my code as simply TF within a call to gamlss.tr::gen.trun.
When I load gamlss.tr manually with library(), this works. However, when I rely on the functions of the dependency automatically being imported by my package through #import, I get an "object not found" error as soon as TF is accessed.
My attempt to be more explicit and reference the function I need as gamlss.dist::TF resulted in a different error ("unexpected '::'").
Any tips on how to use this function in my package would be much appreciated!
The code below reproduces the problem if incorporated into a clean R package (as done in this .zip), built and loaded with document("/path/to/package"):
#' #import gamlss gamlss.tr gamlss.dist
NULL
#' Use GAMLSS
#'
#' Generate a truncated distribution and use it.
#' #export
use_gamlss <- function() {
print("gen.trun():")
gamlss.tr::gen.trun(par=0,family=TF)
#Error in inherits(object, "gamlss.family") : object 'TF' not found
#gamlss.tr::gen.trun(par=0,family=gamlss.dist::TF)
#Error in parse(text = fname) : <text>:1:1: unexpected '::'
y = rTFtr(1000,mu=10,sigma=5, nu=5)
print("trun():")
truncated_dist = gamlss.tr::trun(par=0,family=TF, local=TRUE)
model = gamlss(y~1, family=truncated_dist)
print(model)
}
use_gamlss() will only start working once a user calls library(gamlss.tr).
This is due to bad design of gamlss.tr in particular the trun.x functions (they take character vectors instead of family objects / they evaluate everything in the function environment instead of the calling environment).
To work around this, you have to make sure that gamlss.distr is in the search path of the execution environment of gamlss.tr functions (This is why ## import-ing it in your package does not help: it would need to be #' #import-ed in gamlss.tr).
This can be achieved by adding it to Depends: of your package.
If you want to avoid that attaching your package also attaches gamlss.distr, you could also add the following at the top of use_gamlss:
nsname <-"gamlss.dist"
attname <- paste0("package:", nsname)
if (!(attname %in% search())) {
attachNamespace(nsname)
on.exit(detach(attname, character.only = TRUE))
}
This would temporarily attach gamlss.dist if it is not attached already.
You can read more on namespaces in R in Hadley Wickham's "Advanced R"

How to find out if I am using a package

My R script has evolved over many months with many additions and subtractions. It is long and rambling and I would like to find out which packages I am actually using in the code so I can start deleting library() references. Is there a way of finding redundant dependencies in my R script?
I saw this question so I tried:
library(mvbutils)
library(MyPackage)
library(dplyr)
foodweb( funs=find.funs( asNamespace( 'EndoMineR')), where=
asNamespace( 'EndoMineR'), prune='filter')
But that really tells me where I am using a function from a package whereas I don't necessarily remember which functions I have used from which package.
I tried packrat but this is looking for projects whereas mine is a directory of scripts I am trying to build into a package.
To do this you first parse your file and then use getAnywhere to check for each terminal token in which namespace it is defined. Compare the result with the searchpath and you will have the answer. I compiled a function that takes a filename as argument and returns the packages which are used in the file. Note that it can only find packages that are loaded when the function is executed, so be sure to load all "candidates" first.
findUsedPackages <- function(sourcefile) {
## get parse tree
parse_data <- getParseData(parse(sourcefile))
## extract terminal tokens
terminal_tokens <- parse_data[parse_data$terminal == TRUE, "text"]
## get loaded packages/namespaces
search_path <- search()
## helper function to find the package a token belongs to
findPackage <- function(token) {
## get info where the token is defined
token_info <- getAnywhere(token)
##return the package the comes first in the search path
token_info$where[which.min(match(token_info$where, search_path))]
}
packages <- lapply(unique(terminal_tokens), findPackage)
##remove elements that do not belong to a loaded namespace
packages <- packages[sapply(packages, length) > 0]
packages <- do.call(c, packages)
packages <- unique(packages)
##do not return base and .GlobalEnv
packages[-which(packages %in% c("package:base", ".GlobalEnv"))]
}

Extended R package can't correctly communicate with its 'parent' R package

I am trying to build a package that extends another package. However at its most basic level I am doing something wrong. I build a simple example that presents the same issue:
I have two packages, packageA and packageB. packageA has a single R file in the R folder that reads:
local.env.A <- new.env()
setVal <- function()
{
local.env.A$test <- 1
}
getVal <- function()
{
if(!exists("test", envir = local.env.A)) stop("test does not exist")
return(local.env.A$test)
}
For packageB I have the following single R file in the R folder:
# refers to package A
setVal()
getValinA <- function()
{
return(getVal())
}
I want both packageA and packageB to be available for end users, therefore I set packageB to depend on packageA (in the description file). When packageB is loaded, e.g. by means of library(packageB) I expect it to run setVal() and thus set the test value. However, if I next try to get the value that was set by means of getValinA(), it throws me the stop:
> library(packageB)
Loading required package: PackageA
> getValinA()
Error in getVal() : test does not exist
I am pretty sure it is related to environments, but I am not sure how. Please help!
With thanks to #Roland. The answer was very simple. I was under the impression (assumptions assumptions assumptions!) that when you perform library(packageB) it would load all the actions within it, in my case perform the setVal() function. This is however not the case. If you wish this function to be performed you need to place this within the function .onLoad:
.onLoad <- function(libname, pkgname)
{
setVal()
}
By convention you place this .onload function in an R file called zzz.R. Reason being that if you do not specifically collate your R scripts it will load alphabetically, and it makes sense to perform your actions when at least all the functions in your package are loaded.

Why does using "<<-" in a function in the global workspace work, but not in a package?

I'm creating a package using devtools and roxygen2 (in RStudio), however after I've built the package my function no longer works as intended. Yet, if I load the function's .R file and run the function from there in RStudio, it works perfectly. I've created another package using this method before and it worked fine (13 functions all working as intended from my other package), yet I cant seem to get this new one to work.
To start creating the package I start with:
library("devtools")
devtools::install_github("klutometis/roxygen")
library(roxygen2)
setwd("my parent directory")
create("triale")
All is working fine so far. So I put my .R file containing my function in the R folder under the triale folder. The .R file looks like this:
#' Trial Z Function
#'
#' This function counts the values in the columns
#' #param x is the number
#' #keywords x
#' #export
#' #examples
#' trialz()
trialz = function(x) {w_id= c(25,x,25,25,25,1,1,1,1,1);
wcenter= c(rep("BYSTAR-1",10));
df1 <<- data.frame(w_id, wcenter);
countit <<- data.table(df1);
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
Again if I were to just run the code from the .R file, and test the function it works fine. But to continue, next I enter:
setwd("./triale")
document()
The triale documentation is updated, triale is loaded, and the NAMESPACE and trialz.Rd are both written so that trialz.Rd is under the man folder, and NAMESPACE is under the triale folder as intended. Next I install triale:
setwd("..")
install("triale")
Which I know works because I get the following:
Installing triale
"C:/PROGRA~1/R/R-31~1.3/bin/x64/R" --vanilla CMD INSTALL \
"C:/Users/grice/Documents/R/triale" \
--library="C:/Users/grice/Documents/R/win-library/3.1" --install-tests
* installing *source* package 'triale' ...
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
*** arch - i386
*** arch - x64
* DONE (triale)
Reloading installed triale
Package is now built, so I do the following:
library("triale")
library("data.table")
Note whenever I load the package data.table I get the following error message:
data.table 1.9.4 For help type: ?data.table
*** NB: by=.EACHI is now explicit. See README to restore previous behaviour.
However it doesnt seem to affect my function. So now its time to test my function from my package:
trialz(25)
This goes through, and I of course get a populated df1, and countit, but for whatever reason view is always empty (as in 0 obs. of 0 variables).
So I test my work using the dummy code below:
>trialy = function(x) {wid= c(25,x,25,25,25,1,1,1,1,1);
wc= c(rep("BYSTAR-1",10));
df2 <<- data.frame(wid, wc);
countitt <<- data.table(df2);
viewer <<- countitt[, .N, by = list(wid, wc)];
View(viewer)}
>trialy(25)
Even though this is the same exact code with just the names changed around it works. Dumbfounded I open trialz.R and copy the function from there and run it as below, and that works:
> trialz = function(x) {w_id= c(25,x,25,25,25,1,1,1,1,1);
wcenter= c(rep("BYSTAR-1",10));
df1 <<- data.frame(w_id, wcenter);
countit <<- data.table(df1);
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
> trialz(25)
Since I've created a package before I know my method is solid (that package had 13 dif. functions, all of which worked). I just don't understand how a function can work fine as written, yet when I package it, the function no longer works.
Again here is where it stops working as intended when using my package:
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
And my end result should look something like this, if my package worked:
wid wc N
1 25 BYSTAR-1 5
2 1 BYSTAR-1 5
Can anyone explain why view is never populated after I package my function? I've tested it as much as I know how, and my results should be reproducible for anyone thats willing to try it for themselves.
Thanks, I appreciate any feedback.
Your problem here is that "<<-" does not create variables in the global environment but rather in the parent environment. (See help("<<-").)
The parent environment of a function is the environment in which it has been defined. In the case where you defined your function directly in your workspace, this parent environment actually is the same as your workspace environment (namely: .GlobalEnv), which is why your variables are assigned values as you expect them to. In the case where your function is packaged, however, the parent environment is the package environment and not the .GlobalEnv! This is why you do not see your variables being assigned values in your workspace.
Refer to the chapter on environments in Hadley's book and How R Searches and Finds Stuff for more details on environments in R.
Note that doing this would not be considered a proper debugging technique, to say the least. In general, you never want to use the "<<-" operator.
For options on debugging R code, see, e.g., this question. I, in particular, like the debugonce function very well. See ?debugonce.
I forgot one important part when editing my description file in that I for got to add
Imports: data.table
Also the NAMESPACE file needed to include the data.table package as an import as well, like so:
import(data.table)
export(Z)
export(AS) .... etc.
Doing this ensures that whenever a function within your package uses a function from another package, that (second) package is called up before your code is executed.

Get namespace of function

I'm developing a package where I wish to add an edit history to an object. The package allows other packages to register functions for editing the object. I'm looking for a way to record the version of the package that registered the function that was used for the edit.
The question is: Given a function how do you get the package from where it was exported? My idea is to investigate its search path, but search() only reports the search path for the current environment and thus not for a function, which is what I need.
Any pointers to other approaches is greatly appreciated.
The context for getting the package is this:
registerFunction <- function(fun) {
package <- getPackage(fun) ## This is what I need
version <- getPackageVersion(package)
register(fun, package, version)
}
You can use getAnywhere For example, if you're looking for the namespace for the stringr function str_locate you can do
getAnywhere("str_locate")$where
# [1] "package:stringr" "namespace:stringr"
This will work as long as stringr is "visible on the search path, registered as an S3 method or in a namespace but not exported."
The result is a named list, and you can see what's available from getAnywhere with names
names(getAnywhere("str_locate"))
# [1] "name" "objs" "where" "visible" "dups"
You can use:
environment(fun=someFunctionName)
It will return the environment of the function passed as parameter, specifying also the namespace, i.e. the package name.

Resources