Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

findGlobals() does not acknowledge when expression attaches packages via library() etc. #5

Open
HenrikBengtsson opened this issue May 23, 2015 · 2 comments

Comments

@HenrikBengtsson
Copy link
Owner

findGlobals() does not acknowledge when expression attaches packages via library() etc, e.g.

> library(globals)
> findGlobals(substitute({ globals::getGlobals }, env=list()))
[1] "::" "{"
> findGlobals(substitute({ getGlobals }, env=list()))
[1] "{"        "getGlobals"
> findGlobals(substitute({ library(globals); getGlobals }, env=list()))
[1] "{"        "getGlobals" "library"

In case someone wonders about library();

> codetools::findGlobals(function() { library(globals); getGlobals })
[1] "{"          "getGlobals" "library"

> globals::findGlobals({ library(globals); getGlobals }, substitute=TRUE)
[1] "{"          "getGlobals" "library"

> library(globals)
> g <- getGlobals({ library(globals); getGlobals }, substitute=TRUE)
> g <- cleanup(g)
> str(g)
List of 1
 $ getGlobals:function (expr, envir = parent.frame(), ..., method = c("conservative",
    "liberal"), tweak = NULL, substitute = FALSE, mustExist = TRUE, unlist = TRUE)
 - attr(*, "class")= chr [1:2] "Globals" "list"
> environment(g$getGlobals)
<environment: namespace:globals>
@HenrikBengtsson
Copy link
Owner Author

The "conservative" approach to locating all globals while acknowledging library() calls, is to call those library() and require() statements before searching for globals. This will, as far as possible, imitate what is seen by the compute process.

Another approach would be to first search for globals and the drop those that are exported by the packages loaded by library() and require(). The latter can be queried using getNamespaceExports(), with the drawback that it will also load the package (but at least not attach it).
UPDATE: It is not enough to look at getNamespaceExports() when there's a library() statement, because other packages may end up on the search() path.

@HenrikBengtsson
Copy link
Owner Author

HenrikBengtsson commented May 28, 2015

IDEA:

> library(globals)
> expr <- substitute({ library(listenv); listenv })

## Some fancy way of inferring what package is attached
## (This is where the real work has to be done)
> gpkgs <- "listenv"

## Attach all packages
> dummy <- lapply(gpkgs, FUN=library, character.only=TRUE)

## Search for globals (gives error if unknown at this point)
> g <- getGlobals(expr)
> g <- cleanup(g)
> str(g)
List of 1
 $ listenv:function (length = 0L)
 - attr(*, "class")= chr [1:2] "Globals" "list"

## Drop the ones that are part of the packages attached
> gpkgs <- lapply(g, FUN=function(obj) environmentName(environment(obj)))
> gpkgs <- unlist(gpkgs, use.names=TRUE)
> keep <- !is.element(gpkgs, pkgs)
> g <- g[keep]
> str(g)
 Named list()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant