diff --git a/NEWS.md b/NEWS.md index f39cb49fa0..ee13f1631b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,7 @@ 3. The data.table-only attribute `$.internal.selfref` is no longer set for data.frames. [#5286](https://github.com/Rdatatable/data.table/issues/5286). Thanks @OfekShilon for the report and fix. +4. `setDT()` no longer modifies the class of other names bound to the origin data.frame - e.g., argument DFs names at a caller to a function which uses setDT. Cf [#4784](https://github.com/Rdatatable/data.table/issues/4784). Thanks @OfekShilon for the report and fix. ## NOTES 1. Tests run again when some Suggests packages are missing, [#6411](https://github.com/Rdatatable/data.table/issues/6411). Thanks @aadler for the note and @MichaelChirico for the fix. diff --git a/R/data.table.R b/R/data.table.R index 3b58bb5025..e740c92fdb 100644 --- a/R/data.table.R +++ b/R/data.table.R @@ -2887,9 +2887,13 @@ setDT = function(x, keep.rownames=FALSE, key=NULL, check.names=FALSE) { rn = if (!identical(keep.rownames, FALSE)) rownames(x) else NULL setattr(x, "row.names", .set_row_names(nrow(x))) if (check.names) setattr(x, "names", make.names(names(x), unique=TRUE)) + + # setalloccol results in a shallow copy. Must be performed before class setting, + # to have the class apply only to the new copy. #4784 + setalloccol(x) # fix for #1078 and #1128, see .resetclass() for explanation. setattr(x, "class", .resetclass(x, 'data.frame')) - setalloccol(x) + if (!is.null(rn)) { nm = c(if (is.character(keep.rownames)) keep.rownames[1L] else "rn", names(x)) x[, (nm[1L]) := rn] diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 879881d8ea..2910a78d08 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -19063,3 +19063,9 @@ test(2280.3, foo(), error="Internal error in foo: broken") # fwrite respects dec=',' for sub-second timestamps, #6446 test(2281.1, fwrite(data.table(a=.POSIXct(0.001)), dec=',', sep=';'), output="1970-01-01T00:00:00,001Z") test(2281.2, fwrite(data.table(a=.POSIXct(0.0001)), dec=',', sep=';'), output="1970-01-01T00:00:00,000100Z") + +# setDT no longer leaks class modification to origin copy, #4784 +d1 <- data.frame(a=1) +d2 <- d1 +setDT(d2) +test(2283, !is.data.table(d1)) \ No newline at end of file