fail/0000755000176200001440000000000012603060145011162 5ustar liggesusersfail/tests/0000755000176200001440000000000012514153653012334 5ustar liggesusersfail/tests/test_all.R0000755000176200001440000000004512514153653014270 0ustar liggesuserslibrary(testthat) test_check("fail") fail/tests/testthat/0000755000176200001440000000000012602730642014171 5ustar liggesusersfail/tests/testthat/test_constructor.R0000644000176200001440000000116712602730642017745 0ustar liggesuserscontext("Constructor") test_that("Creation of directories and checking of existing files", { path = tempfile() fail(path) # works on new dirs fail(path) # works on existing dirs path = tempfile() file.create(path) expect_error(fail(path)) }) test_that("Constructor checks input", { path = tempfile() expect_error(fail(path, extension="^")) expect_error(fail(path, extension=".RData")) }) test_that("Argument 'all.files' works", { path = tempfile() f = fail(path, all.files = FALSE) expect_error(f$put(.x = 1), "hidden") f = fail(path, all.files = TRUE) f$put(.x = 1) expect_equal(f$ls(), ".x") }) fail/tests/testthat/test_assign.R0000644000176200001440000000036312514153653016644 0ustar liggesuserscontext("assign") test_that("assign", { path = tempfile() f = fail(path) f$put(a = 1, b = 2) f$assign("a") expect_true(exists("a")) expect_false(exists("b")) a = 3 expect_true(a == 3) f$assign("a") expect_true(a == 1) }) fail/tests/testthat/test_sail.R0000644000176200001440000000172012514153653016306 0ustar liggesuserscontext("sail") test_that("sail", { # test basic usage here. # most of the stuff is identical with fail ... path = tempfile() s = sail(path) expect_equal(s$ls(), character(0L)) expect_equal(s$put(a = 1, b = 2), letters[1:2]) expect_equal(s$ls(), letters[1:2]) expect_equal(s$put(li = list(c = 3)), letters[3]) expect_equal(s$ls(), letters[1:3]) s$put(d = 4, li = list(e = 5)) expect_equal(s$ls(), letters[1:5]) expect_equal(s$as.list(), setNames(as.list(1:5), letters[1:5])) s = sail(path, simplify = FALSE) x = s$as.list() expect_equal(x[[1]], list(a = 1)) s = sail(path, simplify = TRUE) expect_equal(s$as.list(), s$apply(identity)) expect_equal(s$cached(), character(0L)) s$get("a", use.cache=TRUE) expect_equal(s$cached(), "a") expect_equal(s$get("a", use.cache = TRUE), 1) expect_equal(s$clear(), "a") expect_equal(s$cached(), character(0L)) expect_equal(s$remove(s$ls()), setNames(rep(TRUE, 5L), letters[1:5])) }) fail/tests/testthat/test_mapply.R0000644000176200001440000000240712514153653016663 0ustar liggesuserscontext("mapply") test_that("mapply", { path = tempfile() f = fail(path) f$put(a = 1:10, b = 1:100) x = f$mapply(function(key, value) mean(value)) expect_equal(x, list(a = 5.5, b = 50.5)) x = f$mapply(function(key, value) mean(value), keys = c("b", "a")) expect_equal(x, list(b = 50.5, a = 5.5)) x = f$mapply(function(key, value) mean(value), use.names=FALSE) expect_equal(x, list(5.5, 50.5)) x = f$mapply(function(key, value) mean(value), simplify=TRUE) expect_equal(x, setNames(c(5.5, 50.5), letters[1:2])) x = f$mapply(function(key, value, y) mean(value - y), y = 1) expect_equal(x, list(a = 4.5, b = 49.5)) x = f$mapply(function(key, value, y) mean(value - y), moreArgs = list(y = 1)) expect_equal(x, list(a = 4.5, b = 49.5)) expect_error(f$mapply(function(key, value, y) mean(value - y), y = 0, moreArgs = list(y = 1))) # error handling f$remove(f$ls()) f$put(a = 1, b = 2, c = "NA") expect_error(f$mapply(function(key, value) log(value)), "key 'c'") # invalid keys and empty sets fun = function(key, value) value expect_equal(length(f$mapply(fun, keys=NULL)), 0) expect_error(f$mapply(fun, keys="xxx")) expect_equal(length(f$mapply(fun, keys=character(0L))), 0) f$remove(f$ls()) expect_equal(length(f$mapply(fun)), 0) }) fail/tests/testthat/test_apply.R0000644000176200001440000000222612514153653016505 0ustar liggesuserscontext("apply") test_that("apply", { path = tempfile() f = fail(path) f$put(a = 1:10, b = 1:100, c = 1:1000) x = f$apply(mean) expect_true(is.list(x)) expect_true(all(names(x) %in% letters[1:3])) expect_equal(sort(unlist(x, use.names=FALSE)), c(5.5, 50.5, 500.5)) # subsetting keys works x = f$apply(mean, keys=c("c", "b")) expect_equal(names(x), c("c", "b")) # simplify works x = f$apply(mean, keys=letters[1:3], simplify=TRUE) expect_equal(x, setNames(c(5.5, 50.5, 500.5), letters[1:3])) # use.names works x = f$apply(mean, keys=letters[1:3], use.names=FALSE) expect_true(is.null(names(x))) # passing arguments works fun = function(x, y) mean(x) + y x = f$apply(fun, y = -0.5, simplify=TRUE) expect_equal(x, setNames(c(5, 50, 500), letters[1:3])) # error handling f$remove(f$ls()) f$put(a = 1, b = 2, c = "NA") expect_error(f$apply(log), "key 'c'") # invalid keys and empty sets expect_equal(length(f$apply(identity, keys=NULL)), 0) expect_error(f$apply(identity, keys="xxx")) expect_equal(length(f$apply(identity, keys=character(0L))), 0) f$remove(f$ls()) expect_equal(length(f$apply(identity)), 0) }) fail/tests/testthat/test_as_list.R0000644000176200001440000000062712514153653017021 0ustar liggesuserscontext("as.list") test_that("as.list", { path = tempfile() f = fail(path) f$put(a = 1, b = 2, c = 3) expect_equal(f$as.list(), setNames(as.list(1:3), letters[1:3])) expect_equal(f$as.list("a"), setNames(as.list(1), letters[1])) # invalid keys and empty sets expect_equal(length(f$as.list(NULL)), 0) expect_error(f$as.list("xxx")) expect_equal(length(f$as.list(character(0L))), 0L) }) fail/tests/testthat/test_remove.R0000644000176200001440000000215612514153653016657 0ustar liggesuserscontext("remove and clear") test_that("remove", { path = tempfile() f = fail(path) f$put(a = 1, b = 2) expect_equal(f$remove("b"), setNames(TRUE, "b")) expect_equal(f$ls(), "a") f$put(b = 2) expect_equal(f$ls(), letters[1:2]) expect_equal(f$remove(letters[1:2]), setNames(c(TRUE, TRUE), letters[1:2])) f$put(a = 1, b = 2) # invalid keys and empty sets expect_warning(f$remove("c"), "Files not removed") expect_error(f$remove()) expect_equal(f$remove(character(0L)), setNames(logical(0), character(0))) # cache expect_equal(f$get("a", use.cache=TRUE), 1) expect_equal(f$cached(), "a") expect_equal(f$remove("a"), setNames(TRUE, "a")) expect_equal(f$cached(), character(0L)) f$put(a = 1) f$get("a", use.cache=TRUE) f$get("b", use.cache=TRUE) expect_equal(f$cached(), letters[1:2]) f$remove(letters[1:2]) expect_equal(f$cached(), character(0L)) }) test_that("clear", { path = tempfile() f = fail(path) f$put(a = 1, b = 2) f$get("a", use.cache=TRUE) f$get("b", use.cache=TRUE) expect_equal(f$cached(), letters[1:2]) f$clear() expect_equal(f$cached(), character(0L)) }) fail/tests/testthat/test_size.R0000644000176200001440000000065012514153653016331 0ustar liggesuserscontext("size") test_that("size", { path = tempfile() f = fail(path) expect_equal(length(f$size()), 0) f$put(a = 1, b = 2, c = 3) expect_equal(length(f$size(("a"))), 1) expect_equal(length(f$size()), 3) expect_true(is.numeric(f$size())) expect_true(all(f$size() > f$size(unit="Mb"))) expect_true(unname(is.na(f$size("d")))) expect_equal(f$size(character(0L)), setNames(numeric(0L), character(0L))) }) fail/tests/testthat/test_get_put.R0000644000176200001440000000245012514153653017026 0ustar liggesuserscontext("list, get, put") test_that("list, get, put", { path = tempfile() f = fail(path) expect_equal(f$ls(), character(0L)) expect_equal(f$put(a = 1, b = 2), letters[1:2]) expect_equal(f$ls(), letters[1:2]) expect_equal(f$put(li = list(c = 3)), letters[3]) expect_equal(f$ls(), letters[1:3]) f$put(d = 4, li = list(e = 5)) expect_equal(f$ls(), letters[1:5]) expect_equal(f$get("a"), 1) x = f$as.list() y = setNames(as.list(1:5), letters[1:5]) expect_equal(x, y) # positional arguments expect_equal(f$pos(), 1) expect_equal(f$pos(2), 2) expect_equal(f$pos(6), NULL) path = tempfile() f = fail(path) f$put(1, 2, 3, keys = c("x", "y", "z")) expect_equal(f$ls(), c("x", "y", "z")) f$remove(f$ls()) f$put(1, 2, 3, li = list(foo = 5), keys = c("x", "y", "z")) expect_equal(f$get("x"), 1) expect_equal(f$get("foo"), 5) # pattern works expect_equal(f$ls("^[xy]"), c("x", "y")) expect_equal(f$ls("a"), character(0L)) # invalid keys and empty sets expect_error(f$get()) expect_error(f$get("not_existing")) expect_error(f$put(li=list("a - b" = 1))) expect_equal(f$put(), character(0L)) # cache expect_equal(f$cached(), character(0L)) f$get("x", use.cache=TRUE) expect_equal(f$cached(), "x") f$clear() expect_equal(f$cached(), character(0L)) }) fail/NAMESPACE0000644000176200001440000000100412602733211012374 0ustar liggesusers# Generated by roxygen2 (4.1.1): do not edit by hand S3method(as.list,fail) S3method(as.list,sail) S3method(print,fail) S3method(print,sail) export(fail) export(sail) import(checkmate) importFrom(BBmisc,"%nin%") importFrom(BBmisc,argsAsNamedList) importFrom(BBmisc,collapse) importFrom(BBmisc,is.error) importFrom(BBmisc,names2) importFrom(BBmisc,setClasses) importFrom(BBmisc,stopf) importFrom(BBmisc,vlapply) importFrom(BBmisc,warningf) importFrom(stats,setNames) importFrom(utils,head) importFrom(utils,methods) fail/NEWS0000644000176200001440000000131712602737760011700 0ustar liggesusers## Version 1.3 (2015-09-30) * New argument "all.files" to allow working with hidden files * New closure "$pos" to get the n-th key * Added argument suppressMessages to sail * sail now sources files in their respective directory ## Version 1.2 (2013-09-18) * New argument "simplify" to enforce lists to be returned * New object "sail" to access R source files * Closure "$assign" now returns keys of assigned objects * Closure "$clear" now returns keys of cleared objects ## Version 1.1 (2013-02-05) * New closure "$assign" * New closure "$mapply" * New argument in closure "$put": keys * Improved error messages * Relaxed checks for illegal characters in keys ## Version 1.0 (2012-12-04) * Initial release on CRAN fail/R/0000755000176200001440000000000012602733171011370 5ustar liggesusersfail/R/constructor.R0000644000176200001440000000423212602731144014077 0ustar liggesusersmakeObject = function(.self) { force(.self) list( ls = function(pattern = NULL) { Ls(.self, pattern) }, get = function(key, simplify, use.cache) { Get(.self, asKeys(.self, key, len = 1L), use.cache = asFlag(use.cache, default = .self$use.cache)) }, pos = function(n = 1L, use.cache) { keys = Ls(.self) if (n > length(keys)) return(NULL) Get(.self, keys[n], use.cache = asFlag(use.cache, default = .self$use.cache)) }, put = function(..., keys, li = list(), use.cache) { Put(.self, ..., keys = keys, li = as.list(li), use.cache = asFlag(use.cache, default = .self$use.cache)) }, remove = function(keys) { Remove(.self, asKeys(.self, keys)) }, as.list = function(keys, use.cache) { AsList(.self, asKeys(.self, keys, default = Ls(.self)), use.cache = asFlag(use.cache, default = .self$use.cache)) }, apply = function(FUN, ..., keys, use.cache, simplify = FALSE, use.names = TRUE) { Apply(.self, FUN, ..., keys = asKeys(.self, keys, default = Ls(.self)), use.cache = asFlag(use.cache, default = .self$use.cache), simplify = asFlag(simplify), use.names = asFlag(use.names)) }, mapply = function(FUN, ..., keys, use.cache, moreArgs = NULL, simplify = FALSE, use.names = TRUE) { Mapply(.self, FUN, ..., keys = asKeys(.self, keys, default = Ls(.self)), use.cache = asFlag(use.cache, default = .self$use.cache), moreArgs = as.list(moreArgs), simplify = asFlag(simplify), use.names = asFlag(use.names)) }, assign = function(keys, envir = parent.frame(), use.cache) { Assign(.self, keys = asKeys(.self, keys, default = Ls(.self)), envir = as.environment(envir), use.cache = asFlag(use.cache, default = .self$use.cache)) }, size = function(keys, unit = "b") { match.arg(unit, choices = names(UNITCONVERT)) Size(.self, asKeys(.self, keys, default = Ls(.self)), unit = unit) }, clear = function(keys) { Clear(.self, asKeys(.self, keys, default = Ls(.self))) }, cached = function() { Cached(.self) }, info = function() { Info(.self) } ) } fail/R/backends.R0000644000176200001440000000162712514153653013276 0ustar liggesusersloadRData = function(.self, fn) { ee = new.env(parent = emptyenv(), hash = FALSE) ns = load(fn, envir = ee) if (.self$simplify && length(ns) == 1L) return(ee[[ns]]) return(as.list(ee)) } saveRData = function(.self, fn, key, value) { ee = new.env(parent = emptyenv(), hash = FALSE) assign(key, value, envir = ee) save(list = key, envir = ee, file = fn) return(invisible(key)) } loadR = function(.self, fn) { ee = new.env(parent = .GlobalEnv) wrap = if (.self$suppressMessages) function(expr) suppressMessages(suppressPackageStartupMessages(expr)) else identity wrap(sys.source(fn, ee, chdir = TRUE)) ns = ls(ee, all.names = TRUE) if (.self$simplify && length(ns) == 1L) return(ee[[ns]]) return(as.list(ee)) } saveR = function(.self, fn, key, value) { ee = new.env(parent = emptyenv(), hash = FALSE) assign(key, value, envir = ee) dump(key, file = fn, envir = ee) } fail/R/sail.R0000644000176200001440000000364312602730024012443 0ustar liggesusers#' Create a source abstraction interface layer (SAIL) object. #' #' This function returns an object of class \code{sail} which behaves #' like \code{\link{fail}}, but is indented for loading and saving #' R source code files. #' #' @param path [\code{character(1)}]\cr #' Path to work in, will be created if it does not exists. #' @param extension [\code{character(1)}]\cr #' File extension to work with. #' Default is \dQuote{R}. #' @param all.files [\code{logical(1)}]\cr #' Also include hidden files, i.e. files whose name start with a dot (\dQuote{.}). #' Default is \code{FALSE}. #' @param use.cache [\code{logical(1)}]\cr #' Use a memory cache per global default. #' Global option which can locally be overwritten in most functions. #' Default is \code{FALSE} #' @param simplify [\code{character(1)}]\cr #' If only one object is defined in a sourced R file, #' should the return value be simplified? If set to \code{TRUE}, #' instead of a list containing one element the object itself will be returned. #' @param suppressMessages [\code{logical(1)}]\cr #' Wrap the \code{\link[base]{sys.source}} command into \code{\link[base]{suppressMessages}} #' and \code{link[base]{suppressPackageStartupMessages}}? #' Default is \code{FALSE}, i.e. you will see regular output of sourced scripts. #' @return Object of class \code{sail}. See the documentation of \code{\link{fail}} #' for details. #' @export sail = function(path = getwd(), extension = "R", all.files = FALSE, use.cache = FALSE, simplify = TRUE, suppressMessages = FALSE) { .self = list( path = checkPath(path), extension = checkExtension(extension), all.files = asFlag(all.files), use.cache = asFlag(use.cache), simplify = asFlag(simplify, na.ok = TRUE), cache = Cache(), loadFun = loadR, saveFun = saveR, suppressMessages = asFlag(suppressMessages) ) checkCollision(Ls(.self)) setClasses(makeObject(.self), "sail") } fail/R/methods.R0000644000176200001440000000160312602733071013155 0ustar liggesusersprintObject = function(x, type) { info = x$info() cat( sprintf("%s on path %s", type, info$path), sprintf(" %-9s : %s", "extension", info$extension), sprintf(" %-9s : %s", "use.cache", info$use.cache), sprintf(" %-9s : %s", "simplify", info$simplify), sprintf(" %-9s : %i", "items", length(x$ls())), sprintf(" %-9s : %i", "cached", length(x$cached())), sprintf(" %-9s : %s", "functions", collapse(names(x))), sprintf(" %-9s : %s", "methods", collapse(sub("\\.fail$", "", methods(class = "fail")), ", ")), sep = "\n" ) } #' @export print.fail = function(x, ...) { printObject(x, "File Abstraction Interface Layer") } #' @export print.sail = function(x, ...) { printObject(x, "Source Abstraction Interface Layer") } #' @export as.list.fail = function(x, ...) { x$as.list(...) } #' @export as.list.sail = function(x, ...) { x$as.list(...) } fail/R/cache.R0000644000176200001440000000057412514153653012567 0ustar liggesusersCache = function() { ee = new.env(parent = emptyenv()) keys = function() ls(ee, all.names = TRUE) list( keys = keys, get = function(key) get(key, envir = ee), put = function(key, value) assign(key, value, envir = ee), rm = function(keys) { x = intersect(keys, keys()); rm(list = x, envir = ee); x }, exists = function(key) exists(key, envir = ee) ) } fail/R/worker.R0000644000176200001440000000645612602731103013030 0ustar liggesusersLs = function(.self, pattern = NULL) { keys = fn2key(.self, list.files(.self$path, pattern = sprintf("\\.%s$", .self$extension), ignore.case = TRUE, all.files = .self$all.files)) if (!is.null(pattern)) keys = keys[grepl(pattern, keys)] return(keys) } Get = function(.self, key, use.cache) { fn = key2fn(.self, key) if (!file.exists(fn)) stopf("File for key '%s' (%s) not found", key, fn) if (use.cache) { if (!.self$cache$exists(key)) .self$cache$put(key, .self$loadFun(.self, fn)) return(.self$cache$get(key)) } return(.self$loadFun(.self, fn)) } Put = function(.self, ..., keys, li, use.cache) { args = argsAsNamedList(...) if (missing(keys)) keys = names2(args) keys = c(asKeys(.self, keys, len = length(args)), asKeys(.self, names2(li))) args = c(args, as.list(li)) if (anyMissing(keys)) stop("Could not determine all key names from input") if (anyDuplicated(keys)) stop("Duplicated key names") checkCollisionNew(keys, Ls(.self)) if (use.cache) mapply(.self$cache$put, key = keys, value = args, USE.NAMES = FALSE, SIMPLIFY = FALSE) else .self$cache$rm(keys) mapply(.self$saveFun, fn = key2fn(.self, keys), key = keys, value = args, MoreArgs = list(.self = .self), USE.NAMES = FALSE, SIMPLIFY = FALSE) invisible(keys) } Remove = function(.self, keys) { w = function(key) { .self$cache$rm(key) fn = key2fn(.self, key) return(file.exists(fn) && file.remove(fn)) } ok = vlapply(keys, w) if (!all(ok)) warningf("Files not removed: %s", collapse(keys[!ok])) return(invisible(ok)) } Apply = function(.self, FUN, ..., keys, use.cache, simplify, use.names) { wrapper = function(.key, ...) { res = try(FUN(Get(.self, .key, use.cache = use.cache), ...), silent = TRUE) if (is.error(res)) stopf("Error applying function on key '%s': %s", .key, as.character(res)) return(res) } FUN = match.fun(FUN) return(sapply(keys, wrapper, ..., USE.NAMES = use.names, simplify = simplify)) } Mapply = function(.self, FUN, ..., keys, use.cache, moreArgs, simplify, use.names) { wrapper = function(.key, ...) { res = try(FUN(key = .key, value = Get(.self, .key, use.cache = use.cache), ...), silent = TRUE) if (is.error(res)) stopf("Error applying function on key '%s': %s", .key, as.character(res)) return(res) } assertFunction(FUN, args = c("key", "value")) return(mapply(wrapper, .key = keys, ..., MoreArgs = moreArgs, USE.NAMES = use.names, SIMPLIFY = simplify)) } Assign = function(.self, keys, envir, use.cache) { w = function(key, envir) { x = Get(.self, key, use.cache) if (.self$simplify) assign(key, x, envir = envir) else mapply(assign, names(x), x, MoreArgs = list(envir = envir), SIMPLIFY = FALSE, USE.NAMES = FALSE) } lapply(keys, w, envir = envir) return(invisible(keys)) } Size = function(.self, keys, unit = "b") { size = as.integer(file.info(key2fn(.self, keys))$size) setNames(size / UNITCONVERT[unit], keys) } Clear = function(.self, keys) { return(invisible(.self$cache$rm(keys))) } Cached = function(.self) { return(.self$cache$keys()) } AsList = function(.self, keys, use.cache) { setNames(lapply(keys, Get, .self = .self, use.cache = use.cache), keys) } Info = function(.self) { return(.self[c("path", "extension", "use.cache", "simplify")]) } fail/R/helper.R0000644000176200001440000000454512602731461013002 0ustar liggesusersasFlag = function(x, default, na.ok = FALSE) { if (missing(x)) { if (!missing(default)) return(default) stopf("Argument %s is missing", deparse(substitute(x))) } assertFlag(x, na.ok = na.ok, .var.name = deparse(substitute(x))) x } asKeys = function(.self, keys, len, default) { if (missing(keys)) { if (!missing(default)) return(default) stop("Keys are missing") } if (!is.character(keys)) { keys = try(as.character(keys)) if (is.error(keys)) stop("Keys must be of type character or be convertible to character") } if (!missing(len) && length(keys) != len) stop("Keys must have length ", len) if (anyMissing(keys)) stop("Keys contain NAs") # R variable pattern: "^((\\.[[:alpha:]._]+)|([[:alpha:]]+))[[:alnum:]_.]*$" pattern = "^[[:alnum:]._-]+$" ok = grepl(pattern, keys) if (!all(ok)) stopf("Key '%s' in illegal format, see help", head(keys[!ok], 1L)) if (!.self$all.files && any(substr(keys, 1L, 1L) == ".")) stop("Cannot work with hidden files (files starting with a dot) if 'all.files' is set to TRUE.") return(keys) } checkPath = function(path) { qassert(path, "S1") if (!file.exists(path) && !dir.create(path, recursive = TRUE)) stopf("Could not create directory '%s'", path) assertDirectory(path, access = "r") path } checkExtension = function(extension) { qassert(extension, "S1") if (grepl("[^[:alnum:]]", extension)) stop("Extension contains illegal characters: ", collapse(strsplit(gsub("[[:alnum:]]", "", extension), ""), " ")) return(extension) } checkCollision = function(keys) { dups = duplicated(tolower(keys)) if (any(dups)) { warningf("The following keys result in colliding files on case insensitive file systems: %s", collapse(keys[dups])) } invisible(TRUE) } checkCollisionNew = function(new, old) { dups = new %nin% old & tolower(new) %in% tolower(old) if (any(dups)) warningf("Keys collide on case insensitive file systems: %s", collapse(new[dups])) invisible(TRUE) } fn2key = function(.self, fn) { return(sub(sprintf("\\.%s$", .self$extension), "", fn)) } key2fn = function(.self, key) { return(file.path(.self$path, sprintf("%s.%s", key, .self$extension))) } nkeys = function(.self) { length(list.files(.self$path, pattern = sprintf("\\.%s$", .self$extension), ignore.case = TRUE, all.files = .self$all.files)) } fail/R/fail.R0000644000176200001440000001770312602731507012437 0ustar liggesusers#' Create a file abstraction interface layer (FAIL) object. #' #' The general idea is to not bother about file path joining or file extensions. #' Instead, FAIL offers a key-value like interface to RData files in a specified directory. #' The filename (without extension) acts as the key while the stored R objects are the values. #' Fail provides an interface to the basic file system actions: listing, reading / loading, #' writing / saving, removing and applying functions on files. #' An implemented cache mechanism can be used to avoid repeated disk reads. #' #' @param path [\code{character(1)}]\cr #' Path to work in, will be created if it does not exists. #' @param extension [\code{character(1)}]\cr #' File extension to work with. #' Default is \dQuote{RData}. #' @param all.files [\code{logical(1)}]\cr #' Also include hidden files, i.e. files whose name start with a dot (\dQuote{.}). #' Default is \code{FALSE}. #' @param use.cache [\code{logical(1)}]\cr #' Use a memory cache per global default. #' Global option which can locally be overwritten in most functions. #' Default is \code{FALSE} #' @param simplify [\code{character(1)}]\cr #' If only one object is stored in a R data file, #' should the return value be simplified? #' If set to \code{TRUE}, #' instead of a list containing one element the object itself will be returned. #' @return Object of class \code{fail}. See details. #' @details #' For a quick introduction on the usage, see \url{https://github.com/mllg/fail}. #' #' An object with the following functions is returned by \code{fail}: #' \describe{ #' \item{\code{ls(pattern=NULL)}}{ #' Function to list keys in directory \code{path} matching a regular expression pattern \code{pattern}. #' Returns a character vector of keys. #' } #' \item{\code{get(key, use.cache)}}{ #' Function to load a file identified by \code{key} from directory \code{path}. #' To load many objects at once, use \code{as.list}, \code{assign} or \code{get} together with \code{\link[base]{lapply}}. #' Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. #' } #' \item{\code{put(..., li, keys, use.cache)}}{ #' Function to save objects to directory \code{path}. #' Names for objects provided via \code{...} will be looked up or can be provided using a \code{key = value} syntax. #' More objects can be passed as a named list using the argument \code{li}: Each list item will be saved to a separate file. #' If you provide \code{keys} as a character vector, these names will be taken for the arguments passed via \code{...}. #' Argument \code{use.cache} temporarily overwrites the global \code{use.cache} flag. #' Returns a character vector of stored keys. #' } #' \item{\code{remove(keys)}}{ #' Function to remove files identified by \code{keys} from directory \code{path}. #' Returns a character vector of deleted keys. #' } #' \item{\code{apply(FUN, ..., keys, use.cache, simplify=FALSE, use.names=TRUE)}}{ #' Apply function \code{FUN} on files identified by \code{keys}. #' \code{keys} defaults to all keys available and will be used to name the returned list. #' The loaded R objects will be past unnamed as first argument. #' Use \code{...} for additional function arguments. #' Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. #' For arguments \code{simplify} and \code{use.names}, see \code{\link[base]{lapply}}. #' } #' \item{\code{mapply(FUN, ..., keys, use.cache, moreArgs = NULL, simplify=FALSE, use.names=TRUE)}}{ #' Apply function \code{FUN} on files identified by \code{keys}. #' \code{keys} defaults to all keys available and will be used to name the returned list. #' The function \code{FUN} must have the formal arguments \dQuote{key} and \dQuote{value}. #' Both key and value will be passed named. #' Use \code{...} and/or \code{moreArgs} for additional function arguments. #' Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. #' For arguments \code{moreArgs}, \code{simplify} and \code{use.names}, see \code{\link[base]{mapply}}. #' } #' \item{\code{as.list(keys, use.cache)}}{ #' Return a named list of objects identified by \code{keys}. \code{keys} defaults to all keys available. #' Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. #' } #' \item{\code{assign(keys, envir=parent.frame(), use.cache)}}{ #' Assigns all objects identified by the character vector \code{keys} in the environment \code{envir}. #' Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. #' Returns a character vector of assigned keys. #' } #' \item{\code{clear(keys)}}{ #' Clear the cache to free memory. \code{keys} defaults to all keys available. #' Returns a character vector of cleared keys. #' } #' \item{\code{cached()}}{ #' Returns a character vector of keys of cached objects. #' } #' \item{\code{size(keys, unit="b")}}{ #' Get the file size in Bytes of the files identified by \code{keys}. \code{keys} defaults to all keys available. #' Argument \code{unit} accepts \dQuote{b}, \dQuote{Kb}, \dQuote{Mb} and \dQuote{Gb} and can be used to convert Bytes to KiloBytes, MegaBytes or GigaBytes, respectively. #' } #' \item{\code{info()}}{ #' Returns a named list with \code{path}, \code{extension} and \code{use.cache}. #' Internally used for the \code{\link[base]{print}} method with a much nicer summary of the FAIL object. #' } #' } #' Furthermore, the package provides S3 methods for \code{\link[base]{print}} and \code{\link[base]{as.list}}. #' #' Be aware of the following restriction regarding file names and keys: #' The package performs some basic checks for illegal characters on the key names. #' In principle all characters matching the pattern \dQuote{[a-zA-Z0-9._-]} are allowed and should work on most or all file systems. #' But be careful with key names which are not compatible with R's variable naming restrictions, e.g. using the minus character or #' key names starting with a number: these provoke unwanted side effects and will result in errors if used with \code{assign}. #' #' If two files would collide on case-insensitive file systems like Windows' NTFS, the package will throw warnings. Best practice #' is to not rely on case sensitivity. #' #' @export #' @examples #' # initialize a FAIL in a temporary directory #' path <- tempfile("") #' files <- fail(path) #' #' # save x and y, vectors of random numbers #' x <- runif(100) #' files$put(x, y = runif(100)) #' #' # save columns of the iris data set as separate files #' files$put(li = as.list(iris)) #' #' # load all RData files in a named list as a one-liner #' as.list(fail(path)) #' #' # load a single object from the file system #' files$get("Species") #' files$as.list(c("x", "y")) #' #' # remove an object (and related file) #' files$remove("Species") #' #' # apply a function over files #' files$apply(mean) #' files$mapply(function(key, value) sprintf("%s -> %f", key, mean(value)), simplify = TRUE) #' #' # show file size informations #' files$size(unit = "Mb") #' #' # get an object and cache it #' files$get("x", use.cache = TRUE) #' files$cached() #' files$clear() #' files$cached() #' #' # assign variables in the current environment #' files$assign("y") #' mean(y) fail = function(path = getwd(), extension = "RData", all.files = FALSE, use.cache = FALSE, simplify = TRUE) { ### argument checks .self = list( path = checkPath(path), extension = checkExtension(extension), all.files = asFlag(all.files), use.cache = asFlag(use.cache), simplify = asFlag(simplify, na.ok = TRUE), cache = Cache(), loadFun = loadRData, saveFun = saveRData ) checkCollision(Ls(.self)) setClasses(makeObject(.self), "fail") } fail/R/zzz.R0000644000176200001440000000074212602733171012353 0ustar liggesusers#' @import checkmate #' @importFrom stats setNames #' @importFrom utils head #' @importFrom utils methods #' @importFrom BBmisc stopf #' @importFrom BBmisc warningf #' @importFrom BBmisc collapse #' @importFrom BBmisc %nin% #' @importFrom BBmisc is.error #' @importFrom BBmisc setClasses #' @importFrom BBmisc names2 #' @importFrom BBmisc argsAsNamedList #' @importFrom BBmisc vlapply UNITCONVERT = c(1L, 1024L, 1048576L, 1073741824L) names(UNITCONVERT) = c("b", "kB", "Mb", "Gb") fail/MD50000644000176200001440000000241012603060145011467 0ustar liggesusers969176315bdb35acf6bf596047870a1d *DESCRIPTION efba0fc06a435676c10b4300d35ea30d *LICENSE 06e3be4cdd6f927ab91cd726dab4b0a7 *NAMESPACE 2aa666d0fba1b3217c7be84ff0b100ab *NEWS 66762b300064dc215983839f4887965a *R/backends.R a44c643e3af4279dd7e54bc800cec24d *R/cache.R 93ec9d0c536a57a32be7fbe6875b8454 *R/constructor.R 6c828a2b79de94955e22cb2ae7cebda7 *R/fail.R d6b11ee0756d60a73c69315f8b3605f0 *R/helper.R ca10178e518444cc3b0aac55c0bdc39c *R/methods.R 6780eea1d43a369af9d6a583b17e9d2e *R/sail.R be6b5ed5ffb9e39e5375a45ef49a550d *R/worker.R 3c88821a8a129662326763e752f2fb74 *R/zzz.R aa1cc75604c2edecefb8a5c625ac32d7 *man/fail.Rd 217bf01b3a35435e803105e0c02dc796 *man/sail.Rd fed01b14cb7c5e19e8ee595aa24e4234 *tests/test_all.R 44af3f3c31aa37644e35aac06fdcb347 *tests/testthat/test_apply.R 71edfe2bb422057bf7a62495af0ab0dd *tests/testthat/test_as_list.R 5e79c514e8f68dbc2ab6de3b7790583b *tests/testthat/test_assign.R 569ed25e706189e943126b106005dca3 *tests/testthat/test_constructor.R e0677d5ee56f7f8ad322588a021233e0 *tests/testthat/test_get_put.R d4c522e256cca88d8482853245fb591a *tests/testthat/test_mapply.R 1e311c48e2e0cf1612b4b81f776a5867 *tests/testthat/test_remove.R e7af3a79f6835e91ae518018889a361b *tests/testthat/test_sail.R 21aa281c511906b38ff64763d9608603 *tests/testthat/test_size.R fail/DESCRIPTION0000644000176200001440000000104212603060145012665 0ustar liggesusersPackage: fail Type: Package Title: File Abstraction Interface Layer (FAIL) Description: More comfortable interface to work with R data or source files in a key-value fashion. Version: 1.3 Author: Michel Lang Maintainer: Michel Lang URL: https://github.com/mllg/fail License: BSD_3_clause + file LICENSE Imports: stats, utils, BBmisc, checkmate Suggests: testthat ByteCompile: yes NeedsCompilation: no Packaged: 2015-09-30 11:01:23 UTC; lang Repository: CRAN Date/Publication: 2015-10-01 00:21:25 fail/man/0000755000176200001440000000000012514153653011745 5ustar liggesusersfail/man/fail.Rd0000644000176200001440000001646712602731572013165 0ustar liggesusers% Generated by roxygen2 (4.1.1): do not edit by hand % Please edit documentation in R/fail.R \name{fail} \alias{fail} \title{Create a file abstraction interface layer (FAIL) object.} \usage{ fail(path = getwd(), extension = "RData", all.files = FALSE, use.cache = FALSE, simplify = TRUE) } \arguments{ \item{path}{[\code{character(1)}]\cr Path to work in, will be created if it does not exists.} \item{extension}{[\code{character(1)}]\cr File extension to work with. Default is \dQuote{RData}.} \item{all.files}{[\code{logical(1)}]\cr Also include hidden files, i.e. files whose name start with a dot (\dQuote{.}). Default is \code{FALSE}.} \item{use.cache}{[\code{logical(1)}]\cr Use a memory cache per global default. Global option which can locally be overwritten in most functions. Default is \code{FALSE}} \item{simplify}{[\code{character(1)}]\cr If only one object is stored in a R data file, should the return value be simplified? If set to \code{TRUE}, instead of a list containing one element the object itself will be returned.} } \value{ Object of class \code{fail}. See details. } \description{ The general idea is to not bother about file path joining or file extensions. Instead, FAIL offers a key-value like interface to RData files in a specified directory. The filename (without extension) acts as the key while the stored R objects are the values. Fail provides an interface to the basic file system actions: listing, reading / loading, writing / saving, removing and applying functions on files. An implemented cache mechanism can be used to avoid repeated disk reads. } \details{ For a quick introduction on the usage, see \url{https://github.com/mllg/fail}. An object with the following functions is returned by \code{fail}: \describe{ \item{\code{ls(pattern=NULL)}}{ Function to list keys in directory \code{path} matching a regular expression pattern \code{pattern}. Returns a character vector of keys. } \item{\code{get(key, use.cache)}}{ Function to load a file identified by \code{key} from directory \code{path}. To load many objects at once, use \code{as.list}, \code{assign} or \code{get} together with \code{\link[base]{lapply}}. Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. } \item{\code{put(..., li, keys, use.cache)}}{ Function to save objects to directory \code{path}. Names for objects provided via \code{...} will be looked up or can be provided using a \code{key = value} syntax. More objects can be passed as a named list using the argument \code{li}: Each list item will be saved to a separate file. If you provide \code{keys} as a character vector, these names will be taken for the arguments passed via \code{...}. Argument \code{use.cache} temporarily overwrites the global \code{use.cache} flag. Returns a character vector of stored keys. } \item{\code{remove(keys)}}{ Function to remove files identified by \code{keys} from directory \code{path}. Returns a character vector of deleted keys. } \item{\code{apply(FUN, ..., keys, use.cache, simplify=FALSE, use.names=TRUE)}}{ Apply function \code{FUN} on files identified by \code{keys}. \code{keys} defaults to all keys available and will be used to name the returned list. The loaded R objects will be past unnamed as first argument. Use \code{...} for additional function arguments. Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. For arguments \code{simplify} and \code{use.names}, see \code{\link[base]{lapply}}. } \item{\code{mapply(FUN, ..., keys, use.cache, moreArgs = NULL, simplify=FALSE, use.names=TRUE)}}{ Apply function \code{FUN} on files identified by \code{keys}. \code{keys} defaults to all keys available and will be used to name the returned list. The function \code{FUN} must have the formal arguments \dQuote{key} and \dQuote{value}. Both key and value will be passed named. Use \code{...} and/or \code{moreArgs} for additional function arguments. Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. For arguments \code{moreArgs}, \code{simplify} and \code{use.names}, see \code{\link[base]{mapply}}. } \item{\code{as.list(keys, use.cache)}}{ Return a named list of objects identified by \code{keys}. \code{keys} defaults to all keys available. Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. } \item{\code{assign(keys, envir=parent.frame(), use.cache)}}{ Assigns all objects identified by the character vector \code{keys} in the environment \code{envir}. Argument \code{use.cache} can be set to temporarily overwrite the global \code{use.cache} flag. Returns a character vector of assigned keys. } \item{\code{clear(keys)}}{ Clear the cache to free memory. \code{keys} defaults to all keys available. Returns a character vector of cleared keys. } \item{\code{cached()}}{ Returns a character vector of keys of cached objects. } \item{\code{size(keys, unit="b")}}{ Get the file size in Bytes of the files identified by \code{keys}. \code{keys} defaults to all keys available. Argument \code{unit} accepts \dQuote{b}, \dQuote{Kb}, \dQuote{Mb} and \dQuote{Gb} and can be used to convert Bytes to KiloBytes, MegaBytes or GigaBytes, respectively. } \item{\code{info()}}{ Returns a named list with \code{path}, \code{extension} and \code{use.cache}. Internally used for the \code{\link[base]{print}} method with a much nicer summary of the FAIL object. } } Furthermore, the package provides S3 methods for \code{\link[base]{print}} and \code{\link[base]{as.list}}. Be aware of the following restriction regarding file names and keys: The package performs some basic checks for illegal characters on the key names. In principle all characters matching the pattern \dQuote{[a-zA-Z0-9._-]} are allowed and should work on most or all file systems. But be careful with key names which are not compatible with R's variable naming restrictions, e.g. using the minus character or key names starting with a number: these provoke unwanted side effects and will result in errors if used with \code{assign}. If two files would collide on case-insensitive file systems like Windows' NTFS, the package will throw warnings. Best practice is to not rely on case sensitivity. } \examples{ # initialize a FAIL in a temporary directory path <- tempfile("") files <- fail(path) # save x and y, vectors of random numbers x <- runif(100) files$put(x, y = runif(100)) # save columns of the iris data set as separate files files$put(li = as.list(iris)) # load all RData files in a named list as a one-liner as.list(fail(path)) # load a single object from the file system files$get("Species") files$as.list(c("x", "y")) # remove an object (and related file) files$remove("Species") # apply a function over files files$apply(mean) files$mapply(function(key, value) sprintf("\%s -> \%f", key, mean(value)), simplify = TRUE) # show file size informations files$size(unit = "Mb") # get an object and cache it files$get("x", use.cache = TRUE) files$cached() files$clear() files$cached() # assign variables in the current environment files$assign("y") mean(y) } fail/man/sail.Rd0000644000176200001440000000311212602731572013161 0ustar liggesusers% Generated by roxygen2 (4.1.1): do not edit by hand % Please edit documentation in R/sail.R \name{sail} \alias{sail} \title{Create a source abstraction interface layer (SAIL) object.} \usage{ sail(path = getwd(), extension = "R", all.files = FALSE, use.cache = FALSE, simplify = TRUE, suppressMessages = FALSE) } \arguments{ \item{path}{[\code{character(1)}]\cr Path to work in, will be created if it does not exists.} \item{extension}{[\code{character(1)}]\cr File extension to work with. Default is \dQuote{R}.} \item{all.files}{[\code{logical(1)}]\cr Also include hidden files, i.e. files whose name start with a dot (\dQuote{.}). Default is \code{FALSE}.} \item{use.cache}{[\code{logical(1)}]\cr Use a memory cache per global default. Global option which can locally be overwritten in most functions. Default is \code{FALSE}} \item{simplify}{[\code{character(1)}]\cr If only one object is defined in a sourced R file, should the return value be simplified? If set to \code{TRUE}, instead of a list containing one element the object itself will be returned.} \item{suppressMessages}{[\code{logical(1)}]\cr Wrap the \code{\link[base]{sys.source}} command into \code{\link[base]{suppressMessages}} and \code{link[base]{suppressPackageStartupMessages}}? Default is \code{FALSE}, i.e. you will see regular output of sourced scripts.} } \value{ Object of class \code{sail}. See the documentation of \code{\link{fail}} for details. } \description{ This function returns an object of class \code{sail} which behaves like \code{\link{fail}}, but is indented for loading and saving R source code files. } fail/LICENSE0000644000176200001440000000011612514153653012175 0ustar liggesusersYEAR: 2013 COPYRIGHT HOLDER: Michel Lang ORGANIZATION: TU Dortmund University