-
Notifications
You must be signed in to change notification settings - Fork 991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Completes coverage of all .R files #3761
Conversation
R/bmerge.R
Outdated
@@ -57,7 +57,7 @@ bmerge = function(i, x, icols, xcols, roll, rollends, nomatch, mult, ops, verbos | |||
} | |||
} | |||
if (xclass == iclass) { | |||
if (verbose) cat("i.",names(i)[ic],"has same type (",xclass,") as x.",names(x)[xc],". No coercion needed.\n", sep="") | |||
if (verbose) cat("i.", names(i)[ic], " has same type (", xclass, ") as x.", names(x)[xc], ". No coercion needed.\n", sep="") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mainly missing a space, noticed in the verbose
output for 2074.18
tt = grep("^eval|^[^[:alpha:]. ]",byvars,invert=TRUE,value=TRUE) | ||
if (length(tt)) tt = tt[1L] else all.vars(bysubl[[jj+1L]])[1L] | ||
# take the first variable that is (1) not eval (#3758) and (2) starts with a character that can't start a variable name | ||
tt = grep("^eval$|^[^[:alpha:]. ]", byvars, invert=TRUE, value=TRUE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
simple fix for #3758 -- add ending anchor $
to the regex for eval
# take the first variable that is (1) not eval (#3758) and (2) starts with a character that can't start a variable name | ||
tt = grep("^eval$|^[^[:alpha:]. ]", byvars, invert=TRUE, value=TRUE) | ||
# byvars but exclude functions or `0`+`1` becomes `+` | ||
tt = if (length(tt)) tt[1L] else all.vars(bysubl[[jj+1L]])[1L] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
previous code I believe was doing nothing in the else
case, so I'm not 100% sure of the intended behavior but I believe this is it.
@@ -1087,9 +1089,9 @@ replace_order = function(isub, verbose, env) { | |||
if (is.list(k)) { | |||
origj = j = if (name[[1L]] == "$") as.character(name[[3L]]) else eval(name[[3L]], parent.frame(), parent.frame()) | |||
if (is.character(j)) { | |||
if (length(j)!=1L) stop("L[[i]][,:=] syntax only valid when i is length 1, but it's length %d",length(j)) | |||
if (length(j)!=1L) stop("Cannot assign to an under-allocated recursively indexed list -- L[[i]][,:=] syntax is only valid when i is length 1, but it's length ", length(j)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quite the obscure error. Especially because the first code works while the second produces this error:
opt = options(datatable.alloccol=1L)
l = list(foo = list(bar = data.table(a = 1:3, b = 4:6)))
l$foo$bar[ , (letters) := 16:18]
l = list(foo = list(bar = data.table(a = 1:3, b = 4:6)))
l[[c('foo', 'bar')]][ , (letters) := 16:18]
options(opt)
j = match(j, names(k)) | ||
if (is.na(j)) stop("Item '",origj,"' not found in names of list") | ||
if (is.na(j)) stop("Internal error -- item '", origj, "' not found in names of list") # nocov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see a way for this to be triggered, so marking it as internal
@@ -1118,7 +1120,7 @@ replace_order = function(isub, verbose, env) { | |||
xcolsAns = seq_along(ansvars) | |||
icols = icolsAns = integer() | |||
} else { | |||
if (!length(leftcols)) stop("column(s) not found: ", paste(ansvars[wna],collapse=", ")) | |||
if (!length(leftcols)) stop("Internal error -- column(s) not found: ", paste(ansvars[wna],collapse=", ")) # nocov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto above. AFAICT things that might trigger this are caught much earlier than here.
Codecov Report
@@ Coverage Diff @@
## master #3761 +/- ##
==========================================
+ Coverage 98.83% 99.41% +0.58%
==========================================
Files 70 70
Lines 13228 13204 -24
==========================================
+ Hits 13074 13127 +53
+ Misses 154 77 -77
Continue to review full report at Codecov.
|
@@ -1294,7 +1296,7 @@ replace_order = function(isub, verbose, env) { | |||
identical(irows, integer(0L)) && !bynull, | |||
length(irows) && !anyNA(irows) && all(irows==0L) ## anyNA() because all() returns NA (not FALSE) when irows is all-NA. TODO: any way to not check all 'irows' values? | |||
)) | |||
if (is.atomic(jval)) jval = jval[0L] else jval = lapply(jval, `[`, 0L) | |||
jval = lapply(jval, `[`, 0L) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe is.atomic(jval)
is possible here.
Just above you can see this branch enters with either is.list(jval)
or !missingby
:
if ((is.call(jsub) && is.list(jval) && jsub[[1L]] != "get" && !is.object(jval)) || !missingby)
Obviously is.atomic(jval)
is impossible in the first case. You have to scroll a bit further up but I think the second case is also impossible:
if (missingby || bynull || (!byjoin && !length(byval)))
So we've either got bynull
or (!byjoin && !length(byval))
. But I'm not sure how length(byval)
can be 0
but bynull
is FALSE
-- e.g. by = integer()
would have byval = list(integer = integer())
, so it's already en-list
ed.
@@ -1884,7 +1886,7 @@ as.matrix.data.table = function(x, rownames=NULL, rownames.value=NULL, ...) { | |||
non.numeric = non.atomic = FALSE | |||
all.logical = TRUE | |||
for (j in seq_len(p)) { | |||
if (is.ff(X[[j]])) X[[j]] = X[[j]][] # to bring the ff into memory, since we need to create a matrix in memory | |||
if (is.ff(X[[j]])) X[[j]] = X[[j]][] # nocov to bring the ff into memory, since we need to create a matrix in memory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't have ff
in Suggests
, so nocov
. We have is.ff
as a simple wrapper, so technically we could construct some object and force ff
class to it & test but that's not really a test of what this branch is supposed to do. So nocov
unless we want to add ff
to Suggests
, or if you think we should add ff
to the test packages.
@@ -2880,7 +2882,7 @@ isReallyReal = function(x) { | |||
## redirect to normal DT[x == TRUE] | |||
stub = call("==", as.symbol(col), TRUE) | |||
} | |||
if (length(stub[[1L]]) != 1) return(NULL) ## Whatever it is, definitely not one of the valid operators | |||
if (length(stub[[1L]]) != 1) return(NULL) # nocov Whatever it is, definitely not one of the valid operators |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see a way to reach this branch and the comment suggests it's there as an internal default, could you confirm @MarkusBonsch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are completely right.
@@ -2902,7 +2904,6 @@ isReallyReal = function(x) { | |||
# the mode() checks also deals with NULL since mode(NULL)=="NULL" and causes this return, as one CRAN package (eplusr 0.9.1) relies on | |||
return(NULL) | |||
} | |||
if(is.character(x[[col]]) && !operator %chin% c("==", "%in%", "%chin%")) return(NULL) ## base R allows for non-equi operators on character columns, but these can't be optimized. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant to here in current logic:
if (!operator %chin% validOps$op)
@@ -2998,7 +2999,6 @@ isReallyReal = function(x) { | |||
pat = paste0("(", ops, ")", collapse="|") | |||
if (is.call(onsub) && onsub[[1L]] == "eval") { | |||
onsub = eval(onsub[[2L]], parent.frame(2L), parent.frame(2L)) | |||
if (is.call(onsub) && onsub[[1L]] == "eval") { onsub = onsub[[2L]] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The eval
will eliminate any level of nested eval
/quote
already, so I don't think this branch is possible; see:
DT <- data.table(id = 1:3, `counts(a>=0)` = 1:3, sameName = 1:3)
i <- data.table(idi = 1:3, ` weirdName>=` = 1:3, sameName = 1:3)
DT[i, on = eval(eval(quote(eval("id<=idi"))))]
After eval
onsub
becomes id<=idi
Once merged we'll be over 99% coverage! Mission accomplished 😎 |
@@ -87,8 +87,9 @@ round.IDate = function (x, digits=c("weeks", "months", "quarters", "years"), ... | |||
`+.IDate` = function (e1, e2) { | |||
if (nargs() == 1L) | |||
return(e1) | |||
# TODO: investigate Ops.IDate method a la Ops.difftime |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted in ?Ops
The classes of both arguments are considered in dispatching any member of this group. For each argument its vector of classes is examined to see if there is a matching specific (preferred) or Ops method. If a method is found for just one argument or the same method is found for both, it is used. If different methods are found, there is a warning about ‘incompatible methods’: in that case or if no method is found for either argument the internal method is used.
Hence we can't really reach this branch since the incompatible methods
barrier is hit first.
R/last.R
Outdated
@@ -9,14 +9,16 @@ last = function(x, ...) { | |||
if (!length(x)) return(x) else return(x[[length(x)]]) # for vectors, [[ works like [ | |||
} else if (is.data.frame(x)) return(x[NROW(x),]) | |||
} | |||
# nocov start |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw the if
branches covered in first
but not last
(despite apparently neither actually being hit in tests), so just throw the whole sections in nocov
to be sure. maybe surface to Jim as well...
R/transpose.R
Outdated
@@ -4,7 +4,7 @@ transpose = function(l, fill=NA, ignore.empty=FALSE, keep.names=NULL, make.names | |||
if (is.character(make.names)) { | |||
make.names=chmatch(make.names, names(l)) | |||
if (is.na(make.names)) | |||
stop("make.names='",make.names,"' not found in names of input") | |||
stop("make.names not found in names of input") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make.names
original value is overwritten already. Rather than complicate the logic (i.e. by one or two extra lines), just axed here, but easy to change.
test(1613.563, all( | ||
all.equal(rbind(x,y), rbind(y,y), ignore.row.order=FALSE), | ||
all.equal(rbind(x,y), rbind(y,y), ignore.row.order=TRUE), | ||
all.equal(rbind(y,y), rbind(x,y), ignore.row.order=TRUE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New test switches the order to hit the first-but-not-second-has-dups
branch whose second-but-not-first
counterpart is hit by the 2nd test already
…between arguments so we can see where the real spaces inside quotes are. In this instance the diff now shows where the real space was added.
Fantastic! I went through it and all looks good. Great comments. I added comment in the tests.Rraw for the new tests 2074.* file pointing back to this PR so we can get back to the comments if we ever need to. |
Closes #3758 too.
Please see also inline notes