How to debug unexported functions from required packages? - r

A function, in a package I am using is giving me not so informative errors. I don't know what is going on. This function is called internally by the function I call. Something like this:
myres <- the.func(x)
the.func <-function(x){
unexported.func(x)
}
How do I debug unexported.func ?
Using debug doesn't work:
>debug(unexported.func)
Error in debug(undexported.func) : object 'unexported.func' not found
Update:
Currently I do nested debug like the following. But I find it inconvenient:
>debug(the.func) # Initiate debugging for the outer function, so I get unexported.func loaded.
>myres <- the.func(x)
Browse[2]>debug(unexported.func) # Now I can call debug with this.

You can access an unexported function via the ::: (triple-colon) operator, prefacing it with the package namespace name (i.e. the package name).
Assuming the pkgA contains the unexported function unexported.func(), we would set the debugging flag on unexported.func() using:
debug(pkgA:::unexported.func)
If you don't know which package (hence namespace) to use for a given unexported function, you can always determine this using getAnywhere().

Related

how to specify a package or namespace for `rlang::exec`?

I am trying to write a function (within a package) which involves allowing the user to specify a function from a specific package to execute and provide additional arguments for that function.
I can do this in two steps with rlang::call2 as follows:
# `my_pkg` = "foo" (user-input)
# `my_fun` = "bar" (user-input)
# `args` is a named list (user-input)
the_call <- rlang::call2(.fn = my_fun , !!!args , .ns = my_pkg)
base::eval(the_call)
I have a feeling that the "correct" way to do this is to just use rlang::exec, but rlang::exec does not have a .ns argument like rlang::call2 does. Instead, it has an .env argument.
How do you specify the package (or namespace) of a function to rlang::exec? The .env argument to rlang::exec doesn't appear to be the answer, because the user should be able to specify a function in a specific package (that is installed) without first loading that package.
Or is rlang::exec not meant for this purpose?
Try
real_fun <- get(my_fun, envir=as.environment(paste0("package:", my_pkg)))
rlang::exec(real_fun, !!!args)
Since "packagename::functionname" (string) cannot be passed to rlang::exec, we can pass the real function. This can be retrieved by using get and passing a particular environment (from a package namespace, as above).
(This doesn't alleviate the need for two expressions to effect the exec, but it does allow one to use exec directly.)

R - Using patsy.dmatrices() with reticulate

I have a problem of namespace when trying to use function patsy.dmatrices() with the reticulate R package.
Here is a simple reproducible example:
patsy <- import("patsy")
# Data
dataset <- data.frame(Y=rnorm(1000,2.5,1))
# Null model
formula_null <- "I(Y-1) ~ 1"
dmat = patsy$dmatrices(formula_null, data=dataset, NA_action="drop",
return_type="dataframe")
I get the following error:
Error in py_call_impl(callable, dots$args, dots$keywords) :
AttributeError: 'NoneType' object has no attribute 'f_locals'
I think this is associated to the namespace (cf. Namespace issues when calling patsy within a function) which might be fixed by using the eval_env argument of function dmatrices() but I wasn't able to figure out how.
This is quite problematic when we want to use in R the Python statsmodels package which make uses of the patsy package for formulas.
Thanks for your help,
I'm not sure, but I think your guess about namespaces is correct, and this is an unfortunate interaction between patsy and reticulate. By default, patsy tries to look into the caller's scope to evaluate any unrecognized functions/variables in the formula (just like R formula functions do). This requires using Python's stack introspection to peek at the caller's scope. But since the caller is in a different language entirely, this almost certainly isn't going to work.
It is possible to override patsy's normal behavior of reading the caller's namespace, using the eval_env argument to dmatrices. (Docs.) Try this:
dmat = patsy$dmatrices(formula_null, data=dataset, NA_action="drop",
return_type="dataframe",
# New:
eval_env=patsy$EvalEnvironment(c())
)
The idea is that here we create an empty EvalEnvironment object, and tell patsy to use that instead of trying to read the caller's environment.
I'm not familiar with reticulate, so you might need to tweak the above to work – in Python the equivalent would be:
dmat = patsy.dmatrices(formula_null, data=dataset, NA_action="drop",
return_type="dataframe",
eval_env=patsy.EvalEnvironment([])
In particular, if reticulate doesn't convert c() into an empty list, then you'll want to find something that does. (Maybe try patsy$EvalEnvironment(list())?)

R function Call from Another Function

I need to modify the function gamGPDfit() in the package QRM to solve a problem. The function gamGPDfit() in turn calls other functions fit.GPD(​) and gamGPDfitUp() to compute the estimates of the parameters.
The structure of the function is shown below:
#######################################################
gamGPDfit<-function (..., init = fit.GPD(...) , ...)
{
...
Par<-gamGPDfitUp(...)
...
return (list(...))
}
<environment: namespace:QRM>
#######################################################
Now, when I call fit.GPD(​), I get the function on the command window to make the necessary modifications. However, the other function gamGPDfitUp​() returns
> gamGPDfitUp
Error: object 'gamGPDfitUp' not found
The question is, how do I get such an in-built function within another function? Does it have to do with the environment QRM? If so how do I obtain the function to modify it?.
I have attached the function and the call of the gamGPDfitUp() is indicated in colour red.
There's a couple of things that may come in handy.
One is help(":::") - Accessing exported and internal variables in a namespace. You can access GamGPDfitUp probably by prefixing it with QRM:::.
Another function is fixInNamespace, which allows you to modify functions inside packages. The help page for this one lists a few more interesting tools. Play around with this and it should solve most of your problems.

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.

R namespace access and match.fun

I'm working on an R package where one of the functions contains a match.fun call to a function in a package that's imported to the package namespace. But on loading the package, the match.fun call can't find the function name. From Hadley Wickham's description I think I'm doing everything right, but this is clearly not the case.
Example:
# in the package file header, for creation of the NAMESPACE via roxygen2:
##` #import topicmodels
# The function declaration in the package
ModelTopics <- function(doc.term.mat, num.topics, topic.method="LDA"){
topic.fun <- match.fun(topic.method)
output <- topic.fun(doc.term.mat, k=num.topics)
return(output)
}
And then in R:
> library(mypackage)
> sample.output <- ModelTopics(my.dtm, topic.method="LDA", num.topics=5)
Error in get(as.character(FUN), mode = "function", envir = envir) :
object 'LDA' of mode 'function' was not found
From my understanding of namespaces, the match.fun call should have access to the package namespace, which should include the topicmodels functions. But that doesn't appear to be the case here. If I import topicmodels directly to the global namespace for the R session, then this works.
Any help is much appreciated. This is R64 2.14.1 running on OSX.
UPDATE:
The package is here
Re the DESCRIPTION file, perhaps that's the problem: roxygen2 doesn't update the DESCRIPTION file with Imports: statements. But none of the other packages are listed there, either; only the match.fun calls appear to be affected.
Re the NAMESPACE extract, here's the import section:
import(catspec)
import(foreach)
import(gdata)
import(Hmisc)
import(igraph)
import(lsa)
import(Matrix)
import(plyr)
import(RecordLinkage)
import(reshape)
import(RWeka)
import(stringr)
import(tm)
import(topicmodels)
I believe this an issue of scope. Although you have imported topicmodels and thus LDA, you haven't exported these functions, so they aren't available in the search path.
From ?match.fun:
match.fun is not intended to be used at the top level since it will
perform matching in the parent of the caller.
Thus, since you are using ModelTopics in the global environment, and LDA isn't available in the global environment, the match.fun call fails.
It seems to me you have two options:
Option 1: use get
An alternative would be to use get where you can specify the environment. Consider this: try to use match.fun to find print.ggplot in the package ggplot2:
match.fun("print.ggplot")
Error in get(as.character(FUN), mode = "function", envir = envir) :
object 'print.ggplot' of mode 'function' was not found
Since print.ggplot isn't exported, match.fun can't find it.
However, get does find it:
get("print.ggplot", envir=environment(ggplot))
function (x, newpage = is.null(vp), vp = NULL, ...)
{
set_last_plot(x)
if (newpage)
grid.newpage()
data <- ggplot_build(x)
gtable <- ggplot_gtable(data)
if (is.null(vp)) {
grid.draw(gtable)
}
else {
if (is.character(vp))
seekViewport(vp)
else pushViewport(vp)
grid.draw(gtable)
upViewport()
}
invisible(data)
}
<environment: namespace:ggplot2>
Option 2: Export the functions from topicmodels that you need
If you make the necessary functions from topicmodels available in your NAMESPACE, your code should also work.
Do this by either:
Selective exporting LDA and other functions to the namespace using #export
Declare a dependency, using Depends: topicmodels - this is the same as calling library(topicmodels) in the global environment. This will work, but is possibly a bit of a brute force approach. It also means that any subsequent library call can mask your LDA function, thus leading to unexpected results.
Answering my own question: the DESCRIPTION file wasn't updating the Imports: and Depends: fields after re-roxygenizing the updated code. Hence the match.fun issues. Out of curiousity, why does this affect match.fun but not a range of other function calls made elsewhere to imported package functions?

Resources