-
Notifications
You must be signed in to change notification settings - Fork 4
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
export(name, attach = FALSE): Export, but don't attach #165
Comments
@DavisVaughan, @lionel-, @georgestagg suggest that this would be better declared in the
where the default behavior is:
A patch for this is: diff --git src/library/base/R/namespace.R src/library/base/R/namespace.R
index 49bf222c5b..6a7f885ca8 100644
--- src/library/base/R/namespace.R
+++ src/library/base/R/namespace.R
@@ -139,6 +139,9 @@ attachNamespace <- function(ns, pos = 2L, depends = NULL, exclude, include.only)
on.exit(Sys.unsetenv("_R_NS_LOAD_"), add = TRUE)
runHook(".onAttach", ns, dirname(nspath), nsname)
+ ## update 'exclude' by 'excludes' in namespace
+ exclude <- c(exclude, .getNamespaceInfo(ns, "excludes"))
+
## adjust variables for 'exclude', 'include.only' arguments
if (! missing(exclude) && length(exclude) > 0)
rm(list = exclude, envir = env)
@@ -617,6 +620,7 @@ loadNamespace <- function (package, lib.loc = NULL,
}
addNamespaceDynLibs(env, nsInfo$dynlibs)
setNamespaceInfo(env, "nativeRoutines", nativeRoutines)
+ setNamespaceInfo(env, "excludes", nsInfo$excludes)
## used in e.g. utils::assignInNamespace
Sys.setenv("_R_NS_LOAD_" = package)
@@ -812,6 +816,7 @@ loadNamespace <- function (package, lib.loc = NULL,
}
if(lev > 2L) message("--- processing exports for ", dQuote(package))
namespaceExport(ns, exports)
+
if(lev > 2L) message("--- sealing exports for ", dQuote(package))
sealNamespace(ns)
runUserHook(package, pkgpath)
@@ -1303,6 +1308,7 @@ parseNamespaceFile <- function(package, package.lib, mustExist = TRUE)
stop(gettextf("package %s has no 'NAMESPACE' file", sQuote(package)),
domain = NA)
else directives <- NULL
+ excludes <- character()
exports <- character()
exportPatterns <- character()
exportClasses <- character()
@@ -1332,6 +1338,12 @@ parseNamespaceFile <- function(package, package.lib, mustExist = TRUE)
as.character(eval(eval(call("substitute", cc, as.list(vars))),
.GlobalEnv))
}
+ evalToLogical <- function(cc) {
+ vars <- all.vars(cc)
+ names(vars) <- vars
+ as.logical(eval(eval(call("substitute", cc, as.list(vars))),
+ .GlobalEnv))
+ }
switch(as.character(e[[1L]]),
"if" = if (eval(e[[2L]], .GlobalEnv))
parseDirective(e[[3L]])
@@ -1345,9 +1357,16 @@ parseNamespaceFile <- function(package, package.lib, mustExist = TRUE)
names(dynlibs)[length(dynlibs)] <<- asChar(e[[2L]])
},
export = {
+ attach <- e$attach
+ e$attach <- NULL
exp <- e[-1L]
exp <- structure(asChar(exp), names = names(exp))
exports <<- c(exports, exp)
+ if (!is.null(attach)) {
+ attach <- evalToLogical(attach)
+ if (!attach)
+ excludes <<- c(excludes, exp)
+ }
},
exportPattern = {
pat <- asChar(e[-1L])
@@ -1521,7 +1540,7 @@ parseNamespaceFile <- function(package, package.lib, mustExist = TRUE)
## need to preserve the names on dynlibs, so unique() is not appropriate.
dynlibs <- dynlibs[!duplicated(dynlibs)]
- list(imports = imports, exports = exports,
+ list(imports = imports, exports = exports, excludes = excludes,
exportPatterns = unique(exportPatterns),
importClasses = importClasses, importMethods = importMethods,
exportClasses = unique(exportClasses), FWIW, one way this could be added to roxygen2 might be: #' @export
#' @noattach |
This might be more useful as an IDE feature. With the new
and that would allow it to be ignored from autocompletions like when a user types This would actually be useful for two cases:
|
Interesting - I've seen That said, there's also the masking problem, which can be avoided if we don't attach. |
I hope that Another approach could be defining a special symbol in a package namespace—for example, a character vector of symbol names bound to a specific symbol, like |
The roxygen tags can generate
I think it's better to use declarative syntax (via |
Background
Some package functions are not intended for end-users, but are instead meant to be imported by other packages. When attaching a package via
library()
, all the exported objects are attached and therefore put on thesearch()
path.Idea
Let a package decided which exported objects to not be attached by specifying them in optional character vector
.packageExclude
. This avoids cluttering thesearch()
path with objects that are not intended for end-users, yet making them available via the::
form.For example, consider package somepkg declaring functions:
and exporting them in
NAMESPACE
as:These functions can be called as:
and
However, the package can choose to exclude
bye()
from the attached namespace such that it is only available via the first form by specifying:If so, then we will have:
and
Implementation
Implementing this is straightforward, because we can leverage the
exclude
argument thatlibrary()
andrequire()
already supports. All we need to do is to append any objects specified in the optional.packageExclude
character vector. Here's a patch:The text was updated successfully, but these errors were encountered: