Skip to content

Commit 2e2f887

Browse files
committed
Make drop error only when necessary
As suggested by @gmbecker
1 parent 95eeef0 commit 2e2f887

File tree

8 files changed

+68
-24
lines changed

8 files changed

+68
-24
lines changed

NAMESPACE

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export(strict_apply)
88
export(strict_arg)
99
export(strict_deactivate)
1010
export(strict_diag)
11+
export(strict_drop)
1112
export(strict_sample)
1213
export(strict_sapply)
1314
import(rlang)

R/shim-risky.R

+38-15
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,56 @@ strict_arg <- function(name) {
1010
strict_abort("Please supply a value for `", name, "` argument.", help = "strict_arg")
1111
}
1212

13-
register_risky_shims <- function(env) {
13+
#' @export
14+
#' @rdname strict_arg
15+
#' @param j Columns to select
16+
strict_drop <- function(j) {
17+
if (missing(j)) {
18+
return(FALSE)
19+
}
20+
21+
if ((is.numeric(j) || is.character(j)) && length(j) > 1) {
22+
return(FALSE)
23+
}
24+
25+
if (is.logical(j) && sum(j) > 1) {
26+
return(FALSE)
27+
}
28+
29+
strict_abort(
30+
"Please explicitly specify `drop` when selecting a single column",
31+
help = "strict_drop"
32+
)
33+
}
34+
35+
register_shims_risky <- function(env) {
1436
env_bind(env,
15-
`[.data.frame` = force_strict(`[.data.frame`, "drop"),
16-
as.data.frame.character = force_strict(as.data.frame.character, "stringsAsFactors"),
17-
as.data.frame.list = force_strict(as.data.frame.list, "stringsAsFactors"),
18-
data.frame = force_strict(data.frame, "stringsAsFactors"),
19-
read.table = force_strict(utils::read.table, "stringsAsFactors"),
20-
read.csv = strict_read.csv
37+
as.data.frame.character = replace_strings_as_factors(as.data.frame.character),
38+
as.data.frame.list = replace_strings_as_factors(as.data.frame.list),
39+
data.frame = replace_strings_as_factors(data.frame),
40+
read.table = replace_strings_as_factors(utils::read.table),
41+
`[.data.frame` = replace_args(`[.data.frame`, drop = quote(strict_drop(j))),
42+
read.csv = strict_read_csv,
2143
)
2244
}
2345

24-
force_strict <- function(fun, args) {
46+
replace_strings_as_factors <- function(fun) {
47+
replace_args(fun, stringsAsFactors = quote(strict_arg("stringsAsFactors")))
48+
}
49+
50+
replace_args <- function(fun, ...) {
2551
formals <- as.list(fn_fmls(fun))
52+
args <- list(...)
2653

27-
for (arg in args) {
28-
if (has_name(arg, formals) && !is_syntactic_literal(formals[[arg]])) {
29-
formals[[arg]] <- expr(strict_arg(!!arg))
30-
}
54+
for (arg in names(args)) {
55+
formals[[arg]] <- args[[arg]]
3156
}
3257

3358
formals(fun) <- formals
3459
fun
3560
}
3661

37-
strict_read.csv <- function(file, header = TRUE, sep = ",", quote = "\"",
62+
strict_read_csv <- function(file, header = TRUE, sep = ",", quote = "\"",
3863
dec = ".", fill = TRUE, comment.char = "",
3964
stringsAsFactors = strict_arg("stringsAsFactors"),
4065
...) {
@@ -50,8 +75,6 @@ strict_read.csv <- function(file, header = TRUE, sep = ",", quote = "\"",
5075
stringsAsFactors = stringsAsFactors
5176
)
5277
}
53-
54-
5578
# Helpers to find risky functions -----------------------------------------
5679

5780
#' @examples

R/shim-scalar.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
register_shim_scalar <- function(env) {
1+
register_shims_scalar <- function(env) {
22
env_bind(env,
33
sample = strict_sample,
44
diag = strict_diag

R/shims.R

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ register_shims <- function() {
1212

1313
register_shim_T_F(strict_shims)
1414
register_shims_apply(strict_shims)
15-
register_shim_scalar(strict_shims)
16-
register_risky_shims(strict_shims)
15+
register_shims_risky(strict_shims)
16+
register_shims_scalar(strict_shims)
1717
}
1818

1919
register_shim_T_F <- function(env) {

README.Rmd

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ knitr::opts_chunk$set(
1010
comment = "#>",
1111
fig.path = "README-"
1212
)
13+
set.seed(1014)
1314
```
1415

1516
# strict
@@ -64,7 +65,7 @@ devtools::install_github("hadley/strict")
6465
```{r}
6566
library(strict)
6667
67-
df <- data.frame(xyz = 1, stringsAsFactors = FALSE)
68+
df <- data.frame(xyz = 1)
6869
df$x
6970
```
7071

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ Features
4949
library(strict)
5050
mtcars[, 1]
5151
#> Error: [strict]
52-
#> Please supply a value for `drop` argument.
53-
#> Please see ?strict_arg for more details
52+
#> Please explicitly specify `drop` when selecting a single column
53+
#> Please see ?strict_drop for more details
5454

5555
data.frame(x = "a")
5656
#> Error: [strict]
@@ -63,7 +63,7 @@ Features
6363
``` r
6464
library(strict)
6565

66-
df <- data.frame(xyz = 1, stringsAsFactors = FALSE)
66+
df <- data.frame(xyz = 1)
6767
df$x
6868
#> Warning in `$.data.frame`(df, x): Partial match of 'x' to 'xyz' in data
6969
#> frame
@@ -108,11 +108,11 @@ Features
108108
library(strict)
109109

110110
sample(5:3)
111-
#> [1] 4 3 5
111+
#> [1] 5 4 3
112112
sample(5:4)
113113
#> [1] 5 4
114114
lax(sample(5:5))
115-
#> [1] 5 2 1 4 3
115+
#> [1] 3 2 1 4 5
116116

117117
sample(5:5)
118118
#> Error: [strict]

man/strict_arg.Rd

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-shim_risky.R

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
context("shim_risky")
2+
3+
test_that("strict_drop detects when default ok", {
4+
expect_equal(strict_drop(c(TRUE, TRUE)), FALSE)
5+
expect_equal(strict_drop(1:5), FALSE)
6+
expect_equal(strict_drop(letters[1:2]), FALSE)
7+
expect_equal(strict_drop(), FALSE)
8+
})
9+
10+
test_that("strict_drop errors instead of returning TRUE", {
11+
expect_error(strict_drop(c(TRUE)), "`drop`")
12+
expect_error(strict_drop(1), "`drop`")
13+
expect_error(strict_drop("a"), "`drop`")
14+
})

0 commit comments

Comments
 (0)