withr/ 0000755 0001762 0000144 00000000000 13252573074 011417 5 ustar ligges users withr/inst/ 0000755 0001762 0000144 00000000000 13252476110 012365 5 ustar ligges users withr/inst/doc/ 0000755 0001762 0000144 00000000000 13252476110 013132 5 ustar ligges users withr/inst/doc/withr.Rmd 0000644 0001762 0000144 00000006623 13216217255 014745 0 ustar ligges users ---
title: "withr"
author: "Jim Hester"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{withr}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
library(withr)
```
# Whither withr?
Many functions in R modify global state in some fashion. Some common examples
are `par()` for graphics parameters, `dir()` to change the current directory
and `options()` to set a global option. Using these functions is handy
when using R interactively, because you can set them early in your
experimentation and they will remain set for the duration of the session.
However this makes programming with these settings difficult, because they make
your function impure by modifying a global state. Therefore you should always
strive to reset the previous state when the function exits.
One common idiom for dealing with this problem is to save the current state,
make your change, then restore the previous state.
```{r}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
plot(mtcars$hp, mtcars$wt)
par(old)
}
my_plot()
par("col")
```
However this approach can fail if there's an error before you are able to reset
the options.
```{r, error = TRUE}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
plot(mtcars$hpp, mtcars$wt)
par(old)
}
my_plot()
par("col")
```
Using the base function `on.exit()` is a robust solution to this problem.
`on.exit()` will run the code when the function is exited, regardless
of whether it exits normally or with an error.
```{r, error = TRUE}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
on.exit(par(old))
plot(mtcars$hpp, mtcars$wt)
}
my_plot()
par("col")
options(test = 1)
{
print(getOption("test"))
on.exit(options(test = 2))
}
getOption("test")
```
However this solution is somewhat cumbersome to work with. You
need to remember to use an `on.exit()` call after each stateful call. In
addition by default each `on.exit()` action will overwrite any previous
`on.exit()` action in the same function unless you use the `add = TRUE` option.
`add = TRUE` also adds additional code to the _end_ of existing code, which
means the code is not run in the [Last-In,
First-Out](https://en.wikipedia.org/wiki/FIFO_and_LIFO_accounting) order you
would generally prefer. It is also not possible to have this cleanup code
performed before the function has finished.
[withr](http://withr.r-lib.org) is a solution to these issues. It defines a
[large set of
functions](http://withr.r-lib.org/#withr---run-code-with-modified-state) for
dealing with global settings in R, such as `with_par()`. These functions set one of
the global settings for the duration of a block of code, then automatically
reset it after the block is completed.
```{r}
par("col" = "black")
my_plot <- function(new) {
with_par(list(col = "red", pch = 19),
plot(mtcars$hp, mtcars$wt)
)
par("col")
}
my_plot()
par("col")
```
In addition to the `with_*` functions there are `local_*` variants whose effects
last until the end of the function they are included in. These work similar to
`on.exit()`, but you can set the options in one call rather than two.
```{r}
par("col" = "black")
my_plot <- function(new) {
local_par(list(col = "red", pch = 19))
plot(mtcars$hp, mtcars$wt)
}
my_plot()
par("col")
```
withr/inst/doc/withr.html 0000644 0001762 0000144 00000226721 13252476110 015167 0 ustar ligges users
withr
withr
Jim Hester
2018-03-15
Whither withr?
Many functions in R modify global state in some fashion. Some common examples are par()
for graphics parameters, dir()
to change the current directory and options()
to set a global option. Using these functions is handy when using R interactively, because you can set them early in your experimentation and they will remain set for the duration of the session. However this makes programming with these settings difficult, because they make your function impure by modifying a global state. Therefore you should always strive to reset the previous state when the function exits.
One common idiom for dealing with this problem is to save the current state, make your change, then restore the previous state.

However this approach can fail if there’s an error before you are able to reset the options.
Using the base function on.exit()
is a robust solution to this problem. on.exit()
will run the code when the function is exited, regardless of whether it exits normally or with an error.
However this solution is somewhat cumbersome to work with. You need to remember to use an on.exit()
call after each stateful call. In addition by default each on.exit()
action will overwrite any previous on.exit()
action in the same function unless you use the add = TRUE
option. add = TRUE
also adds additional code to the end of existing code, which means the code is not run in the Last-In, First-Out order you would generally prefer. It is also not possible to have this cleanup code performed before the function has finished.
withr is a solution to these issues. It defines a large set of functions for dealing with global settings in R, such as with_par()
. These functions set one of the global settings for the duration of a block of code, then automatically reset it after the block is completed.

#> [1] "black"
par("col")
#> [1] "black"
In addition to the with_*
functions there are local_*
variants whose effects last until the end of the function they are included in. These work similar to on.exit()
, but you can set the options in one call rather than two.

withr/inst/doc/withr.R 0000644 0001762 0000144 00000002553 13252476110 014417 0 ustar ligges users ## ----setup, include = FALSE----------------------------------------------
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
library(withr)
## ------------------------------------------------------------------------
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
plot(mtcars$hp, mtcars$wt)
par(old)
}
my_plot()
par("col")
## ---- error = TRUE-------------------------------------------------------
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
plot(mtcars$hpp, mtcars$wt)
par(old)
}
my_plot()
par("col")
## ---- error = TRUE-------------------------------------------------------
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
on.exit(par(old))
plot(mtcars$hpp, mtcars$wt)
}
my_plot()
par("col")
options(test = 1)
{
print(getOption("test"))
on.exit(options(test = 2))
}
getOption("test")
## ------------------------------------------------------------------------
par("col" = "black")
my_plot <- function(new) {
with_par(list(col = "red", pch = 19),
plot(mtcars$hp, mtcars$wt)
)
par("col")
}
my_plot()
par("col")
## ------------------------------------------------------------------------
par("col" = "black")
my_plot <- function(new) {
local_par(list(col = "red", pch = 19))
plot(mtcars$hp, mtcars$wt)
}
my_plot()
par("col")
withr/tests/ 0000755 0001762 0000144 00000000000 12634157537 012566 5 ustar ligges users withr/tests/testthat.R 0000644 0001762 0000144 00000000066 12565664242 014552 0 ustar ligges users library(testthat)
library(withr)
test_check("withr")
withr/tests/testthat/ 0000755 0001762 0000144 00000000000 13252573074 014421 5 ustar ligges users withr/tests/testthat/test-connection.R 0000644 0001762 0000144 00000002553 13171140516 017654 0 ustar ligges users context("connection")
describe("with_connection", {
it("errors if connection is not named", {
expect_error({
with_connection(list(TRUE), TRUE)
}, "all(is.named(con)) is not TRUE", fixed = TRUE)
})
it("creates a single connection", {
tmp <- tempfile()
on.exit(unlink(tmp))
expect_false(exists("con"))
with_connection(list(con = file(tmp, "w")), {
writeLines(c("foo", "bar"), con)
})
expect_false(exists("con"))
expect_equal(readLines(tmp), c("foo", "bar"))
})
it("creates multiple connections", {
tmp <- tempfile()
tmp2 <- tempfile()
on.exit(unlink(c(tmp, tmp2)))
expect_false(exists("con"))
expect_false(exists("con2"))
with_connection(list(con = file(tmp, "w"), con2 = file(tmp2, "w")), {
writeLines(c("foo", "bar"), con)
writeLines(c("baz", "qux"), con2)
})
expect_false(exists("con"))
expect_false(exists("con2"))
expect_equal(readLines(tmp), c("foo", "bar"))
expect_equal(readLines(tmp2), c("baz", "qux"))
})
})
describe("local_connection", {
it("creates a single connection", {
tmp <- tempfile()
on.exit(unlink(tmp))
expect_false(exists("con"))
(function() {
con <- local_connection(file(tmp, "w"))
writeLines(c("foo", "bar"), con)
})()
expect_false(exists("con"))
expect_equal(readLines(tmp), c("foo", "bar"))
})
})
withr/tests/testthat/test-tempfile.R 0000644 0001762 0000144 00000001621 13152261106 017313 0 ustar ligges users context("tempfile")
test_that("with_tempfile works", {
f1 <- character()
f2 <- character()
with_tempfile("file1", {
writeLines("foo", file1)
expect_equal(readLines(file1), "foo")
with_tempfile("file2", {
writeLines("bar", file2)
expect_equal(readLines(file1), "foo")
expect_equal(readLines(file2), "bar")
f2 <<- file2
})
expect_false(file.exists(f2))
f1 <<- file1
})
expect_false(file.exists(f1))
})
test_that("local_tempfile works", {
f1 <- character()
f2 <- character()
f <- function() {
local_tempfile("file1")
writeLines("foo", file1)
expect_equal(readLines(file1), "foo")
local_tempfile("file2")
writeLines("bar", file2)
expect_equal(readLines(file1), "foo")
expect_equal(readLines(file2), "bar")
f1 <<- file1
f2 <<- file2
}
f()
expect_false(file.exists(f1))
expect_false(file.exists(f2))
})
withr/tests/testthat/test-local.R 0000644 0001762 0000144 00000014111 13044121712 016574 0 ustar ligges users context("local")
test_that("local_envvar sets and unsets variables", {
# Make sure the "set_env_testvar" environment var is not set.
Sys.unsetenv("set_env_testvar")
expect_false("set_env_testvar" %in% names(Sys.getenv()))
# Use local_envvar (which calls set_envvar) to temporarily set it to 1
local({
local_envvar(c("set_env_testvar" = 1))
expect_identical("1", Sys.getenv("set_env_testvar"))
})
# set_env_testvar shouldn't stay in the list of environment vars
expect_false("set_env_testvar" %in% names(Sys.getenv()))
})
test_that("local_envar respects suffix and prefix", {
nested <- function(op1, op2) {
local({
local_envvar(c(A = 1), action = op1)
local({
local_envvar(c(A = 2), action = op2)
Sys.getenv("A")[[1]]
})
})
}
expect_equal(nested("replace", "suffix"), c("1 2"))
expect_equal(nested("replace", "prefix"), c("2 1"))
expect_equal(nested("prefix", "suffix"), c("1 2"))
expect_equal(nested("prefix", "prefix"), c("2 1"))
expect_equal(nested("suffix", "suffix"), c("1 2"))
expect_equal(nested("suffix", "prefix"), c("2 1"))
})
test_that("local_options works", {
expect_false(getOption("scipen") == 999)
local({
local_options(c(scipen=999))
expect_equal(getOption("scipen"), 999)
})
expect_false(getOption("scipen") == 999)
expect_false(identical(getOption("zyxxyzyx"), "qwrbbl"))
local({
local_options(c(zyxxyzyx="qwrbbl"))
expect_equal(getOption("zyxxyzyx"), "qwrbbl")
})
expect_false(identical(getOption("zyxxyzyx"), "qwrbbl"))
})
test_that("local_libpaths works and resets library", {
lib <- .libPaths()
new_lib <- "."
local({
local_libpaths(new_lib)
expect_equal(normalizePath(new_lib), normalizePath(.libPaths()[[1L]]))
})
expect_equal(lib, .libPaths())
})
test_that("local_temp_libpaths works and resets library", {
lib <- .libPaths()
local({
local_temp_libpaths()
expect_equal(.libPaths()[-1], lib)
})
expect_equal(lib, .libPaths())
})
test_that("local_ works", {
res <- NULL
set <- function(new) {
res <<- c(res, 1L)
}
reset <- function(old) {
res <<- c(res, 3L)
}
local_res <- local_(set, reset)
local({
local_res(NULL)
res <<- c(res, 2L)
})
expect_equal(res, 1L:3L)
})
test_that("local_ works on functions without arguments", {
res <- NULL
set <- function() {
res <<- c(res, 1L)
}
reset <- function(x) {
res <<- c(res, 3L)
}
local_res <- local_(set, reset)
local({
local_res()
res <<- c(res, 2L)
})
expect_equal(res, 1L:3L)
})
test_that("local_path works and resets path", {
current <- normalizePath(get_path(), mustWork = FALSE)
new_path <- normalizePath(".")
local({
local_path(new_path)
expect_equal(normalizePath(new_path), head(get_path(), n = 1))
expect_equal(length(get_path()), length(current) + 1L)
})
expect_equal(current, get_path())
})
test_that("local_path with suffix action works and resets path", {
current <- normalizePath(get_path(), mustWork = FALSE)
new_path <- normalizePath(".")
local({
local_path(new_path, action = "suffix")
expect_equal(normalizePath(new_path), tail(get_path(), n = 1))
expect_equal(length(get_path()), length(current) + 1L)
})
expect_equal(current, get_path())
})
test_that("local_path with replace action works and resets path", {
current <- normalizePath(get_path(), mustWork = FALSE)
new_path <- normalizePath(".")
local({
local_path(new_path, action = "replace")
expect_equal(normalizePath(new_path), get_path())
expect_equal(length(get_path()), 1L)
})
expect_equal(current, get_path())
})
test_that("local_libpaths works and resets library", {
lib <- .libPaths()
new_lib <- "."
local({
local_libpaths(new_lib)
expect_equal(normalizePath(new_lib), normalizePath(.libPaths()[[1L]], mustWork = FALSE))
})
expect_equal(lib, .libPaths())
})
test_that("local_locale works and resets locales", {
current <- Sys.getlocale("LC_CTYPE")
new <- "C"
local({
local_locale(c(LC_CTYPE = new))
expect_equal(new, Sys.getlocale("LC_CTYPE"))
})
expect_equal(current, Sys.getlocale("LC_CTYPE"))
})
test_that("local_locale fails with LC_ALL", {
local({
expect_error(local_locale(c(LC_ALL = "C")), "LC_ALL")
})
})
test_that("local_collate works and resets collate", {
current <- Sys.getlocale("LC_COLLATE")
new <- "C"
local({
local_collate(new)
expect_equal(new, Sys.getlocale("LC_COLLATE"))
})
expect_equal(current, Sys.getlocale("LC_COLLATE"))
})
test_that("local_makevars works and resets the Makevars file", {
current <- tempfile()
writeLines(con = current, c("CFLAGS=-03"), sep = "\n")
new <- c(CFLAGS = "-O0")
local({
local_makevars(new, path = current)
expect_equal("CFLAGS=-O0", readLines(Sys.getenv("R_MAKEVARS_USER")))
})
expect_equal("CFLAGS=-03", readLines(current))
})
test_that("local_makevars changes only the defined variables", {
current_name <- tempfile()
current <- c("CFLAGS=-03", "LDFLAGS=-lz")
writeLines(con = current_name, current, sep = "\n")
new <- c(CFLAGS = "-O0")
local({
local_makevars(new, path = current_name)
expect_equal(c("CFLAGS=-O0", "LDFLAGS=-lz"), readLines(Sys.getenv("R_MAKEVARS_USER")))
})
expect_equal(current, readLines(current_name))
})
test_that("local_makevars works with alternative assignments", {
current <- tempfile()
writeLines(con = current, c("CFLAGS=-03"), sep = "\n")
new <- c(CFLAGS = "-O0")
local({
local_makevars(new, path = current, assignment = "+=")
expect_equal("CFLAGS+=-O0", readLines(Sys.getenv("R_MAKEVARS_USER")))
})
expect_equal("CFLAGS=-03", readLines(current))
})
test_that("local_dir works as expected", {
old <- normalizePath(getwd())
local({
local_dir("..")
expect_equal(normalizePath(getwd()), normalizePath(file.path(old, "..")))
})
expect_equal(normalizePath(getwd()), normalizePath(old))
})
test_that("local_par works as expected", {
tmp <- tempfile()
pdf(tmp)
on.exit(unlink(tmp), add = TRUE)
old <- par("pty")
local({
local_par(list(pty = "s"))
expect_equal(par("pty"), "s")
})
expect_equal(par("pty"), old)
dev.off()
})
withr/tests/testthat/test-devices.R 0000644 0001762 0000144 00000004444 13176341636 017153 0 ustar ligges users context("devices")
test_that("with_*device* functions create a plot file", {
# A plot
p <- lattice::xyplot(y ~ x, data.frame(x = -2:2, y = dnorm(-2:2)))
# A directory to store the plots
plot_dir <- tempfile("withr-test-plots-")
dir.create(plot_dir)
fn_names <- c("with_bmp", "with_cairo_pdf", "with_cairo_ps", "with_jpeg",
"with_pdf", "with_png", "with_svg", "with_tiff", "with_xfig")
fns <- mget(fn_names, envir = asNamespace("withr"))
extensions <- c("bmp", "pdf", "ps", "jpg", "pdf", "png", "svg", "tiff", "xfig")
for (i in seq_along(fns)) {
filename <- file.path(plot_dir, paste0("test-", fn_names[i], ".", extensions[i]))
info <- paste0("function = ", fn_names[i], "; filename = ", filename)
if (fn_names[i] == "with_xfig") {
# grDevices::xfig weirdly gives a warning with the default inputs
expect_warning(
fns[[i]](filename, print(p)),
"will only return the last plot"
)
} else {
expect_silent(fns[[i]](filename, print(p)))
}
expect_true(file.exists(filename), info = info)
expect_gt(file.info(filename)$size, 0, label = info)
}
unlink(plot_dir)
})
test_that("local_device functions create a plot file", {
# A plot
p <- lattice::xyplot(y ~ x, data.frame(x = -2:2, y = dnorm(-2:2)))
# A directory to store the plots
plot_dir <- tempfile("withr-test-plots-local-")
dir.create(plot_dir)
fn_names <- c("local_bmp", "local_cairo_pdf", "local_cairo_ps", "local_jpeg",
"local_pdf", "local_png", "local_svg", "local_tiff", "local_xfig")
fns <- mget(fn_names, envir = asNamespace("withr"))
extensions <- c("bmp", "pdf", "ps", "jpg", "pdf", "png", "svg", "tiff", "xfig")
for (i in seq_along(fns)) {
filename <- file.path(plot_dir, paste0("test-", fn_names[i], ".", extensions[i]))
info <- paste0("function = ", fn_names[i], "; filename = ", filename)
(function(i) {
if (fn_names[i] == "local_xfig") {
# grDevices::xfig weirdly gives a warning with the default inputs
expect_warning(
fns[[i]](filename),
"will only return the last plot")
} else {
expect_silent(fns[[i]](filename))
}
print(p)
})(i)
expect_true(file.exists(filename), info = info)
expect_gt(file.info(filename)$size, 0, label = info)
}
unlink(plot_dir)
})
withr/tests/testthat/test-wrap.R 0000644 0001762 0000144 00000000324 13011171152 016451 0 ustar ligges users context("wrap")
test_that("wrap works", {
v <- c(0, 0, 0)
set <- function(x) v[2] <<- x
f <- wrap(set, v[1] <<- v[1] + 1, v[3] <<- v[3] + 3)
expect_equal(v, c(0, 0, 0))
f(2)
expect_equal(v, 1:3)
})
withr/tests/testthat/test-sink.R 0000644 0001762 0000144 00000001642 13216216054 016460 0 ustar ligges users context("With sink")
test_that("with_output_sink works as expected", {
tmp <- tempfile()
on.exit(unlink(tmp), add = TRUE)
tmp2 <- tempfile()
on.exit(unlink(tmp2), add = TRUE)
tmp3 <- tempfile()
on.exit(unlink(tmp3), add = TRUE)
expect_identical(sink.number(), 0L)
with_output_sink(tmp, {
expect_identical(sink.number(), 1L)
cat("output\n")
})
expect_identical(readLines(tmp), "output")
expect_identical(sink.number(), 0L)
with_output_sink(tmp, append = TRUE, {
expect_identical(sink.number(), 1L)
cat("output 2\n")
})
expect_identical(readLines(tmp), c("output", "output 2"))
expect_identical(sink.number(), 0L)
expect_warning(
with_output_sink(tmp, {
sink()
}),
"already removed"
)
expect_identical(sink.number(), 0L)
expect_error(
with_output_sink(NULL, {
NULL
}),
"cannot be NULL"
)
expect_identical(sink.number(), 0L)
})
withr/tests/testthat/test-with.R 0000644 0001762 0000144 00000016504 13252301176 016472 0 ustar ligges users context("With")
test_that("with_envvar sets and unsets variables", {
# Make sure the "set_env_testvar" environment var is not set.
Sys.unsetenv("set_env_testvar")
expect_false("set_env_testvar" %in% names(Sys.getenv()))
# Use with_envvar (which calls set_envvar) to temporarily set it to 1
expect_identical("1", with_envvar(c("set_env_testvar" = 1),
Sys.getenv("set_env_testvar")))
# set_env_testvar shouldn't stay in the list of environment vars
expect_false("set_env_testvar" %in% names(Sys.getenv()))
})
test_that("with_envar respects suffix and prefix", {
nested <- function(op1, op2) {
with_envvar(c(A = 1), action = op1,
with_envvar(c(A = 2), action = op2,
Sys.getenv("A")[[1]]
)
)
}
expect_equal(nested("replace", "suffix"), c("1 2"))
expect_equal(nested("replace", "prefix"), c("2 1"))
expect_equal(nested("prefix", "suffix"), c("1 2"))
expect_equal(nested("prefix", "prefix"), c("2 1"))
expect_equal(nested("suffix", "suffix"), c("1 2"))
expect_equal(nested("suffix", "prefix"), c("2 1"))
})
test_that("with_options works", {
expect_false(identical(getOption("scipen"), 999))
expect_equal(with_options(c(scipen=999), getOption("scipen")), 999)
expect_false(identical(getOption("scipen"), 999))
expect_false(identical(getOption("zyxxyzyx"), "qwrbbl"))
expect_equal(with_options(c(zyxxyzyx="qwrbbl"), getOption("zyxxyzyx")), "qwrbbl")
expect_false(identical(getOption("zyxxyzyx"), "qwrbbl"))
})
test_that("with_libpaths works and resets library", {
lib <- .libPaths()
new_lib <- "."
with_libpaths(
new_lib,
{
expect_equal(normalizePath(new_lib), normalizePath(.libPaths()[[1L]]))
}
)
expect_equal(lib, .libPaths())
})
test_that("with_temp_libpaths works and resets library", {
lib <- .libPaths()
with_temp_libpaths(
expect_equal(.libPaths()[-1], lib)
)
expect_equal(lib, .libPaths())
})
test_that("with_temp_libpaths has an action argument", {
lib <- .libPaths()
with_temp_libpaths(
action = "suffix",
expect_equal(.libPaths()[-length(.libPaths())], lib)
)
expect_equal(lib, .libPaths())
})
test_that("with_ works", {
res <- NULL
set <- function(new) {
res <<- c(res, 1L)
}
reset <- function(old) {
res <<- c(res, 3L)
}
with_res <- with_(set, reset)
with_res(NULL, res <- c(res, 2L))
expect_equal(res, 1L:3L)
})
test_that("with_ works on functions without arguments", {
res <- NULL
set <- function() {
res <<- c(res, 1L)
}
reset <- function(x) {
res <<- c(res, 3L)
}
with_res <- with_(set, reset)
with_res(res <- c(res, 2L))
expect_equal(res, 1L:3L)
})
test_that("with_path works and resets path", {
current <- normalizePath(get_path(), mustWork = FALSE)
new_path <- normalizePath(".")
with_path(
new_path,
{
expect_equal(normalizePath(new_path), head(get_path(), n = 1))
expect_equal(length(get_path()), length(current) + 1L)
}
)
expect_equal(current, get_path())
})
test_that("with_path with suffix action works and resets path", {
current <- normalizePath(get_path(), mustWork = FALSE)
new_path <- normalizePath(".")
with_path(
new_path,
action = "suffix",
{
expect_equal(normalizePath(new_path), tail(get_path(), n = 1))
expect_equal(length(get_path()), length(current) + 1L)
}
)
expect_equal(current, get_path())
})
test_that("with_path with replace action works and resets path", {
current <- normalizePath(get_path(), mustWork = FALSE)
new_path <- normalizePath(".")
with_path(
new_path,
action = "replace",
{
expect_equal(normalizePath(new_path), get_path())
expect_equal(length(get_path()), 1L)
}
)
expect_equal(current, get_path())
})
test_that("with_libpaths works and resets library", {
lib <- .libPaths()
new_lib <- "."
with_libpaths(
new_lib,
{
expect_equal(normalizePath(new_lib), normalizePath(.libPaths()[[1L]]))
}
)
expect_equal(lib, .libPaths())
})
test_that("with_locale works and resets locales", {
current <- Sys.getlocale("LC_CTYPE")
new <- "C"
with_locale(
c(LC_CTYPE = new),
{
expect_equal(new, Sys.getlocale("LC_CTYPE"))
}
)
expect_equal(current, Sys.getlocale("LC_CTYPE"))
})
test_that("with_locale fails with LC_ALL", {
expect_error(with_locale(c(LC_ALL = "C"), NULL), "LC_ALL")
})
test_that("with_collate works and resets collate", {
current <- Sys.getlocale("LC_COLLATE")
new <- "C"
with_collate(
new,
{
expect_equal(new, Sys.getlocale("LC_COLLATE"))
}
)
expect_equal(current, Sys.getlocale("LC_COLLATE"))
})
test_that("with_makevars works and resets the Makevars file", {
current <- tempfile()
writeLines(con = current, c("CFLAGS=-03"), sep = "\n")
new <- c(CFLAGS = "-O0")
with_makevars(
new, path = current,
{
expect_equal("CFLAGS=-O0", readLines(Sys.getenv("R_MAKEVARS_USER")))
}
)
expect_equal("CFLAGS=-03", readLines(current))
})
test_that("with_makevars changes only the defined variables", {
current_name <- tempfile()
current <- c("CFLAGS=-03", "LDFLAGS=-lz")
writeLines(con = current_name, current, sep = "\n")
new <- c(CFLAGS = "-O0")
with_makevars(
new, path = current_name,
{
expect_equal(c("CFLAGS=-O0", "LDFLAGS=-lz"), readLines(Sys.getenv("R_MAKEVARS_USER")))
}
)
expect_equal(current, readLines(current_name))
})
test_that("with_makevars works with alternative assignments", {
current <- tempfile()
writeLines(con = current, c("CFLAGS=-03"), sep = "\n")
new <- c(CFLAGS = "-O0")
with_makevars(
new, path = current, assignment = "+=",
{
expect_equal("CFLAGS+=-O0", readLines(Sys.getenv("R_MAKEVARS_USER")))
}
)
expect_equal("CFLAGS=-03", readLines(current))
})
test_that("set_makevars works as expected", {
expect_equal(set_makevars(character(0)), NULL)
tmp_old <- tempfile()
tmp_new <- tempfile()
# empty old file
set_makevars(c(CFLAGS = "-O3"), tmp_old, tmp_new)
expect_equal(readLines(tmp_new), c("CFLAGS=-O3"))
# non-empty old file without new field
writeLines(con=tmp_old, c("LDFLAGS=-lz"))
set_makevars(c(CFLAGS = "-O3"), tmp_old, tmp_new)
expect_equal(readLines(tmp_new), c("LDFLAGS=-lz", "CFLAGS=-O3"))
# non-empty old file without multiple field definitions (error)
writeLines(con=tmp_old, c("CFLAGS=-O0", "CFLAGS=-O1"))
expect_error(set_makevars(c(CFLAGS = "-O3"), tmp_old, tmp_new))
unlink(tmp_old)
unlink(tmp_new)
})
test_that("with_dir works as expected", {
old <- normalizePath(getwd())
with_dir("..", {
expect_equal(normalizePath(getwd()), normalizePath(file.path(old, "..")))
})
expect_equal(normalizePath(getwd()), normalizePath(old))
})
test_that("with_par works as expected", {
tmp <- tempfile()
pdf(tmp)
on.exit(unlink(tmp), add = TRUE)
old <- par("pty")
with_par(list(pty = "s"), {
expect_equal(par("pty"), "s")
})
expect_equal(par("pty"), old)
dev.off()
})
test_that("with_seed works as expected", {
expect_identical(
with_preserve_seed(runif(10L)),
runif(10L))
expect_identical(
with_preserve_seed(runif(10L)),
with_preserve_seed(runif(10L)))
expect_identical(
with_seed(1L, runif(10L)),
with_seed(1L, runif(10L)))
expect_false(with_seed(1L, runif(1L)) == runif(1L))
expect_false(with_seed(sample.int(.Machine$integer.max, 1), runif(1L)) ==
with_seed(sample.int(.Machine$integer.max, 1), runif(1L)))
})
withr/tests/testthat/test-db.R 0000644 0001762 0000144 00000004470 13171222334 016101 0 ustar ligges users context("db")
describe("with_db_connection", {
#it("errors if connection is not named", {
#expect_error({
#with_db_connection(list(TRUE), TRUE)
#}, "all(is.named(con)) is not TRUE", fixed = TRUE)
#})
#it("errors if connection is not a DBI connection", {
#expect_error({
#with_db_connection(list(con = TRUE), TRUE)
#}, "all(vlapply(con, methods::is, \"DBIConnection\")) is not TRUE", fixed = TRUE)
#})
it("creates a single connection", {
db <- tempfile()
on.exit(unlink(db))
expect_false(exists("con"))
with_db_connection(
list(con = DBI::dbConnect(RSQLite::SQLite(), db)), {
DBI::dbWriteTable(con, "test", data.frame(a = 1:2, b = 3:4))
})
expect_false(exists("con"))
con2 <- DBI::dbConnect(RSQLite::SQLite(), db)
on.exit(DBI::dbDisconnect(con2), add = TRUE)
expect_equal(DBI::dbReadTable(con2, "test"), data.frame(a = 1:2, b = 3:4))
})
it("creates multiple connections", {
db <- tempfile()
db2 <- tempfile()
on.exit(unlink(c(db, db2)))
expect_false(exists("con"))
expect_false(exists("con2"))
with_db_connection(
list(con = DBI::dbConnect(RSQLite::SQLite(), db),
con2 = DBI::dbConnect(RSQLite::SQLite(), db2)), {
DBI::dbWriteTable(con, "test", data.frame(a = 1:2, b = 3:4))
DBI::dbWriteTable(con2, "test", data.frame(c = 5:6, d = 7:8))
})
expect_false(exists("con"))
expect_false(exists("con2"))
con3 <- DBI::dbConnect(RSQLite::SQLite(), db)
con4 <- DBI::dbConnect(RSQLite::SQLite(), db2)
on.exit({
DBI::dbDisconnect(con3)
DBI::dbDisconnect(con4)
}, add = TRUE)
expect_equal(DBI::dbReadTable(con3, "test"), data.frame(a = 1:2, b = 3:4))
expect_equal(DBI::dbReadTable(con4, "test"), data.frame(c = 5:6, d = 7:8))
})
})
describe("local_db_connection", {
it("creates a single connection", {
db <- tempfile()
on.exit(unlink(db))
expect_false(exists("con"))
(function() {
con <- local_db_connection(DBI::dbConnect(RSQLite::SQLite(), db))
DBI::dbWriteTable(con, "test", data.frame(a = 1:2, b = 3:4))
})()
expect_false(exists("con"))
con2 <- DBI::dbConnect(RSQLite::SQLite(), db)
on.exit(DBI::dbDisconnect(con2), add = TRUE)
expect_equal(DBI::dbReadTable(con2, "test"), data.frame(a = 1:2, b = 3:4))
})
})
withr/tests/testthat/test-defer.R 0000644 0001762 0000144 00000000572 13152261106 016577 0 ustar ligges users context("defer")
test_that("defer_parent works", {
local_file <- function(path) {
file.create(path)
defer_parent(unlink(path))
}
# create tempfile path
path <- tempfile()
# use 'local_file' in a function
local({
local_file(path)
stopifnot(file.exists(path))
})
# file is deleted as we leave 'local' scope
expect_false(file.exists(path))
})
withr/tests/testthat/test-file.R 0000644 0001762 0000144 00000003446 13177065114 016444 0 ustar ligges users context("file")
describe("with_file", {
it("can use unnamed arguments", {
with_file("file1", {
writeLines("foo", "file1")
expect_equal(readLines("file1"), "foo")
with_file("file2", {
writeLines("bar", "file2")
expect_equal(readLines("file1"), "foo")
expect_equal(readLines("file2"), "bar")
})
expect_false(file.exists("file2"))
})
expect_false(file.exists("file1"))
})
it("can use named arguments", {
with_file(list("file1" = writeLines("foo", "file1")), {
expect_equal(readLines("file1"), "foo")
with_file(list("file2" = writeLines("bar", "file2")), {
expect_equal(readLines("file1"), "foo")
expect_equal(readLines("file2"), "bar")
})
expect_false(file.exists("file2"))
})
expect_false(file.exists("file1"))
})
it("works with multiple files", {
with_file(
list("file1" = writeLines("foo", "file1"),
"file2",
"file3" = writeLines("baz", "file3")), {
writeLines("bar", "file2")
expect_equal(readLines("file1"), "foo")
expect_equal(readLines("file2"), "bar")
expect_equal(readLines("file3"), "baz")
})
expect_false(file.exists("file1"))
expect_false(file.exists("file2"))
expect_false(file.exists("file3"))
})
})
describe("local_file", {
it("works with unnamed arguments", {
f <- function() {
local_file("file1")
writeLines("foo", "file1")
expect_equal(readLines("file1"), "foo")
}
expect_no_output(f())
expect_false(file.exists("file1"))
})
it("works with named arguments", {
f <- function() {
local_file(list("file1" = writeLines("foo", "file1")))
expect_equal(readLines("file1"), "foo")
}
expect_no_output(f())
expect_false(file.exists("file1"))
})
})
withr/tests/testthat/helper.R 0000644 0001762 0000144 00000000122 13177062746 016023 0 ustar ligges users expect_no_output <- function(...) {
testthat::expect_output(..., regexp = NA)
}
withr/tests/testthat/test-namespace.R 0000644 0001762 0000144 00000004725 13176341636 017467 0 ustar ligges users context("namespace")
test_that("with_package works", {
# tools package not attached to the search path
expect_false("package:tools" %in% search())
with_package("tools",
# SIGINT is an exported object in tools
expect_equal(SIGINT, 2))
# tools package still not attached to the search path
expect_false("package:tools" %in% search())
})
test_that("local_package works", {
# tools package not attached to the search path
expect_false("package:tools" %in% search())
f <- function() {
local_package("tools")
# SIGINT is an exported object in tools
expect_equal(SIGINT, 2)
}
f()
# tools package still not attached to the search path
expect_false("package:tools" %in% search())
})
test_that("with_namespace works", {
# tools package not attached to the search path
expect_false("" %in% search())
with_namespace("tools", {
expect_true("" %in% search())
# .check_packages is a non-exported object in tools
expect_true(is.function(.check_packages))
})
# tools namespace still not attached to the search path
expect_false("" %in% search())
})
test_that("local_namespace works", {
# tools package not attached to the search path
expect_false("" %in% search())
f <- function() {
local_namespace("tools")
expect_true("" %in% search())
# .check_packages is a non-exported object in tools
expect_true(is.function(.check_packages))
}
f()
# tools namespace still not attached to the search path
expect_false("" %in% search())
})
test_that("with_environment works", {
e <- new.env()
e$a <- 1
# environment not attached to the search path
expect_false(format(e) %in% search())
with_environment(e, {
# environment attached to the search path
expect_true(format(e) %in% search())
expect_equal(a, 1)
})
# environment not attached to the search path
expect_false(format(e) %in% search())
})
test_that("local_environment works", {
e <- new.env()
e$a <- 1
# environment not attached to the search path
expect_false(format(e) %in% search())
f <- function() {
local_environment(e)
# environment attached to the search path
expect_true(format(e) %in% search())
expect_equal(a, 1)
}
f()
# environment not attached to the search path
expect_false(format(e) %in% search())
})
withr/NAMESPACE 0000644 0001762 0000144 00000002647 13252301176 012637 0 ustar ligges users # Generated by roxygen2: do not edit by hand
export(defer)
export(defer_parent)
export(local_)
export(local_bmp)
export(local_cairo_pdf)
export(local_cairo_ps)
export(local_collate)
export(local_connection)
export(local_db_connection)
export(local_dir)
export(local_environment)
export(local_envvar)
export(local_file)
export(local_jpeg)
export(local_libpaths)
export(local_locale)
export(local_message_sink)
export(local_namespace)
export(local_options)
export(local_output_sink)
export(local_package)
export(local_par)
export(local_path)
export(local_pdf)
export(local_png)
export(local_postscript)
export(local_svg)
export(local_temp_libpaths)
export(local_tempfile)
export(local_tiff)
export(local_xfig)
export(set_makevars)
export(with_)
export(with_bmp)
export(with_cairo_pdf)
export(with_cairo_ps)
export(with_collate)
export(with_connection)
export(with_db_connection)
export(with_dir)
export(with_environment)
export(with_envvar)
export(with_file)
export(with_jpeg)
export(with_libpaths)
export(with_locale)
export(with_makevars)
export(with_message_sink)
export(with_namespace)
export(with_options)
export(with_output_sink)
export(with_package)
export(with_par)
export(with_path)
export(with_pdf)
export(with_png)
export(with_postscript)
export(with_preserve_seed)
export(with_seed)
export(with_svg)
export(with_temp_libpaths)
export(with_tempfile)
export(with_tiff)
export(with_xfig)
importFrom(stats,runif)
importFrom(stats,setNames)
withr/NEWS.md 0000644 0001762 0000144 00000002735 13252475431 012522 0 ustar ligges users # withr 2.1.2
- `set_makevars()` is now exported (#68, @gaborcsardi).
- `with_temp_libpaths()` gains an `action` argument, to specify how the
temporary library path will be added (#66, @krlmlr).
# withr 2.1.1
- Fixes test failures with testthat 2.0.0
- `with_file()` function to automatically remove files.
# withr 2.1.0
- `with_connection()` function to automatically close R file connections.
- `with_db_connection()` function to automatically disconnect from DBI database
connections.
- `with_gctorture2` command to run code with gctorture2, useful for testing
(#47).
- `with_package()`, `with_namespace()` and `with_environment()` (and equivalent
locals) functions added, to run code with a modified object search path (#38,
#48).
- Add `with_tempfile()` and `local_tempfile()` functions to create temporary
files which are cleanup up afterwards. (#32)
- Remove the `code` argument from `local_` functions (#50).
# withr 2.0.0
- Each `with_` function now has a `local_` variant, which reset at the end of
their local scope, generally at the end of the function body.
- New functions `with_seed()` and `with_preserve_seed()` for running code with
a given random seed (#45, @krlmlr).
# withr 1.0.2
- `with_makevars()` gains an `assignment` argument to allow specifying
additional assignment types.
# withr 1.0.1
- Relaxed R version requirement to 3.0.2 (#35, #39).
- New `with_output_sink()` and `with_message_sink()` (#24).
# withr 1.0.0
- First Public Release
withr/R/ 0000755 0001762 0000144 00000000000 13252476111 011612 5 ustar ligges users withr/R/db.R 0000644 0001762 0000144 00000003036 13171222334 012320 0 ustar ligges users #' DBMS Connections which disconnect themselves.
#'
#' Connections to Database Management Systems which automatically disconnect. In
#' particular connections which are created with `DBI::dbConnect()` and closed
#' with `DBI::dbDisconnect()`.
#'
#' @template with
#' @param con For `with_db_connection()` a named list with the connection(s) to
#' create. For `local_db_connection()` the code to create a single connection,
#' which is then returned.
#' @param .local_envir `[environment]`\cr The environment to use for scoping.
#' @importFrom stats setNames
#' @examples
#' db <- tempfile()
#' with_db_connection(
#' list(con = DBI::dbConnect(RSQLite::SQLite(), db)), {
#' DBI::dbWriteTable(con, "mtcars", mtcars)
#' })
#'
#' head_db_table <- function(...) {
#' con <- local_db_connection(DBI::dbConnect(RSQLite::SQLite(), db))
#' head(DBI::dbReadTable(con, "mtcars"), ...)
#' }
#' head_db_table()
#' unlink(db)
#' @export
with_db_connection <- function(con, code) {
requireNamespace("DBI")
stopifnot(all(is.named(con)))
stopifnot(all(vlapply(con, methods::is, "DBIConnection")))
nme <- tempfile()
(get("attach", baseenv()))(con, name = nme, warn.conflicts = FALSE)
on.exit({
for (connection in con) DBI::dbDisconnect(connection)
detach(nme, character.only = TRUE)
})
force(code)
}
#' @rdname with_db_connection
#' @export
local_db_connection <- function(con, .local_envir = parent.frame()) {
requireNamespace("DBI")
stopifnot(methods::is(con, "DBIConnection"))
defer(DBI::dbDisconnect(con), envir = .local_envir)
con
}
withr/R/locale.R 0000644 0001762 0000144 00000001402 13134200551 013161 0 ustar ligges users # locale ---------------------------------------------------------------------
set_locale <- function(cats) {
stopifnot(is.named(cats), is.character(cats))
if ("LC_ALL" %in% names(cats)) {
stop("Setting LC_ALL category not implemented.", call. = FALSE)
}
old <- vapply(names(cats), Sys.getlocale, character(1))
mapply(Sys.setlocale, names(cats), cats)
invisible(old)
}
#' Locale settings
#'
#' Temporarily change locale settings.
#'
#' Setting the `LC_ALL` category is currently not implemented.
#'
#' @template with
#' @param new `[named character]`\cr New locale settings
#' @inheritParams with_collate
#' @seealso [Sys.setlocale()]
#' @export
with_locale <- with_(set_locale)
#' @rdname with_locale
#' @export
local_locale <- local_(set_locale)
withr/R/sink.R 0000644 0001762 0000144 00000005217 13134200551 012676 0 ustar ligges users # sink -----------------------------------------------------------------------
# FIXME: Use (a better version of) pryr:::partial2 when available
output_sink <- function(file = NULL, append = FALSE, split = FALSE) {
sink(file = file, append = append, type = "output", split = split)
}
message_sink <- function(file = NULL, append = FALSE) {
sink(file = file, append = append, type = "message", split = FALSE)
}
#' @include wrap.R
set_output_sink <- wrap(
output_sink,
if (is.null(file)) {
stop("file cannot be NULL", call. = FALSE)
},
list(n = sink.number()))
set_message_sink <- wrap(
message_sink,
{
if (is.null(file)) {
stop("file cannot be NULL,", call. = FALSE)
}
if (sink.number(type = "message") != 2L) {
stop("Cannot establish message sink when another sink is active.",
call. = FALSE)
}
con <- if (is.character(file)) {
file <- file(file, if (append) "a" else "w")
}
},
{
list(n = sink.number(type = "message"), con = con)
})
reset_output_sink <- function(sink_info) {
repeat {
n <- sink.number()
delta <- n - sink_info$n
if (delta >= 0L) {
sink()
if (delta > 0L) {
warning("Removing a different sink.", call. = FALSE)
} else {
return()
}
} else {
warning("Sink #", sink_info$n, " already removed.", call. = FALSE)
return()
}
}
}
reset_message_sink <- function(sink_info) {
if (!is.null(sink_info$con)) {
on.exit(close(sink_info$con), add = TRUE)
}
do_reset_message_sink(sink_info)
}
do_reset_message_sink <- function(sink_info) {
n <- sink.number(type = "message")
if (n == 2L) {
warning("No message sink to remove.", call. = FALSE)
} else if (n == sink_info$n) {
sink(type = "message")
} else {
warning("Not removing a different message sink.", call. = FALSE)
}
}
#' Output redirection
#'
#' Temporarily divert output to a file via [sink()]. For
#' sinks of type `message`, an error is raised if such a sink is already
#' active.
#'
#' @template with
#' @param new `[character(1)|connection]`\cr
#' A writable \link{connection} or a character string naming the file to write
#' to. Passing `NULL` will throw an error.
#' @inheritParams base::sink
#' @inheritParams with_collate
#' @seealso [sink()]
#' @export
#' @name with_sink
with_output_sink <- with_(set_output_sink, reset_output_sink)
#' @rdname with_sink
#' @export
local_output_sink <- local_(set_output_sink, reset_output_sink)
#' @rdname with_sink
#' @export
with_message_sink <- with_(set_message_sink, reset_message_sink)
#' @rdname with_sink
#' @export
local_message_sink <- local_(set_message_sink, reset_message_sink)
withr/R/connection.R 0000644 0001762 0000144 00000002047 13177062566 014112 0 ustar ligges users #' Connections which close themselves
#'
#' R file connections which are automatically closed.
#'
#' @template with
#' @param con For `with_connection()` a named list with the connection(s) to
#' create. For `local_connection()` the code to create a single connection,
#' which is then returned.
#' @param .local_envir `[environment]`\cr The environment to use for scoping.
#' @importFrom stats setNames
#' @examples
#' with_connection(list(con = file("foo", "w")), {
#' writeLines(c("foo", "bar"), con)
#' })
#'
#' read_foo <- function() {
#' readLines(local_connection(file("foo", "r")))
#' }
#' read_foo()
#' @export
with_connection <- function(con, code) {
stopifnot(all(is.named(con)))
nme <- tempfile()
(get("attach", baseenv()))(con, name = nme, warn.conflicts = FALSE)
on.exit({
for (connection in con) close(connection)
detach(nme, character.only = TRUE)
})
force(code)
}
#' @rdname with_connection
#' @export
local_connection <- function(con, .local_envir = parent.frame()) {
defer(close(con), envir = .local_envir)
con
}
withr/R/utils.R 0000644 0001762 0000144 00000000452 13177060742 013103 0 ustar ligges users make_call <- function(...) {
as.call(list(...))
}
vlapply <- function(X, FUN, ..., FUN.VALUE = logical(1)) {
vapply(X, FUN, ..., FUN.VALUE = FUN.VALUE)
}
names2 <- function(x) {
nms <- names(x)
if (is.null(nms)) {
rep("", length(x))
} else {
nms[is.na(nms)] <- ""
nms
}
}
withr/R/tempfile.R 0000644 0001762 0000144 00000002001 13177066010 013532 0 ustar ligges users #' Temporary files
#'
#' Temporarily create a tempfile, which is automatically removed afterwards.
#' @template with
#' @param new `[character vector]`\cr Names of temporary file handles to create.
#' @param envir `[environment]`\cr Environment in which to define the temporary files.
#' @inheritParams base::tempfile
#' @export
with_tempfile <- function(new, code, envir = parent.frame(),
pattern = "file", tmpdir = tempdir(), fileext = "") {
env <- new.env(parent = envir)
for (f in new) {
assign(f,
tempfile(pattern = pattern, tmpdir = tmpdir, fileext = fileext),
envir = env)
}
on.exit(unlink(mget(new, envir = env)))
eval(substitute(code), envir = env)
}
#' @rdname with_tempfile
#' @export
local_tempfile <- function(new, envir = parent.frame(),
pattern = "file", tmpdir = tempdir(), fileext = "") {
for (f in new) {
assign(f,
tempfile(pattern = pattern, tmpdir = tmpdir, fileext = fileext),
envir = envir)
}
defer(unlink(mget(new, envir = envir)), envir = envir)
}
withr/R/with_.R 0000644 0001762 0000144 00000006522 13252301176 013052 0 ustar ligges users #' @include local_.R
NULL
#' Create a new "with" or "local" function
#'
#' These are constructors for `with_...` or `local_...` functions.
#' They are only needed if you want to alter some global state which is not
#' covered by the existing `with_...` functions, see \link{withr-package}
#' for an overview.
#'
#' The `with_...` functions reset the state immediately after the
#' `code` argument has been evaluated. The `local_...` functions
#' reset their arguments after they go out of scope, usually at the end of the
#' function body.
#'
#' @param set `[function(...)]`\cr Function used to set the state.
#' The function can have arbitrarily many arguments, they will be replicated
#' in the formals of the returned function.
#' @param reset `[function(x)]`\cr Function used to reset the state.
#' The first argument can be named arbitrarily, further arguments with default
#' values, or a "dots" argument, are supported but not used: The function will
#' be called as `reset(old)`.
#' @param envir `[environment]`\cr Environment of the returned function.
#' @param new `[logical(1)]`\cr Replace the first argument of the `set` function
#' by `new`? Set to `FALSE` if the `set` function only has optional arguments.
#' @return `[function(new, code, ...)]` A function with at least two arguments,
#' \itemize{
#' \item `new`: New state to use
#' \item `code`: Code to run in that state.
#' }
#' If there are more arguments to the function passed in `set` they are
#' added to the returned function. If `set` does not have arguments,
#' or `new` is `FALSE`, the returned function does not have a `code` argument.
#' @keywords internal
#' @examples
#' with_(setwd)
#'
#' global_stack <- list()
#' set_global_state <- function(state, msg = "Changing global state.") {
#' global_stack <- c(list(state), global_stack)
#' message(msg)
#' state
#' }
#' reset_global_state <- function(state) {
#' old_state <- global_stack[[1]]
#' global_stack <- global_stack[-1]
#' stopifnot(identical(state, old_state))
#' }
#' with_(set_global_state, reset_global_state)
#' @export
with_ <- function(set, reset = set, envir = parent.frame(), new = TRUE) {
fmls <- formals(set)
if (length(fmls) > 0L) {
# called pass all extra formals on
called_fmls <- stats::setNames(lapply(names(fmls), as.symbol), names(fmls))
if (new) {
# rename first formal to new
called_fmls[[1]] <- as.symbol("new")
fun_args <- c(alist(new =, code =), fmls[-1L])
} else {
fun_args <- c(alist(code =), fmls)
}
} else {
# no formals -- only have code
called_fmls <- NULL
fun_args <- alist(code =)
}
set_call <- as.call(c(substitute(set), called_fmls))
fun <- eval(bquote(function(args) {
old <- .(set_call)
on.exit(.(reset)(old))
force(code)
}, as.environment(list(set_call = set_call,
reset = if (missing(reset)) substitute(set) else substitute(reset)))))
# substitute does not work on arguments, so we need to fix them manually
formals(fun) <- fun_args
environment(fun) <- envir
fun
}
merge_new <- function(old, new, action, merge_fun = c) {
action <- match.arg(action, c("replace", "prefix", "suffix"))
if (action == "suffix") {
new <- merge_fun(old, new)
} else if (action == "prefix") {
new <- merge_fun(new, old)
}
new
}
is.named <- function(x) {
!is.null(names(x)) && all(names(x) != "")
}
withr/R/env.R 0000644 0001762 0000144 00000002727 13134200551 012525 0 ustar ligges users # env ------------------------------------------------------------------------
set_envvar <- function(envs, action = "replace") {
if (length(envs) == 0) return()
stopifnot(is.named(envs))
stopifnot(is.character(action), length(action) == 1)
action <- match.arg(action, c("replace", "prefix", "suffix"))
# if there are duplicated entries keep only the last one
envs <- envs[!duplicated(names(envs), fromLast = TRUE)]
old <- Sys.getenv(names(envs), names = TRUE, unset = NA)
set <- !is.na(envs)
both_set <- set & !is.na(old)
if (any(both_set)) {
if (action == "prefix") {
envs[both_set] <- paste(envs[both_set], old[both_set])
} else if (action == "suffix") {
envs[both_set] <- paste(old[both_set], envs[both_set])
}
}
if (any(set)) do.call("Sys.setenv", as.list(envs[set]))
if (any(!set)) Sys.unsetenv(names(envs)[!set])
invisible(old)
}
#' Environment variables
#'
#' Temporarily change system environment variables.
#'
#' @template with
#' @param new `[named character]`\cr New environment variables
#' @param action should new values `"replace"`, `"prefix"` or
#' `"suffix"` existing variables with the same name.
#' @inheritParams with_collate
#' @details if `NA` is used those environment variables will be unset.
#' If there are any duplicated variable names only the last one is used.
#' @seealso [Sys.setenv()]
#' @export
with_envvar <- with_(set_envvar)
#' @rdname with_envvar
#' @export
local_envvar <- local_(set_envvar)
withr/R/collate.R 0000644 0001762 0000144 00000001057 13134200551 013353 0 ustar ligges users #' @include with_.R
# collate --------------------------------------------------------------------
set_collate <- function(locale) set_locale(c(LC_COLLATE = locale))[[1]]
#' Collation Order
#'
#' Temporarily change collation order by changing the value of the
#' `LC_COLLATE` locale.
#'
#' @template with
#' @param new `[character(1)]`\cr New collation order
#' @param .local_envir `[environment]`\cr The environment to use for scoping.
#' @export
with_collate <- with_(set_collate)
#' @rdname with_collate
#' @export
local_collate <- local_(set_collate)
withr/R/par.R 0000644 0001762 0000144 00000000762 13134200551 012514 0 ustar ligges users #' @include with_.R
NULL
# par ------------------------------------------------------------------------
#' Graphics parameters
#'
#' Temporarily change graphics parameters.
#'
#' @template with
#' @param new `[named list]`\cr New graphics parameters and their values
#' @param no.readonly `[logical(1)]`\cr see [par()] documentation.
#' @inheritParams with_collate
#' @seealso [par()]
#' @export
with_par <- with_(graphics::par)
#' @rdname with_par
#' @export
local_par <- local_(graphics::par)
withr/R/namespace.R 0000644 0001762 0000144 00000006001 13203046043 013657 0 ustar ligges users #' Execute code with a modified search path
#'
#' `with_package()` attaches a package to the search path, executes the code, then
#' removes the package from the search path. The package namespace is _not_
#' unloaded however. `with_namespace()` does the same thing, but attaches the
#' package namespace to the search path, so all objects (even unexported ones) are also
#' available on the search path.
#' @param package \code{[character(1)]}\cr package name to load.
#' @param env \code{[environment()]}\cr Environment to attach.
#' @param .local_envir `[environment]`\cr The environment to use for scoping.
#' @inheritParams defer
#' @inheritParams base::library
#' @template with
#' @examples
#' \dontrun{
#' with_package("ggplot2", {
#' ggplot(mtcars) + geom_point(aes(wt, hp))
#' })
#' }
#' @export
with_package <- function(package, code, help, pos = 2, lib.loc = NULL,
character.only = TRUE, logical.return = FALSE, warn.conflicts = FALSE,
quietly = TRUE, verbose = getOption("verbose")) {
suppressPackageStartupMessages(
(get("library"))(package, help = help, pos = pos, lib.loc = lib.loc,
character.only = character.only, logical.return = logical.return,
warn.conflicts = warn.conflicts, quietly = quietly, verbose = verbose))
on.exit(detach(paste0("package:", package), character.only = TRUE))
force(code)
}
#' @rdname with_package
#' @export
local_package <- function(package, help, pos = 2, lib.loc = NULL,
character.only = TRUE, logical.return = FALSE, warn.conflicts = FALSE,
quietly = TRUE, verbose = getOption("verbose"),
.local_envir = parent.frame()) {
suppressPackageStartupMessages(
(get("library"))(package, help = help, pos = pos, lib.loc = lib.loc,
character.only = character.only, logical.return = logical.return,
warn.conflicts = warn.conflicts, quietly = quietly, verbose = verbose))
defer(detach(paste0("package:", package), character.only = TRUE), envir = .local_envir)
}
#' @rdname with_package
#' @export
with_namespace <- function(package, code, warn.conflicts = FALSE) {
ns <- asNamespace(package)
name <- format(ns)
(get("attach"))(ns, name = name, warn.conflicts = FALSE)
on.exit(detach(name, character.only = TRUE))
force(code)
}
#' @rdname with_package
#' @export
local_namespace <- function(package, .local_envir = parent.frame(), warn.conflicts = FALSE) {
ns <- asNamespace(package)
name <- format(ns)
(get("attach"))(ns, name = name, warn.conflicts = FALSE)
defer(detach(name, character.only = TRUE), envir = .local_envir)
}
#' @rdname with_package
#' @inheritParams base::attach
#' @export
with_environment <- function(env, code, pos = 2L, name = format(env),
warn.conflicts = FALSE) {
(get("attach"))(env, name = name)
on.exit(detach(name, character.only = TRUE))
force(code)
}
#' @rdname with_package
#' @export
local_environment <- function(env, pos = 2L, name = format(env),
warn.conflicts = FALSE, .local_envir = parent.frame()) {
(get("attach"))(env, name = name)
defer(detach(name, character.only = TRUE), envir = .local_envir)
}
withr/R/seed.R 0000644 0001762 0000144 00000002550 13176337143 012665 0 ustar ligges users #' Random seed
#'
#' `with_seed()` runs code with a specific random seed and resets it afterwards.
#'
#' @template with
#' @param seed `[integer(1)]`\cr The random seed to use to evaluate the code.
#' @examples
#' # Same random values:
#' with_preserve_seed(runif(5))
#' with_preserve_seed(runif(5))
#'
#' # Use a pseudorandom value as seed to advance the RNG and pick a different
#' # value for the next call:
#' with_seed(seed <- sample.int(.Machine$integer.max, 1L), runif(5))
#' with_seed(seed, runif(5))
#' with_seed(seed <- sample.int(.Machine$integer.max, 1L), runif(5))
#' @export
with_seed <- function(seed, code) {
force(seed)
with_preserve_seed({
set.seed(seed)
code
})
}
#' @rdname with_seed
#' @description
#' `with_preserve_seed()` runs code with the current random seed and resets it
#' afterwards.
#'
#' @export
with_preserve_seed <- function(code) {
old_seed <- get_valid_seed()
on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE)
code
}
#' @importFrom stats runif
get_valid_seed <- function() {
seed <- get_seed()
if (is.null(seed)) {
# Trigger initialisation of RNG
runif(1L)
seed <- get_seed()
}
seed
}
get_seed <- function() {
if (!exists(".Random.seed", globalenv(), mode = "integer", inherits = FALSE)) {
return(NULL)
}
get(".Random.seed", globalenv(), mode = "integer", inherits = FALSE)
}
withr/R/defer.R 0000644 0001762 0000144 00000006551 13156036363 013035 0 ustar ligges users #' Defer Evaluation of an Expression
#'
#' Similar to [on.exit()], but allows one to attach
#' an expression to be evaluated when exiting any frame currently
#' on the stack. This provides a nice mechanism for scoping side
#' effects for the duration of a function's execution.
#'
#' @param expr `[expression]`\cr An expression to be evaluated.
#' @param envir `[environment]`\cr Attach exit handlers to this environment.
#' Typically, this should be either the current environment or
#' a parent frame (accessed through [parent.frame()]).
#' @param priority `[character(1)]`\cr Specify whether this handler should
#' be executed `"first"` or `"last"`, relative to any other
#' registered handlers on this environment.
#'
#' @details
#'
#' `defer` works by attaching handlers to the requested environment (as an
#' attribute called `"handlers"`), and registering an exit handler that
#' executes the registered handler when the function associated with the
#' requested environment finishes execution.
#'
#' @family local-related functions
#' @export
#' @author Kevin Ushey
#' @examples
#' # define a 'local' function that creates a file, and
#' # removes it when the parent function has finished executing
#' local_file <- function(path) {
#' file.create(path)
#' defer_parent(unlink(path))
#' }
#'
#' # create tempfile path
#' path <- tempfile()
#'
#' # use 'local_file' in a function
#' local({
#' local_file(path)
#' stopifnot(file.exists(path))
#' })
#'
#' # file is deleted as we leave 'local' local
#' stopifnot(!file.exists(path))
#'
#' # investigate how 'defer' modifies the
#' # executing function's environment
#' local({
#' local_file(path)
#' print(attributes(environment()))
#' })
defer <- function(expr, envir = parent.frame(), priority = c("first", "last")) {
if (identical(envir, .GlobalEnv))
stop("attempt to defer event on global environment")
priority <- match.arg(priority)
front <- priority == "first"
invisible(add_handler(envir, list(expr = substitute(expr), envir = parent.frame()), front))
}
#' @rdname defer
#' @export
defer_parent <- function(expr, priority = c("first", "last")) {
eval(substitute(
defer(expr, envir, priority),
list(expr = substitute(expr), envir = parent.frame(2), priority = priority)
), envir = parent.frame())
}
## Handlers used for 'defer' calls. Attached as a list of expressions for the
## 'handlers' attribute on the environment, with 'on.exit' called to ensure
## those handlers get executed on exit.
get_handlers <- function(envir) {
as.list(attr(envir, "handlers"))
}
set_handlers <- function(envir, handlers) {
has_handlers <- "handlers" %in% names(attributes(envir))
attr(envir, "handlers") <- handlers
if (!has_handlers) {
call <- make_call(execute_handlers, envir)
# We have to use do.call here instead of eval because of the way on.exit
# determines its evaluation context
# (https://stat.ethz.ch/pipermail/r-devel/2013-November/067867.html)
do.call(base::on.exit, list(substitute(call), TRUE), envir = envir)
}
}
execute_handlers <- function(envir) {
handlers <- get_handlers(envir)
for (handler in handlers)
tryCatch(eval(handler$expr, handler$envir), error = identity)
}
add_handler <- function(envir, handler, front) {
handlers <- if (front)
c(list(handler), get_handlers(envir))
else
c(get_handlers(envir), list(handler))
set_handlers(envir, handlers)
handler
}
withr/R/options.R 0000644 0001762 0000144 00000000754 13134200551 013426 0 ustar ligges users #' @include with_.R
# options --------------------------------------------------------------------
set_options <- function(new_options) {
do.call(options, as.list(new_options))
}
#' Options
#'
#' Temporarily change global options.
#'
#' @template with
#' @param new `[named list]`\cr New options and their values
#' @inheritParams with_collate
#' @seealso [options()]
#' @export
with_options <- with_(set_options)
#' @rdname with_options
#' @export
local_options <- local_(set_options)
withr/R/path.R 0000644 0001762 0000144 00000001634 13134200551 012665 0 ustar ligges users # path -----------------------------------------------------------------------
get_path <- function() {
strsplit(Sys.getenv("PATH"), .Platform$path.sep)[[1]]
}
set_path <- function(path, action = "prefix") {
path <- normalizePath(path, mustWork = FALSE)
old <- get_path()
path <- merge_new(old, path, action)
path <- paste(path, collapse = .Platform$path.sep)
Sys.setenv(PATH = path)
invisible(old)
}
#' PATH environment variable
#'
#' Temporarily change the system search path.
#'
#' @template with
#' @param new `[character]`\cr New `PATH` entries
#' @param action `[character(1)]`\cr Should new values `"replace"`, `"prefix"` or
#' `"suffix"` existing paths
#' @inheritParams with_collate
#' @seealso [Sys.setenv()]
#' @export
with_path <- with_(set_path, function(old) set_path(old, "replace"))
#' @rdname with_path
#' @export
local_path <- local_(set_path, function(old) set_path(old, "replace"))
withr/R/file.R 0000644 0001762 0000144 00000001644 13177065730 012670 0 ustar ligges users #' Files which delete themselves
#'
#' Create files, which are then automatically removed afterwards.
#' @template with
#' @param file `[named list]`\cr Files to create.
#' @param .local_envir `[environment]`\cr The environment to use for scoping.
#' @examples
#' with_file("file1", {
#' writeLines("foo", "file1")
#' readLines("file1")
#' })
#'
#' with_file(list("file1" = writeLines("foo", "file1")), {
#' readLines("file1")
#' })
#' @export
with_file <- function(file, code) {
file_nms <- names2(file)
unnamed <- file_nms == ""
file_nms[unnamed] <- as.character(file[unnamed])
on.exit(unlink(file_nms))
eval.parent(code)
invisible(file)
}
#' @rdname with_file
#' @export
local_file <- function(file, .local_envir = parent.frame()) {
file_nms <- names2(file)
unnamed <- file_nms == ""
file_nms[unnamed] <- as.character(file[unnamed])
defer(unlink(file_nms), envir = .local_envir)
invisible(file)
}
withr/R/wrap.R 0000644 0001762 0000144 00000001120 12652144715 012705 0 ustar ligges users wrap <- function(f, pre, post, envir = parent.frame()) {
fmls <- formals(f)
# called pass all extra formals on
called_fmls <- stats::setNames(lapply(names(fmls), as.symbol), names(fmls))
f_call <- as.call(c(substitute(f), called_fmls))
pre <- substitute(pre)
post <- substitute(post)
fun <- eval(bquote(function(args) {
.(pre)
.retval <- .(f_call)
.(post)
}, as.environment(list(f_call = f_call, pre = pre, post = post))))
# substitute does not work on arguments, so we need to fix them manually
formals(fun) <- fmls
environment(fun) <- envir
fun
}
withr/R/libpaths.R 0000644 0001762 0000144 00000002431 13252301176 013541 0 ustar ligges users #' @include with_.R
# lib ------------------------------------------------------------------------
set_libpaths <- function(paths, action = "replace") {
paths <- normalizePath(paths, mustWork = TRUE)
old <- .libPaths()
paths <- merge_new(old, paths, action)
.libPaths(paths)
invisible(old)
}
set_temp_libpath <- function(action = "prefix") {
paths <- tempfile("temp_libpath")
dir.create(paths)
set_libpaths(paths, action = action)
}
#' Library paths
#'
#' Temporarily change library paths.
#'
#' @template with
#' @param new `[character]`\cr New library paths
#' @param action `[character(1)]`\cr should new values `"replace"`, `"prefix"` or
#' `"suffix"` existing paths.
#' @inheritParams with_collate
#' @seealso [.libPaths()]
#' @family libpaths
#' @export
with_libpaths <- with_(set_libpaths, .libPaths)
#' @rdname with_libpaths
#' @export
local_libpaths <- local_(set_libpaths, .libPaths)
#' Library paths
#'
#' Temporarily prepend a new temporary directory to the library paths.
#'
#' @template with
#' @seealso [.libPaths()]
#' @inheritParams with_libpaths
#' @family libpaths
#' @export
with_temp_libpaths <- with_(set_temp_libpath, .libPaths, new = FALSE)
#' @rdname with_temp_libpaths
#' @export
local_temp_libpaths <- local_(set_temp_libpath, .libPaths, new = FALSE)
withr/R/with.R 0000644 0001762 0000144 00000004354 13152075036 012716 0 ustar ligges users #' Execute code in temporarily altered environment
#'
#' All functions prefixed by `with_` work as follows. First, a particular
#' aspect of the global environment is modified (see below for a list).
#' Then, custom code (passed via the `code` argument) is executed.
#' Upon completion or error, the global environment is restored to the previous
#' state. Each `with_` function has a `local_` variant, which instead resets
#' the state when the current evaluation context ends (such as the end of a
#' function).
#'
#' @section Arguments pattern:
#' \tabular{lll}{
#' `new` \tab `[various]` \tab Values for setting \cr
#' `code` \tab `[any]` \tab Code to execute in the temporary environment \cr
#' `...` \tab \tab Further arguments \cr
#' }
#' @section Usage pattern:
#' `with_...(new, code, ...)`
#' @name withr
#' @docType package
#' @section withr functions:
#' \itemize{
#' \item [with_collate()]: collation order
#' \item [with_dir()]: working directory
#' \item [with_envvar()]: environment variables
#' \item [with_libpaths()]: library paths, replacing current libpaths
#' \item [with_locale()]: any locale setting
#' \item [with_makevars()]: Makevars variables
#' \item [with_options()]: options
#' \item [with_par()]: graphics parameters
#' \item [with_path()]: `PATH` environment variable
#' \item [with_sink()]: output redirection
#' }
#' @section Creating new "with" functions:
#' All `with_` functions are created by a helper function,
#' [with_()]. This functions accepts two arguments:
#' a setter function and an optional resetter function. The setter function is
#' expected to change the global state and return an "undo instruction".
#' This undo instruction is then passed to the resetter function, which changes
#' back the global state. In many cases, the setter function can be used
#' naturally as resetter.
#' @examples
#' getwd()
#' with_dir(tempdir(), getwd())
#' getwd()
#'
#' Sys.getenv("WITHR")
#' with_envvar(c("WITHR" = 2), Sys.getenv("WITHR"))
#' Sys.getenv("WITHR")
#'
#' with_envvar(c("A" = 1),
#' with_envvar(c("A" = 2), action = "suffix", Sys.getenv("A"))
#' )
#'
#' # local variants are best used within other functions
#' f <- function(x) {
#' local_envvar(c("WITHR" = 2))
#' Sys.getenv("WITHR")
#' }
#' Sys.getenv("WITHR")
NULL
withr/R/local_.R 0000644 0001762 0000144 00000002012 13252301176 013157 0 ustar ligges users #' @rdname with_
#' @export
local_ <- function(set, reset = set, envir = parent.frame(), new = TRUE) {
fmls <- formals(set)
if (length(fmls) > 0L) {
# called pass all extra formals on
called_fmls <- stats::setNames(lapply(names(fmls), as.symbol), names(fmls))
if (new) {
# rename first formal to new
called_fmls[[1]] <- as.symbol("new")
fun_args <- c(alist(new =), fmls[-1L])
} else {
fun_args <- fmls
}
} else {
# no formals
called_fmls <- NULL
fun_args <- alist()
}
set_call <- as.call(c(substitute(set), called_fmls))
fun <- eval(bquote(function(args) {
old <- .(set_call)
defer(.(reset)(old), envir = .local_envir)
old
}, as.environment(list(set_call = set_call,
reset = if (missing(reset)) substitute(set) else substitute(reset)))))
# substitute does not work on arguments, so we need to fix them manually
formals(fun) <- c(fun_args, alist(.local_envir = parent.frame()))
environment(fun) <- envir
fun
}
withr/R/dir.R 0000644 0001762 0000144 00000000630 13134200551 012502 0 ustar ligges users #' @include with_.R
NULL
# working directory ----------------------------------------------------------
#' Working directory
#'
#' Temporarily change the current working directory.
#'
#' @template with
#' @param new `[character(1)]`\cr New working directory
#' @inheritParams with_collate
#' @seealso [setwd()]
#' @export
with_dir <- with_(setwd)
#' @rdname with_dir
#' @export
local_dir <- local_(setwd)
withr/R/torture.R 0000644 0001762 0000144 00000000567 13152342467 013456 0 ustar ligges users #' Torture Garbage Collector
#'
#' Temporarily turn gctorture2 on.
#'
#' @template with
#' @param new `[integer]`\cr run GC every 'step' allocations.
#' @inheritParams base::gctorture
#' @inheritParams local_
with_gctorture2 <- with_(gctorture2)
formals(with_gctorture2)[[3]] <- quote(new)
local_gctorture2 <- local_(gctorture2)
formals(local_gctorture2)[[2]] <- quote(new)
withr/R/devices.R 0000644 0001762 0000144 00000010163 13176337143 013366 0 ustar ligges users #' @include wrap.R
NULL
# Internal *_dev functions ------------------------------------------------
pdf_dev <- wrap(grDevices::pdf, NULL, grDevices::dev.cur())
postscript_dev <- wrap(grDevices::postscript, NULL, grDevices::dev.cur())
svg_dev <- wrap(grDevices::svg, NULL, grDevices::dev.cur())
xfig_dev <- wrap(grDevices::xfig, NULL, grDevices::dev.cur())
# These functions arguments differ between R versions, so just use ...
cairo_pdf_dev <- function(filename, ...) {
grDevices::cairo_pdf(filename = filename, ...)
grDevices::dev.cur()
}
cairo_ps_dev <- function(filename, ...) {
grDevices::cairo_ps(filename = filename, ...)
grDevices::dev.cur()
}
# These functions arguments differ between unix and windows, so just use ...
bmp_dev <- function(filename, ...) {
grDevices::bmp(filename = filename, ...)
grDevices::dev.cur()
}
tiff_dev <- function(filename, ...) {
grDevices::tiff(filename = filename, ...)
grDevices::dev.cur()
}
png_dev <- function(filename, ...) {
grDevices::png(filename = filename, ...)
grDevices::dev.cur()
}
jpeg_dev <- function(filename, ...) {
grDevices::jpeg(filename = filename, ...)
grDevices::dev.cur()
}
# User-level with_* fns ---------------------------------------------------
#' Graphics devices
#'
#' Temporarily use a graphics device.
#'
#' @name devices
#' @aliases with_dev with_device
#' @template with
#' @param new \code{[named character]}\cr New graphics device
#' @param ... Additional arguments passed to the graphics device.
#' @param .local_envir `[environment]`\cr The environment to use for scoping.
#' @seealso \code{\link[grDevices]{Devices}}
#' @examples
#' # dimensions are in inches
#' with_pdf(file.path(tempdir(), "test.pdf"), width = 7, height = 5,
#' plot(runif(5))
#' )
#'
#' # dimensions are in pixels
#' with_png(file.path(tempdir(), "test.png"), width = 800, height = 600,
#' plot(runif(5))
#' )
NULL
#' @describeIn devices BMP device
#' @export
with_bmp <- with_(bmp_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_bmp <- local_(bmp_dev, grDevices::dev.off)
#' @describeIn devices CAIRO_PDF device
#' @inheritParams grDevices::cairo_pdf
#' @export
with_cairo_pdf <- with_(cairo_pdf_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_cairo_pdf <- local_(cairo_pdf_dev, grDevices::dev.off)
#' @describeIn devices CAIRO_PS device
#' @inheritParams grDevices::cairo_ps
#' @export
with_cairo_ps <- with_(cairo_ps_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_cairo_ps <- local_(cairo_ps_dev, grDevices::dev.off)
#' @describeIn devices PDF device
#' @inheritParams grDevices::pdf
#' @export
with_pdf <- with_(pdf_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_pdf <- local_(pdf_dev, grDevices::dev.off)
#' @describeIn devices POSTSCRIPT device
#' @inheritParams grDevices::postscript
#' @param command the command to be used for \sQuote{printing}. Defaults
#' to \code{"default"}, the value of option \code{"printcmd"}. The
#' length limit is \code{2*PATH_MAX}, typically 8096 bytes on unix systems and
#' 520 bytes on windows.
#' @export
with_postscript <- with_(postscript_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_postscript <- local_(postscript_dev, grDevices::dev.off)
#' @describeIn devices SVG device
#' @inheritParams grDevices::svg
#' @export
with_svg <- with_(svg_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_svg <- local_(svg_dev, grDevices::dev.off)
#' @describeIn devices TIFF device
#' @export
with_tiff <- with_(tiff_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_tiff <- local_(tiff_dev, grDevices::dev.off)
#' @describeIn devices XFIG device
#' @inheritParams grDevices::xfig
#' @export
with_xfig <- with_(xfig_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_xfig <- local_(xfig_dev, grDevices::dev.off)
#' @describeIn devices PNG device
#' @export
with_png <- with_(png_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_png <- local_(png_dev, grDevices::dev.off)
#' @describeIn devices JPEG device
#' @export
with_jpeg <- with_(jpeg_dev, grDevices::dev.off)
#' @rdname devices
#' @export
local_jpeg <- local_(jpeg_dev, grDevices::dev.off)
withr/R/makevars.R 0000644 0001762 0000144 00000006244 13252301176 013552 0 ustar ligges users #' @include with_.R
NULL
# Makevars --------------------------------------------------------------------
#' Create a new `Makevars` file, by adding new variables
#'
#' You probably want [with_makevars()] instead of this function.
#'
#' Unlike [with_makevars()], it does not activate the new `Makevars`
#' file, i.e. it does not set the `R_MAKEVARS_USER` environment variable.
#'
#' @param variables `[named character]`\cr new variables and their values
#' @param old_path `[character(1)]`\cr location of existing `Makevars`
#' file to modify.
#' @param new_path `[character(1)]`\cr location of the new `Makevars` file
#' @param assignment `[character(1)]`\cr assignment type to use.
#'
#' @keywords internal
#' @export
set_makevars <- function(variables,
old_path = file.path("~", ".R", "Makevars"),
new_path = tempfile(),
assignment = c("=", ":=", "?=", "+=")) {
if (length(variables) == 0) {
return()
}
stopifnot(is.named(variables))
assignment <- match.arg(assignment)
old <- NULL
if (file.exists(old_path)) {
lines <- readLines(old_path)
old <- lines
for (var in names(variables)) {
loc <- grep(paste(c("^[[:space:]]*", var, "[[:space:]]*", "="), collapse = ""), lines)
if (length(loc) == 0) {
lines <- append(lines, paste(sep = assignment, var, variables[var]))
} else if(length(loc) == 1) {
lines[loc] <- paste(sep = assignment, var, variables[var])
} else {
stop("Multiple results for ", var, " found, something is wrong.", .call = FALSE)
}
}
} else {
lines <- paste(names(variables), variables, sep = assignment)
}
if (!identical(old, lines)) {
writeLines(con = new_path, lines)
}
old
}
#' Makevars variables
#'
#' Temporarily change contents of an existing `Makevars` file.
#'
#' @details If no `Makevars` file exists or the fields in `new` do
#' not exist in the existing `Makevars` file then the fields are added to
#' the new file. Existing fields which are not included in `new` are
#' appended unchanged. Fields which exist in `Makevars` and in `new`
#' are modified to use the value in `new`.
#'
#' @template with
#' @param new `[named character]`\cr New variables and their values
#' @param path `[character(1)]`\cr location of existing `Makevars` file to modify.
#' @param assignment `[character(1)]`\cr assignment type to use.
#' @export
with_makevars <- function(new, code, path = file.path("~", ".R", "Makevars"), assignment = c("=", ":=", "?=", "+=")) {
assignment <- match.arg(assignment)
makevars_file <- tempfile()
on.exit(unlink(makevars_file), add = TRUE)
with_envvar(c(R_MAKEVARS_USER = makevars_file), {
set_makevars(new, path, makevars_file, assignment = assignment)
force(code)
})
}
local_makevars <- function(new, path = file.path("~", ".R", "Makevars"), assignment = c("=", ":=", "?=", "+="), .local_envir = parent.frame()) {
assignment <- match.arg(assignment)
makevars_file <- tempfile()
defer(unlink(makevars_file), envir = .local_envir)
local_envvar(c(R_MAKEVARS_USER = makevars_file), .local_envir = .local_envir)
set_makevars(new, path, makevars_file, assignment = assignment)
}
withr/vignettes/ 0000755 0001762 0000144 00000000000 13252476111 013421 5 ustar ligges users withr/vignettes/withr.Rmd 0000644 0001762 0000144 00000006623 13216217255 015233 0 ustar ligges users ---
title: "withr"
author: "Jim Hester"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{withr}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
library(withr)
```
# Whither withr?
Many functions in R modify global state in some fashion. Some common examples
are `par()` for graphics parameters, `dir()` to change the current directory
and `options()` to set a global option. Using these functions is handy
when using R interactively, because you can set them early in your
experimentation and they will remain set for the duration of the session.
However this makes programming with these settings difficult, because they make
your function impure by modifying a global state. Therefore you should always
strive to reset the previous state when the function exits.
One common idiom for dealing with this problem is to save the current state,
make your change, then restore the previous state.
```{r}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
plot(mtcars$hp, mtcars$wt)
par(old)
}
my_plot()
par("col")
```
However this approach can fail if there's an error before you are able to reset
the options.
```{r, error = TRUE}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
plot(mtcars$hpp, mtcars$wt)
par(old)
}
my_plot()
par("col")
```
Using the base function `on.exit()` is a robust solution to this problem.
`on.exit()` will run the code when the function is exited, regardless
of whether it exits normally or with an error.
```{r, error = TRUE}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
on.exit(par(old))
plot(mtcars$hpp, mtcars$wt)
}
my_plot()
par("col")
options(test = 1)
{
print(getOption("test"))
on.exit(options(test = 2))
}
getOption("test")
```
However this solution is somewhat cumbersome to work with. You
need to remember to use an `on.exit()` call after each stateful call. In
addition by default each `on.exit()` action will overwrite any previous
`on.exit()` action in the same function unless you use the `add = TRUE` option.
`add = TRUE` also adds additional code to the _end_ of existing code, which
means the code is not run in the [Last-In,
First-Out](https://en.wikipedia.org/wiki/FIFO_and_LIFO_accounting) order you
would generally prefer. It is also not possible to have this cleanup code
performed before the function has finished.
[withr](http://withr.r-lib.org) is a solution to these issues. It defines a
[large set of
functions](http://withr.r-lib.org/#withr---run-code-with-modified-state) for
dealing with global settings in R, such as `with_par()`. These functions set one of
the global settings for the duration of a block of code, then automatically
reset it after the block is completed.
```{r}
par("col" = "black")
my_plot <- function(new) {
with_par(list(col = "red", pch = 19),
plot(mtcars$hp, mtcars$wt)
)
par("col")
}
my_plot()
par("col")
```
In addition to the `with_*` functions there are `local_*` variants whose effects
last until the end of the function they are included in. These work similar to
`on.exit()`, but you can set the options in one call rather than two.
```{r}
par("col" = "black")
my_plot <- function(new) {
local_par(list(col = "red", pch = 19))
plot(mtcars$hp, mtcars$wt)
}
my_plot()
par("col")
```
withr/vignettes/releases/ 0000755 0001762 0000144 00000000000 13216217142 015221 5 ustar ligges users withr/vignettes/releases/withr-2.1.0.Rmd 0000644 0001762 0000144 00000015663 13216217142 017471 0 ustar ligges users ---
title: withr 2.1.0
date: '2017-11-16'
slug: withr-2.1.0
author: Jim Hester
categories: [package]
description: >
withr 2.1.0 is now available on CRAN.
photo:
url: https://unsplash.com/photos/V1YEEItoOTE
author: Suganth
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(
comment = "#>",
collapse = TRUE
)
library(withr)
```
[withr 2.1.0](http://withr.r-lib.org/news/index.html) is now available on CRAN!
[withr](http://withr.r-lib.org) makes working with global state in R safer and
less error prone. It has only base package dependencies so is easily included
in packages.
Install the latest version with:
```{r, eval = FALSE}
install.packages("withr")
```
# Whither withr?
Many functions in R modify global state in some fashion. Some common examples
are `par()` for graphics parameters, `dir()` to change the current directory
and `options()` to set a global option. Using these functions is handy
when using R interactively, because you can set them early in your
experimentation and they will remain set for the duration of the session.
However this makes programming with these settings difficult, because they make
your function impure by modifying a global state. Therefore you should always
strive to reset the previous state when the function exits.
One common idiom for dealing with this problem is to save the current state,
make your change, then restore the previous state.
```{r}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
plot(mtcars$hp, mtcars$wt)
par(old)
}
my_plot()
par("col")
```
However this approach can fail if there's an error before you are able to reset
the options.
```{r, error = TRUE}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
plot(mtcars$hpp, mtcars$wt)
par(old)
}
my_plot()
par("col")
```
Using the base function `on.exit()` is a robust solution to this problem.
`on.exit()` will run the code when the function is exited, regardless
of whether it exits normally or with an error.
```{r, error = TRUE}
par("col" = "black")
my_plot <- function(new) {
old <- par(col = "red", pch = 19)
on.exit(par(old))
plot(mtcars$hpp, mtcars$wt)
}
my_plot()
par("col")
options(test = 1)
{
print(getOption("test"))
on.exit(options(test = 2))
}
getOption("test")
```
However this solution is somewhat cumbersome to work with. You
need to remember to use an `on.exit()` call after each stateful call. In
addition by default each `on.exit()` action will overwrite any previous
`on.exit()` action in the same function unless you use the `add = TRUE` option.
`add = TRUE` also adds additional code to the _end_ of existing code, which
means the code is not run in the [Last-In,
First-Out](https://en.wikipedia.org/wiki/FIFO_and_LIFO_accounting) order you
would generally prefer. It is also not possible to have this cleanup code
performed before the function has finished.
[withr](http://withr.r-lib.org) is a solution to these issues. It defines a
[large set of
functions](http://withr.r-lib.org/#withr---run-code-with-modified-state) for
dealing with global settings in R, such as `with_par()`. These functions set one of
the global settings for the duration of a block of code, then automatically
reset it after the block is completed.
```{r}
par("col" = "black")
my_plot <- function(new) {
with_par(list(col = "red", pch = 19),
plot(mtcars$hp, mtcars$wt)
)
par("col")
}
my_plot()
par("col")
```
In addition to the `with_*` functions there are `local_*` variants whose effects
last until the end of the function they are included in. These work similar to
`on.exit()`, but you can set the options in one call rather than two.
```{r}
par("col" = "black")
my_plot <- function(new) {
local_par(list(col = "red", pch = 19))
plot(mtcars$hp, mtcars$wt)
}
my_plot()
par("col")
```
# New features
Here are some highlights of new functions for v2.1.0.
## Graphics devices
There are now a comprehensive set of functions to deal with R's builtin
[graphics devices](http://withr.r-lib.org/reference/devices.html).
These functions open a new graphics device, run some code, then automatically
close the device.
```{r}
path <- file.path(Sys.glob("*withr*_files/figure-html"), "test.png")
with_png(path, width = 400, height = 300, {
plot(mtcars$hp, mtcars$mpg)
})
```

Thanks to [Richard Cotton's](https://github.com/richierocks) great [pull
request](https://github.com/r-lib/withr/pull/37) for this feature!
## Connections
There are two new functions for cleaning up connections in R.
`with_connection()` allows you to automatically close R's file connections.
Here we create a writable file connection, write some lines to it with
`with_connection()`, then open a read-only connection and read the file using
`local_connection()`.
```{r}
with_connection(list(con = file("temp", "w")), {
writeLines(c("foo", "bar"), con)
})
read_temp <- function() {
con <- local_connection(file("temp", "r"))
readLines(con)
}
read_temp()
```
```{r, echo = FALSE}
unlink("temp")
```
`with_db_connection()` provides [DBI](http://rstats-db.github.io/DBI)
connections to databases which automatically call
`DBI::dbDisconnect()`. Here we create a new [SQLite](https://www.sqlite.org/)
database, connect to it with `with_db_connection()`, and write a new table to
it. We then create another connection with `local_db_connection()` and read
from the table.
```{r}
db <- tempfile()
with_db_connection(
list(con = DBI::dbConnect(RSQLite::SQLite(), db)), {
DBI::dbWriteTable(con, "mtcars", mtcars)
})
head_db_table <- function(...) {
con <- local_db_connection(DBI::dbConnect(RSQLite::SQLite(), db))
head(DBI::dbReadTable(con, "mtcars"), ...)
}
head_db_table()
unlink(db)
```
## Packages
`with_package()` allows you to temporarily attach a package.
```{r}
with_package("lattice", {
xyplot(y ~ x, data.frame(x = -2:2, y = dnorm(-2:2)))
})
```
## Tempfiles
`with_tempfile()` handy for creating a new temporary files that are removed,
often useful when writing tests.
```{r}
with_tempfile("file1", {
print(file1)
writeLines("foo", file1)
readLines(file1)
})
```
## Other changes
There are many other bug fixes and other minor improvements in this release.
You can see a complete list in the [release
notes](https://github.com/r-lib/withr/releases/tag/v2.1.0).
A big thanks goes to all the community members who contributed code and opened
issues since the last release!
```{r, eval = FALSE, include = FALSE}
x <- gh::gh("/repos/:owner/:repo/issues", owner = "r-lib", repo = "withr", since = "2017-06-16", state = "all")
users <- unique(purrr::map_chr(x, c("user", "login")))
clipr::write_clip(glue::collapse(glue::glue("[\\@{users}](https://github.com/{users})"), ", ", last = ", and "))
```
[\@QuLogic](https://github.com/QuLogic),
[\@krlmlr](https://github.com/krlmlr),
[\@hadley](https://github.com/hadley),
[\@wlandau-lilly](https://github.com/wlandau-lilly),
[\@jimhester](https://github.com/jimhester),
[\@kevinushey](https://github.com/kevinushey),
and [\@richierocks](https://github.com/richierocks)
withr/README.md 0000644 0001762 0000144 00000005675 13252476015 012710 0 ustar ligges users
# Withr - Run Code ‘With’ Modified State
[](https://travis-ci.org/r-lib/withr)
[](https://ci.appveyor.com/project/jimhester/withr)
[](https://codecov.io/github/r-lib/withr?branch=master)
[](http://www.r-pkg.org/pkg/withr)
A set of functions to run code ‘with’ safely and temporarily modified
global state. There are two sets of functions, those prefixed with
`with_` and those with `local_`. The former reset their state as soon as
the `code` argument has been evaluated. The latter reset when they reach
the end of their scope, usually at the end of a function body.
Many of these functions were originally a part of the
[devtools](https://github.com/hadley/devtools) package, this provides a
simple package with limited dependencies to provide access to these
functions.
- `with_collate()` / `local_collate()` - collation order
- `with_dir()` / `local_dir()` - working directory
- `with_envvar()` / `local_envvar()` - environment variables
- `with_libpaths()` / `local_libpaths()` - library paths
- `with_locale()` / `local_locale()` - any locale setting
- `with_makevars()` / `local_makevars()` - Makevars variables
- `with_options()` / `local_options()` - options
- `with_par()` / `local_par()` - graphics parameters
- `with_path()` / `local_path()` - PATH environment variable
- `with_*()` and `local_()` functions for the built in R devices,
`bmp`, `cairo_pdf`, `cairo_ps`, `pdf`, `postscript`, `svg`, `tiff`,
`xfig`, `png`, `jpeg`.
- `with_connection()` / `local_connection()` - R connections.
- `with_package()`, `with_namespace()` and `with_environment()` - to
run code with modified object search paths.
- `with_tempfile()` / `local_tempfile()` - Create and clean up a temp
file.
- `with_file()` / `local_file()` - Create and clean up a normal file.
There are also `with_()` and `local_()` functions to construct new
`with_*` and `local_*` functions if needed.
``` r
Sys.getenv("WITHR")
#> [1] ""
with_envvar(c("WITHR" = 2), Sys.getenv("WITHR"))
#> [1] "2"
Sys.getenv("WITHR")
#> [1] ""
with_envvar(c("A" = 1),
with_envvar(c("A" = 2), action = "suffix", Sys.getenv("A"))
)
#> [1] "1 2"
```
## local functions
These functions are variants of the corresponding `with_()` function,
but rather than resetting the value at the end of the function call they
reset when the current context goes out of scope. This is most useful
for using within functions.
``` r
f <- function(x) {
local_envvar(c("WITHR" = 2))
Sys.getenv("WITHR")
}
Sys.getenv("WITHR")
#> [1] ""
```
# See Also
- [Devtools](https://github.com/hadley/devtools)
withr/MD5 0000644 0001762 0000144 00000007010 13252573074 011725 0 ustar ligges users 4558186135fa52f59b6d7bca5f4e18c8 *DESCRIPTION
4f5cd788faf0e194f4cccaa3c3fe678d *NAMESPACE
badcbb849e510a9d3bec9d03ac9b5af6 *NEWS.md
e1cbb655f59eff445b7950e74e535fd8 *R/collate.R
d21aa3dfe1f98bf20fcca6f3bace2cf9 *R/connection.R
5367808d24945c8a3cfffd992a0a0f4b *R/db.R
ba35bf8d7954ce170ed6046af5c0644a *R/defer.R
b112ddd38b7d221237767da419766c0e *R/devices.R
a2d830766da6848a85c7ddc774ccea71 *R/dir.R
4b5c0d27740b8f7cf5c0b65ebeb432ac *R/env.R
8e423cce2d946b965160fee84c4090ab *R/file.R
9b1bc5608957a633f8828af5b62aed51 *R/libpaths.R
c73eb3e8f66c34f8fd6ff411cab5c59b *R/local_.R
5df03f3868961416b20e8f3f4f1afe55 *R/locale.R
705ad4b5645f846a81c823a2e6fd42da *R/makevars.R
2ddba27e734132a5fc04f5c26d1c205b *R/namespace.R
0ffde56e2ef1adc0b3ba462c78556212 *R/options.R
188e3db591fcbb3744adbc9eac9ba076 *R/par.R
25aa34b8e8e014b2e88e276602d05018 *R/path.R
04c7d8612b078effbb76e6dbec2fe564 *R/seed.R
1939e43a0b29a1a8b446de3e0b33c233 *R/sink.R
dc01411e0ee843eebd65900889e03c91 *R/tempfile.R
bd03783290e342d399ae55e4b96a5b2b *R/torture.R
37e32adfc1d04c33eb160c8bc39c250b *R/utils.R
79d8537ea64031d18a07c7c594ae9f15 *R/with.R
d0070c67391fee5e6eecacec513b0610 *R/with_.R
88e44ec61deb387dd1c2d8a607c420ee *R/wrap.R
5deef8b20a5c1a043bc4348510ae6a54 *README.md
d7deee5123b6576e7d1c3b5b0e244c83 *build/vignette.rds
a4b9e60614d09fa9a49ada7a5d9c34a1 *inst/doc/withr.R
72f96df45a4e2d9f4081c3a2ea2e8cd6 *inst/doc/withr.Rmd
c3c2a8cd290576fe0b7fde2f93ca2db2 *inst/doc/withr.html
ec146ff954b93557f07c608514109318 *man/defer.Rd
5d7f68ad3e0895931de77ee9dd2f0196 *man/devices.Rd
1d0c1c0cee9dba91bd5c6495faa6db5a *man/set_makevars.Rd
7d78950cdb803e4d92abdc3f1591bbd6 *man/with_.Rd
0b9c878587610015751f3fbbf64b4c09 *man/with_collate.Rd
8ab578f58534056d1b9d11f44de62af4 *man/with_connection.Rd
f4409fea8292158fa660931fd52cfa72 *man/with_db_connection.Rd
b215321be57c6be7e0cda435ed396a67 *man/with_dir.Rd
9b23b3d00276f924d91a40d0d6a09d32 *man/with_envvar.Rd
ffa1adcfe1ababb86c2160a5fb40fd83 *man/with_file.Rd
2a33569b52280c025e40f0a8a00498ed *man/with_gctorture2.Rd
7d6b9ba2e7eeecca182e147423e351ab *man/with_libpaths.Rd
c163c7dedf9d85b0c54d9b17f385afd4 *man/with_locale.Rd
b72a85d8789a8b1741d045ac84e73600 *man/with_makevars.Rd
7b6f676c325ff2822e64a6245c9a1f81 *man/with_options.Rd
59c60d56c9b2ba245f54895438587d98 *man/with_package.Rd
2f95ec870ee579deb0801fcecfe823f0 *man/with_par.Rd
b98fbc3f8b613b49e76ad97be57a0aa1 *man/with_path.Rd
007fd826d391517d74b124aff1e5c725 *man/with_seed.Rd
5ea9bddb1beb3dacf1380f7792b5cbc2 *man/with_sink.Rd
4db8a21af817be1429e8dbf3310e2e04 *man/with_temp_libpaths.Rd
e29f4500358c94da6f964bb9f820c008 *man/with_tempfile.Rd
aeceda0f70c58facc5a31a8093a72d22 *man/withr.Rd
70c4d334a0974e15d0309c48ca52ca08 *tests/testthat.R
3cf3c83f8d894870bb07b53fff39bc86 *tests/testthat/helper.R
4219376f4cfaccbaeccc614ba9e9866c *tests/testthat/test-connection.R
d2ed51542e4abe02bb3b1b3d8f5aec8d *tests/testthat/test-db.R
5989fee73522cde134a8bf71815c7352 *tests/testthat/test-defer.R
c5cae288b0b53b6ca2e48d021e2e5d28 *tests/testthat/test-devices.R
a408511923bf2b0a2b62dd703be8160e *tests/testthat/test-file.R
d575d8af40350566635a5a45c5262de4 *tests/testthat/test-local.R
95249441369039d904fa844406f0e057 *tests/testthat/test-namespace.R
fcef549d413f2a1ec9a59470fea99b69 *tests/testthat/test-sink.R
83c5918263499305b818480c00e86f3d *tests/testthat/test-tempfile.R
538404656b614b41e5714e5ee6abc06c *tests/testthat/test-with.R
0effd9528f896e3322dfeb26a0fdc7d5 *tests/testthat/test-wrap.R
17c36e4653dede588f89ead562305710 *vignettes/releases/withr-2.1.0.Rmd
72f96df45a4e2d9f4081c3a2ea2e8cd6 *vignettes/withr.Rmd
withr/build/ 0000755 0001762 0000144 00000000000 13252476110 012507 5 ustar ligges users withr/build/vignette.rds 0000644 0001762 0000144 00000000300 13252476110 015037 0 ustar ligges users b```b`faf`b2 1#',,(MA`K rATgɰC(Hyz]RRR@g;<E
T
[fN*ސ89
dBw(,/׃
@?{49'ݣ\)%ziE@ w !e withr/DESCRIPTION 0000644 0001762 0000144 00000003405 13252573074 013127 0 ustar ligges users Encoding: UTF-8
Package: withr
Title: Run Code 'With' Temporarily Modified Global State
Version: 2.1.2
Authors@R: c(
person("Jim", "Hester", , "james.f.hester@gmail.com", role = c("aut", "cre")),
person("Kirill", "Müller", , "krlmlr+r@mailbox.org", role = "aut"),
person("Kevin", "Ushey", email = "kevinushey@gmail.com", role = c("aut")),
person("Hadley", "Wickham", , "hadley@rstudio.com", role = "aut"),
person("Winston", "Chang", role = "aut"),
person("Richard", "Cotton", role = c("ctb")),
person("RStudio", role = "cph"))
Description: A set of functions to run code 'with' safely and temporarily
modified global state. Many of these functions were originally a part of the
'devtools' package, this provides a simple package with limited dependencies
to provide access to these functions.
URL: http://withr.r-lib.org, http://github.com/r-lib/withr#readme
BugReports: http://github.com/r-lib/withr/issues
Depends: R (>= 3.0.2)
License: GPL (>= 2)
LazyData: true
Imports: stats, graphics, grDevices
Suggests: testthat, covr, lattice, DBI, RSQLite, methods, knitr,
rmarkdown
RoxygenNote: 6.0.1
Collate: 'local_.R' 'with_.R' 'collate.R' 'connection.R' 'db.R'
'defer.R' 'wrap.R' 'devices.R' 'dir.R' 'env.R' 'file.R'
'libpaths.R' 'locale.R' 'makevars.R' 'namespace.R' 'options.R'
'par.R' 'path.R' 'seed.R' 'sink.R' 'tempfile.R' 'torture.R'
'utils.R' 'with.R'
VignetteBuilder: knitr
NeedsCompilation: no
Packaged: 2018-03-15 13:59:37 UTC; jhester
Author: Jim Hester [aut, cre],
Kirill Müller [aut],
Kevin Ushey [aut],
Hadley Wickham [aut],
Winston Chang [aut],
Richard Cotton [ctb],
RStudio [cph]
Maintainer: Jim Hester
Repository: CRAN
Date/Publication: 2018-03-15 22:39:56 UTC
withr/man/ 0000755 0001762 0000144 00000000000 13252301176 012162 5 ustar ligges users withr/man/with_envvar.Rd 0000644 0001762 0000144 00000002024 13216244121 014777 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/env.R
\name{with_envvar}
\alias{with_envvar}
\alias{local_envvar}
\title{Environment variables}
\usage{
with_envvar(new, code, action = "replace")
local_envvar(new, action = "replace", .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[named character]}\cr New environment variables}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{action}{should new values \code{"replace"}, \code{"prefix"} or
\code{"suffix"} existing variables with the same name.}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change system environment variables.
}
\details{
if \code{NA} is used those environment variables will be unset.
If there are any duplicated variable names only the last one is used.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=Sys.setenv]{Sys.setenv()}}
}
withr/man/devices.Rd 0000644 0001762 0000144 00000017646 13216244121 014105 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/devices.R
\name{devices}
\alias{devices}
\alias{with_dev}
\alias{with_device}
\alias{with_bmp}
\alias{local_bmp}
\alias{with_cairo_pdf}
\alias{local_cairo_pdf}
\alias{with_cairo_ps}
\alias{local_cairo_ps}
\alias{with_pdf}
\alias{local_pdf}
\alias{with_postscript}
\alias{local_postscript}
\alias{with_svg}
\alias{local_svg}
\alias{with_tiff}
\alias{local_tiff}
\alias{with_xfig}
\alias{local_xfig}
\alias{with_png}
\alias{local_png}
\alias{with_jpeg}
\alias{local_jpeg}
\title{Graphics devices}
\usage{
with_bmp(new, code, ...)
local_bmp(new, ..., .local_envir = parent.frame())
with_cairo_pdf(new, code, ...)
local_cairo_pdf(new, ..., .local_envir = parent.frame())
with_cairo_ps(new, code, ...)
local_cairo_ps(new, ..., .local_envir = parent.frame())
with_pdf(new, code, width, height, onefile, family, title, fonts, version,
paper, encoding, bg, fg, pointsize, pagecentre, colormodel, useDingbats,
useKerning, fillOddEven, compress)
local_pdf(new, width, height, onefile, family, title, fonts, version, paper,
encoding, bg, fg, pointsize, pagecentre, colormodel, useDingbats, useKerning,
fillOddEven, compress, .local_envir = parent.frame())
with_postscript(new, code, onefile, family, title, fonts, encoding, bg, fg,
width, height, horizontal, pointsize, paper, pagecentre, print.it, command,
colormodel, useKerning, fillOddEven)
local_postscript(new, onefile, family, title, fonts, encoding, bg, fg, width,
height, horizontal, pointsize, paper, pagecentre, print.it, command,
colormodel, useKerning, fillOddEven, .local_envir = parent.frame())
with_svg(new, code, width = 7, height = 7, pointsize = 12,
onefile = FALSE, family = "sans", bg = "white",
antialias = c("default", "none", "gray", "subpixel"))
local_svg(new, width = 7, height = 7, pointsize = 12, onefile = FALSE,
family = "sans", bg = "white", antialias = c("default", "none", "gray",
"subpixel"), .local_envir = parent.frame())
with_tiff(new, code, ...)
local_tiff(new, ..., .local_envir = parent.frame())
with_xfig(new, code, onefile = FALSE, encoding = "none",
paper = "default", horizontal = TRUE, width = 0, height = 0,
family = "Helvetica", pointsize = 12, bg = "transparent",
fg = "black", pagecentre = TRUE, defaultfont = FALSE,
textspecial = FALSE)
local_xfig(new, onefile = FALSE, encoding = "none", paper = "default",
horizontal = TRUE, width = 0, height = 0, family = "Helvetica",
pointsize = 12, bg = "transparent", fg = "black", pagecentre = TRUE,
defaultfont = FALSE, textspecial = FALSE, .local_envir = parent.frame())
with_png(new, code, ...)
local_png(new, ..., .local_envir = parent.frame())
with_jpeg(new, code, ...)
local_jpeg(new, ..., .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[named character]}\cr New graphics device}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{...}{Additional arguments passed to the graphics device.}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
\item{width}{the width of the device in inches.}
\item{height}{the height of the device in inches.}
\item{onefile}{should all plots appear in one file or in separate files?}
\item{family}{one of the device-independent font families,
\code{"sans"}, \code{"serif"} and \code{"mono"}, or a character
string specify a font family to be searched for in a
system-dependent way.
See, the \sQuote{Cairo fonts} section in the help for \code{\link{X11}}.
}
\item{title}{title string to embed as the \samp{/Title} field in the
file. Defaults to \code{"R Graphics Output"}.}
\item{fonts}{a character vector specifying \R graphics font family
names for additional fonts which will be included in the PDF file.
Defaults to \code{NULL}.}
\item{version}{a string describing the PDF version that will be
required to view the output. This is a minimum, and will be
increased (with a warning) if necessary. Defaults to \code{"1.4"},
but see \sQuote{Details}.}
\item{paper}{the target paper size. The choices are
\code{"a4"}, \code{"letter"}, \code{"legal"} (or \code{"us"}) and
\code{"executive"} (and these can be capitalized), or \code{"a4r"}
and \code{"USr"} for rotated (\sQuote{landscape}).
The default is \code{"special"}, which means that the \code{width}
and \code{height} specify the paper size. A further choice is
\code{"default"}; if this is selected, the
papersize is taken from the option \code{"papersize"}
if that is set and as \code{"a4"} if it is unset or empty.
Defaults to \code{"special"}.
}
\item{encoding}{the name of an encoding file. See
\code{\link{postscript}} for details. Defaults to \code{"default"}.}
\item{bg}{the initial background colour: can be overridden by setting
par("bg").}
\item{fg}{the initial foreground color to be used. Defaults to
\code{"black"}.}
\item{pointsize}{the default pointsize of plotted text (in big points).}
\item{pagecentre}{logical: should the device region be centred on the
page? -- is only relevant for \code{paper != "special"}.
Defaults to \code{TRUE}.}
\item{colormodel}{a character string describing the color model:
currently allowed values are \code{"srgb"}, \code{"gray"} (or
\code{"grey"}) and \code{"cmyk"}. Defaults to \code{"srgb"}. See section
\sQuote{Color models}.}
\item{useDingbats}{logical. Should small circles be rendered
\emph{via} the Dingbats font? Defaults to \code{TRUE}, which produces
smaller and better output. Setting this to \code{FALSE} can work
around font display problems in broken PDF viewers: although this
font is one of the 14 guaranteed to be available in all PDF viewers,
that guarantee is not always honoured.
See the \sQuote{Note} for a possible fix for some viewers.
}
\item{useKerning}{logical. Should kerning corrections be included in
setting text and calculating string widths? Defaults to \code{TRUE}.}
\item{fillOddEven}{logical controlling the polygon fill mode: see
\code{\link{polygon}} for details. Defaults to \code{FALSE}.}
\item{compress}{logical. Should PDF streams be generated with Flate
compression? Defaults to \code{TRUE}.}
\item{horizontal}{the orientation of the printed image, a logical.
Defaults to true, that is landscape orientation on paper sizes
with width less than height.}
\item{print.it}{logical: should the file be printed when the device is
closed? (This only applies if \code{file} is a real file name.)
Defaults to false.}
\item{command}{the command to be used for \sQuote{printing}. Defaults
to \code{"default"}, the value of option \code{"printcmd"}. The
length limit is \code{2*PATH_MAX}, typically 8096 bytes on unix systems and
520 bytes on windows.}
\item{antialias}{string, the type of anti-aliasing (if any) to be used;
defaults to \code{"default"}.}
\item{defaultfont}{logical: should the device use xfig's default
font?}
\item{textspecial}{logical: should the device set the textspecial flag
for all text elements. This is useful when generating pstex from xfig
figures.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily use a graphics device.
}
\section{Functions}{
\itemize{
\item \code{with_bmp}: BMP device
\item \code{with_cairo_pdf}: CAIRO_PDF device
\item \code{with_cairo_ps}: CAIRO_PS device
\item \code{with_pdf}: PDF device
\item \code{with_postscript}: POSTSCRIPT device
\item \code{with_svg}: SVG device
\item \code{with_tiff}: TIFF device
\item \code{with_xfig}: XFIG device
\item \code{with_png}: PNG device
\item \code{with_jpeg}: JPEG device
}}
\examples{
# dimensions are in inches
with_pdf(file.path(tempdir(), "test.pdf"), width = 7, height = 5,
plot(runif(5))
)
# dimensions are in pixels
with_png(file.path(tempdir(), "test.png"), width = 800, height = 600,
plot(runif(5))
)
}
\seealso{
\code{\link{withr}} for examples
\code{\link[grDevices]{Devices}}
}
withr/man/with_file.Rd 0000644 0001762 0000144 00000001535 13216244121 014423 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/file.R
\name{with_file}
\alias{with_file}
\alias{local_file}
\title{Files which delete themselves}
\usage{
with_file(file, code)
local_file(file, .local_envir = parent.frame())
}
\arguments{
\item{file}{\code{[named list]}\cr Files to create.}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Create files, which are then automatically removed afterwards.
}
\examples{
with_file("file1", {
writeLines("foo", "file1")
readLines("file1")
})
with_file(list("file1" = writeLines("foo", "file1")), {
readLines("file1")
})
}
\seealso{
\code{\link{withr}} for examples
}
withr/man/set_makevars.Rd 0000644 0001762 0000144 00000001740 13252301176 015137 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/makevars.R
\name{set_makevars}
\alias{set_makevars}
\title{Create a new \code{Makevars} file, by adding new variables}
\usage{
set_makevars(variables, old_path = file.path("~", ".R", "Makevars"),
new_path = tempfile(), assignment = c("=", ":=", "?=", "+="))
}
\arguments{
\item{variables}{\code{[named character]}\cr new variables and their values}
\item{old_path}{\code{[character(1)]}\cr location of existing \code{Makevars}
file to modify.}
\item{new_path}{\code{[character(1)]}\cr location of the new \code{Makevars} file}
\item{assignment}{\code{[character(1)]}\cr assignment type to use.}
}
\description{
You probably want \code{\link[=with_makevars]{with_makevars()}} instead of this function.
}
\details{
Unlike \code{\link[=with_makevars]{with_makevars()}}, it does not activate the new \code{Makevars}
file, i.e. it does not set the \code{R_MAKEVARS_USER} environment variable.
}
\keyword{internal}
withr/man/with_options.Rd 0000644 0001762 0000144 00000001301 13216244121 015166 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/options.R
\name{with_options}
\alias{with_options}
\alias{local_options}
\title{Options}
\usage{
with_options(new, code)
local_options(new, .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[named list]}\cr New options and their values}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change global options.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=options]{options()}}
}
withr/man/with_sink.Rd 0000644 0001762 0000144 00000002730 13216244121 014446 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/sink.R
\name{with_sink}
\alias{with_sink}
\alias{with_output_sink}
\alias{local_output_sink}
\alias{with_message_sink}
\alias{local_message_sink}
\title{Output redirection}
\usage{
with_output_sink(new, code, append = FALSE, split = FALSE)
local_output_sink(new, append = FALSE, split = FALSE,
.local_envir = parent.frame())
with_message_sink(new, code, append = FALSE)
local_message_sink(new, append = FALSE, .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[character(1)|connection]}\cr
A writable \link{connection} or a character string naming the file to write
to. Passing \code{NULL} will throw an error.}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{append}{logical. If \code{TRUE}, output will be appended to
\code{file}; otherwise, it will overwrite the contents of
\code{file}.}
\item{split}{logical: if \code{TRUE}, output will be sent to the new
sink and to the current output stream, like the Unix program \code{tee}.}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily divert output to a file via \code{\link[=sink]{sink()}}. For
sinks of type \code{message}, an error is raised if such a sink is already
active.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=sink]{sink()}}
}
withr/man/with_gctorture2.Rd 0000644 0001762 0000144 00000001366 13216244121 015606 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/torture.R
\name{with_gctorture2}
\alias{with_gctorture2}
\title{Torture Garbage Collector}
\usage{
with_gctorture2(new, code, wait = new, inhibit_release = FALSE)
}
\arguments{
\item{new}{\code{[integer]}\cr run GC every 'step' allocations.}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{wait}{integer; number of allocations to wait before starting
GC torture.}
\item{inhibit_release}{logical; do not release free objects for
re-use: use with caution.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily turn gctorture2 on.
}
\seealso{
\code{\link{withr}} for examples
}
withr/man/withr.Rd 0000644 0001762 0000144 00000005052 13152330153 013604 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/with.R
\docType{package}
\name{withr}
\alias{withr}
\alias{withr-package}
\title{Execute code in temporarily altered environment}
\description{
All functions prefixed by \code{with_} work as follows. First, a particular
aspect of the global environment is modified (see below for a list).
Then, custom code (passed via the \code{code} argument) is executed.
Upon completion or error, the global environment is restored to the previous
state. Each \code{with_} function has a \code{local_} variant, which instead resets
the state when the current evaluation context ends (such as the end of a
function).
}
\section{Arguments pattern}{
\tabular{lll}{
\code{new} \tab \code{[various]} \tab Values for setting \cr
\code{code} \tab \code{[any]} \tab Code to execute in the temporary environment \cr
\code{...} \tab \tab Further arguments \cr
}
}
\section{Usage pattern}{
\code{with_...(new, code, ...)}
}
\section{withr functions}{
\itemize{
\item \code{\link[=with_collate]{with_collate()}}: collation order
\item \code{\link[=with_dir]{with_dir()}}: working directory
\item \code{\link[=with_envvar]{with_envvar()}}: environment variables
\item \code{\link[=with_libpaths]{with_libpaths()}}: library paths, replacing current libpaths
\item \code{\link[=with_locale]{with_locale()}}: any locale setting
\item \code{\link[=with_makevars]{with_makevars()}}: Makevars variables
\item \code{\link[=with_options]{with_options()}}: options
\item \code{\link[=with_par]{with_par()}}: graphics parameters
\item \code{\link[=with_path]{with_path()}}: \code{PATH} environment variable
\item \code{\link[=with_sink]{with_sink()}}: output redirection
}
}
\section{Creating new "with" functions}{
All \code{with_} functions are created by a helper function,
\code{\link[=with_]{with_()}}. This functions accepts two arguments:
a setter function and an optional resetter function. The setter function is
expected to change the global state and return an "undo instruction".
This undo instruction is then passed to the resetter function, which changes
back the global state. In many cases, the setter function can be used
naturally as resetter.
}
\examples{
getwd()
with_dir(tempdir(), getwd())
getwd()
Sys.getenv("WITHR")
with_envvar(c("WITHR" = 2), Sys.getenv("WITHR"))
Sys.getenv("WITHR")
with_envvar(c("A" = 1),
with_envvar(c("A" = 2), action = "suffix", Sys.getenv("A"))
)
# local variants are best used within other functions
f <- function(x) {
local_envvar(c("WITHR" = 2))
Sys.getenv("WITHR")
}
Sys.getenv("WITHR")
}
withr/man/with_locale.Rd 0000644 0001762 0000144 00000001431 13216244121 014736 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/locale.R
\name{with_locale}
\alias{with_locale}
\alias{local_locale}
\title{Locale settings}
\usage{
with_locale(new, code)
local_locale(new, .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[named character]}\cr New locale settings}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change locale settings.
}
\details{
Setting the \code{LC_ALL} category is currently not implemented.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=Sys.setlocale]{Sys.setlocale()}}
}
withr/man/with_par.Rd 0000644 0001762 0000144 00000001501 13216244121 014257 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/par.R
\name{with_par}
\alias{with_par}
\alias{local_par}
\title{Graphics parameters}
\usage{
with_par(new, code, no.readonly = FALSE)
local_par(new, no.readonly = FALSE, .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[named list]}\cr New graphics parameters and their values}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{no.readonly}{\code{[logical(1)]}\cr see \code{\link[=par]{par()}} documentation.}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change graphics parameters.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=par]{par()}}
}
withr/man/with_temp_libpaths.Rd 0000644 0001762 0000144 00000001623 13252301176 016341 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/libpaths.R
\name{with_temp_libpaths}
\alias{with_temp_libpaths}
\alias{local_temp_libpaths}
\title{Library paths}
\usage{
with_temp_libpaths(code, action = "prefix")
local_temp_libpaths(action = "prefix", .local_envir = parent.frame())
}
\arguments{
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{action}{\code{[character(1)]}\cr should new values \code{"replace"}, \code{"prefix"} or
\code{"suffix"} existing paths.}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily prepend a new temporary directory to the library paths.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=.libPaths]{.libPaths()}}
Other libpaths: \code{\link{with_libpaths}}
}
withr/man/with_dir.Rd 0000644 0001762 0000144 00000001271 13216244121 014257 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/dir.R
\name{with_dir}
\alias{with_dir}
\alias{local_dir}
\title{Working directory}
\usage{
with_dir(new, code)
local_dir(new, .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[character(1)]}\cr New working directory}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change the current working directory.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=setwd]{setwd()}}
}
withr/man/with_.Rd 0000644 0001762 0000144 00000004462 13252301176 013571 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/local_.R, R/with_.R
\name{local_}
\alias{local_}
\alias{with_}
\title{Create a new "with" or "local" function}
\usage{
local_(set, reset = set, envir = parent.frame(), new = TRUE)
with_(set, reset = set, envir = parent.frame(), new = TRUE)
}
\arguments{
\item{set}{\code{[function(...)]}\cr Function used to set the state.
The function can have arbitrarily many arguments, they will be replicated
in the formals of the returned function.}
\item{reset}{\code{[function(x)]}\cr Function used to reset the state.
The first argument can be named arbitrarily, further arguments with default
values, or a "dots" argument, are supported but not used: The function will
be called as \code{reset(old)}.}
\item{envir}{\code{[environment]}\cr Environment of the returned function.}
\item{new}{\code{[logical(1)]}\cr Replace the first argument of the \code{set} function
by \code{new}? Set to \code{FALSE} if the \code{set} function only has optional arguments.}
}
\value{
\code{[function(new, code, ...)]} A function with at least two arguments,
\itemize{
\item \code{new}: New state to use
\item \code{code}: Code to run in that state.
}
If there are more arguments to the function passed in \code{set} they are
added to the returned function. If \code{set} does not have arguments,
or \code{new} is \code{FALSE}, the returned function does not have a \code{code} argument.
}
\description{
These are constructors for \code{with_...} or \code{local_...} functions.
They are only needed if you want to alter some global state which is not
covered by the existing \code{with_...} functions, see \link{withr-package}
for an overview.
}
\details{
The \code{with_...} functions reset the state immediately after the
\code{code} argument has been evaluated. The \code{local_...} functions
reset their arguments after they go out of scope, usually at the end of the
function body.
}
\examples{
with_(setwd)
global_stack <- list()
set_global_state <- function(state, msg = "Changing global state.") {
global_stack <- c(list(state), global_stack)
message(msg)
state
}
reset_global_state <- function(state) {
old_state <- global_stack[[1]]
global_stack <- global_stack[-1]
stopifnot(identical(state, old_state))
}
with_(set_global_state, reset_global_state)
}
\keyword{internal}
withr/man/with_db_connection.Rd 0000644 0001762 0000144 00000002477 13216244121 016316 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/db.R
\name{with_db_connection}
\alias{with_db_connection}
\alias{local_db_connection}
\title{DBMS Connections which disconnect themselves.}
\usage{
with_db_connection(con, code)
local_db_connection(con, .local_envir = parent.frame())
}
\arguments{
\item{con}{For \code{with_db_connection()} a named list with the connection(s) to
create. For \code{local_db_connection()} the code to create a single connection,
which is then returned.}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Connections to Database Management Systems which automatically disconnect. In
particular connections which are created with \code{DBI::dbConnect()} and closed
with \code{DBI::dbDisconnect()}.
}
\examples{
db <- tempfile()
with_db_connection(
list(con = DBI::dbConnect(RSQLite::SQLite(), db)), {
DBI::dbWriteTable(con, "mtcars", mtcars)
})
head_db_table <- function(...) {
con <- local_db_connection(DBI::dbConnect(RSQLite::SQLite(), db))
head(DBI::dbReadTable(con, "mtcars"), ...)
}
head_db_table()
unlink(db)
}
\seealso{
\code{\link{withr}} for examples
}
withr/man/with_libpaths.Rd 0000644 0001762 0000144 00000001636 13216244121 015314 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/libpaths.R
\name{with_libpaths}
\alias{with_libpaths}
\alias{local_libpaths}
\title{Library paths}
\usage{
with_libpaths(new, code, action = "replace")
local_libpaths(new, action = "replace", .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[character]}\cr New library paths}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{action}{\code{[character(1)]}\cr should new values \code{"replace"}, \code{"prefix"} or
\code{"suffix"} existing paths.}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change library paths.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=.libPaths]{.libPaths()}}
Other libpaths: \code{\link{with_temp_libpaths}}
}
withr/man/with_connection.Rd 0000644 0001762 0000144 00000002013 13216244121 015633 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/connection.R
\name{with_connection}
\alias{with_connection}
\alias{local_connection}
\title{Connections which close themselves}
\usage{
with_connection(con, code)
local_connection(con, .local_envir = parent.frame())
}
\arguments{
\item{con}{For \code{with_connection()} a named list with the connection(s) to
create. For \code{local_connection()} the code to create a single connection,
which is then returned.}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
R file connections which are automatically closed.
}
\examples{
with_connection(list(con = file("foo", "w")), {
writeLines(c("foo", "bar"), con)
})
read_foo <- function() {
readLines(local_connection(file("foo", "r")))
}
read_foo()
}
\seealso{
\code{\link{withr}} for examples
}
withr/man/with_path.Rd 0000644 0001762 0000144 00000001556 13216244121 014443 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/path.R
\name{with_path}
\alias{with_path}
\alias{local_path}
\title{PATH environment variable}
\usage{
with_path(new, code, action = "prefix")
local_path(new, action = "prefix", .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[character]}\cr New \code{PATH} entries}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{action}{\code{[character(1)]}\cr Should new values \code{"replace"}, \code{"prefix"} or
\code{"suffix"} existing paths}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change the system search path.
}
\seealso{
\code{\link{withr}} for examples
\code{\link[=Sys.setenv]{Sys.setenv()}}
}
withr/man/defer.Rd 0000644 0001762 0000144 00000003574 13216244121 013543 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/defer.R
\name{defer}
\alias{defer}
\alias{defer_parent}
\title{Defer Evaluation of an Expression}
\usage{
defer(expr, envir = parent.frame(), priority = c("first", "last"))
defer_parent(expr, priority = c("first", "last"))
}
\arguments{
\item{expr}{\code{[expression]}\cr An expression to be evaluated.}
\item{envir}{\code{[environment]}\cr Attach exit handlers to this environment.
Typically, this should be either the current environment or
a parent frame (accessed through \code{\link[=parent.frame]{parent.frame()}}).}
\item{priority}{\code{[character(1)]}\cr Specify whether this handler should
be executed \code{"first"} or \code{"last"}, relative to any other
registered handlers on this environment.}
}
\description{
Similar to \code{\link[=on.exit]{on.exit()}}, but allows one to attach
an expression to be evaluated when exiting any frame currently
on the stack. This provides a nice mechanism for scoping side
effects for the duration of a function's execution.
}
\details{
\code{defer} works by attaching handlers to the requested environment (as an
attribute called \code{"handlers"}), and registering an exit handler that
executes the registered handler when the function associated with the
requested environment finishes execution.
}
\examples{
# define a 'local' function that creates a file, and
# removes it when the parent function has finished executing
local_file <- function(path) {
file.create(path)
defer_parent(unlink(path))
}
# create tempfile path
path <- tempfile()
# use 'local_file' in a function
local({
local_file(path)
stopifnot(file.exists(path))
})
# file is deleted as we leave 'local' local
stopifnot(!file.exists(path))
# investigate how 'defer' modifies the
# executing function's environment
local({
local_file(path)
print(attributes(environment()))
})
}
\author{
Kevin Ushey
}
withr/man/with_makevars.Rd 0000644 0001762 0000144 00000002205 13216244121 015310 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/makevars.R
\name{with_makevars}
\alias{with_makevars}
\title{Makevars variables}
\usage{
with_makevars(new, code, path = file.path("~", ".R", "Makevars"),
assignment = c("=", ":=", "?=", "+="))
}
\arguments{
\item{new}{\code{[named character]}\cr New variables and their values}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{path}{\code{[character(1)]}\cr location of existing \code{Makevars} file to modify.}
\item{assignment}{\code{[character(1)]}\cr assignment type to use.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change contents of an existing \code{Makevars} file.
}
\details{
If no \code{Makevars} file exists or the fields in \code{new} do
not exist in the existing \code{Makevars} file then the fields are added to
the new file. Existing fields which are not included in \code{new} are
appended unchanged. Fields which exist in \code{Makevars} and in \code{new}
are modified to use the value in \code{new}.
}
\seealso{
\code{\link{withr}} for examples
}
withr/man/with_package.Rd 0000644 0001762 0000144 00000006667 13216244121 015112 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/namespace.R
\name{with_package}
\alias{with_package}
\alias{local_package}
\alias{with_namespace}
\alias{local_namespace}
\alias{with_environment}
\alias{local_environment}
\title{Execute code with a modified search path}
\usage{
with_package(package, code, help, pos = 2, lib.loc = NULL,
character.only = TRUE, logical.return = FALSE, warn.conflicts = FALSE,
quietly = TRUE, verbose = getOption("verbose"))
local_package(package, help, pos = 2, lib.loc = NULL,
character.only = TRUE, logical.return = FALSE, warn.conflicts = FALSE,
quietly = TRUE, verbose = getOption("verbose"),
.local_envir = parent.frame())
with_namespace(package, code, warn.conflicts = FALSE)
local_namespace(package, .local_envir = parent.frame(),
warn.conflicts = FALSE)
with_environment(env, code, pos = 2L, name = format(env),
warn.conflicts = FALSE)
local_environment(env, pos = 2L, name = format(env),
warn.conflicts = FALSE, .local_envir = parent.frame())
}
\arguments{
\item{package}{\code{[character(1)]}\cr package name to load.}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{help}{the name of a package, given as a \link{name} or
literal character string, or a character string, depending on
whether \code{character.only} is \code{FALSE} (default) or
\code{TRUE}).}
\item{pos}{the position on the search list at which to attach the
loaded namespace. Can also be the name of a position on the current
search list as given by \code{\link{search}()}.}
\item{lib.loc}{a character vector describing the location of \R
library trees to search through, or \code{NULL}. The default value
of \code{NULL} corresponds to all libraries currently known to
\code{\link{.libPaths}()}.
Non-existent library trees are silently ignored.}
\item{character.only}{a logical indicating whether \code{package} or
\code{help} can be assumed to be character strings.}
\item{logical.return}{logical. If it is \code{TRUE}, \code{FALSE} or
\code{TRUE} is returned to indicate success.}
\item{warn.conflicts}{logical. If \code{TRUE}, warnings are
printed about \code{\link{conflicts}} from attaching the new
package. A conflict is a function masking a function,
or a non-function masking a non-function.
}
\item{quietly}{a logical. If \code{TRUE}, no message confirming
package attaching is printed, and most often, no errors/warnings are
printed if package attaching fails.}
\item{verbose}{a logical. If \code{TRUE}, additional diagnostics are
printed.}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
\item{env}{\code{[environment()]}\cr Environment to attach.}
\item{name}{name to use for the attached database. Names starting with
\code{package:} are reserved for \code{\link{library}}.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
\code{with_package()} attaches a package to the search path, executes the code, then
removes the package from the search path. The package namespace is \emph{not}
unloaded however. \code{with_namespace()} does the same thing, but attaches the
package namespace to the search path, so all objects (even unexported ones) are also
available on the search path.
}
\examples{
\dontrun{
with_package("ggplot2", {
ggplot(mtcars) + geom_point(aes(wt, hp))
})
}
}
\seealso{
\code{\link{withr}} for examples
}
withr/man/with_tempfile.Rd 0000644 0001762 0000144 00000002123 13216244121 015303 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/tempfile.R
\name{with_tempfile}
\alias{with_tempfile}
\alias{local_tempfile}
\title{Temporary files}
\usage{
with_tempfile(new, code, envir = parent.frame(), pattern = "file",
tmpdir = tempdir(), fileext = "")
local_tempfile(new, envir = parent.frame(), pattern = "file",
tmpdir = tempdir(), fileext = "")
}
\arguments{
\item{new}{\code{[character vector]}\cr Names of temporary file handles to create.}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{envir}{\code{[environment]}\cr Environment in which to define the temporary files.}
\item{pattern}{a non-empty character vector giving the initial part
of the name.}
\item{tmpdir}{a non-empty character vector giving the directory name}
\item{fileext}{a non-empty character vector giving the file extension}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily create a tempfile, which is automatically removed afterwards.
}
\seealso{
\code{\link{withr}} for examples
}
withr/man/with_seed.Rd 0000644 0001762 0000144 00000002062 13216244121 014420 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/seed.R
\name{with_seed}
\alias{with_seed}
\alias{with_preserve_seed}
\title{Random seed}
\usage{
with_seed(seed, code)
with_preserve_seed(code)
}
\arguments{
\item{seed}{\code{[integer(1)]}\cr The random seed to use to evaluate the code.}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
\code{with_seed()} runs code with a specific random seed and resets it afterwards.
\code{with_preserve_seed()} runs code with the current random seed and resets it
afterwards.
}
\examples{
# Same random values:
with_preserve_seed(runif(5))
with_preserve_seed(runif(5))
# Use a pseudorandom value as seed to advance the RNG and pick a different
# value for the next call:
with_seed(seed <- sample.int(.Machine$integer.max, 1L), runif(5))
with_seed(seed, runif(5))
with_seed(seed <- sample.int(.Machine$integer.max, 1L), runif(5))
}
\seealso{
\code{\link{withr}} for examples
}
withr/man/with_collate.Rd 0000644 0001762 0000144 00000001326 13216244121 015125 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/collate.R
\name{with_collate}
\alias{with_collate}
\alias{local_collate}
\title{Collation Order}
\usage{
with_collate(new, code)
local_collate(new, .local_envir = parent.frame())
}
\arguments{
\item{new}{\code{[character(1)]}\cr New collation order}
\item{code}{\code{[any]}\cr Code to execute in the temporary environment}
\item{.local_envir}{\code{[environment]}\cr The environment to use for scoping.}
}
\value{
\code{[any]}\cr The results of the evaluation of the \code{code}
argument.
}
\description{
Temporarily change collation order by changing the value of the
\code{LC_COLLATE} locale.
}
\seealso{
\code{\link{withr}} for examples
}