This is inspired by the python idiom from module import object as new_name.

import_from(
  x,
  ...,
  .into = parent.frame(),
  .parent = .GlobalEnv,
  .overwrite = interactive(),
  .chdir = FALSE,
  .recursive = FALSE,
  .pos = 2L
)

Arguments

x

a bare symbol name of a package, a character vector of filepaths, an environment (which could be a python module), or any object with names and [[ methods defined.

...

objects to import from x into .into. if named, the name will be the the new name after import. Alternatively, you can also supply the wildcard string "*" or "**", along with some additional overrides. See examples for details.

.into

An R environment, or something coercible to one by as.environment, or a character string that is the name of a (potentially new) attached environment. The default is the current frame.

.parent, .chdir, .recursive

Only applicable if x is a character vector of filepaths to R scripts, in which case these are passed on to include (chdir, recursive) or new.env(parent)

.overwrite

One of "warn", "error" or "ignore". Can also be a boolean TRUE (same as "ignore") or FALSE (same as "error"). What should be done if the requested import operation would overwrite an existing object. Character arguments can be abbreviated as partial matching is performed.

.pos

Only applicable if .into is a string that is the name of a new environment that will be attached, in which case this will be the position on new environment on the search path.

Value

The R environment or object that x resolved to, invisibly.

Note

If x is a package name, then no check is performed to ensure the object being imported is an exported function. As such, import_from() can be used to access package internal objects, though doing so is usually bad practice.

Examples

show_whats_imported <- function(...) {
  import_from(...)
  setdiff(names(environment()), "...")
}

## Importing from an R package
# import one object
show_whats_imported(envir, include)
#> [1] "include"

# rename an object on import
show_whats_imported(envir, sys_source = include)
#> [1] "sys_source"

# import all NAMESPACE exports
show_whats_imported(envir, "*")
#> [1] "include"       "import_from"   "attach_source" "attach_eval"  
show_whats_imported(envir) # missing `...` is interpreted as "*"
#> [1] "include"       "import_from"   "attach_source" "attach_eval"  

# import all NAMESPACE exports, except for `include`
show_whats_imported(envir, "*", -include)
#> [1] "import_from"   "attach_source" "attach_eval"  

# import all NAMESPACE exports, except rename `include` to `sys_source`
show_whats_imported(envir, "*", sys_source = include)
#> [1] "sys_source"    "import_from"   "attach_source" "attach_eval"  

# exclude more than one
show_whats_imported(envir, "*", -include, -attach_eval)
#> [1] "import_from"   "attach_source"
show_whats_imported(envir, "*", -c(include, attach_eval))
#> [1] "import_from"   "attach_source"

# import all NAMESPACE exports, also one internal function names `find_r_files`
show_whats_imported(envir, "*", find_r_files)
#> [1] "find_r_files"  "include"       "import_from"   "attach_source"
#> [5] "attach_eval"  

# import ALL package functions, including all internal functions
show_whats_imported(envir, "**")
#>  [1] "complete_names"                        
#>  [2] "expand_wildcard_imports_from_namespace"
#>  [3] "check_requested_imports_valid"         
#>  [4] "set_library_default_pos"               
#>  [5] "check_all_symbols"                     
#>  [6] "str_collapse"                          
#>  [7] "as_maybe_attached_env"                 
#>  [8] "check_overwrite"                       
#>  [9] "expand_wildcard_imports_from_object"   
#> [10] "find_r_files"                          
#> [11] "warn_about_conflicts"                  
#> [12] "within.environment"                    
#> [13] "as_tidy_env_name"                      
#> [14] "resolve_wildcard_imports"              
#> [15] "within.character"                      
#> [16] "include"                               
#> [17] "import_from"                           
#> [18] "attach_source"                         
#> [19] "attach_eval"                           

# import ALL objects in the package NAMESPACE, including R's NAMESPACE machinery
show_whats_imported(envir, "***")
#>  [1] ".__S3MethodsTable__."                  
#>  [2] ".__NAMESPACE__."                       
#>  [3] "complete_names"                        
#>  [4] "expand_wildcard_imports_from_namespace"
#>  [5] "check_requested_imports_valid"         
#>  [6] "set_library_default_pos"               
#>  [7] ".packageName"                          
#>  [8] "check_all_symbols"                     
#>  [9] "str_collapse"                          
#> [10] "as_maybe_attached_env"                 
#> [11] "check_overwrite"                       
#> [12] "expand_wildcard_imports_from_object"   
#> [13] "find_r_files"                          
#> [14] "warn_about_conflicts"                  
#> [15] "within.environment"                    
#> [16] "as_tidy_env_name"                      
#> [17] "resolve_wildcard_imports"              
#> [18] "within.character"                      
#> [19] "include"                               
#> [20] "import_from"                           
#> [21] "attach_source"                         
#> [22] "attach_eval"                           


## Importing from R files
# setup
dir.create(tmpdir <- tempfile())
owd <- setwd(tmpdir)
writeLines(c("useful_function <- function() 'I am useful'",
             ".less_useful_fn <- function() 'less useful'"),
           "my_helpers.R")

# import one function by name
show_whats_imported("my_helpers.R", useful_function)
#> [1] "useful_function"

# import all objects whose names don't start with a "." or "_"
show_whats_imported("my_helpers.R", "*")
#> [1] "useful_function"

# import all objects
show_whats_imported("my_helpers.R", "**")
#> [1] "useful_function" ".less_useful_fn"

# if the filepath to your scripts is stored in a variable, supply it in a call
x <- "my_helpers.R"
try(show_whats_imported(x)) # errors out, because no package 'x'
#> Error in loadNamespace(name) : there is no package called ‘x’
# to force the value to be used, just supply it as a call rather than a bare symbol.
# the simplest call can be just wrapping in () or {}
show_whats_imported({x})
#> [1] "useful_function"
show_whats_imported((x))
#> [1] "useful_function"
show_whats_imported(c(x))
#> [1] "useful_function"
show_whats_imported({{x}}) # tidyverse style unquoting
#> [1] "useful_function"

## Importing R objects

# if you have an actual R object that you want to import from, you will
# have to supply it in a call
x <- list(obj1 = "one", obj2 = "two")
show_whats_imported({x})
#> [1] "obj2" "obj1"

if (FALSE) {
  # don't run this so we don't take a reticulate dependency
  import_from(reticulate, py_module = import) # rename object on import

  # import one object
  show_whats_imported(py_module("numpy"), random)

  # to prevent automatic conversion
  show_whats_imported(py_module("numpy", convert = FALSE), random)

  # import all objects that don't begin with a `_`
  # by default, other modules found in the module are also not imported
  show_whats_imported(py_module("glob"), "*")

  # to import EVERYTHING pass "**"
  # now includes modules that your modules imported, like `os`
  show_whats_imported(py_module("glob"), "**")

  rm(py_module) # clean up
}

# cleanup
setwd(owd)
unlink(tmpdir, recursive = TRUE)
rm(show_whats_imported, tmpdir, owd)