diff --git a/.travis.yml b/.travis.yml index 7598804..bc44fc9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,8 @@ r_packages: r_github_packages: - rstudio/rmarkdown - hadley/pkgdown - + - zoonproject/modules@dark_modules + ## After success update the code coverage and deploy the pkgdown to gh-pages after_success: - Rscript -e 'library(covr);codecov()' diff --git a/DESCRIPTION b/DESCRIPTION index 4b15088..8cb4c15 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -15,6 +15,8 @@ Description: Reproducible and remixable species distribution modelling. The SDM workflows and returns output that is fully reproducible. License: BSD_3_clause + file LICENSE Imports: + remotes, + gh, dismo, methods, plyr, diff --git a/NAMESPACE b/NAMESPACE index 092ebbc..ab44603 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -14,10 +14,7 @@ export(FindExtent) export(GetMaxEnt) export(GetModuleList) export(GetPackage) -export(LoadModule) export(Model) -export(ModuleArguments) -export(ModuleHelp) export(Occurrence) export(Output) export(Process) @@ -43,11 +40,11 @@ import(roxygen2) import(rworldmap) import(sp) import(testthat) -importFrom(RCurl,getURL) importFrom(RCurl,url.exists) importFrom(SDMTools,auc) importFrom(SDMTools,confusion.matrix) importFrom(future,future_lapply) +importFrom(gh,gh) importFrom(grDevices,dev.off) importFrom(grDevices,grey) importFrom(grDevices,png) @@ -62,8 +59,8 @@ importFrom(stats,na.omit) importFrom(utils,browseURL) importFrom(utils,capture.output) importFrom(utils,data) -importFrom(utils,download.file) importFrom(utils,install.packages) importFrom(utils,installed.packages) importFrom(utils,methods) +importFrom(utils,packageDescription) importFrom(utils,sessionInfo) diff --git a/R/HelpFunctions.R b/R/HelpFunctions.R deleted file mode 100644 index 3ea2241..0000000 --- a/R/HelpFunctions.R +++ /dev/null @@ -1,132 +0,0 @@ -#' ModuleHelp -#' -#' Returns the help file for a zoon module. -#' -#' @param module The name of a zoon module -#' -#' @return Prints the help page to screen. -#' @seealso \code{\link{GetModuleList}} -#' @name ModuleHelp -#' @export - -ModuleHelp <- function(module) { - module <- as.character(substitute(module)) - if (!is.character(module) | !length(module) == 1) - stop("module must be a character of length 1") - - helpURL <- paste0("https://raw.githubusercontent.com/", - "zoonproject/modules/master/man/", - module, ".Rd") - - if (url.exists(helpURL)) { - - # txt <- getURL(helpURL, ssl.verifypeer=FALSE) - # helpFile <- paste0(tempdir(), '/', module, '.Rd') - # writeLines(txt, helpFile) - # tools::Rd2txt(tools::parse_Rd(helpFile)) - DisplayModuleHelp(helpURL) - } else { - modList <- GetModuleList() - idx <- agrep(module, unlist(modList), max.distance = 0.3) - closeMatches <- unlist(modList)[idx] - if (length(closeMatches) == 0) { - stop ("Can't find '", module, - "' or any modules with closely matching names.") - } else if (length(closeMatches) == 1) { - stop ("Can't find '", module, - "'. Did you mean '", closeMatches, "'?") - } else { - stop ("Can't find '", module, - "'. Did you mean one of '", - paste(closeMatches, collapse = "', "), "'?") - } - } -} - - -# Download a file with libcurl and no messages to the console -#' @importFrom utils download.file - -DownloadQuietly <- function(url, file) { - download.file( - url, - file, - method = "libcurl", - quiet = TRUE - ) -} - - - -# Display a module helpfile in accordance with the 'help_type' option -# help is either displayed as an HTML or text, pdf is not supported and -# an error is returned -#' @importFrom utils browseURL - -DisplayModuleHelp <- function(url) { - - # get Rd file - f_raw <- tempfile() - DownloadQuietly(url, f_raw) - - # get the help type - types <- c("text", "html", "pdf") - type <- getOption("help_type") - if (is.null(type)) { - type <- "text" - } - - match.arg(tolower(type), types) - - # html case (opens in default viewer) - if (type == "html") { - - # create a temporary help file and stick the html version in it - tempDir <- tempfile() - dir.create(tempDir) - htmlFile <- file.path(tempDir, "index.html") - htmlFile <- tools::Rd2HTML( - f_raw, - out = htmlFile - ) - - browser <- getOption("viewer") - - if (is.null(browser)) { - - # Produce a warning and continue using text - warning(paste( - "To display html help files (your default option) you", - "need to specify a default viewer. Try changing your", - "viewer via options. Printing to console instead", sep = "\n" - )) - - temp <- tools::Rd2txt(f_raw) - } else { - - # view the help file - browseURL( - url = htmlFile, - browser = browser - ) - } - } - - if (type == "text") { - - # otherwise just dump to the console - temp <- tools::Rd2txt(f_raw) - } - - if (type == "pdf") { - warning(paste( - "pdf help files (your default option) cannot currently be displayed", - "for zoon modules. Try changing your help viewing settings with:", - 'options(help_type = "html") or options(help_type = "text"). Printing', - "to console instead", sep = "\n" - )) - temp <- tools::Rd2txt(f_raw) - } - - invisible(NULL) -} diff --git a/R/ModuleArguments.R b/R/ModuleArguments.R deleted file mode 100644 index bfb8074..0000000 --- a/R/ModuleArguments.R +++ /dev/null @@ -1,45 +0,0 @@ -#' ModuleArguments -#' -#' Produce list of module arguments -#' -#' @param ModuleName string giving the name of the module -#' @return A list of arguments for user-intput to that module -#' @name ModuleArguments -#' @importFrom RCurl getURL -#' @export -#' @examples ModuleArguments('Background') - -ModuleArguments <- function(ModuleName) { - - # Build URL - ModuleURL <- sprintf( - "%s/%s/R/%s.R", - options("zoonRepo"), - options("zoonRepoBranch"), - ModuleName - ) - - # Check the URL exists - if (!RCurl::url.exists(ModuleURL)) - stop("URL for module does not exist: ", ModuleURL) - - # Extract module function from webpage - rawText <- RCurl::getURL(ModuleURL, ssl.verifypeer = FALSE) - - # Parse text from webpage - txt <- parse(text = rawText) - - # Evaluate text in this function environment - Module <- eval(txt) - - # Extract arguments - all_arguments <- formals(Module) - - # Make sure all arguments display as character - all_arguments_character <- lapply(all_arguments, deparse) - - # Remove the default arguments - arguments <- all_arguments_character[grepl('^\\.', names(all_arguments_character)) == FALSE] - arguments - -} diff --git a/R/sync_modules.R b/R/sync_modules.R new file mode 100644 index 0000000..75c5436 --- /dev/null +++ b/R/sync_modules.R @@ -0,0 +1,49 @@ +# check the modules are up to date and fetch them if not +#' @noRd +#' @importFrom gh gh +latest_sha <- function() { + query <- paste("/repos", + getOption("zoonModulesRepo"), + "branches", + getOption("zoonModulesBranch"), + sep = "/") + branch <- gh::gh(query) + branch$commit$sha +} + +#' @noRd +#' @importFrom utils packageDescription +current_sha <- function () { + suppressWarnings(desc <- utils::packageDescription("zoon.modules")) + sha <- "" + if (inherits(desc, "packageDescription")) { + sha <- desc$RemoteSha + if (is.null(sha)) + sha <- "" + } + sha +} + +sync_modules <- function () { + + # see if the modules are out of date + if (latest_sha() != current_sha()) { + message("\nyour zoon modules are out of date") + + # give the user the option to update + if (interactive()) { + + message("would you like to update them?") + installChoice <- utils::menu(c("yes", "no")) + + if (installChoice == 1) { + remotes::install_github(getOption("zoonModulesRepo"), ref = getOption("zoonModulesBranch"), + dependencies = FALSE, quiet = TRUE) + message("zoon modules updated") + } + } + } + + # try to load them + suppressWarnings(require("zoon.modules", quietly = TRUE)) +} diff --git a/R/test_outputs.R b/R/test_outputs.R index ac0c9a7..48135e7 100644 --- a/R/test_outputs.R +++ b/R/test_outputs.R @@ -36,15 +36,6 @@ test_occurrence_outputs <- function (roxy_parse, modulePath, en) { NaiveRandomRaster <- Crossvalidate <- LogisticRegression <- NULL NoProcess <- PrintMap <- NULL - ## Move these to the sections where they are needed - LoadModule("Background") - LoadModule("BackgroundAndCrossvalid") - LoadModule("Crossvalidate") - LoadModule("LogisticRegression") - LoadModule("NaiveRandomRaster") - LoadModule("NoProcess") - LoadModule("PrintMap") - # Load the script source(modulePath) @@ -308,13 +299,6 @@ test_covariate_outputs <- function (roxy_parse, modulePath, en) { LogisticRegression <- NaiveRandomPresence <- NULL PrintMap <- NULL - ## Move these to the sections where they are needed - LoadModule("Background") - LoadModule("BackgroundAndCrossvalid") - LoadModule("LogisticRegression") - LoadModule("NaiveRandomPresence") - LoadModule("PrintMap") - # Load the script source(modulePath) @@ -455,18 +439,6 @@ test_process_outputs <- function (roxy_parse, modulePath, en) { NoProcess <- NULL PrintMap <- Domain <- UKAir <- UKAnophelesPlumbeus <- NULL - ## Move these to the sections where they are needed - LoadModule("Background") - LoadModule("NaiveRandomPresenceAbsence") - LoadModule("Crossvalidate") - LoadModule("LogisticRegression") - LoadModule("NaiveRandomRaster") - LoadModule("NoProcess") - LoadModule("PrintMap") - LoadModule("Domain") - LoadModule("UKAir") - LoadModule("UKAnophelesPlumbeus") - # Load the script source(modulePath) @@ -780,17 +752,6 @@ test_model_outputs <- function (roxy_parse, modulePath, en) { NaiveRandomPresenceAbsence <- NoProcess <- PerformanceMeasures <- NULL PrintMap <- UKAir <- UKAnophelesPlumbeus <- NULL - ## Move these to the sections where they are needed - LoadModule("Background") - LoadModule("Crossvalidate") - LoadModule("NaiveRandomRaster") - LoadModule("NaiveRandomPresenceAbsence") - LoadModule("NoProcess") - LoadModule("PerformanceMeasures") - LoadModule("PrintMap") - LoadModule("UKAir") - LoadModule("UKAnophelesPlumbeus") - # Load the script source(modulePath) @@ -1120,12 +1081,6 @@ test_output_outputs <- function (roxy_parse, modulePath, en) { Background <- LogisticRegression <- NULL UKAir <- UKAnophelesPlumbeus <- NULL - ## Move these to the sections where they are needed - LoadModule("Background") - LoadModule("LogisticRegression") - LoadModule("UKAir") - LoadModule("UKAnophelesPlumbeus") - # Load the script source(modulePath) diff --git a/R/zoonHelpers.R b/R/zoonHelpers.R index ad5b5a9..a9fd498 100644 --- a/R/zoonHelpers.R +++ b/R/zoonHelpers.R @@ -1,70 +1,4 @@ -#' A function to load a module function from url or disk. -#' -#' Loads a module function into the global environment ready to be used in a -#' zoon workflow. This function is mostly for use while developing modules. -#' Workflows run with modules defined locally are no longer reproducible and -#' so are discouraged and will be tagged as 'unreproducible'. -#' -#' @param module A string that describes the location of the R file. Can be a -#' a full URL or a path to a local file. -#' -#' @return Name of the function. Adds function to global namespace. -#' @name LoadModule -#' @export - -LoadModule <- function(module) { - - # module must be a string - - # URL to module in user's favourite repo & branch - zoonURL <- sprintf( - "%s/%s/R/%s.R", - options("zoonRepo"), - options("zoonRepoBranch"), - module - ) - - # If module is a path, load module - if (file.exists(module)) { - txt <- parse(text = paste(readLines(module), collapse = "\n")) - # If zoonURL is a zoon repo url, load module Could probably do same thing as - # GetModule here to avoid repeated web call - } else if (url.exists(zoonURL, .opts = list(ssl.verifypeer = FALSE))) { - txt <- parse(text = getURL(zoonURL, ssl.verifypeer = FALSE)) - # If module on its own is a url, load module - } else if (url.exists(module, .opts = list(ssl.verifypeer = FALSE))) { - txt <- parse(text = getURL(module, ssl.verifypeer = FALSE)) - # Otherwise throw error. - } else { - modList <- GetModuleList() - module_idx <- agrep(module, unlist(modList), max.distance = 0.3) - closeMatches <- unlist(modList)[module_idx] - if (length(closeMatches) == 0) { - stop ("Can't find '", module, - "' or any modules with closely matching names.") - } else if (length(closeMatches) == 1) { - stop ("Can't find '", module, - "'. Did you mean '", closeMatches, "'?") - } else { - stop ("Can't find '", module, "'. Did you mean one of '", - paste(closeMatches, collapse = "', "), "'?") - } - } - # Load to global environment - eval(txt, envir = globalenv()) - # Return the actual name of the module that has been loaded. - # Don't just return 'module' argument as that can be url/path - # which isn't useful. - # Cruddy code. But module name is the only other object in this - # call environment. - eval(txt) - new.func.name <- ls()[!ls() %in% c("module", "txt", "zoonURL")] - return(new.func.name) -} - - - # A function to get a module function. # # Checks for the module in the global namespace, then the zoon repo. Then reads @@ -83,50 +17,21 @@ LoadModule <- function(module) { GetModule <- function(module, forceReproducible, environment = parent.frame()) { - # URL to module in user's favourite repo & branch - zoonURL <- sprintf( - "%s/%s/R/%s.R", - options("zoonRepo"), - options("zoonRepoBranch"), - module - ) - - # If the module is in global namespace, use that function - # unless forceReproduce is TRUE, in which case we want to get from repo. - # - # Get module from zoonURL otherwise. - module_exists <- exists(module, - where = ".GlobalEnv", - mode = "function", - inherits = FALSE) - if (module_exists & !forceReproducible) { - assign(module, - eval(parse(text = module), envir = globalenv()), - envir = environment) - attr(module, "version") <- "local copy" - return(module) + if (forceReproducible) { + envir_from <- asNamespace("zoon.modules") } else { - rawText <- getURL(zoonURL, ssl.verifypeer = FALSE) + envir_from <- globalenv() } + + module_function <- get(module, envir = envir_from) - # getURL returns "Not Found" if no webpage found. - # Use this to avoid two web call.s - if (grepl("^404: Not Found", rawText)) { - stop('Cannot find "', module, - '". Check that the module is on the zoon repository ', - 'or in the global namespace.') - } - - # Parse text from webpage. - txt <- parse(text = rawText) - - # Evaluate text in the workflow call environment - eval(txt, envir = environment) - - # Assign version attribute - attr(module, "version") <- GetModuleVersion(rawText) + assign(module, + module_function, + envir = environment) - return(module) + # assign version attribute + attr(module, "version") <- GetModuleVersion(module) + module } @@ -774,17 +679,28 @@ StringToCall <- function(x) { # GetModuleVersion # -# Using the raw text returned from a GetURL call to github -# this extracts the version number +# Get the version of a module from its helpfile -GetModuleVersion <- function(rawText) { +GetModuleVersion <- function(module) { + + # see if it's a versioned module + versioned_modules <- names(asNamespace("zoon.modules")) + if (!module %in% versioned_modules) { + return ("local copy") + } + + # get helpfile text + file <- file.path(find.package("zoon.modules"), "help", module) + rawText <- capture.output(tools::Rd2txt(utils:::.getHelpFile(file))) - # Break down into lines - ModLines <- strsplit(rawText, "\n")[[1]] - VersionLine <- ModLines[grep("@section Version: ", ModLines)] - TagPosition <- gregexpr("@section Version: ", VersionLine) - Start <- TagPosition[[1]] + attr(TagPosition[[1]], "match.length") - substr(VersionLine, Start, nchar(VersionLine)) + # strip bad characters and empty lines + rawText <- gsub("_\b", "", rawText) + rawText <- rawText[rawText != ""] + + # find version line + idx <- which(rawText == "Version:") + 1 + gsub(" ", "", rawText[idx]) + } diff --git a/R/zzz.R b/R/zzz.R index 9799fc5..a282654 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,15 +1,22 @@ # things to do on loading the package .onLoad <- function(libname, pkgname) { + # set up a temporary directory for raster::getData calls if (is.null(getOption("rasterDataDir"))) { options(rasterDataDir = tempdir()) } + # set up the default modules repo - if (is.null(getOption("zoonRepo"))) { - options(zoonRepo = "https://raw.githubusercontent.com/zoonproject/modules") + if (is.null(getOption("zoonModulesRepo"))) { + options(zoonModulesRepo = "zoonproject/modules") } + # set up the default branch - if (is.null(getOption("zoonRepoBranch"))) { - options(zoonRepoBranch = "master") + if (is.null(getOption("zoonModulesBranch"))) { + options(zoonModulesBranch = "dark_modules") } + + # check the module versions are up to date, and load + sync_modules() + } diff --git a/man/LoadModule.Rd b/man/LoadModule.Rd deleted file mode 100644 index 8074ef1..0000000 --- a/man/LoadModule.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/zoonHelpers.R -\name{LoadModule} -\alias{LoadModule} -\title{A function to load a module function from url or disk.} -\usage{ -LoadModule(module) -} -\arguments{ -\item{module}{A string that describes the location of the R file. Can be a -a full URL or a path to a local file.} -} -\value{ -Name of the function. Adds function to global namespace. -} -\description{ -Loads a module function into the global environment ready to be used in a - zoon workflow. This function is mostly for use while developing modules. - Workflows run with modules defined locally are no longer reproducible and - so are discouraged and will be tagged as 'unreproducible'. -} diff --git a/man/ModuleArguments.Rd b/man/ModuleArguments.Rd deleted file mode 100644 index 50a8322..0000000 --- a/man/ModuleArguments.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ModuleArguments.R -\name{ModuleArguments} -\alias{ModuleArguments} -\title{ModuleArguments} -\usage{ -ModuleArguments(ModuleName) -} -\arguments{ -\item{ModuleName}{string giving the name of the module} -} -\value{ -A list of arguments for user-intput to that module -} -\description{ -Produce list of module arguments -} -\examples{ -ModuleArguments('Background') -} diff --git a/man/ModuleHelp.Rd b/man/ModuleHelp.Rd deleted file mode 100644 index 95f3fc2..0000000 --- a/man/ModuleHelp.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/HelpFunctions.R -\name{ModuleHelp} -\alias{ModuleHelp} -\title{ModuleHelp} -\usage{ -ModuleHelp(module) -} -\arguments{ -\item{module}{The name of a zoon module} -} -\value{ -Prints the help page to screen. -} -\description{ -Returns the help file for a zoon module. -} -\seealso{ -\code{\link{GetModuleList}} -} diff --git a/tests/testthat/testLoadModule.R b/tests/testthat/testLoadModule.R deleted file mode 100644 index 77b5e98..0000000 --- a/tests/testthat/testLoadModule.R +++ /dev/null @@ -1,37 +0,0 @@ -context("LoadModule") - -test_that("LoadModule works", { - - path <- paste0("https://raw.githubusercontent.com/zoonproject/modules/", - "master/R/NoProcess.R") - - # Load module is only used to URLS and paths. - - # Create local module to test load. - # This will only work on unix. But I don't know how to test otherwise. - # LoadModule has to take the actual path, - # NOT e.g. fileName = '~/Test.R', LoadModule(fileName) - # So can't save to paste(getwd(), 'TestFile.R') - write( - "#test file for zoon package\n TestModule <- function(){z <- 2}", - file = "~/TestModule.R" - ) - - - TestWorkflow <- function() { - LoadModule("~/TestModule.R") - return(class(TestModule)) - } - - TestURL <- function() { - LoadModule(path) - return(class(NoProcess)) - } - - expect_error(LoadModule("xxx")) - expect_that(LoadModule("~/TestModule.R"), equals("TestModule")) - expect_that(LoadModule("NoProcess"), equals("NoProcess")) - expect_that(LoadModule(path), equals("NoProcess")) - - file.remove("~/TestModule.R") -}) diff --git a/tests/testthat/testModuleArguments.R b/tests/testthat/testModuleArguments.R deleted file mode 100644 index 31102a3..0000000 --- a/tests/testthat/testModuleArguments.R +++ /dev/null @@ -1,23 +0,0 @@ -context("ModuleArguments") - -test_that("Check error if not found", { - skip_on_cran() - - expect_error( - ModuleArguments("ThisDoesNotExist"), - "URL for module does not exist" - ) - -}) - -test_that("Check returns list with all the names", { - x <- ModuleArguments("Background") - - arguments <- list( - n = '100', - bias = 'NULL', - seed = 'NULL' - ) - - expect_that(x, is_identical_to(arguments)) -}) \ No newline at end of file diff --git a/tests/testthat/testModuleHelp.R b/tests/testthat/testModuleHelp.R deleted file mode 100644 index 7efa423..0000000 --- a/tests/testthat/testModuleHelp.R +++ /dev/null @@ -1,112 +0,0 @@ -context("ModuleHelp") - -directory <- tempdir() - -test_that("ModuleHelp errors", { - if (!capabilities("libcurl")) - skip("skipping as libcurl not supported") - - expect_error( - ModuleHelp(c(one, two)), - "module must be a character of length 1" - ) - - expect_error( - ModuleHelp("NoProce1s"), - "Can't find 'NoProce1s'. Did you mean" - ) -}) - -test_that("Help as text", { - org <- getOption("help_type") - options(help_type = "text") - - capture.output( - ModuleHelp("NoProcess"), - file = file.path(directory, "help_text.txt") - ) - - expect_true(file.exists(file.path(directory, "help_text.txt"))) - unlink(x = file.path(directory, "help_text.txt")) - - options(help_type = org) -}) - -test_that("Help as NULL", { - org <- getOption("help_type") - options(help_type = NULL) - - capture.output( - ModuleHelp("NoProcess"), - file = file.path(directory, "help_null.txt") - ) - - expect_true(file.exists(file.path(directory, "help_null.txt"))) - unlink(x = file.path(directory, "help_null.txt")) - - options(help_type = org) -}) - -test_that("Help as html", { - org <- getOption("help_type") - options(help_type = "html") - browser <- getOption("viewer") - options(viewer = NULL) - - expect_warning( - capture.output( - ModuleHelp("NoProcess"), - file = file.path(directory, "help.html") - ), - "^To display html help" - ) - - expect_true(file.exists(file.path(directory, "help.html"))) - unlink(x = file.path(directory, "help.html")) - - options(viewer = browser) - - capture.output( - ModuleHelp("NoProcess"), - file = file.path(directory, "help.html") - ) - - expect_true(file.exists(file.path(directory, "help.html"))) - unlink(x = file.path(directory, "help.html")) - - options(help_type = org) -}) - - -test_that("Help as pdf", { - org <- getOption("help_type") - options(help_type = "pdf") - - expect_warning( - capture.output( - ModuleHelp("NoProcess"), - file = file.path(directory, "help.txt") - ), - "^pdf help files" - ) - - expect_true(file.exists(file.path(directory, "help.txt"))) - unlink(x = file.path(directory, "help.txt")) - - options(help_type = org) - - - - # Some modules with no close matches - expect_error(ModuleHelp("zzzzz123232"), - "or any modules with closely matching names") - - - # Module with 1 close matches - expect_error(ModuleHelp("NoProcesss"), - "Can't find 'NoProcesss'. Did you mean") - - # Module with 2 close matches - expect_error(ModuleHelp("Crissvalid"), - "Can't find 'Crissvalid'. Did you mean one of") -}) diff --git a/tests/testthat/testplot.zoonWorkflow.r b/tests/testthat/testplot.zoonWorkflow.r index 514b653..8839d9e 100644 --- a/tests/testthat/testplot.zoonWorkflow.r +++ b/tests/testthat/testplot.zoonWorkflow.r @@ -92,7 +92,7 @@ test_that("plot.zoonWorkflow module not on repo", { rm(myMissing) - LoadModule(module = file.path(directory, "myMissing.R")) + source(file.path(directory, "myMissing.R")) # NamespaceModule <- function(){ # return(myMissing)