diff --git a/.Rbuildignore b/.Rbuildignore index 28455c37ba..99c6f14c66 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -8,3 +8,4 @@ ^codecov\.yml$ ^_pkgdown\.yml$ ^docs$ +^appveyor\.yml$ diff --git a/.travis.yml b/.travis.yml index e76cae1737..eacc46264b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,14 @@ language: r sudo: false cache: packages -r: - - oldrel - - release - - devel + +matrix: + include: + - r: 3.1 + warnings_are_errors: false + - r: oldrel + - r: release + - r: devel after_success: - Rscript -e 'covr::codecov(line_exclusions = c("R/lazy.R", "R/lazy-as.R", "R/lazy-dots.R", "R/lazy-names.R", "R/lazy-call.R", "R/lazy-eval.R", "R/lazy-interp.R", "src/lazy.c"))' diff --git a/DESCRIPTION b/DESCRIPTION index fbab7f8a98..55047fa14c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: rlang -Version: 0.1.1 +Version: 0.1.2 Title: Functions for Base Types and Core R and 'Tidyverse' Features Description: A toolbox for working with base types, core R features like the condition system, and core 'Tidyverse' features like tidy diff --git a/NEWS.md b/NEWS.md index 86364948af..db76322a7d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,9 @@ +# rlang 0.1.2 + +This hotfix release makes rlang compatible with the R 3.1 branch. + + # rlang 0.1.1 This release includes two important fixes for tidy evaluation: diff --git a/R/compat-oldrel.R b/R/compat-oldrel.R index 8557bc35ae..1c9cf93ac6 100644 --- a/R/compat-oldrel.R +++ b/R/compat-oldrel.R @@ -1,57 +1,39 @@ -# nocov start - compat-oldrel (last updated: rlang 0.1.9000) +# nocov start - compat-oldrel (last updated: rlang 0.1.2) # This file serves as a reference for compatibility functions for old -# versions of R. - - -# Compat function for capture functions (that will hopefully make -# their way to the next R version) ----------------------------------- - -if (TRUE || utils::packageVersion("base") < "3.4.0") { - - captureArg <- function(x, strict = TRUE) { - caller_env <- parent.frame() - - if (identical(caller_env, globalenv())) { - stop("must be called in a function") - } - if (missing(x)) { - stop("argument \"x\" is missing") - } - - .Call(rlang_capturearg, NULL, NULL, pairlist(caller_env, strict), get_env()) - } - - captureDots <- function(strict = TRUE) { - caller_env <- parent.frame() - - if (!exists("...", caller_env)) { - stop("must be called in a function where dots exist") - } - - .Call(rlang_capturedots, NULL, NULL, pairlist(caller_env, strict), get_env()) - } - -} +# versions of R. Please find the most recent version in rlang's +# repository. # R 3.2.0 ------------------------------------------------------------ -if (utils::packageVersion("base") < "3.2.0") { +if (getRversion() < "3.2.0") { dir_exists <- function(path) { !identical(path, "") && file.exists(paste0(path, .Platform$file.sep)) } dir.exists <- function(paths) { - map_lgl(paths, dir_exists) + vapply(paths, dir_exists, logical(1)) } names <- function(x) { if (is.environment(x)) { - ls(x, all.names = TRUE) + return(ls(x, all.names = TRUE)) } else { - base::names(x) + return(base::names(x)) } + + # So R CMD check on old versions of R sees a generic, since we + # declare a names() method for dictionary objects + UseMethod("names") + } + + trimws <- function(x, which = c("both", "left", "right")) { + switch(match.arg(which), + left = sub("^[ \t\r\n]+", "", x, perl = TRUE), + right = sub("[ \t\r\n]+$", "", x, perl = TRUE), + both = trimws(trimws(x, "left"), "right") + ) } } diff --git a/R/env.R b/R/env.R index c7a7838800..c33a7e2c59 100644 --- a/R/env.R +++ b/R/env.R @@ -425,15 +425,11 @@ set_env <- function(env, new_env = caller_env()) { ) } -mut_parent_env <- function(env, new_env) { - env_ <- get_env(env) - parent.env(env_) <- get_env(new_env) - env +mut_env_parent <- function(env, new_env) { + .Call(rlang_mut_env_parent, get_env(env), new_env) } `env_parent<-` <- function(x, value) { - env_ <- get_env(x) - parent.env(env_) <- get_env(value) - x + .Call(rlang_mut_env_parent, get_env(x), value) } diff --git a/R/eval-tidy.R b/R/eval-tidy.R index 651a8e73c3..75d294d55a 100644 --- a/R/eval-tidy.R +++ b/R/eval-tidy.R @@ -295,7 +295,7 @@ overscope_eval_next <- function(overscope, quo, env = base_env()) { lexical_env <- f_env(quo) overscope$.env <- lexical_env - mut_parent_env(overscope$.top_env, lexical_env) + mut_env_parent(overscope$.top_env, lexical_env) .Call(rlang_eval, f_rhs(quo), overscope) } @@ -328,13 +328,10 @@ f_self_eval <- function(overscope, overscope_top) { return(missing_arg()) } - # Swap enclosures temporarily by rechaining the top of the - # dynamic scope to the enclosure of the new formula, if it has - # one. We do it at C level to avoid GC adjustments when changing - # the parent. This should be safe since we reset everything - # afterwards. - .Call(rlang_set_parent, overscope_top, f_env(f) %||% overscope$.env) - on.exit(.Call(rlang_set_parent, overscope_top, overscope$.env)) + # Swap enclosures temporarily by rechaining the top of the dynamic + # scope to the enclosure of the new formula, if it has one + mut_env_parent(overscope_top, f_env(f) %||% overscope$.env) + on.exit(mut_env_parent(overscope_top, overscope$.env)) .Call(rlang_eval, f_rhs(f), overscope) } diff --git a/R/types.R b/R/types.R index d4ddc49eb4..f01b0e7da3 100644 --- a/R/types.R +++ b/R/types.R @@ -664,11 +664,6 @@ lang_type_of <- function(x) { #' #' structure(base::list, foo = "bar") #' str(base::list) -#' -#' # In expressions, calls and pairlists are safely copyable. However, -#' # symbols are not: -#' structure(quote(foo), foo = "bar") -#' quote(foo) is_copyable <- function(x) { switch_type(x, NULL = , diff --git a/R/utils.R b/R/utils.R index b3718f8b55..197054f340 100644 --- a/R/utils.R +++ b/R/utils.R @@ -75,3 +75,25 @@ discard_unnamed <- function(x) { sxp_address <- function(x) { .Call(rlang_sxp_address, x) } + +captureArg <- function(x, strict = TRUE) { + caller_env <- parent.frame() + + if (identical(caller_env, globalenv())) { + stop("must be called in a function") + } + if (missing(x)) { + stop("argument \"x\" is missing") + } + + .Call(rlang_capturearg, NULL, NULL, pairlist(caller_env, strict), get_env()) +} +captureDots <- function(strict = TRUE) { + caller_env <- parent.frame() + + if (!exists("...", caller_env)) { + stop("must be called in a function where dots exist") + } + + .Call(rlang_capturedots, NULL, NULL, pairlist(caller_env, strict), get_env()) +} diff --git a/cran-comments.md b/cran-comments.md index c5642e9c30..a1b8966123 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,16 +1,8 @@ -## Bugfix release - -The last rlang release was sent recently, but we have discovered one -issue with the bytecode compiler that causes downstream failures in -the reverse dependencies of the next dplyr version. This release -should prevent many R CMD check failures for compiled packages -depending on dplyr. - ## Test environments -* local OS X install, R 3.4.0 -* ubuntu 12.04 (on travis-ci), R 3.4.0 +* local OS X install, R 3.4.1 +* ubuntu 12.04 (on travis-ci), R 3.4.1 * win-builder (devel and release) @@ -21,7 +13,7 @@ depending on dplyr. ## Reverse dependencies -I have run R CMD check on the 2 downstream dependencies. (Summary at -https://github.com/tidyverse/rlang/tree/master/revdep). +I have run R CMD check on the 37 downstream dependencies. (Summary at +https://github.com/tidyverse/rlang/tree/v0.1.2/revdep). There were no problems. diff --git a/man/is_copyable.Rd b/man/is_copyable.Rd index bcae55e794..88a162c316 100644 --- a/man/is_copyable.Rd +++ b/man/is_copyable.Rd @@ -31,9 +31,4 @@ is_copyable(env) structure(base::list, foo = "bar") str(base::list) - -# In expressions, calls and pairlists are safely copyable. However, -# symbols are not: -structure(quote(foo), foo = "bar") -quote(foo) } diff --git a/revdep/README.md b/revdep/README.md index 2e1fdc2ba0..4d8e8442e0 100644 --- a/revdep/README.md +++ b/revdep/README.md @@ -1,53 +1,69 @@ -# Setup +# Platform -## Platform - -|setting |value | +|field |value | |:--------|:----------------------------| -|version |R version 3.4.0 (2017-04-21) | +|version |R version 3.4.1 (2017-06-30) | +|os |macOS Sierra 10.12 | |system |x86_64, darwin15.6.0 | |ui |X11 | |language |(EN) | |collate |en_US.UTF-8 | |tz |Europe/Brussels | -|date |2017-05-17 | - -## Packages - -|package |* |version |date |source | -|:---------|:--|:-------|:----------|:--------------| -|covr | |2.2.2 |2017-01-05 |cran (@2.2.2) | -|knitr | |1.15.1 |2016-11-22 |cran (@1.15.1) | -|rlang | |0.1 |2017-05-06 |cran (@0.1) | -|rmarkdown | |1.5 |2017-04-26 |cran (@1.5) | -|testthat | |1.0.2 |2016-04-23 |cran (@1.0.2) | - -# Check results +|date |2017-08-08 | -2 packages +# Dependencies -|package |version | errors| warnings| notes| -|:-------|:-------|------:|--------:|-----:| -|sf |0.4-3 | 0| 0| 1| -|tibble |1.3.1 | 0| 0| 0| +|package |old |new |Δ | +|:-------|:-----|:-----|:--| +|rlang |0.1.1 |0.1.2 |* | -## sf (0.4-3) -Maintainer: Edzer Pebesma -Bug reports: https://github.com/edzer/sfr/issues/ +# Revdeps -0 errors | 0 warnings | 1 note +## Broken (1) -``` -checking installed package size ... NOTE - installed size is 7.9Mb - sub-directories of 1Mb or more: - doc 4.0Mb - sqlite 1.5Mb -``` +|package |version |error |warning |note | +|:------------------------|:-------|:------|:-------|:----| +|[banR](problems.md#banR) |0.2.0 |__+1__ | |1 | -## tibble (1.3.1) -Maintainer: Kirill Müller -Bug reports: https://github.com/tidyverse/tibble/issues +## All (37) -0 errors | 0 warnings | 0 notes +|package |version |error |warning |note | +|:------------------------|:-------|:------|:-------|:----| +|[banR](problems.md#banR) |0.2.0 |__+1__ | |1 | +|dbplyr |1.1.0 | | |1 | +|dexter |0.4.2 | |2 |1 | +|dplyr |0.7.2 | | |2 | +|fold |0.2.1 | | | | +|ggformula |0.5 | | |1 | +|iadf |0.1.0 | | | | +|implyr |0.2.1 |1 | | | +|later |0.3 | | | | +|metaplot |0.1.5 | | | | +|mosaicCore |0.2.0 | | | | +|nofrills |0.1.0 | | | | +|nonmemica |0.7.6 | |1 |1 | +|NPMOD |0.1.0 |1 | | | +|polypoly |0.0.2 | | | | +|prisonbrief |0.1.0 | | |1 | +|purrr |0.2.3 | | | | +|recipes |0.1.0 | | | | +|rsample |0.0.1 | | | | +|RSDA |2.0.2 | | | | +|seplyr |0.1.3 | | |1 | +|sf |0.5-3 |1 | | | +|sjmisc |2.6.0 | | | | +|sjPlot |2.3.2 | | |2 | +|sjstats |0.10.3 | | |1 | +|sparklyr |0.6.1 |1 | | | +|spdplyr |0.1.3 | | | | +|statar |0.6.5 | | | | +|stplanr |0.1.9 | |1 | | +|sugrrants |0.1.0 | | | | +|tatoo |1.0.7 | | | | +|taxa |0.1.0 | | |1 | +|tibble |1.3.3 | | | | +|tidygraph |1.0.0 | | | | +|tidyselect |0.1.1 | | |1 | +|valr |0.3.1 | | | | +|vdiffr |0.2.0 | | | | diff --git a/revdep/data.sqlite b/revdep/data.sqlite new file mode 100644 index 0000000000..c960798a82 Binary files /dev/null and b/revdep/data.sqlite differ diff --git a/revdep/problems.md b/revdep/problems.md index 7ad489f347..a3ef2b563a 100644 --- a/revdep/problems.md +++ b/revdep/problems.md @@ -1,31 +1,40 @@ -# Setup - -## Platform - -|setting |value | -|:--------|:----------------------------| -|version |R version 3.4.0 (2017-04-21) | -|system |x86_64, darwin15.6.0 | -|ui |X11 | -|language |(EN) | -|collate |en_US.UTF-8 | -|tz |Europe/Brussels | -|date |2017-05-17 | - -## Packages - -|package |* |version |date |source | -|:---------|:--|:-------|:----------|:--------------| -|covr | |2.2.2 |2017-01-05 |cran (@2.2.2) | -|knitr | |1.15.1 |2016-11-22 |cran (@1.15.1) | -|rlang | |0.1 |2017-05-06 |cran (@0.1) | -|rmarkdown | |1.5 |2017-04-26 |cran (@1.5) | -|testthat | |1.0.2 |2016-04-23 |cran (@1.0.2) | - -# Check results - -0 packages with problems - - - +# banR + +Version: 0.2.0 + +## Newly broken + +* checking examples ... ERROR + ``` + ... + If file is larger than 8 MB, it must be splitted + Size is : 61 bytes + SuccessOKSuccess: (200) OK + # A tibble: 3 x 16 + y z x latitude longitude + + 1 75015 -0.6264538 39 quai Andre Citroen 48.84683 2.279092 + 2 75012 0.1836433 64 Allee de Bercy 48.84255 2.375933 + 3 75007 -0.8356286 20 avenue de Segur 48.85032 2.308332 + # ... with 11 more variables: result_label , result_score , + # result_type , result_id , result_housenumber , + # result_name , result_street , result_postcode , + # result_city , result_context , result_citycode + > geocode_tbl(tbl = table_test, adresse = x, code_postal = y) + Writing tempfile to.../var/folders/b9/1vbq6rn93_1fk71sn95dqb8r0000gn/T//RtmpTIqQ1D/file970d7b3ad7f0.csv + If file is larger than 8 MB, it must be splitted + Size is : 81 bytes + Server errorService UnavailableServer error: (503) Service Unavailable + Error in geocode_tbl(tbl = table_test, adresse = x, code_postal = y) : + The API sent back an error 503 + Execution halted + ``` + +## In both + +* checking dependencies in R code ... NOTE + ``` + Namespace in Imports field not imported from: ‘stringr’ + All declared Imports should be used. + ``` diff --git a/src/env.c b/src/env.c new file mode 100644 index 0000000000..ce145450d3 --- /dev/null +++ b/src/env.c @@ -0,0 +1,7 @@ +#define R_NO_REMAP +#include + +SEXP r_mut_env_parent(SEXP env, SEXP new_parent) { + SET_ENCLOS(env, new_parent); + return env; +} diff --git a/src/init.c b/src/init.c index 846b70da58..c1f2777f26 100644 --- a/src/init.c +++ b/src/init.c @@ -12,6 +12,7 @@ extern bool is_clevel_spliceable(SEXP); // Callable from this package extern SEXP f_lhs_(SEXP); extern SEXP f_rhs_(SEXP); +extern SEXP r_mut_env_parent(SEXP, SEXP); extern SEXP rlang_replace_na(SEXP, SEXP); extern SEXP rlang_car(SEXP); extern SEXP rlang_cdr(SEXP); @@ -40,7 +41,6 @@ extern SEXP rlang_is_reference(SEXP, SEXP); extern SEXP rlang_sxp_address(SEXP); extern SEXP rlang_length(SEXP); extern SEXP rlang_new_dictionary(SEXP, SEXP, SEXP); -extern SEXP rlang_set_parent(SEXP, SEXP); extern SEXP rlang_squash(SEXP, SEXP, SEXP, SEXP); extern SEXP rlang_symbol(SEXP); extern SEXP rlang_symbol_to_character(SEXP); @@ -78,7 +78,7 @@ static const R_CallMethodDef call_entries[] = { {"rlang_set_cdar", (DL_FUNC) &rlang_set_cdar, 2}, {"rlang_set_cddr", (DL_FUNC) &rlang_set_cddr, 2}, {"rlang_set_cdr", (DL_FUNC) &rlang_set_cdr, 2}, - {"rlang_set_parent", (DL_FUNC) &rlang_set_parent, 2}, + {"rlang_mut_env_parent", (DL_FUNC) &r_mut_env_parent, 2}, {"rlang_set_tag", (DL_FUNC) &rlang_set_tag, 2}, {"rlang_shallow_duplicate", (DL_FUNC) &rlang_shallow_duplicate, 1}, {"rlang_squash", (DL_FUNC) &rlang_squash, 4}, diff --git a/src/internals.c b/src/internals.c deleted file mode 100644 index d272c2b690..0000000000 --- a/src/internals.c +++ /dev/null @@ -1,17 +0,0 @@ -#define R_NO_REMAP -#define USE_RINTERNALS -#include - -SEXP rlang_set_parent(SEXP env, SEXP new_parent) { - ENCLOS(env) = new_parent; - return env; -} - -SEXP rlang_mut_language_type(SEXP node) { - TYPEOF(node) = LANGSXP; - return node; -} -SEXP rlang_mut_pairlist_type(SEXP node) { - TYPEOF(node) = LISTSXP; - return node; -} diff --git a/src/vector.h b/src/vector.h index fcc566d3c7..d9c25936d8 100644 --- a/src/vector.h +++ b/src/vector.h @@ -91,7 +91,7 @@ SEXP namespace_rlang_sym(SEXP sym) { static SEXP rlang_sym = NULL; if (!rlang_sym) rlang_sym = Rf_install("rlang"); - return(Rf_lang3(R_DoubleColonSymbol, rlang_sym, sym)); + return(Rf_lang3(Rf_install("::"), rlang_sym, sym)); } SEXP vec_coercer_sym(SEXP dest) { diff --git a/tests/testthat.R b/tests/testthat.R index 156ae82aa9..70f8b030af 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,4 +1,4 @@ -library(testthat) -library(rlang) +library("testthat") +library("rlang") test_check("rlang") diff --git a/tests/testthat/test-compat.R b/tests/testthat/test-compat.R index 429fbb30c9..25c924fe1a 100644 --- a/tests/testthat/test-compat.R +++ b/tests/testthat/test-compat.R @@ -81,3 +81,10 @@ test_that("compat_lazy() handles bare formulas", { expect_identical(compat_lazy(~foo), quo(foo)) expect_identical(compat_lazy_dots(~foo), named_list(quo(foo))) }) + +test_that("trimws() trims", { + x <- " foo. " + expect_identical(trimws(x), "foo.") + expect_identical(trimws(x, "l"), "foo. ") + expect_identical(trimws(x, "r"), " foo.") +}) diff --git a/tests/testthat/test-env.R b/tests/testthat/test-env.R index aa9391ccd6..ff7da3c4d9 100644 --- a/tests/testthat/test-env.R +++ b/tests/testthat/test-env.R @@ -165,16 +165,16 @@ test_that("scoped_env() deals with empty environment", { }) test_that("env() doesn't partial match on env_bind()'s .env", { - expect_named(env(.data = 1, . = 2), c(".data", ".")) + expect_true(all(env_has(env(.data = 1, . = 2), c(".data", ".")))) }) test_that("new_environment() creates a child of the empty env", { env <- new_environment(list(a = 1, b = 2)) - expect_named(env, c("a", "b")) + expect_true(all(env_has(env, c("a", "b")))) expect_identical(env_parent(env), empty_env()) }) test_that("new_environment() accepts empty vectors", { - expect_named(new_environment(), chr()) - expect_named(new_environment(dbl()), chr()) + expect_identical(length(new_environment()), 0L) + expect_identical(length(new_environment(dbl())), 0L) })