From dc4c578432d9bf261162823dd8350e290dc7eaae Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 16 Dec 2019 19:32:44 -0300 Subject: [PATCH 01/31] Adds yaml.extra to add custom attributes to fwrite's yaml --- R/fwrite.R | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/R/fwrite.R b/R/fwrite.R index 1971c0e4ea..4d6eacdf4b 100644 --- a/R/fwrite.R +++ b/R/fwrite.R @@ -82,7 +82,8 @@ fwrite = function(x, file="", append=FALSE, quote="auto", return(invisible()) } } - yaml = if (!yaml) "" else { + write_yaml <- yaml == TRUE || (is.list(yaml) && length(yaml) != 0) + yaml = if (!write_yaml) "" else { if (!requireNamespace('yaml', quietly=TRUE)) stop("'data.table' relies on the package 'yaml' to write the file header; please add this to your library with install.packages('yaml') and try again.") # nocov schema_vec = sapply(x, class) @@ -103,6 +104,10 @@ fwrite = function(x, file="", append=FALSE, quote="auto", header=col.names, sep=sep, sep2=sep2, eol=eol, na.strings=na, dec=dec, qmethod=qmethod, logical01=logical01 ) + if (is.list(yaml)) { + yaml_header <- c(yaml_header, yaml) + } + paste0('---', eol, yaml::as.yaml(yaml_header, line.sep=eol), '---', eol) # NB: as.yaml adds trailing newline } file = enc2native(file) # CfwriteR cannot handle UTF-8 if that is not the native encoding, see #3078. From 5d22788d34cb56f4c71e945b0c5f1774260217f5 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Tue, 17 Dec 2019 12:13:10 -0300 Subject: [PATCH 02/31] Adds test --- inst/tests/tests.Rraw | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 80f2bc25e1..1958b72a0e 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -16400,6 +16400,12 @@ test(2124.1, format(as.ITime(t0)), '00:00:00') test(2124.2, format(as.IDate(t0)), '2019-10-01') Sys.setenv(TZ=oldtz) +# Extra arguments in yaml +data = data.table(x = 1, y = 100) +file = tempfile() +fwrite(data, file, yaml = list(something_else = "o hai!")) +x = fread(file, yaml = TRUE) +test(2125, attr(x, "yaml_metadata")$something_else, "o hai!") ################################### # Add new tests above this line # From c3bb737a634b68c191917cb312c2d8113511f499 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Sat, 28 Dec 2019 15:43:35 -0300 Subject: [PATCH 03/31] Escapes test --- inst/tests/tests.Rraw | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 1958b72a0e..3298f843cc 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14758,6 +14758,15 @@ if (test_yaml) { # csvy; #1701 close(fcon) test(2033.14, fread(f), DT) unlink(f) + + # Extra arguments in yaml + data = data.table(x = 1, y = 100) + file = tempfile() + fwrite(data, file, yaml = list(something_else = "o hai!")) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.01, attr(x, "yaml_metadata")$something_else, "o hai!") + test(2125.02, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") } # fcast coverage @@ -16400,12 +16409,6 @@ test(2124.1, format(as.ITime(t0)), '00:00:00') test(2124.2, format(as.IDate(t0)), '2019-10-01') Sys.setenv(TZ=oldtz) -# Extra arguments in yaml -data = data.table(x = 1, y = 100) -file = tempfile() -fwrite(data, file, yaml = list(something_else = "o hai!")) -x = fread(file, yaml = TRUE) -test(2125, attr(x, "yaml_metadata")$something_else, "o hai!") ################################### # Add new tests above this line # From 6fbca5d3d077e1eb03869716e50255e712554df1 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Sun, 16 Feb 2020 19:16:12 -0300 Subject: [PATCH 04/31] Adapts to new syntax for yaml. --- R/fwrite.R | 48 ++++++++++++++++++++++--------------------- R/utils.R | 31 ++++++++++++++++++++++++++++ inst/tests/tests.Rraw | 35 +++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 25 deletions(-) diff --git a/R/fwrite.R b/R/fwrite.R index 4d6eacdf4b..6e01768c71 100644 --- a/R/fwrite.R +++ b/R/fwrite.R @@ -82,33 +82,36 @@ fwrite = function(x, file="", append=FALSE, quote="auto", return(invisible()) } } - write_yaml <- yaml == TRUE || (is.list(yaml) && length(yaml) != 0) + write_yaml = isTRUE(yaml) || (is.list(yaml) && length(yaml) != 0L) yaml = if (!write_yaml) "" else { if (!requireNamespace('yaml', quietly=TRUE)) stop("'data.table' relies on the package 'yaml' to write the file header; please add this to your library with install.packages('yaml') and try again.") # nocov - schema_vec = sapply(x, class) - # multi-class objects reduced to first class - if (is.list(schema_vec)) schema_vec = sapply(schema_vec, `[`, 1L) - # as.vector strips names - schema_vec = list(name=names(schema_vec), type=as.vector(schema_vec)) - yaml_header = list( - source = sprintf('R[v%s.%s]::data.table[v%s]::fwrite', - R.version$major, R.version$minor, format(tryCatch(utils::packageVersion('data.table'), error=function(e) 'DEV'))), - creation_time_utc = format(Sys.time(), tz='UTC'), - schema = list( - fields = lapply( - seq_along(x), - function(i) list(name=schema_vec$name[i], type=schema_vec$type[i]) - ) - ), - header=col.names, sep=sep, sep2=sep2, eol=eol, na.strings=na, - dec=dec, qmethod=qmethod, logical01=logical01 - ) - if (is.list(yaml)) { - yaml_header <- c(yaml_header, yaml) + + if (isTRUE(yaml)) { + yaml = generate_yaml(x = x, col.names = col.names, sep = sep, + sep2 = sep2, eol = eol, na = na, dec = dec, + qmethod = qmethod, logical01 = logical01) + } else { + names = names(yaml) + if (is.null(names)) { + names = rep("", length(yaml)) + } + unnamed = names == "" + true_yaml = vapply_1b(yaml, isTRUE) + + generated_yaml = unnamed & true_yaml + if (any(unnamed & !true_yaml)) { + stop("`yaml` contains unnamed elements that are not `TRUE`") + } + if (any(generated_yaml)) { + yaml_header = generate_yaml(x = x, col.names = col.names, sep = sep, + sep2 = sep2, eol = eol, na = na, dec = dec, + qmethod = qmethod, logical01 = logical01) + yaml = c(yaml_header, yaml[!generated_yaml]) + } } - paste0('---', eol, yaml::as.yaml(yaml_header, line.sep=eol), '---', eol) # NB: as.yaml adds trailing newline + paste0('---', eol, yaml::as.yaml(yaml, line.sep=eol), '---', eol) # NB: as.yaml adds trailing newline } file = enc2native(file) # CfwriteR cannot handle UTF-8 if that is not the native encoding, see #3078. .Call(CfwriteR, x, file, sep, sep2, eol, na, dec, quote, qmethod=="escape", append, @@ -116,4 +119,3 @@ fwrite = function(x, file="", append=FALSE, quote="auto", showProgress, is_gzip, bom, yaml, verbose) invisible() } - diff --git a/R/utils.R b/R/utils.R index de35e709c0..e517f1f6bd 100644 --- a/R/utils.R +++ b/R/utils.R @@ -117,6 +117,37 @@ do_patterns = function(pat_sub, all_cols) { return(matched) } + +generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", + eol = if (.Platform$OS.type=="windows") "\r\n" else "\n", + na = "", dec = "", qmethod = "double", + logical01 = getOption("datatable.logical01", FALSE)) { + schema_vec = sapply(x, class) + # multi-class objects reduced to first class + if (is.list(schema_vec)) schema_vec = sapply(schema_vec, `[`, 1L) + # as.vector strips names + schema_vec = list(name=names(schema_vec), type=as.vector(schema_vec)) + list( + source = sprintf('R[v%s.%s]::data.table[v%s]::fwrite', + R.version$major, R.version$minor, format(tryCatch(utils::packageVersion('data.table'), error=function(e) 'DEV'))), + creation_time_utc = format(Sys.time(), tz='UTC'), + schema = list( + fields = lapply( + seq_along(x), + function(i) list(name=schema_vec$name[i], type=schema_vec$type[i]) + ) + ), + header = col.names, + sep = sep, + sep2 = sep2, + eol = eol, + na.strings = na, + dec = dec, + qmethod = qmethod, + logical01 = logical01 + ) +} + # nocov start #593 always return a data.table edit.data.table = function(name, ...) { setDT(NextMethod('edit', name))[] diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 3298f843cc..c8d5ee012b 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14761,12 +14761,43 @@ if (test_yaml) { # csvy; #1701 # Extra arguments in yaml data = data.table(x = 1, y = 100) - file = tempfile() + file = tmpfile() + fwrite(data, file, yaml = list(something_else = "o hai!")) x = fread(file, yaml = TRUE) unlink(file) test(2125.01, attr(x, "yaml_metadata")$something_else, "o hai!") - test(2125.02, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2125.02, attr(x, "yaml_metadata")$schema, NULL) + + + fwrite(data, file, yaml = TRUE) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.03, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + + + fwrite(data, file, yaml = list(TRUE)) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.04, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + + + fwrite(data, file, yaml = list(TRUE, something_else = "o hai!")) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.05, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2125.06, attr(x, "yaml_metadata")$something_else, "o hai!") + + + fwrite(data, file, yaml = list(TRUE, something_else = "o hai!", this_is_true = TRUE)) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.07, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2125.08, attr(x, "yaml_metadata")$something_else, "o hai!") + test(2125.09, attr(x, "yaml_metadata")$this_is_true, TRUE) + + test(2125.10, fwrite(data, file, yaml = list(TRUE, "unnamed_stuff")), error = "unnamed") + } # fcast coverage From 27a9d11811656a3e560de8e7cd96b3611dbcfa6e Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 17 Feb 2020 14:19:27 +0800 Subject: [PATCH 05/31] whitespace --- R/fwrite.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/fwrite.R b/R/fwrite.R index 6e01768c71..6b247bf2c5 100644 --- a/R/fwrite.R +++ b/R/fwrite.R @@ -89,8 +89,8 @@ fwrite = function(x, file="", append=FALSE, quote="auto", if (isTRUE(yaml)) { yaml = generate_yaml(x = x, col.names = col.names, sep = sep, - sep2 = sep2, eol = eol, na = na, dec = dec, - qmethod = qmethod, logical01 = logical01) + sep2 = sep2, eol = eol, na = na, dec = dec, + qmethod = qmethod, logical01 = logical01) } else { names = names(yaml) if (is.null(names)) { From 31986b65c1e6f727fc6657fa6eb82c41348a6cf8 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 17 Feb 2020 12:29:13 -0300 Subject: [PATCH 06/31] Small refactor in generate_yaml's schema --- R/utils.R | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/R/utils.R b/R/utils.R index ea7c016ad5..675749b6c1 100644 --- a/R/utils.R +++ b/R/utils.R @@ -124,26 +124,22 @@ do_patterns = function(pat_sub, all_cols) { return(matched) } + generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", - eol = if (.Platform$OS.type=="windows") "\r\n" else "\n", + eol = if (.Platform$OS.type == "windows") "\r\n" else "\n", na = "", dec = "", qmethod = "double", logical01 = getOption("datatable.logical01", FALSE)) { - schema_vec = sapply(x, class) - # multi-class objects reduced to first class - if (is.list(schema_vec)) schema_vec = sapply(schema_vec, `[`, 1L) - # as.vector strips names - schema_vec = list(name=names(schema_vec), type=as.vector(schema_vec)) + schema_vec = sapply(x, class, simplify = FALSE) list( source = sprintf('R[v%s.%s]::data.table[v%s]::fwrite', R.version$major, R.version$minor, format(tryCatch(utils::packageVersion('data.table'), error=function(e) 'DEV'))), creation_time_utc = format(Sys.time(), tz='UTC'), schema = list( - fields = lapply( - seq_along(x), - function(i) list(name=schema_vec$name[i], type=schema_vec$type[i]) - ) + fields = lapply(seq_along(x), function(i) { + list(name = names(schema_vec)[i], type = schema_vec[[i]][[1L]]) # multi-class objects reduced to first class + }) ), - header = col.names, + header = col.names, sep = sep, sep2 = sep2, eol = eol, From 5e2b09200fdd03a6a4f3a803339e0cc305be2ac4 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 17 Feb 2020 13:04:00 -0300 Subject: [PATCH 07/31] More clear yaml logic --- R/fwrite.R | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/R/fwrite.R b/R/fwrite.R index 6b247bf2c5..e9d5f2a1ba 100644 --- a/R/fwrite.R +++ b/R/fwrite.R @@ -83,12 +83,13 @@ fwrite = function(x, file="", append=FALSE, quote="auto", } } write_yaml = isTRUE(yaml) || (is.list(yaml) && length(yaml) != 0L) - yaml = if (!write_yaml) "" else { + yaml_text = "" + if (write_yaml) { if (!requireNamespace('yaml', quietly=TRUE)) stop("'data.table' relies on the package 'yaml' to write the file header; please add this to your library with install.packages('yaml') and try again.") # nocov if (isTRUE(yaml)) { - yaml = generate_yaml(x = x, col.names = col.names, sep = sep, + yaml_text = generate_yaml(x = x, col.names = col.names, sep = sep, sep2 = sep2, eol = eol, na = na, dec = dec, qmethod = qmethod, logical01 = logical01) } else { @@ -103,19 +104,20 @@ fwrite = function(x, file="", append=FALSE, quote="auto", if (any(unnamed & !true_yaml)) { stop("`yaml` contains unnamed elements that are not `TRUE`") } + yaml_text <- yaml[!generated_yaml] if (any(generated_yaml)) { yaml_header = generate_yaml(x = x, col.names = col.names, sep = sep, sep2 = sep2, eol = eol, na = na, dec = dec, qmethod = qmethod, logical01 = logical01) - yaml = c(yaml_header, yaml[!generated_yaml]) + yaml_text = c(yaml_header, yaml_text) } } - paste0('---', eol, yaml::as.yaml(yaml, line.sep=eol), '---', eol) # NB: as.yaml adds trailing newline + yaml_text = paste0('---', eol, yaml::as.yaml(yaml_text, line.sep = eol), '---', eol) # NB: as.yaml adds trailing newline } file = enc2native(file) # CfwriteR cannot handle UTF-8 if that is not the native encoding, see #3078. .Call(CfwriteR, x, file, sep, sep2, eol, na, dec, quote, qmethod=="escape", append, row.names, col.names, logical01, scipen, dateTimeAs, buffMB, nThread, - showProgress, is_gzip, bom, yaml, verbose) + showProgress, is_gzip, bom, yaml_text, verbose) invisible() } From b809f19dbd2d45dc2f1f105ddb478b3106da9649 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 14:46:21 -0300 Subject: [PATCH 08/31] Saves and reads column attributes Refers to #3540 --- R/fread.R | 5 +++++ R/utils.R | 20 ++++++++++++++------ inst/tests/tests.Rraw | 13 ++++++++++++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/R/fread.R b/R/fread.R index d57d2cd6fd..389227636b 100644 --- a/R/fread.R +++ b/R/fread.R @@ -305,6 +305,11 @@ yaml=FALSE, autostart=NA, tmpdir=tempdir()) return(v) }, error = fun) + + if (yaml) { + attributes(new_v) <- c(attributes(new_v), yaml_header$schema$fields[[j]]$attributes) + } + set(ans, j = j, value = new_v) # aside: new_v == v if the coercion was aborted } setattr(ans, "colClassesAs", NULL) diff --git a/R/utils.R b/R/utils.R index 675749b6c1..c2261f9f87 100644 --- a/R/utils.R +++ b/R/utils.R @@ -129,16 +129,24 @@ generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", eol = if (.Platform$OS.type == "windows") "\r\n" else "\n", na = "", dec = "", qmethod = "double", logical01 = getOption("datatable.logical01", FALSE)) { - schema_vec = sapply(x, class, simplify = FALSE) + fields = sapply(seq_along(x), function(i) { + attrs <- attributes(x[[i]]) + attrs <- attrs[!(names(attrs) %in% "class")] + + ret <- list(name = colnames(x)[i], + type = class(x[[i]])[[1]]) # multi-class objects reduced to first class + + if (!is.null(attrs)) { + ret <- c(ret, list(attributes = attrs)) + } + return(ret) + }, simplify = FALSE) + list( source = sprintf('R[v%s.%s]::data.table[v%s]::fwrite', R.version$major, R.version$minor, format(tryCatch(utils::packageVersion('data.table'), error=function(e) 'DEV'))), creation_time_utc = format(Sys.time(), tz='UTC'), - schema = list( - fields = lapply(seq_along(x), function(i) { - list(name = names(schema_vec)[i], type = schema_vec[[i]][[1L]]) # multi-class objects reduced to first class - }) - ), + schema = list(fields = fields), header = col.names, sep = sep, sep2 = sep2, diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index cd345eb04d..a386571b18 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14862,7 +14862,18 @@ if (test_yaml) { # csvy; #1701 test(2125.09, attr(x, "yaml_metadata")$this_is_true, TRUE) test(2125.10, fwrite(data, file, yaml = list(TRUE, "unnamed_stuff")), error = "unnamed") - + + + data = data.table(x = 1, y = 100, + c = factor(letters[1:3], levels = letters[1:4]), + date = Sys.Date()) + attr(data$x, "attr") <- "attribute" + fwrite(data, file, yaml = TRUE) + x = fread(file, yaml = TRUE) + unlink(file) + + test(2126.01, levels(x$c), letters[1:4]) + test(2126.02, attr(data$x, "attr"), "attribute") } # fcast coverage From 1608fa3cbdeaf6833668ee4c0356b3b6adbd0a3c Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 15:05:09 -0300 Subject: [PATCH 09/31] Adds test --- R/fread.R | 1 - inst/tests/tests.Rraw | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/R/fread.R b/R/fread.R index 389227636b..761773483b 100644 --- a/R/fread.R +++ b/R/fread.R @@ -284,7 +284,6 @@ yaml=FALSE, autostart=NA, tmpdir=tempdir()) if (check.names) { setattr(ans, 'names', make.names(names(ans), unique=TRUE)) } - colClassesAs = attr(ans, "colClassesAs", exact=TRUE) # should only be present if one or more are != "" for (j in which(colClassesAs!="")) { # # 1634 v = .subset2(ans, j) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index a386571b18..a4f37b79f9 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14874,6 +14874,10 @@ if (test_yaml) { # csvy; #1701 test(2126.01, levels(x$c), letters[1:4]) test(2126.02, attr(data$x, "attr"), "attribute") + + fwrite(data, file, yaml = TRUE) + test(2126.03, fread(file, yaml = FALSE), x) + unlink(file) } # fcast coverage From 2eee0de9b4e3c213de27884faeb49ab00aaa1085 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 15:14:32 -0300 Subject: [PATCH 10/31] Adds attributes to all columns, not just factors et.al. --- R/fread.R | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/R/fread.R b/R/fread.R index 761773483b..2b1344b0d2 100644 --- a/R/fread.R +++ b/R/fread.R @@ -305,10 +305,6 @@ yaml=FALSE, autostart=NA, tmpdir=tempdir()) }, error = fun) - if (yaml) { - attributes(new_v) <- c(attributes(new_v), yaml_header$schema$fields[[j]]$attributes) - } - set(ans, j = j, value = new_v) # aside: new_v == v if the coercion was aborted } setattr(ans, "colClassesAs", NULL) @@ -334,7 +330,13 @@ yaml=FALSE, autostart=NA, tmpdir=tempdir()) } setkeyv(ans, key) } - if (yaml) setattr(ans, 'yaml_metadata', yaml_header) + if (yaml) { + setattr(ans, 'yaml_metadata', yaml_header) + + for (j in seq_along(ans)) { + attributes(ans[[j]]) <- c(attributes(ans[[j]]), yaml_header$schema$fields[[j]]$attributes) + } + } if (!is.null(index) && data.table) { if (!all(sapply(index, is.character))) stop("index argument of data.table() must be a character vector naming columns (NB: col.names are applied before this)") From 3ae164b67411df762ac09a984735359c1581f824 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 15:46:29 -0300 Subject: [PATCH 11/31] Skips length 0 attributes --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index c2261f9f87..ff5e05d084 100644 --- a/R/utils.R +++ b/R/utils.R @@ -136,7 +136,7 @@ generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", ret <- list(name = colnames(x)[i], type = class(x[[i]])[[1]]) # multi-class objects reduced to first class - if (!is.null(attrs)) { + if (!is.null(attrs) & length(attrs != 0)) { ret <- c(ret, list(attributes = attrs)) } return(ret) From c109708e37904b430c83e615c6663f5dd8a7211d Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 17:19:45 -0300 Subject: [PATCH 12/31] Fix previous commit --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index ff5e05d084..107d88c12d 100644 --- a/R/utils.R +++ b/R/utils.R @@ -136,7 +136,7 @@ generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", ret <- list(name = colnames(x)[i], type = class(x[[i]])[[1]]) # multi-class objects reduced to first class - if (!is.null(attrs) & length(attrs != 0)) { + if (!is.null(attrs) & length(attrs) != 0) { ret <- c(ret, list(attributes = attrs)) } return(ret) From d47a83fb2e25582e508f191f87a31ca81b736b57 Mon Sep 17 00:00:00 2001 From: Matt Dowle Date: Fri, 22 May 2020 18:27:57 -0600 Subject: [PATCH 13/31] dev script updates only: CRAN_Release, and added my .bash_aliases and .Rprofile --- .dev/.Rprofile | 14 ++++++++++++++ .dev/.bash_aliases | 21 +++++++++++++++++++++ .dev/CRAN_Release.cmd | 11 ++++++----- 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 .dev/.Rprofile create mode 100644 .dev/.bash_aliases diff --git a/.dev/.Rprofile b/.dev/.Rprofile new file mode 100644 index 0000000000..7d4ab3239d --- /dev/null +++ b/.dev/.Rprofile @@ -0,0 +1,14 @@ +# Matt's ~/.Rprofile is a link to this file at ~/GitHub/data.table/.dev/.Rprofile + +# options(repos = c(CRAN="http://cran.stat.ucla.edu")) +# options(repos = c(CRAN=c("http://cran.stat.ucla.edu", "http://cloud.r-project.org"))) # both needed for revdep checks sometimes +options(repos = c(CRAN="http://cloud.r-project.org")) + +options(help_type="html") +options(error=quote(dump.frames())) +options(width=200) +options(digits.secs=3) # for POSIXct to print milliseconds +suppressWarnings(RNGversion("3.5.0")) # so when I create tests in dev there isn't a mismatch when run by cc() + +Sys.setenv(PROJ_PATH=path.expand("~/GitHub/data.table")) +source(paste0(Sys.getenv("PROJ_PATH"),"/.dev/cc.R")) diff --git a/.dev/.bash_aliases b/.dev/.bash_aliases new file mode 100644 index 0000000000..93ea44ed5c --- /dev/null +++ b/.dev/.bash_aliases @@ -0,0 +1,21 @@ +# Matt's ~/.bash_aliases is a link to this file ~/GitHub/data.table/.dev/.bash_aliases + +# One off configure meld as difftool: +# git config --global diff.tool meld +# git config --global difftool.prompt false +alias gd='git difftool &> /dev/null' +alias gdm='git difftool master &> /dev/null' + +alias Rdevel='~/build/R-devel/bin/R --vanilla' +alias Rdevel-strict-gcc='~/build/R-devel-strict-gcc/bin/R --vanilla' +alias Rdevel-strict-clang='~/build/R-devel-strict-clang/bin/R --vanilla' +alias Rdevel32='~/build/32bit/R-devel/bin/R --vanilla' +alias R310='~/build/R-3.1.0/bin/R --vanilla' +alias revdepsh='cd ~/build/revdeplib/ && export TZ=UTC && export R_LIBS_SITE=none && export R_LIBS=~/build/revdeplib/ && export _R_CHECK_FORCE_SUGGESTS_=false' +alias revdepr='revdepsh; R_PROFILE_USER=~/GitHub/data.table/.dev/revdep.R ~/build/R-devel/bin/R' + +export R_PROFILE_USER='~/.Rprofile' +# there's a .Rprofile in ~/GitHub/data.table/ so Matt sets R_PROFILE_USER here to always use ~/.Rprofile +# even when starting R in ~/GitHub/data.table +# Matt's ~/.Rprofile as a link to ~/GitHub/data.table/.dev/.Rprofile + diff --git a/.dev/CRAN_Release.cmd b/.dev/CRAN_Release.cmd index e629ee980b..f9d435455e 100644 --- a/.dev/CRAN_Release.cmd +++ b/.dev/CRAN_Release.cmd @@ -304,7 +304,7 @@ cd R-devel # used for revdep testing: .dev/revdep.R. ./configure CFLAGS="-O2 -Wall -pedantic" make -# use latest available below `apt cache search gcc-` or `clang-` +# use latest available below `apt-cache search gcc-` or `clang-` cd ../R-devel-strict-clang ./configure --without-recommended-packages --disable-byte-compiled-packages --disable-openmp --enable-strict-barrier --disable-long-double CC="clang-8 -fsanitize=undefined,address -fno-sanitize=float-divide-by-zero -fno-omit-frame-pointer" make @@ -479,7 +479,7 @@ sudo apt-get -y install r-base r-base-dev sudo apt-get -y build-dep r-base-dev sudo apt-get -y build-dep qpdf sudo apt-get -y install aptitude -sudo aptitude build-dep r-cran-rgl # leads to libglu1-mesa-dev +sudo aptitude -y build-dep r-cran-rgl # leads to libglu1-mesa-dev sudo apt-get -y build-dep r-cran-rmpi sudo apt-get -y build-dep r-cran-cairodevice sudo apt-get -y build-dep r-cran-tkrplot @@ -490,8 +490,7 @@ sudo apt-get -y install libv8-dev sudo apt-get -y install gsl-bin libgsl0-dev sudo apt-get -y install libgtk2.0-dev netcdf-bin sudo apt-get -y install libcanberra-gtk-module -sudo apt-get -y install git -sudo apt-get -y install openjdk-8-jdk +sudo apt-get -y install openjdk-11-jdk # solves "fatal error: jni.h: No such file or directory"; change 11 to match "java --version" sudo apt-get -y install libnetcdf-dev udunits-bin libudunits2-dev sudo apt-get -y install tk8.6-dev sudo apt-get -y install clustalo # for package LowMACA @@ -512,7 +511,7 @@ sudo apt-get -y install libmagick++-dev # for magick sudo apt-get -y install libjq-dev libprotoc-dev libprotobuf-dev and protobuf-compiler # for protolite sudo apt-get -y install python-dev # for PythonInR sudo apt-get -y install gdal-bin libgeos-dev # for rgdal/raster tested via lidR -sudo apt-get build-dep r-cran-rsymphony # for Rsymphony: coinor-libcgl-dev coinor-libclp-dev coinor-libcoinutils-dev coinor-libosi-dev coinor-libsymphony-dev +sudo apt-get -y build-dep r-cran-rsymphony # for Rsymphony: coinor-libcgl-dev coinor-libclp-dev coinor-libcoinutils-dev coinor-libosi-dev coinor-libsymphony-dev sudo apt-get -y install libtesseract-dev libleptonica-dev tesseract-ocr-eng # for tesseract sudo apt-get -y install libssl-dev libsasl2-dev sudo apt-get -y install biber # for ctsem @@ -520,6 +519,8 @@ sudo apt-get -y install libopenblas-dev # for ivmte (+ local R build with defau sudo apt-get -y install libhiredis-dev # for redux used by nodbi sudo apt-get -y install libzmq3-dev # for rzmq sudo apt-get -y install libimage-exiftool-perl # for camtrapR +sudo apt-get -y install parallel # for revdepr.R +sudo apt-get -y install pandoc-citeproc # for basecallQC sudo R CMD javareconf # ENDIF From f6bc553e73f3a5c8df1c7cfefb577fa7dcdebe48 Mon Sep 17 00:00:00 2001 From: Matt Dowle Date: Mon, 25 May 2020 16:54:45 -0600 Subject: [PATCH 14/31] relaxed test 1590 given change in R-devel on ordering encodings (#4492) --- inst/tests/tests.Rraw | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index ed17470383..3a6148221d 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -8120,7 +8120,7 @@ test(1588.7, dt[ch>"c"], dt[4:6]) # coverage of a return(NULL) in .prepareFastS # data.table operates consistently independent of locale, but it's R that changes and is sensitive to it. # Because keys/indexes depend on a sort order. If a data.table is stored on disk with a key -# created in a locale-sensitive order and then loaded by another R session in a different locale, the ability to re-use existing sortedness +# created in a locale-sensitive order and then loaded by another R session in a different locale, the ability to reuse existing sortedness # will break because the order would depend on the locale. Which is why data.table is deliberately C-locale only. For consistency and simpler # internals for robustness to reduce the change of errors and to avoid that class of bug. It would be possible to have locale-sensitive keys # and indexes but we've, so far, decided not to, for those reasons. @@ -8137,12 +8137,20 @@ Encoding(x1) = "latin1" x2 = iconv(x1, "latin1", "UTF-8") test(1590.01, identical(x1,x2)) test(1590.02, x1==x2) -test(1590.03, forderv( c(x2,x1,x1,x2)), integer()) # desirable consistent result given data.table's needs -test(1590.04, base::order(c(x2,x1,x1,x2)), INT(1,4,2,3)) # different result in base R under C locale even though identical(x1,x2) +test(1590.03, forderv( c(x2,x1,x1,x2)), integer()) # desirable consistent result given identical(x1, x2) + # ^^ data.table consistent over time regardless of which version of R or locale +baseR = base::order(c(x2,x1,x1,x2)) + # Even though C locale and identical(x1,x2), base R considers the encoding too; i.e. orders the same-encoding together. + # In R <= 4.0.0, base R put x2 (UTF-8) before x1 (latin1). + # Then in R-devel around May 2020, R-devel on Windows started putting x1 before x2. + # Jan emailed R-devel on 23 May 2020. PR#4492 retained this test of base R but relaxed the encoding to be in either order. + # It's good to know that baseR changed. We still want to know in future if base R changes again (so we relaxed 1590.04 and 1590.07 rather than remove them). +test(1590.04, identical(baseR, INT(1,4,2,3)) || identical(baseR, INT(2,3,1,4))) Encoding(x2) = "unknown" test(1590.05, x1!=x2) test(1590.06, forderv( c(x2,x1,x1,x2)), INT(1,4,2,3)) # consistent with Windows-1252 result, tested further below -test(1590.07, base::order(c(x2,x1,x1,x2)), INT(2,3,1,4)) # different result; base R is encoding-sensitive in C-locale +baseR = base::order(c(x2,x1,x1,x2)) +test(1590.07, identical(baseR, INT(1,4,2,3)) || identical(baseR, INT(2,3,1,4))) Sys.setlocale("LC_CTYPE", ctype) Sys.setlocale("LC_COLLATE", collate) test(1590.08, Sys.getlocale(), oldlocale) # checked restored locale fully back to how it was before this test From cacdc92df71b777369a217b6c902c687cf35a70d Mon Sep 17 00:00:00 2001 From: Matt Dowle Date: Mon, 25 May 2020 20:25:59 -0600 Subject: [PATCH 15/31] further relaxation of 1590.04 and 1590.07; base R ordering of identical strings in different encodings (#4494) --- inst/tests/tests.Rraw | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 3a6148221d..f51f2b641f 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -8140,17 +8140,17 @@ test(1590.02, x1==x2) test(1590.03, forderv( c(x2,x1,x1,x2)), integer()) # desirable consistent result given identical(x1, x2) # ^^ data.table consistent over time regardless of which version of R or locale baseR = base::order(c(x2,x1,x1,x2)) - # Even though C locale and identical(x1,x2), base R considers the encoding too; i.e. orders the same-encoding together. - # In R <= 4.0.0, base R put x2 (UTF-8) before x1 (latin1). - # Then in R-devel around May 2020, R-devel on Windows started putting x1 before x2. - # Jan emailed R-devel on 23 May 2020. PR#4492 retained this test of base R but relaxed the encoding to be in either order. - # It's good to know that baseR changed. We still want to know in future if base R changes again (so we relaxed 1590.04 and 1590.07 rather than remove them). -test(1590.04, identical(baseR, INT(1,4,2,3)) || identical(baseR, INT(2,3,1,4))) + # Even though C locale and identical(x1,x2), base R<=4.0.0 considers the encoding too; i.e. orders the encoding together x2 (UTF-8) before x1 (latin1). + # Then around May 2020, R-devel (but just on Windows) started either respecting identical() like data.table has always done, or put latin1 before UTF-8. + # Jan emailed R-devel on 23 May 2020. + # We relaxed 1590.04 and 1590.07 (tests of base R behaviour) rather than remove them, PR#4492 and its follow-up. But these two tests + # are so relaxed now that they barely testing anything. It appears base R behaviour is undefined in this rare case of identical strings in different encodings. +test(1590.04, identical(baseR, INT(1,4,2,3)) || identical(baseR, INT(2,3,1,4)) || identical(baseR, 1:4)) Encoding(x2) = "unknown" test(1590.05, x1!=x2) test(1590.06, forderv( c(x2,x1,x1,x2)), INT(1,4,2,3)) # consistent with Windows-1252 result, tested further below baseR = base::order(c(x2,x1,x1,x2)) -test(1590.07, identical(baseR, INT(1,4,2,3)) || identical(baseR, INT(2,3,1,4))) +test(1590.07, identical(baseR, INT(1,4,2,3)) || identical(baseR, INT(2,3,1,4)) || identical(baseR, 1:4)) Sys.setlocale("LC_CTYPE", ctype) Sys.setlocale("LC_COLLATE", collate) test(1590.08, Sys.getlocale(), oldlocale) # checked restored locale fully back to how it was before this test From 3aa82c5d2f60a6d5c2454dfcedc9f7e7b14fbd6e Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 16 Dec 2019 19:32:44 -0300 Subject: [PATCH 16/31] Adds yaml.extra to add custom attributes to fwrite's yaml --- R/fwrite.R | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/R/fwrite.R b/R/fwrite.R index 1971c0e4ea..4d6eacdf4b 100644 --- a/R/fwrite.R +++ b/R/fwrite.R @@ -82,7 +82,8 @@ fwrite = function(x, file="", append=FALSE, quote="auto", return(invisible()) } } - yaml = if (!yaml) "" else { + write_yaml <- yaml == TRUE || (is.list(yaml) && length(yaml) != 0) + yaml = if (!write_yaml) "" else { if (!requireNamespace('yaml', quietly=TRUE)) stop("'data.table' relies on the package 'yaml' to write the file header; please add this to your library with install.packages('yaml') and try again.") # nocov schema_vec = sapply(x, class) @@ -103,6 +104,10 @@ fwrite = function(x, file="", append=FALSE, quote="auto", header=col.names, sep=sep, sep2=sep2, eol=eol, na.strings=na, dec=dec, qmethod=qmethod, logical01=logical01 ) + if (is.list(yaml)) { + yaml_header <- c(yaml_header, yaml) + } + paste0('---', eol, yaml::as.yaml(yaml_header, line.sep=eol), '---', eol) # NB: as.yaml adds trailing newline } file = enc2native(file) # CfwriteR cannot handle UTF-8 if that is not the native encoding, see #3078. From 063a4bc1aeb9b6466b18a4b50a377243f9542fa8 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Tue, 17 Dec 2019 12:13:10 -0300 Subject: [PATCH 17/31] Adds test --- inst/tests/tests.Rraw | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index f51f2b641f..07f23ed66e 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -16649,6 +16649,12 @@ test(2125.09, capture.output(print(DT, trunc.cols=TRUE)), test(2125.10, capture.output(print(DT, trunc.cols=TRUE, class=TRUE)), "4 variables not shown: [a , b , c , d ]") options(old_width) +# Extra arguments in yaml +data = data.table(x = 1, y = 100) +file = tempfile() +fwrite(data, file, yaml = list(something_else = "o hai!")) +x = fread(file, yaml = TRUE) +test(2125, attr(x, "yaml_metadata")$something_else, "o hai!") # segfault when i is NULL or zero-column, #4060 DT = data.table(A="a", key="A") From fa0d66c82ca51bbc0bf912d076788a279ab18a81 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Sat, 28 Dec 2019 15:43:35 -0300 Subject: [PATCH 18/31] Escapes test --- inst/tests/tests.Rraw | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 07f23ed66e..ea3b0f7f4d 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14847,6 +14847,15 @@ if (test_yaml) { # csvy; #1701 close(fcon) test(2033.14, fread(f), DT) unlink(f) + + # Extra arguments in yaml + data = data.table(x = 1, y = 100) + file = tempfile() + fwrite(data, file, yaml = list(something_else = "o hai!")) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.01, attr(x, "yaml_metadata")$something_else, "o hai!") + test(2125.02, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") } # fcast coverage From ff474613f043c4d1caed65d8d5f9d92ea5abfd10 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Sun, 16 Feb 2020 19:16:12 -0300 Subject: [PATCH 19/31] Adapts to new syntax for yaml. --- R/fwrite.R | 48 ++++++++++++++++++++++--------------------- R/utils.R | 31 ++++++++++++++++++++++++++++ inst/tests/tests.Rraw | 35 +++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 25 deletions(-) diff --git a/R/fwrite.R b/R/fwrite.R index 4d6eacdf4b..6e01768c71 100644 --- a/R/fwrite.R +++ b/R/fwrite.R @@ -82,33 +82,36 @@ fwrite = function(x, file="", append=FALSE, quote="auto", return(invisible()) } } - write_yaml <- yaml == TRUE || (is.list(yaml) && length(yaml) != 0) + write_yaml = isTRUE(yaml) || (is.list(yaml) && length(yaml) != 0L) yaml = if (!write_yaml) "" else { if (!requireNamespace('yaml', quietly=TRUE)) stop("'data.table' relies on the package 'yaml' to write the file header; please add this to your library with install.packages('yaml') and try again.") # nocov - schema_vec = sapply(x, class) - # multi-class objects reduced to first class - if (is.list(schema_vec)) schema_vec = sapply(schema_vec, `[`, 1L) - # as.vector strips names - schema_vec = list(name=names(schema_vec), type=as.vector(schema_vec)) - yaml_header = list( - source = sprintf('R[v%s.%s]::data.table[v%s]::fwrite', - R.version$major, R.version$minor, format(tryCatch(utils::packageVersion('data.table'), error=function(e) 'DEV'))), - creation_time_utc = format(Sys.time(), tz='UTC'), - schema = list( - fields = lapply( - seq_along(x), - function(i) list(name=schema_vec$name[i], type=schema_vec$type[i]) - ) - ), - header=col.names, sep=sep, sep2=sep2, eol=eol, na.strings=na, - dec=dec, qmethod=qmethod, logical01=logical01 - ) - if (is.list(yaml)) { - yaml_header <- c(yaml_header, yaml) + + if (isTRUE(yaml)) { + yaml = generate_yaml(x = x, col.names = col.names, sep = sep, + sep2 = sep2, eol = eol, na = na, dec = dec, + qmethod = qmethod, logical01 = logical01) + } else { + names = names(yaml) + if (is.null(names)) { + names = rep("", length(yaml)) + } + unnamed = names == "" + true_yaml = vapply_1b(yaml, isTRUE) + + generated_yaml = unnamed & true_yaml + if (any(unnamed & !true_yaml)) { + stop("`yaml` contains unnamed elements that are not `TRUE`") + } + if (any(generated_yaml)) { + yaml_header = generate_yaml(x = x, col.names = col.names, sep = sep, + sep2 = sep2, eol = eol, na = na, dec = dec, + qmethod = qmethod, logical01 = logical01) + yaml = c(yaml_header, yaml[!generated_yaml]) + } } - paste0('---', eol, yaml::as.yaml(yaml_header, line.sep=eol), '---', eol) # NB: as.yaml adds trailing newline + paste0('---', eol, yaml::as.yaml(yaml, line.sep=eol), '---', eol) # NB: as.yaml adds trailing newline } file = enc2native(file) # CfwriteR cannot handle UTF-8 if that is not the native encoding, see #3078. .Call(CfwriteR, x, file, sep, sep2, eol, na, dec, quote, qmethod=="escape", append, @@ -116,4 +119,3 @@ fwrite = function(x, file="", append=FALSE, quote="auto", showProgress, is_gzip, bom, yaml, verbose) invisible() } - diff --git a/R/utils.R b/R/utils.R index 42e67ea8de..6c9dc01cce 100644 --- a/R/utils.R +++ b/R/utils.R @@ -124,6 +124,37 @@ do_patterns = function(pat_sub, all_cols) { return(matched) } + +generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", + eol = if (.Platform$OS.type=="windows") "\r\n" else "\n", + na = "", dec = "", qmethod = "double", + logical01 = getOption("datatable.logical01", FALSE)) { + schema_vec = sapply(x, class) + # multi-class objects reduced to first class + if (is.list(schema_vec)) schema_vec = sapply(schema_vec, `[`, 1L) + # as.vector strips names + schema_vec = list(name=names(schema_vec), type=as.vector(schema_vec)) + list( + source = sprintf('R[v%s.%s]::data.table[v%s]::fwrite', + R.version$major, R.version$minor, format(tryCatch(utils::packageVersion('data.table'), error=function(e) 'DEV'))), + creation_time_utc = format(Sys.time(), tz='UTC'), + schema = list( + fields = lapply( + seq_along(x), + function(i) list(name=schema_vec$name[i], type=schema_vec$type[i]) + ) + ), + header = col.names, + sep = sep, + sep2 = sep2, + eol = eol, + na.strings = na, + dec = dec, + qmethod = qmethod, + logical01 = logical01 + ) +} + # check UTC status is_utc = function(tz) { # via grep('UTC|GMT', OlsonNames(), value = TRUE); ordered by "prior" frequency diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index ea3b0f7f4d..482a357dff 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14850,12 +14850,43 @@ if (test_yaml) { # csvy; #1701 # Extra arguments in yaml data = data.table(x = 1, y = 100) - file = tempfile() + file = tmpfile() + fwrite(data, file, yaml = list(something_else = "o hai!")) x = fread(file, yaml = TRUE) unlink(file) test(2125.01, attr(x, "yaml_metadata")$something_else, "o hai!") - test(2125.02, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2125.02, attr(x, "yaml_metadata")$schema, NULL) + + + fwrite(data, file, yaml = TRUE) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.03, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + + + fwrite(data, file, yaml = list(TRUE)) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.04, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + + + fwrite(data, file, yaml = list(TRUE, something_else = "o hai!")) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.05, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2125.06, attr(x, "yaml_metadata")$something_else, "o hai!") + + + fwrite(data, file, yaml = list(TRUE, something_else = "o hai!", this_is_true = TRUE)) + x = fread(file, yaml = TRUE) + unlink(file) + test(2125.07, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2125.08, attr(x, "yaml_metadata")$something_else, "o hai!") + test(2125.09, attr(x, "yaml_metadata")$this_is_true, TRUE) + + test(2125.10, fwrite(data, file, yaml = list(TRUE, "unnamed_stuff")), error = "unnamed") + } # fcast coverage From f91c99f7677497218d8a8ccf3ab555464e491c56 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 17 Feb 2020 14:19:27 +0800 Subject: [PATCH 20/31] whitespace --- R/fwrite.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/fwrite.R b/R/fwrite.R index 6e01768c71..6b247bf2c5 100644 --- a/R/fwrite.R +++ b/R/fwrite.R @@ -89,8 +89,8 @@ fwrite = function(x, file="", append=FALSE, quote="auto", if (isTRUE(yaml)) { yaml = generate_yaml(x = x, col.names = col.names, sep = sep, - sep2 = sep2, eol = eol, na = na, dec = dec, - qmethod = qmethod, logical01 = logical01) + sep2 = sep2, eol = eol, na = na, dec = dec, + qmethod = qmethod, logical01 = logical01) } else { names = names(yaml) if (is.null(names)) { From dce4e2ea5a27ae12c407227221b15c692109b541 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 17 Feb 2020 12:29:13 -0300 Subject: [PATCH 21/31] Small refactor in generate_yaml's schema --- R/utils.R | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/R/utils.R b/R/utils.R index 6c9dc01cce..675749b6c1 100644 --- a/R/utils.R +++ b/R/utils.R @@ -126,25 +126,20 @@ do_patterns = function(pat_sub, all_cols) { generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", - eol = if (.Platform$OS.type=="windows") "\r\n" else "\n", + eol = if (.Platform$OS.type == "windows") "\r\n" else "\n", na = "", dec = "", qmethod = "double", logical01 = getOption("datatable.logical01", FALSE)) { - schema_vec = sapply(x, class) - # multi-class objects reduced to first class - if (is.list(schema_vec)) schema_vec = sapply(schema_vec, `[`, 1L) - # as.vector strips names - schema_vec = list(name=names(schema_vec), type=as.vector(schema_vec)) + schema_vec = sapply(x, class, simplify = FALSE) list( source = sprintf('R[v%s.%s]::data.table[v%s]::fwrite', R.version$major, R.version$minor, format(tryCatch(utils::packageVersion('data.table'), error=function(e) 'DEV'))), creation_time_utc = format(Sys.time(), tz='UTC'), schema = list( - fields = lapply( - seq_along(x), - function(i) list(name=schema_vec$name[i], type=schema_vec$type[i]) - ) + fields = lapply(seq_along(x), function(i) { + list(name = names(schema_vec)[i], type = schema_vec[[i]][[1L]]) # multi-class objects reduced to first class + }) ), - header = col.names, + header = col.names, sep = sep, sep2 = sep2, eol = eol, From 24f446e81282e9c0169dc2013043af417fb2057d Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 17 Feb 2020 13:04:00 -0300 Subject: [PATCH 22/31] More clear yaml logic --- R/fwrite.R | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/R/fwrite.R b/R/fwrite.R index 6b247bf2c5..e9d5f2a1ba 100644 --- a/R/fwrite.R +++ b/R/fwrite.R @@ -83,12 +83,13 @@ fwrite = function(x, file="", append=FALSE, quote="auto", } } write_yaml = isTRUE(yaml) || (is.list(yaml) && length(yaml) != 0L) - yaml = if (!write_yaml) "" else { + yaml_text = "" + if (write_yaml) { if (!requireNamespace('yaml', quietly=TRUE)) stop("'data.table' relies on the package 'yaml' to write the file header; please add this to your library with install.packages('yaml') and try again.") # nocov if (isTRUE(yaml)) { - yaml = generate_yaml(x = x, col.names = col.names, sep = sep, + yaml_text = generate_yaml(x = x, col.names = col.names, sep = sep, sep2 = sep2, eol = eol, na = na, dec = dec, qmethod = qmethod, logical01 = logical01) } else { @@ -103,19 +104,20 @@ fwrite = function(x, file="", append=FALSE, quote="auto", if (any(unnamed & !true_yaml)) { stop("`yaml` contains unnamed elements that are not `TRUE`") } + yaml_text <- yaml[!generated_yaml] if (any(generated_yaml)) { yaml_header = generate_yaml(x = x, col.names = col.names, sep = sep, sep2 = sep2, eol = eol, na = na, dec = dec, qmethod = qmethod, logical01 = logical01) - yaml = c(yaml_header, yaml[!generated_yaml]) + yaml_text = c(yaml_header, yaml_text) } } - paste0('---', eol, yaml::as.yaml(yaml, line.sep=eol), '---', eol) # NB: as.yaml adds trailing newline + yaml_text = paste0('---', eol, yaml::as.yaml(yaml_text, line.sep = eol), '---', eol) # NB: as.yaml adds trailing newline } file = enc2native(file) # CfwriteR cannot handle UTF-8 if that is not the native encoding, see #3078. .Call(CfwriteR, x, file, sep, sep2, eol, na, dec, quote, qmethod=="escape", append, row.names, col.names, logical01, scipen, dateTimeAs, buffMB, nThread, - showProgress, is_gzip, bom, yaml, verbose) + showProgress, is_gzip, bom, yaml_text, verbose) invisible() } From df5b5418601997d118bbd0733ecdc9eb641e7683 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 14:46:21 -0300 Subject: [PATCH 23/31] Saves and reads column attributes Refers to #3540 --- R/fread.R | 5 +++++ R/utils.R | 20 ++++++++++++++------ inst/tests/tests.Rraw | 13 ++++++++++++- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/R/fread.R b/R/fread.R index d57d2cd6fd..389227636b 100644 --- a/R/fread.R +++ b/R/fread.R @@ -305,6 +305,11 @@ yaml=FALSE, autostart=NA, tmpdir=tempdir()) return(v) }, error = fun) + + if (yaml) { + attributes(new_v) <- c(attributes(new_v), yaml_header$schema$fields[[j]]$attributes) + } + set(ans, j = j, value = new_v) # aside: new_v == v if the coercion was aborted } setattr(ans, "colClassesAs", NULL) diff --git a/R/utils.R b/R/utils.R index 675749b6c1..c2261f9f87 100644 --- a/R/utils.R +++ b/R/utils.R @@ -129,16 +129,24 @@ generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", eol = if (.Platform$OS.type == "windows") "\r\n" else "\n", na = "", dec = "", qmethod = "double", logical01 = getOption("datatable.logical01", FALSE)) { - schema_vec = sapply(x, class, simplify = FALSE) + fields = sapply(seq_along(x), function(i) { + attrs <- attributes(x[[i]]) + attrs <- attrs[!(names(attrs) %in% "class")] + + ret <- list(name = colnames(x)[i], + type = class(x[[i]])[[1]]) # multi-class objects reduced to first class + + if (!is.null(attrs)) { + ret <- c(ret, list(attributes = attrs)) + } + return(ret) + }, simplify = FALSE) + list( source = sprintf('R[v%s.%s]::data.table[v%s]::fwrite', R.version$major, R.version$minor, format(tryCatch(utils::packageVersion('data.table'), error=function(e) 'DEV'))), creation_time_utc = format(Sys.time(), tz='UTC'), - schema = list( - fields = lapply(seq_along(x), function(i) { - list(name = names(schema_vec)[i], type = schema_vec[[i]][[1L]]) # multi-class objects reduced to first class - }) - ), + schema = list(fields = fields), header = col.names, sep = sep, sep2 = sep2, diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 482a357dff..40b505d1be 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14886,7 +14886,18 @@ if (test_yaml) { # csvy; #1701 test(2125.09, attr(x, "yaml_metadata")$this_is_true, TRUE) test(2125.10, fwrite(data, file, yaml = list(TRUE, "unnamed_stuff")), error = "unnamed") - + + + data = data.table(x = 1, y = 100, + c = factor(letters[1:3], levels = letters[1:4]), + date = Sys.Date()) + attr(data$x, "attr") <- "attribute" + fwrite(data, file, yaml = TRUE) + x = fread(file, yaml = TRUE) + unlink(file) + + test(2126.01, levels(x$c), letters[1:4]) + test(2126.02, attr(data$x, "attr"), "attribute") } # fcast coverage From a5d1ce8ee20937e1b397fd8b3e3addef34667ac9 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 15:05:09 -0300 Subject: [PATCH 24/31] Adds test --- R/fread.R | 1 - inst/tests/tests.Rraw | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/R/fread.R b/R/fread.R index 389227636b..761773483b 100644 --- a/R/fread.R +++ b/R/fread.R @@ -284,7 +284,6 @@ yaml=FALSE, autostart=NA, tmpdir=tempdir()) if (check.names) { setattr(ans, 'names', make.names(names(ans), unique=TRUE)) } - colClassesAs = attr(ans, "colClassesAs", exact=TRUE) # should only be present if one or more are != "" for (j in which(colClassesAs!="")) { # # 1634 v = .subset2(ans, j) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 40b505d1be..0da918a681 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14898,6 +14898,10 @@ if (test_yaml) { # csvy; #1701 test(2126.01, levels(x$c), letters[1:4]) test(2126.02, attr(data$x, "attr"), "attribute") + + fwrite(data, file, yaml = TRUE) + test(2126.03, fread(file, yaml = FALSE), x) + unlink(file) } # fcast coverage From 47355095450ae4f1b9a08d07f8f8b84c6c1a02d7 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 15:14:32 -0300 Subject: [PATCH 25/31] Adds attributes to all columns, not just factors et.al. --- R/fread.R | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/R/fread.R b/R/fread.R index 761773483b..2b1344b0d2 100644 --- a/R/fread.R +++ b/R/fread.R @@ -305,10 +305,6 @@ yaml=FALSE, autostart=NA, tmpdir=tempdir()) }, error = fun) - if (yaml) { - attributes(new_v) <- c(attributes(new_v), yaml_header$schema$fields[[j]]$attributes) - } - set(ans, j = j, value = new_v) # aside: new_v == v if the coercion was aborted } setattr(ans, "colClassesAs", NULL) @@ -334,7 +330,13 @@ yaml=FALSE, autostart=NA, tmpdir=tempdir()) } setkeyv(ans, key) } - if (yaml) setattr(ans, 'yaml_metadata', yaml_header) + if (yaml) { + setattr(ans, 'yaml_metadata', yaml_header) + + for (j in seq_along(ans)) { + attributes(ans[[j]]) <- c(attributes(ans[[j]]), yaml_header$schema$fields[[j]]$attributes) + } + } if (!is.null(index) && data.table) { if (!all(sapply(index, is.character))) stop("index argument of data.table() must be a character vector naming columns (NB: col.names are applied before this)") From b783fe39765c68c24fc37662c195c1d5b60c6532 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 15:46:29 -0300 Subject: [PATCH 26/31] Skips length 0 attributes --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index c2261f9f87..ff5e05d084 100644 --- a/R/utils.R +++ b/R/utils.R @@ -136,7 +136,7 @@ generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", ret <- list(name = colnames(x)[i], type = class(x[[i]])[[1]]) # multi-class objects reduced to first class - if (!is.null(attrs)) { + if (!is.null(attrs) & length(attrs != 0)) { ret <- c(ret, list(attributes = attrs)) } return(ret) From 9b43bdc97a372ae95843a247def14ae165036d33 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Thu, 20 Feb 2020 17:19:45 -0300 Subject: [PATCH 27/31] Fix previous commit --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index ff5e05d084..107d88c12d 100644 --- a/R/utils.R +++ b/R/utils.R @@ -136,7 +136,7 @@ generate_yaml = function(x, col.names = TRUE, sep = ",", sep2 = "", ret <- list(name = colnames(x)[i], type = class(x[[i]])[[1]]) # multi-class objects reduced to first class - if (!is.null(attrs) & length(attrs != 0)) { + if (!is.null(attrs) & length(attrs) != 0) { ret <- c(ret, list(attributes = attrs)) } return(ret) From 1942aa00ffee4c096df658010e6ae168e537900b Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Tue, 26 May 2020 12:58:14 -0300 Subject: [PATCH 28/31] Changes News and Description --- DESCRIPTION | 3 ++- NEWS.md | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5dd73e284c..29258612ac 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -57,7 +57,8 @@ Authors@R: c( person("David","Simons", role="ctb"), person("Elliott","Sales de Andrade", role="ctb"), person("Cole","Miller", role="ctb"), - person("@JenspederM","", role="ctb")) + person("@JenspederM","", role="ctb"), + person("Elio", "Campitelli", role="ctb")) Depends: R (>= 3.1.0) Imports: methods Suggests: bit64, curl, R.utils, knitr, xts, nanotime, zoo, yaml diff --git a/NEWS.md b/NEWS.md index 7ecd4bc5af..b11172db78 100644 --- a/NEWS.md +++ b/NEWS.md @@ -81,6 +81,9 @@ unit = "s") 14. Added support for `round()` and `trunc()` to extend functionality of `ITime`. `round()` and `trunc()` can be used with argument units: "hours" or "minutes". Thanks to @JensPederM for the suggestion and PR. +15. The `yaml` argument in `fread` now accepts a list which will be used to populate the yaml header of the generated csv file. Thanks to @eliocamp for the PR. + + ## BUG FIXES 1. A NULL timezone on POSIXct was interpreted by `as.IDate` and `as.ITime` as UTC rather than the session's default timezone (`tz=""`) , [#4085](https://github.com/Rdatatable/data.table/issues/4085). From 8dae2ba6b8df757d567f62e5e16c930086dbbc1f Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Tue, 26 May 2020 12:58:22 -0300 Subject: [PATCH 29/31] Fixes test number --- inst/tests/tests.Rraw | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 0da918a681..ee02b79187 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14855,40 +14855,40 @@ if (test_yaml) { # csvy; #1701 fwrite(data, file, yaml = list(something_else = "o hai!")) x = fread(file, yaml = TRUE) unlink(file) - test(2125.01, attr(x, "yaml_metadata")$something_else, "o hai!") - test(2125.02, attr(x, "yaml_metadata")$schema, NULL) + test(2139.01, attr(x, "yaml_metadata")$something_else, "o hai!") + test(2139.02, attr(x, "yaml_metadata")$schema, NULL) fwrite(data, file, yaml = TRUE) x = fread(file, yaml = TRUE) unlink(file) - test(2125.03, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2139.03, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") fwrite(data, file, yaml = list(TRUE)) x = fread(file, yaml = TRUE) unlink(file) - test(2125.04, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2139.04, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") fwrite(data, file, yaml = list(TRUE, something_else = "o hai!")) x = fread(file, yaml = TRUE) unlink(file) - test(2125.05, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") - test(2125.06, attr(x, "yaml_metadata")$something_else, "o hai!") + test(2139.05, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2139.06, attr(x, "yaml_metadata")$something_else, "o hai!") fwrite(data, file, yaml = list(TRUE, something_else = "o hai!", this_is_true = TRUE)) x = fread(file, yaml = TRUE) unlink(file) - test(2125.07, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") - test(2125.08, attr(x, "yaml_metadata")$something_else, "o hai!") - test(2125.09, attr(x, "yaml_metadata")$this_is_true, TRUE) + test(2139.07, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") + test(2139.08, attr(x, "yaml_metadata")$something_else, "o hai!") + test(2139.09, attr(x, "yaml_metadata")$this_is_true, TRUE) - test(2125.10, fwrite(data, file, yaml = list(TRUE, "unnamed_stuff")), error = "unnamed") + test(2139.10, fwrite(data, file, yaml = list(TRUE, "unnamed_stuff")), error = "unnamed") - data = data.table(x = 1, y = 100, + data = data.table(x = 1L, y = 100L, c = factor(letters[1:3], levels = letters[1:4]), date = Sys.Date()) attr(data$x, "attr") <- "attribute" @@ -14896,11 +14896,14 @@ if (test_yaml) { # csvy; #1701 x = fread(file, yaml = TRUE) unlink(file) - test(2126.01, levels(x$c), letters[1:4]) - test(2126.02, attr(data$x, "attr"), "attribute") + test(2139.11, levels(x$c), letters[1:4]) + test(2139.12, attr(data$x, "attr"), "attribute") - fwrite(data, file, yaml = TRUE) - test(2126.03, fread(file, yaml = FALSE), x) + attr(data$x, "attr") <- NULL + data$c = as.character(data$c) + data$date = as.character(data$date) + + test(2139.13, fread(file, yaml = FALSE), data) unlink(file) } @@ -16704,12 +16707,7 @@ test(2125.09, capture.output(print(DT, trunc.cols=TRUE)), test(2125.10, capture.output(print(DT, trunc.cols=TRUE, class=TRUE)), "4 variables not shown: [a , b , c , d ]") options(old_width) -# Extra arguments in yaml -data = data.table(x = 1, y = 100) -file = tempfile() -fwrite(data, file, yaml = list(something_else = "o hai!")) -x = fread(file, yaml = TRUE) -test(2125, attr(x, "yaml_metadata")$something_else, "o hai!") + # segfault when i is NULL or zero-column, #4060 DT = data.table(A="a", key="A") From e857360d1cabbe9368d6a5bb742a016292e970a1 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Tue, 26 May 2020 13:05:54 -0300 Subject: [PATCH 30/31] Fixes error in test --- inst/tests/tests.Rraw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index ee02b79187..96f12a0843 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14894,7 +14894,7 @@ if (test_yaml) { # csvy; #1701 attr(data$x, "attr") <- "attribute" fwrite(data, file, yaml = TRUE) x = fread(file, yaml = TRUE) - unlink(file) + test(2139.11, levels(x$c), letters[1:4]) test(2139.12, attr(data$x, "attr"), "attribute") From ae58f35488ce7af6b1a3b78a50fc40f17f9df205 Mon Sep 17 00:00:00 2001 From: Elio Campitelli Date: Tue, 26 May 2020 13:09:26 -0300 Subject: [PATCH 31/31] Fixes bad merge --- inst/tests/tests.Rraw | 50 ++++++------------------------------------- 1 file changed, 7 insertions(+), 43 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 0bd0ccdc2e..e32821a5a4 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -14855,51 +14855,35 @@ if (test_yaml) { # csvy; #1701 fwrite(data, file, yaml = list(something_else = "o hai!")) x = fread(file, yaml = TRUE) unlink(file) -<<<<<<< HEAD test(2139.01, attr(x, "yaml_metadata")$something_else, "o hai!") test(2139.02, attr(x, "yaml_metadata")$schema, NULL) -======= - test(2125.01, attr(x, "yaml_metadata")$something_else, "o hai!") - test(2125.02, attr(x, "yaml_metadata")$schema, NULL) ->>>>>>> yaml-attrs - fwrite(data, file, yaml = TRUE) x = fread(file, yaml = TRUE) unlink(file) -<<<<<<< HEAD + test(2139.03, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") -======= - test(2125.03, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") ->>>>>>> yaml-attrs - + fwrite(data, file, yaml = list(TRUE)) x = fread(file, yaml = TRUE) unlink(file) -<<<<<<< HEAD + test(2139.04, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") -======= - test(2125.04, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") ->>>>>>> yaml-attrs - + fwrite(data, file, yaml = list(TRUE, something_else = "o hai!")) x = fread(file, yaml = TRUE) unlink(file) -<<<<<<< HEAD + test(2139.05, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") test(2139.06, attr(x, "yaml_metadata")$something_else, "o hai!") -======= - test(2125.05, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") - test(2125.06, attr(x, "yaml_metadata")$something_else, "o hai!") ->>>>>>> yaml-attrs - + fwrite(data, file, yaml = list(TRUE, something_else = "o hai!", this_is_true = TRUE)) x = fread(file, yaml = TRUE) unlink(file) -<<<<<<< HEAD + test(2139.07, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") test(2139.08, attr(x, "yaml_metadata")$something_else, "o hai!") test(2139.09, attr(x, "yaml_metadata")$this_is_true, TRUE) @@ -14908,22 +14892,11 @@ if (test_yaml) { # csvy; #1701 data = data.table(x = 1L, y = 100L, -======= - test(2125.07, attr(x, "yaml_metadata")$schema$fields[[1]]$name, "x") - test(2125.08, attr(x, "yaml_metadata")$something_else, "o hai!") - test(2125.09, attr(x, "yaml_metadata")$this_is_true, TRUE) - - test(2125.10, fwrite(data, file, yaml = list(TRUE, "unnamed_stuff")), error = "unnamed") - - - data = data.table(x = 1, y = 100, ->>>>>>> yaml-attrs c = factor(letters[1:3], levels = letters[1:4]), date = Sys.Date()) attr(data$x, "attr") <- "attribute" fwrite(data, file, yaml = TRUE) x = fread(file, yaml = TRUE) -<<<<<<< HEAD test(2139.11, levels(x$c), letters[1:4]) @@ -14934,15 +14907,6 @@ if (test_yaml) { # csvy; #1701 data$date = as.character(data$date) test(2139.13, fread(file, yaml = FALSE), data) -======= - unlink(file) - - test(2126.01, levels(x$c), letters[1:4]) - test(2126.02, attr(data$x, "attr"), "attribute") - - fwrite(data, file, yaml = TRUE) - test(2126.03, fread(file, yaml = FALSE), x) ->>>>>>> yaml-attrs unlink(file) }