Nothing
#' Return the namespace environment for a package.
#'
#' Contains all (exported and non-exported) objects, and is a descendant of
#' `R_GlobalEnv`. The hierarchy is `<namespace:pkg>`,
#' `<imports:pkg>`, `<namespace:base>`, and then
#' `R_GlobalEnv`.
#'
#' If the package is not loaded, this function returns `NULL`.
#'
#' @param package package name.
#' @keywords internal
#' @seealso [pkg_env()] for the attached environment that
#' contains the exported objects.
#' @seealso [imports_env()] for the environment that contains
#' imported objects for the package.
#' @export
ns_env <- function(package) {
if (!is_loaded(package)) return(NULL)
asNamespace(package)
}
ns_path <- function(package) {
ns <- asNamespace(package)
if (isBaseNamespace(ns))
return(path.package(package))
getNamespaceInfo(ns, "path")
}
# Create the namespace environment for a package
create_ns_env <- function(path = ".", call = caller_env()) {
path <- pkg_path(path)
package <- pkg_name(path)
version <- pkg_version_raw(path)
if (is_loaded(package)) {
cli::cli_abort(
"Namespace for {.pkg {package}} can't already exist.",
call = call
)
}
env <- makeNamespace(package, version)
methods::setPackageName(package, env)
# Create devtools metadata in namespace
create_dev_meta(package)
setNamespaceInfo(env, "path", path)
setup_ns_imports(path)
env
}
# This is taken directly from base::loadNamespace()
# https://github.com/wch/r-source/blob/tags/R-3-3-0/src/library/base/R/namespace.R#L235-L258
onload_assign("makeNamespace",
eval(
modify_lang(
extract_lang(body(loadNamespace),
# Find makeNamespace definition
comp_lang, y = quote(makeNamespace <- NULL), idx = 1:2)[[3]],
# Replace call to .Internal(registerNamespace()) is replaced by a call to
# register_namespace
function(x) {
if (comp_lang(x, quote(.Internal(registerNamespace(name, env))))) {
quote(register_namespace(name, env))
} else {
x
}
}))
)
# Read the NAMESPACE file and set up the imports metadata.
# (which is stored in .__NAMESPACE__.)
setup_ns_imports <- function(path = ".") {
path <- pkg_path(path)
package <- pkg_name(path)
nsInfo <- parse_ns_file(path)
setNamespaceInfo(package, "imports", nsInfo$imports)
}
# Read the NAMESPACE file and set up the exports metadata. This must be
# run after all the objects are loaded into the namespace because
# namespaceExport throw errors if the objects are not present.
setup_ns_exports <- function(path = ".") {
path <- pkg_path(path)
package <- pkg_name(path)
nsInfo <- parse_ns_file(path)
nsenv <- ns_env(package)
# This code is from base::loadNamespace
exports <- nsInfo$exports
for (p in nsInfo$exportPatterns) {
# FIXME! Needs a test for `exportPatterns`
exports <- c(ls(nsenv, pattern = p, all.names = TRUE), exports)
}
# Don't try to export objects that are missing from the namespace and imports
ns_and_imports <- c(
env_names(nsenv),
env_names(imports_env(package))
)
extra_exports <- setdiff(exports, ns_and_imports)
if (length(extra_exports) > 0) {
cli::cli_warn(c(
"Objects listed as exports, but not present in namespace: ",
set_names(extra_exports, "*")
))
exports <- intersect(ns_and_imports, exports)
}
# Add any S4 methods or classes, this needs to be done after checking for
# missing exports as S4 methods with generics imported from other packages
# are not defined in the namespace.
exports <- add_classes_to_exports(
ns = nsenv,
package = package,
exports = exports,
nsInfo = nsInfo
)
# Update the exports metadata for the namespace with base::namespaceExport
# It will throw warnings if objects are already listed in the exports
# metadata, so catch those warnings and ignore them.
suppressWarnings(
namespaceExport(nsenv, exports)
)
invisible()
}
# Lookup S4 classes for export
#
# This function uses code from base::loadNamespace. Previously this code was
# copied directly, now it is dynamically looked up instead, to prevent drift as
# base::loadNamespace changes.
onload_assign("add_classes_to_exports",
{
pattern <- if (getRversion() >= "4.1.0") {
quote(if (.isMethodsDispatchOn() && hasS4m && !identical(package, "methods")) NULL)
} else {
quote(if (.isMethodsDispatchOn() && .hasS4MetaData(ns) && !identical(package, "methods")) NULL)
}
make_function(alist(ns =, package =, exports =, nsInfo =),
call("{",
quote(lev <- 0L),
quote(hasS4m <- .hasS4MetaData(ns)),
extract_lang(
f = comp_lang,
y = pattern,
idx = c(1, 2),
modify_lang(body(base::loadNamespace), strip_internal_calls, "methods")
),
quote(exports)
), asNamespace("methods")
)
}
)
#' Parses the NAMESPACE file for a package
#'
#' @inheritParams load_all
#' @examples
#' if (has_tests()) {
#' parse_ns_file(pkgtest("testLoadHooks"))
#' }
#' @keywords internal
#' @export
parse_ns_file <- function(path = ".") {
path <- pkg_path(path)
parseNamespaceFile(basename(path), dirname(path),
mustExist = FALSE)
}
# Register the S3 methods for this package
register_s3 <- function(path = ".") {
path <- pkg_path(path)
package <- pkg_name(path)
nsInfo <- parse_ns_file(path)
# Adapted from loadNamespace
try(registerS3methods(nsInfo$S3methods, package, ns_env(package)))
}
# Reports whether a package is loaded into a namespace. It may be
# attached or not attached.
is_loaded <- function(package) {
package %in% loadedNamespaces()
}
# Register a namespace
register_namespace <- function(name = NULL, env = NULL) {
if (!is.character(name) || name == "" || length(name) != 1) {
cli::cli_abort("{.arg name} must be a non-empty character string.")
}
if (!is.environment(env)) {
cli::cli_abort("{.arg env} must be an environment.")
}
if (name %in% loadedNamespaces()) {
cli::cli_abort("Namespace {.arg {name}} can't be already registered.")
}
# Add the environment to the registry
nsr <- ns_registry_env()
nsr[[name]] <- env
env
}
# Unregister a namespace - should be used only if unloadNamespace()
# fails for some reason
unregister_namespace <- function(name = NULL) {
if (!is_string(name) || name == "") {
cli::cli_abort("{.arg name} must be a non-empty character string.")
}
if (!(name %in% loadedNamespaces())) {
cli::cli_abort("{.pkg {name}} must be a registered namespace.")
}
# Force all bindings of the namespace in case of dangling
# references. If lazy bindings are forced after the namespace is
# unloaded, it might lead to decompress errors if unloaded or to
# inconsistencies if reloaded (the bindings are resolved in the new
# namespace).
#
# We take precautions not to trigger active bindings in case these
# have side effects such as throwing an error.
ns <- ns_env(name)
active_bindings <- env_binding_are_active(ns)
env_get_list(ns, names(active_bindings)[!active_bindings])
# Remove the item from the registry
env_unbind(ns_registry_env(), name)
invisible()
}
unregister_methods <- function(package) {
# Unloading S3 methods manually avoids lazy-load errors when the new
# package is loaded overtop the old one. It also prevents removed
# methods from staying registered.
s3_unregister(package)
# S4 classes that were created by the package need to be removed in a special way.
remove_s4_classes(package)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.