[med-svn] [r-cran-memoise] 13/15: New upstream version 1.1.0

Andreas Tille tille at debian.org
Fri Sep 29 19:56:28 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository r-cran-memoise.

commit 9e18f0e407bbbe23f3604ea82b95795717385eb9
Author: Andreas Tille <tille at debian.org>
Date:   Fri Sep 29 21:52:52 2017 +0200

    New upstream version 1.1.0
---
 DESCRIPTION                      | 17 +++++----
 LICENSE                          |  2 +-
 MD5                              | 34 +++++++++++-------
 NAMESPACE                        |  3 ++
 NEWS.md                          | 10 +++++-
 R/cache_filesystem.R             | 57 +++++++++++++++++++++++++++++
 R/{cache.r => cache_memory.R}    |  9 ++++-
 R/cache_s3.R                     | 69 +++++++++++++++++++++++++++++++++++
 R/{memoise.r => memoise.R}       | 36 +++++++++++--------
 README.md                        | 77 +++++++++++++++++++++++++++++++++++-----
 man/cache_filesystem.Rd          | 35 ++++++++++++++++++
 man/cache_memory.Rd              | 15 ++++++++
 man/cache_s3.Rd                  | 33 +++++++++++++++++
 man/forget.Rd                    |  3 +-
 man/has_cache.Rd                 |  3 +-
 man/is.memoised.Rd               |  3 +-
 man/memoise.Rd                   | 11 +++---
 man/timeout.Rd                   |  3 +-
 tests/testthat/helper.R          | 16 +++++++++
 tests/testthat/test-filesystem.R | 38 ++++++++++++++++++++
 tests/testthat/test-memoise.R    | 54 +++++++++++++++++++++++-----
 tests/testthat/test-s3.R         | 27 ++++++++++++++
 22 files changed, 486 insertions(+), 69 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
index 893105c..43f0a0c 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,24 +1,27 @@
 Encoding: UTF-8
 Package: memoise
 Title: Memoisation of Functions
-Version: 1.0.0
+Version: 1.1.0
 Authors at R: c(
     person("Hadley", "Wickham", , "hadley at rstudio.com", role = "aut"),
     person("Jim", "Hester", , "jim.hester at rstudio.com", role = c("aut", "cre")),
-    person("Kirill", "Müller", , "krlmlr+r at mailbox.org", role = "aut"))
+    person("Kirill", "Müller", , "krlmlr+r at mailbox.org", role = "aut"),
+    person("Daniel", "Cook", , "danielecook at gmail.com", role = "aut"))
 Description: Cache the results of a function so that when you call it
     again with the same arguments it returns the pre-computed value.
 URL: https://github.com/hadley/memoise
 BugReports: https://github.com/hadley/memoise/issues
 Imports: digest (>= 0.6.3)
-Suggests: testthat
+Suggests: testthat, aws.s3, httr, covr
+Additional_repositories: http://cloudyr.github.io/drat
 License: MIT + file LICENSE
-RoxygenNote: 5.0.1
+RoxygenNote: 6.0.1
 NeedsCompilation: no
-Packaged: 2016-01-28 19:30:15 UTC; jhester
+Packaged: 2017-04-20 17:35:47 UTC; jhester
 Author: Hadley Wickham [aut],
   Jim Hester [aut, cre],
-  Kirill Müller [aut]
+  Kirill Müller [aut],
+  Daniel Cook [aut]
 Maintainer: Jim Hester <jim.hester at rstudio.com>
 Repository: CRAN
-Date/Publication: 2016-01-29 05:58:01
+Date/Publication: 2017-04-21 05:54:22 UTC
diff --git a/LICENSE b/LICENSE
index 267ea46..3136e20 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,2 +1,2 @@
-YEAR: 2010-2016
+YEAR: 2010-2017
 COPYRIGHT HOLDER: Hadley Wickham
diff --git a/MD5 b/MD5
index 701f020..2587176 100644
--- a/MD5
+++ b/MD5
@@ -1,14 +1,22 @@
-b207f226950a7040e1c319f2faa62694 *DESCRIPTION
-5a2ffc012eac074809a07ea440f872a8 *LICENSE
-29ff4bc0eaf941a3184340888a3adfce *NAMESPACE
-46d7d31fbc75bc3b4484b8ab0b5c4b22 *NEWS.md
-65efb37c5ec0b0aef53eba56fdbbb49f *R/cache.r
-06c37351cb0331bc22da278d43ff72a2 *R/memoise.r
-0be5258a057bcfe22b8fc5cb3b004b9c *README.md
-903db28a663ac1ba554e9b1fc2b9d364 *man/forget.Rd
-866463e90847d285f3a6d6cf736a61ca *man/has_cache.Rd
-ad48c04294167c927c44fe272047c7cf *man/is.memoised.Rd
-18ce3fffab957386abc962f6816144ec *man/memoise.Rd
-8e261440b9a586b0640437382d4d35df *man/timeout.Rd
+1206465e603904886c34375ed3e4153c *DESCRIPTION
+722211a1118fa7bad3f44650438df16f *LICENSE
+c8048cff1dfa17e590d39dda91fac613 *NAMESPACE
+3ac6db7d68d0236b9e246cae78eb5aad *NEWS.md
+03970fb1487e5e2661ceefb641a3092c *R/cache_filesystem.R
+d841451868115d25dadde8698457cfaa *R/cache_memory.R
+596de90c02bd1d5c59205afbfa18ba2f *R/cache_s3.R
+744002eaba6f98e5e415b3f776953a8f *R/memoise.R
+b5b1093427ab48ed04390d58dfdd7654 *README.md
+2b8d663545955c84410fd43443a6e204 *man/cache_filesystem.Rd
+521d9869c3b32561ae749eaa3f91c5a1 *man/cache_memory.Rd
+6b256f1905f1bea07e4ed00f6968c8a1 *man/cache_s3.Rd
+5b4864d5b27d9a06b0bb64ec6e6773bb *man/forget.Rd
+cba4d5fd07c64d83b9c6e044e5d39866 *man/has_cache.Rd
+24bd09185cedc4fc6ad4a742d645ee31 *man/is.memoised.Rd
+9c8367375fa6e4014e2e40ef9b5ff99a *man/memoise.Rd
+7173ef6c72af631d5ffbeccf66ec7d1b *man/timeout.Rd
 c4111f4662e1dada1a4d23df123018f9 *tests/testthat.R
-76a18f20ca3d39b0d82c7f84598f9d53 *tests/testthat/test-memoise.R
+31ae9c0755190a25d14eaa3f3007302b *tests/testthat/helper.R
+422bfad7a3cf8713a8dc30f2770ef528 *tests/testthat/test-filesystem.R
+99072c677b43fcf6c51c3050d66a52c1 *tests/testthat/test-memoise.R
+20058da8fbaa76a0ab08d0e0eb0412d7 *tests/testthat/test-s3.R
diff --git a/NAMESPACE b/NAMESPACE
index 0bf84c1..1736c94 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,6 +1,9 @@
 # Generated by roxygen2: do not edit by hand
 
 S3method(print,memoised)
+export(cache_filesystem)
+export(cache_memory)
+export(cache_s3)
 export(forget)
 export(has_cache)
 export(is.memoised)
diff --git a/NEWS.md b/NEWS.md
index 43a6786..0036569 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,13 @@
-# Version 1.0.0
+# Version 1.1.0
+* Caches now hash the function body along with the arguments, to ensure
+  functions with identical arguments use a separate file-system cache. (#38)
+* Handle missing arguments in memoised functions for simple cases not using
+  non-standard-evaluation (#19).
+* `memoise()` gains a `cache=` argument to specify an external cache. Two types
+  of caches are available, `cache_s3()` for amazon S3 and
+  `cache_filesystem()` for a file system cache (#25, @danielecook).
 
+# Version 1.0.0
 * `memoise()` now signals an error if an already memoised function is used as
   input (#4, @richierocks).
 * `has_cache()` function added which returns a boolean depending on if the
diff --git a/R/cache_filesystem.R b/R/cache_filesystem.R
new file mode 100644
index 0000000..71a71cc
--- /dev/null
+++ b/R/cache_filesystem.R
@@ -0,0 +1,57 @@
+#' Filesystem Cache
+#'
+#' Use a cache on the local filesystem that will persist between R sessions.
+#'
+#' @param path Directory in which to store cached items.
+#'
+#' @examples
+#'
+#' \dontrun{
+#' # Use with Dropbox
+#'
+#' db <- cache_filesystem("~/Dropbox/.rcache")
+#'
+#' mem_runif <- memoise(runif, cache = db)
+#'
+#' # Use with Google Drive
+#'
+#' gd <- cache_filesystem("~/Google Drive/.rcache")
+#'
+#' mem_runif <- memoise(runif, cache = gd)
+#'
+#' }
+#'
+#' @export
+#' @inheritParams cache_memory
+cache_filesystem <- function(path, algo = "xxhash64") {
+
+  if (!dir.exists(path)) {
+    dir.create(path, showWarnings = FALSE)
+  }
+
+  cache_reset <- function() {
+    cache_files <- list.files(path, full.names = TRUE)
+    file.remove(cache_files)
+  }
+
+  cache_set <- function(key, value) {
+    saveRDS(value, file = file.path(path, key))
+  }
+
+  cache_get <- function(key) {
+    readRDS(file = file.path(path, key))
+  }
+
+  cache_has_key <- function(key) {
+    file.exists(file.path(path, key))
+  }
+
+  list(
+    digest = function(...) digest::digest(..., algo = algo),
+    reset = cache_reset,
+    set = cache_set,
+    get = cache_get,
+    has_key = cache_has_key,
+    keys = function() list.files(path)
+  )
+}
diff --git a/R/cache.r b/R/cache_memory.R
similarity index 60%
rename from R/cache.r
rename to R/cache_memory.R
index 23d542f..f7fe9f2 100644
--- a/R/cache.r
+++ b/R/cache_memory.R
@@ -1,4 +1,10 @@
-new_cache <- function() {
+#' In Memory Cache
+#'
+#' A cache in memory, that lasts only in the current R session.
+#' @param algo The hashing algorithm used for the cache, see
+#' \code{\link[digest]{digest}} for available algorithms.
+#' @export
+cache_memory <- function(algo = "sha512") {
 
   cache <- NULL
   cache_reset <- function() {
@@ -19,6 +25,7 @@ new_cache <- function() {
 
   cache_reset()
   list(
+    digest = function(...) digest::digest(..., algo = algo),
     reset = cache_reset,
     set = cache_set,
     get = cache_get,
diff --git a/R/cache_s3.R b/R/cache_s3.R
new file mode 100644
index 0000000..164ae60
--- /dev/null
+++ b/R/cache_s3.R
@@ -0,0 +1,69 @@
+#' Amazon Web Services S3 Cache
+#' Amazon Web Services S3 backed cache, for remote caching.
+#'
+#' @examples
+#'
+#' \dontrun{
+#' # Set AWS credentials.
+#' Sys.setenv("AWS_ACCESS_KEY_ID" = "<access key>",
+#'            "AWS_SECRET_ACCESS_KEY" = "<access secret>")
+#'
+#' # Set up a unique bucket name.
+#' s3 <- cache_s3("unique-bucket-name")
+#' mem_runif <- memoise(runif, cache = s3)
+#' }
+#'
+#'
+#' @param cache_name Bucket name for storing cache files.
+#' @inheritParams cache_memory
+#' @export
+
+cache_s3 <- function(cache_name, algo = "sha512") {
+
+  if (!(requireNamespace("aws.s3"))) { stop("Package `aws.s3` must be installed for `cache_s3()`.") } # nocov
+
+  if (!(aws.s3::bucket_exists(cache_name))) {
+    aws.s3::put_bucket(cache_name) # nocov
+  }
+
+  path <- tempfile("memoise-")
+  dir.create(path)
+
+  cache_reset <- function() {
+    keys <- cache_keys()
+    lapply(keys, aws.s3::delete_bucket, bucket = cache_name)
+  }
+
+  cache_set <- function(key, value) {
+    temp_file <- file.path(path, key)
+    on.exit(unlink(temp_file))
+    saveRDS(value, file = temp_file)
+    aws.s3::put_object(temp_file, object = key, bucket = cache_name)
+  }
+
+  cache_get <- function(key) {
+    temp_file <- file.path(path, key)
+    httr::with_config(httr::write_disk(temp_file, overwrite = TRUE), {
+      aws.s3::get_object(object = key, bucket = cache_name)
+    })
+    readRDS(temp_file)
+  }
+
+  cache_has_key <- function(key) {
+    aws.s3::head_object(object = key, bucket = cache_name)
+  }
+
+  cache_keys <- function() {
+    items <- lapply(aws.s3::get_bucket(bucket = cache_name), `[[`, "Key")
+    unlist(Filter(Negate(is.null), items))
+  }
+
+  list(
+    digest = function(...) digest::digest(..., algo = algo),
+    reset = cache_reset,
+    set = cache_set,
+    get = cache_get,
+    has_key = cache_has_key,
+    keys = cache_keys
+  )
+}
diff --git a/R/memoise.r b/R/memoise.R
similarity index 90%
rename from R/memoise.r
rename to R/memoise.R
index ac0ae73..1cfd465 100644
--- a/R/memoise.r
+++ b/R/memoise.R
@@ -38,6 +38,7 @@
 #' @param ... optional variables specified as formulas with no RHS to use as
 #' additional restrictions on caching. See Examples for usage.
 #' @param envir Environment of the returned function.
+#' @param cache Cache function.
 #' @seealso \code{\link{forget}}, \code{\link{is.memoised}},
 #'   \code{\link{timeout}}, \url{http://en.wikipedia.org/wiki/Memoization}
 #' @aliases memoise memoize
@@ -70,7 +71,7 @@
 #' formals(b)
 #' formals(memB)
 #' # However, it doesn't know about parameter relevance.
-#' # Different call means different cacheing, no matter
+#' # Different call means different caching, no matter
 #' # that the outcome is the same.
 #' memB(2, dummy="b")
 #'
@@ -93,11 +94,11 @@
 #' memA3 <- memoise(a, ~{current <- as.numeric(Sys.time()); (current - current %% 10) %/% 10 })
 #' memA3(2)
 #'
-#' # The timeout function is any easy way to do the above.
+#' # The timeout function is an easy way to do the above.
 #' memA4 <- memoise(a, ~timeout(10))
 #' memA4(2)
 #' @importFrom stats setNames
-memoise <- memoize <- function(f, ..., envir = environment(f)) {
+memoise <- memoize <- function(f, ..., envir = environment(f), cache = cache_memory()) {
   f_formals <- formals(args(f))
   if(is.memoised(f)) {
     stop("`f` must not be memoised.", call. = FALSE)
@@ -106,23 +107,29 @@ memoise <- memoize <- function(f, ..., envir = environment(f)) {
   f_formal_names <- names(f_formals)
   f_formal_name_list <- lapply(f_formal_names, as.name)
 
-  # list(...)
-  list_call <- make_call(quote(list), f_formal_name_list)
-
   # memoised_function(...)
   init_call_args <- setNames(f_formal_name_list, f_formal_names)
   init_call <- make_call(quote(`_f`), init_call_args)
 
-  cache <- new_cache()
-
   validate_formulas(...)
   additional <- list(...)
 
   memo_f <- eval(
     bquote(function(...) {
-      hash <- `_digest`(c(.(list_call),
-          lapply(`_additional`, function(x) eval(x[[2L]], environment(x)))),
-        algo = "sha512")
+      called_args <- as.list(match.call())[-1]
+
+      # Formals with a default
+      default_args <- Filter(function(x) !identical(x, quote(expr = )), as.list(formals()))
+
+      # That has not been called
+      default_args <- default_args[setdiff(names(default_args), names(called_args))]
+
+      # Evaluate all the arguments
+      args <- c(lapply(called_args, eval, parent.frame()),
+        lapply(default_args, eval, envir = environment()))
+
+      hash <- `_cache`$digest(c(body(`_f`), args,
+          lapply(`_additional`, function(x) eval(x[[2L]], environment(x)))))
 
       if (`_cache`$has_key(hash)) {
         res <- `_cache`$get(hash)
@@ -137,7 +144,7 @@ memoise <- memoize <- function(f, ..., envir = environment(f)) {
         invisible(res$value)
       }
     },
-    as.environment(list(list_call = list_call, init_call = init_call)))
+    as.environment(list(init_call = init_call)))
   )
   formals(memo_f) <- f_formals
   attr(memo_f, "memoised") <- TRUE
@@ -150,7 +157,6 @@ memoise <- memoize <- function(f, ..., envir = environment(f)) {
   memo_f_env <- new.env(parent = envir)
   memo_f_env$`_cache` <- cache
   memo_f_env$`_f` <- f
-  memo_f_env$`_digest` <- digest
   memo_f_env$`_additional` <- additional
   environment(memo_f) <- memo_f_env
 
@@ -224,7 +230,7 @@ forget <- function(f) {
   }
 
   env <- environment(f)
-  if (!exists("_cache", env, inherits = FALSE)) return(FALSE)
+  if (!exists("_cache", env, inherits = FALSE)) return(FALSE) # nocovr
 
   cache <- get("_cache", env)
   cache$reset()
@@ -263,7 +269,7 @@ has_cache <- function(f, ...) {
   # Modify the function body of the function to simply return TRUE and FALSE
   # rather than get or set the results of the cache
   body <- body(f)
-  body[[3]] <- quote(if (`_cache`$has_key(hash)) return(TRUE) else return(FALSE))
+  body[[7]] <- quote(if (`_cache`$has_key(hash)) return(TRUE) else return(FALSE))
   body(f) <- body
 
   f
diff --git a/README.md b/README.md
index f2b4566..5895ae5 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,80 @@
-# memoise [![Travis-CI Build Status](https://travis-ci.org/hadley/memoise.svg?branch=master)](https://travis-ci.org/hadley/memoise) [![Coverage Status](https://img.shields.io/codecov/c/github/hadley/memoise/master.svg)](https://codecov.io/github/hadley/memoise?branch=master)
+# memoise
+[![Travis-CI Build Status](https://travis-ci.org/hadley/memoise.svg?branch=master)](https://travis-ci.org/hadley/memoise) [![Coverage Status](https://img.shields.io/codecov/c/github/hadley/memoise/master.svg)](https://codecov.io/github/hadley/memoise?branch=master)
 
+# Memoization
 
 If a function is called multiple times with the same input, you can
 often speed things up by keeping a cache of known answers that it can
 retrieve. This is called memoisation <http://en.wikipedia.org/wiki/Memoization>.
-The `memoise` package provides a simple syntax 
+The `memoise` package provides a simple syntax
 
-    mf <- memoise(f)
+```r
+mf <- memoise(f)
+```
 
 to create `mf()`, a memoised wrapper around `f()`. You can clear `mf`'s
-cache with 
+cache with
 
-    forget(mf)
+```r
+forget(mf)
+```
 
-, and you can test whether a function is memoised with
+and you can test whether a function is memoised with
 
-    is.memoised(mf) # TRUE
-    is.memoised(f)  # FALSE
+```r
+is.memoised(mf) # TRUE
+is.memoised(f)  # FALSE
+```
 
-.
+# Installation
+
+```
+devtools::install_github("hadley/memoise")
+```
+
+# External Caches
+
+`memoise` also supports external caching in addition to the default in-memory caches.
+
+* `cache_filesystem()` allows caching using files on a local filesystem. You
+  can point this to a shared file such as dropbox or google drive to share
+  caches between systems.
+* `cache_s3()` allows caching on [Amazon S3](https://aws.amazon.com/s3/)
+
+
+## AWS S3
+
+Use `cache_s3()` to cache objects using s3 storage. Requires you to specify
+a bucket using `cache_name`. When creating buckets, they must be unique among
+all s3 users when created.
+
+```r
+Sys.setenv("AWS_ACCESS_KEY_ID" = "<access key>",
+           "AWS_SECRET_ACCESS_KEY" = "<access secret>")
+
+mrunif <- memoise(runif, cache = cache_s3("<unique bucket name>"))
+
+mrunif(10) # First run, saves cache
+mrunif(10) # Loads cache, results should be identical
+
+```
+
+## Filesystem
+
+`cache_filesystem` can be used for a file system cache. This is useful for
+preserving the cache between R sessions as well as sharing between systems
+when using a shared or synced files system such as Dropbox or Google Drive.
+
+```r
+fc <- cache_filesystem("~/.cache")
+mrunif <- memoise(runif, cache = fc)
+mrunif(20) # Results stored in local file
+
+dbc <- cache_filesystem("~/Dropbox/.rcache")
+mrunif <- memoise(runif, cache = dbc)
+mrunif(20) # Results stored in Dropbox .rcache folder which will be synced between computers.
+
+gdc <- cache_filesystem("~/Google Drive/.rcache")
+mrunif <- memoise(runif, cache = gdc)
+mrunif(20) # Results stored in Google Drive .rcache folder which will be synced between computers.
+```
diff --git a/man/cache_filesystem.Rd b/man/cache_filesystem.Rd
new file mode 100644
index 0000000..7722041
--- /dev/null
+++ b/man/cache_filesystem.Rd
@@ -0,0 +1,35 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/cache_filesystem.R
+\name{cache_filesystem}
+\alias{cache_filesystem}
+\title{Filesystem Cache}
+\usage{
+cache_filesystem(path, algo = "xxhash64")
+}
+\arguments{
+\item{path}{Directory in which to store cached items.}
+
+\item{algo}{The hashing algorithm used for the cache, see
+\code{\link[digest]{digest}} for available algorithms.}
+}
+\description{
+Use a cache on the local filesystem that will persist between R sessions.
+}
+\examples{
+
+\dontrun{
+# Use with Dropbox
+
+db <- cache_filesystem("~/Dropbox/.rcache")
+
+mem_runif <- memoise(runif, cache = db)
+
+# Use with Google Drive
+
+gd <- cache_filesystem("~/Google Drive/.rcache")
+
+mem_runif <- memoise(runif, cache = gd)
+
+}
+
+}
diff --git a/man/cache_memory.Rd b/man/cache_memory.Rd
new file mode 100644
index 0000000..d375847
--- /dev/null
+++ b/man/cache_memory.Rd
@@ -0,0 +1,15 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/cache_memory.R
+\name{cache_memory}
+\alias{cache_memory}
+\title{In Memory Cache}
+\usage{
+cache_memory(algo = "sha512")
+}
+\arguments{
+\item{algo}{The hashing algorithm used for the cache, see
+\code{\link[digest]{digest}} for available algorithms.}
+}
+\description{
+A cache in memory, that lasts only in the current R session.
+}
diff --git a/man/cache_s3.Rd b/man/cache_s3.Rd
new file mode 100644
index 0000000..c338ff4
--- /dev/null
+++ b/man/cache_s3.Rd
@@ -0,0 +1,33 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/cache_s3.R
+\name{cache_s3}
+\alias{cache_s3}
+\title{Amazon Web Services S3 Cache
+Amazon Web Services S3 backed cache, for remote caching.}
+\usage{
+cache_s3(cache_name, algo = "sha512")
+}
+\arguments{
+\item{cache_name}{Bucket name for storing cache files.}
+
+\item{algo}{The hashing algorithm used for the cache, see
+\code{\link[digest]{digest}} for available algorithms.}
+}
+\description{
+Amazon Web Services S3 Cache
+Amazon Web Services S3 backed cache, for remote caching.
+}
+\examples{
+
+\dontrun{
+# Set AWS credentials.
+Sys.setenv("AWS_ACCESS_KEY_ID" = "<access key>",
+           "AWS_SECRET_ACCESS_KEY" = "<access secret>")
+
+# Set up a unique bucket name.
+s3 <- cache_s3("unique-bucket-name")
+mem_runif <- memoise(runif, cache = s3)
+}
+
+
+}
diff --git a/man/forget.Rd b/man/forget.Rd
index 633e40a..5951e23 100644
--- a/man/forget.Rd
+++ b/man/forget.Rd
@@ -1,5 +1,5 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/memoise.r
+% Please edit documentation in R/memoise.R
 \name{forget}
 \alias{forget}
 \title{Forget past results.
@@ -25,4 +25,3 @@ system.time(print(memX()))
 \seealso{
 \code{\link{memoise}}, \code{\link{is.memoised}}
 }
-
diff --git a/man/has_cache.Rd b/man/has_cache.Rd
index 69f4ad7..3f3390d 100644
--- a/man/has_cache.Rd
+++ b/man/has_cache.Rd
@@ -1,5 +1,5 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/memoise.r
+% Please edit documentation in R/memoise.R
 \name{has_cache}
 \alias{has_cache}
 \title{Test whether a memoised function has been cached for particular arguments.}
@@ -23,4 +23,3 @@ has_cache(mem_sum)(1, 2, 3) # TRUE
 \seealso{
 \code{\link{is.memoised}}, \code{\link{memoise}}
 }
-
diff --git a/man/is.memoised.Rd b/man/is.memoised.Rd
index cfac4d2..0ec7293 100644
--- a/man/is.memoised.Rd
+++ b/man/is.memoised.Rd
@@ -1,5 +1,5 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/memoise.r
+% Please edit documentation in R/memoise.R
 \name{is.memoised}
 \alias{is.memoised}
 \alias{is.memoized}
@@ -25,4 +25,3 @@ is.memoised(mem_lm) # TRUE
 \seealso{
 \code{\link{memoise}}, \code{\link{forget}}
 }
-
diff --git a/man/memoise.Rd b/man/memoise.Rd
index c3ba39a..c4fdfe1 100644
--- a/man/memoise.Rd
+++ b/man/memoise.Rd
@@ -1,11 +1,11 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/memoise.r
+% Please edit documentation in R/memoise.R
 \name{memoise}
 \alias{memoise}
 \alias{memoize}
 \title{Memoise a function.}
 \usage{
-memoise(f, ..., envir = environment(f))
+memoise(f, ..., envir = environment(f), cache = cache_memory())
 }
 \arguments{
 \item{f}{Function of which to create a memoised copy.}
@@ -14,6 +14,8 @@ memoise(f, ..., envir = environment(f))
 additional restrictions on caching. See Examples for usage.}
 
 \item{envir}{Environment of the returned function.}
+
+\item{cache}{Cache function.}
 }
 \description{
 \code{mf <- memoise(f)} creates \code{mf}, a memoised copy of
@@ -78,7 +80,7 @@ memB(2, dummy="a")
 formals(b)
 formals(memB)
 # However, it doesn't know about parameter relevance.
-# Different call means different cacheing, no matter
+# Different call means different caching, no matter
 # that the outcome is the same.
 memB(2, dummy="b")
 
@@ -101,7 +103,7 @@ memA(2)
 memA3 <- memoise(a, ~{current <- as.numeric(Sys.time()); (current - current \%\% 10) \%/\% 10 })
 memA3(2)
 
-# The timeout function is any easy way to do the above.
+# The timeout function is an easy way to do the above.
 memA4 <- memoise(a, ~timeout(10))
 memA4(2)
 }
@@ -109,4 +111,3 @@ memA4(2)
 \code{\link{forget}}, \code{\link{is.memoised}},
   \code{\link{timeout}}, \url{http://en.wikipedia.org/wiki/Memoization}
 }
-
diff --git a/man/timeout.Rd b/man/timeout.Rd
index 588d3d0..a269470 100644
--- a/man/timeout.Rd
+++ b/man/timeout.Rd
@@ -1,5 +1,5 @@
 % Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/memoise.r
+% Please edit documentation in R/memoise.R
 \name{timeout}
 \alias{timeout}
 \title{Return a new number after a given number of seconds}
@@ -28,4 +28,3 @@ memA(2)
 \seealso{
 \code{\link{memoise}}
 }
-
diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R
new file mode 100644
index 0000000..8816ee3
--- /dev/null
+++ b/tests/testthat/helper.R
@@ -0,0 +1,16 @@
+skip_without_aws_credetials <- function() {
+  # -# Sys.setenv("AWS_ACCESS_KEY_ID" = "<access key>", "AWS_SECRET_ACCESS_KEY" = "<access secret>")
+  if (nzchar(Sys.getenv("AWS_ACCESS_KEY_ID")) && nzchar(Sys.getenv("AWS_SECRET_ACCESS_KEY"))) {
+    return(invisible(TRUE))
+  }
+
+  testthat::skip("No AWS Credentials")
+}
+
+skip_on_travis_pr <- function() {
+  if (identical(Sys.getenv("TRAVIS"), "true") && !identical(Sys.getenv("TRAVIS_PULL_REQUEST", "false"), "false")) {
+    return(testthat::skip("On Travis PR"))
+  }
+
+  invisible(TRUE)
+}
diff --git a/tests/testthat/test-filesystem.R b/tests/testthat/test-filesystem.R
new file mode 100644
index 0000000..b4a4c4a
--- /dev/null
+++ b/tests/testthat/test-filesystem.R
@@ -0,0 +1,38 @@
+context("filesystem")
+
+test_that("using a filesystem cache works", {
+
+  fs <- cache_filesystem(tempfile())
+  i <- 0
+  fn <- function() { i <<- i + 1; i }
+  fnm <- memoise(fn, cache = fs)
+  on.exit(forget(fnm))
+
+  expect_equal(fn(), 1)
+  expect_equal(fn(), 2)
+  expect_equal(fnm(), 3)
+  expect_equal(fnm(), 3)
+  expect_equal(fn(), 4)
+  expect_equal(fnm(), 3)
+
+  expect_false(forget(fn))
+  expect_true(forget(fnm))
+  expect_equal(fnm(), 5)
+
+  expect_true(is.memoised(fnm))
+  expect_false(is.memoised(fn))
+})
+
+test_that("two functions with the same arguments produce different caches (#38)", {
+
+  temp <- tempfile()
+  fs <- cache_filesystem(temp)
+
+  f1 <- memoise(function() 1, cache = fs)
+  f2 <- memoise(function() 2, cache = fs)
+
+  expect_equal(f1(), 1)
+  expect_equal(f2(), 2)
+
+  expect_equal(length(list.files(temp)), 2)
+})
diff --git a/tests/testthat/test-memoise.R b/tests/testthat/test-memoise.R
index 7eb9138..262a2d0 100644
--- a/tests/testthat/test-memoise.R
+++ b/tests/testthat/test-memoise.R
@@ -4,7 +4,7 @@ test_that("memoisation works", {
   fn <- function() { i <<- i + 1; i }
   i <- 0
 
-  expect_that(fnm <- memoise(fn), not(gives_warning()))
+  expect_warning(fnm <- memoise(fn), NA)
   expect_equal(fn(), 1)
   expect_equal(fn(), 2)
   expect_equal(fnm(), 3)
@@ -14,6 +14,7 @@ test_that("memoisation works", {
 
   expect_false(forget(fn))
   expect_true(forget(fnm))
+  expect_true(forget(fnm))
   expect_equal(fnm(), 5)
 
   expect_true(is.memoised(fnm))
@@ -24,7 +25,7 @@ test_that("memoisation depends on argument", {
   fn <- function(j) { i <<- i + 1; i }
   i <- 0
 
-  expect_that(fnm <- memoise(fn), not(gives_warning()))
+  expect_warning(fnm <- memoise(fn), NA)
   expect_equal(fn(1), 1)
   expect_equal(fn(1), 2)
   expect_equal(fnm(1), 3)
@@ -50,12 +51,13 @@ test_that("dot arguments are used for hash", {
   fn <- function(...) { i <<- i + 1; i }
   i <- 0
 
-  expect_that(fnm <- memoise(fn), not(gives_warning()))
+  expect_warning(fnm <- memoise(fn), NA)
   expect_equal(fn(1), 1)
   expect_equal(fnm(1), 2)
   expect_equal(fnm(1), 2)
   expect_equal(fnm(1, 2), 3)
   expect_equal(fnm(1), 2)
+  expect_equal(fnm(1, 2), 3)
   expect_equal(fnm(), 4)
 
   expect_true(forget(fnm))
@@ -69,7 +71,7 @@ test_that("default arguments are used for hash", {
   fn <- function(j = 1) { i <<- i + 1; i }
   i <- 0
 
-  expect_that(fnm <- memoise(fn), not(gives_warning()))
+  expect_warning(fnm <- memoise(fn), NA)
   expect_equal(fn(1), 1)
   expect_equal(fnm(1), 2)
   expect_equal(fnm(1), 2)
@@ -84,7 +86,7 @@ test_that("default arguments are evaluated correctly", {
   fn <- function(j = g()) { i <<- i + 1; i }
   i <- 0
 
-  expect_that(fnm <- memoise(fn), not(gives_warning()))
+  expect_warning(fnm <- memoise(fn), NA)
   expect_equal(fn(1), 1)
   expect_equal(fnm(1), 2)
   expect_equal(fnm(1), 2)
@@ -133,7 +135,7 @@ test_that("visibility", {
 })
 
 test_that("can memoise anonymous function", {
-  expect_that(fm <- memoise(function(a = 1) a), not(gives_warning()))
+  expect_warning(fm <- memoise(function(a = 1) a), NA)
   expect_equal(names(formals(fm))[[1]], "a")
   expect_equal(fm(1), 1)
   expect_equal(fm(2), 2)
@@ -141,7 +143,7 @@ test_that("can memoise anonymous function", {
 })
 
 test_that("can memoise primitive", {
-  expect_that(fm <- memoise(`+`), not(gives_warning()))
+  expect_warning(fm <- memoise(`+`), NA)
   expect_equal(names(formals(fm)), names(formals(args(`+`))))
   expect_equal(fm(1, 2), 1 + 2)
   expect_equal(fm(2, 3), 2 + 3)
@@ -218,6 +220,19 @@ test_that("it does have namespace clashes with internal memoise symbols", {
   expect_equal(fun(10), fun_mem(10))
 })
 
+test_that("arguments are evaluated before hashing", {
+  i <- 1
+
+  f <- memoise(function(x, y, z = 3) { x + y + z})
+  f2 <- function(x, y) f(x, y)
+
+  expect_equal(f2(1, 1), 5)
+
+  expect_equal(f2(1, 1), 5)
+
+  expect_equal(f2(2, 2), 7)
+})
+
 context("has_cache")
 test_that("it works as expected with memoised functions", {
   mem_sum <- memoise(sum)
@@ -245,7 +260,7 @@ test_that("it stays the same if not enough time has passed", {
   expect_equal(first, timeout(duration, 7))
   expect_equal(first, timeout(duration, 9))
 
-  expect_that(first, not(equals(timeout(duration, 10))))
+  expect_true(first != timeout(duration, 10))
 
 
   duration <- 100
@@ -256,5 +271,26 @@ test_that("it stays the same if not enough time has passed", {
   expect_equal(first, timeout(duration, 70))
   expect_equal(first, timeout(duration, 99))
 
-  expect_that(first, not(equals(timeout(duration, 100))))
+  expect_true(first != timeout(duration, 100))
+})
+
+context("missing")
+test_that("it works with missing arguments", {
+  fn <- function(x, y) {
+    i <<- i + 1
+    if (missing(y)) {
+      y <- 1
+    }
+    x + y
+  }
+  fnm <- memoise(fn)
+  i <- 0
+
+  expect_equal(fn(1), fnm(1))
+  expect_equal(fn(1, 2), fnm(1, 2))
+  expect_equal(i, 4)
+  fnm(1)
+  expect_equal(i, 4)
+  fnm(1, 2)
+  expect_equal(i, 4)
 })
diff --git a/tests/testthat/test-s3.R b/tests/testthat/test-s3.R
new file mode 100644
index 0000000..d5d1e94
--- /dev/null
+++ b/tests/testthat/test-s3.R
@@ -0,0 +1,27 @@
+context("s3")
+
+test_that("using a s3 cache works", {
+  skip_on_cran()
+  skip_on_travis_pr()
+  skip_without_aws_credetials()
+
+  aws <- cache_s3("memoise-tests")
+  i <- 0
+  fn <- function() { i <<- i + 1; i }
+  fnm <- memoise(fn, cache = aws)
+  on.exit(forget(fnm))
+
+  expect_equal(fn(), 1)
+  expect_equal(fn(), 2)
+  expect_equal(fnm(), 3)
+  expect_equal(fnm(), 3)
+  expect_equal(fn(), 4)
+  expect_equal(fnm(), 3)
+
+  expect_false(forget(fn))
+  expect_true(forget(fnm))
+  expect_equal(fnm(), 5)
+
+  expect_true(is.memoised(fnm))
+  expect_false(is.memoised(fn))
+})

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-memoise.git



More information about the debian-med-commit mailing list