From 27934f2f31dd65f5b942004584dca5bb354e2281 Mon Sep 17 00:00:00 2001 From: chiricom Date: Thu, 30 Jul 2026 22:57:23 +0000 Subject: [PATCH 01/23] add 4 new locales --- .github/workflows/R-CMD-check-occasional.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index b598e0e784..612ae0c064 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -1,4 +1,5 @@ on: + push: schedule: - cron: '17 13 23 * *' # 23rd of month at 13:17 UTC workflow_dispatch: @@ -17,7 +18,9 @@ jobs: matrix: os: [macOS-latest, windows-latest, ubuntu-latest] r: ['devel', 'release', '3.5', '3.6', '4.0', '4.1', '4.2', '4.3', '4.4', '4.5'] - locale: ['en_US.utf8', 'zh_CN.utf8', 'lv_LV.utf8'] # Chinese for translations, Latvian for collate order (#3502) + # Mandarin: multibyte characters + # Latvian, Azeri, Hungarian, Faroese, Albanian: collate order (#3502, see also #7837) + locale: ['en_US.utf8', 'zh_CN.utf8', 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8'] exclude: # only run non-English locale CI on Ubuntu - os: macOS-latest From ea50a207f4296cedd94a08e7f30eea675995b404 Mon Sep 17 00:00:00 2001 From: chiricom Date: Thu, 30 Jul 2026 23:02:18 +0000 Subject: [PATCH 02/23] Gemini: clean up growing complexity of maintaining locales --- .github/workflows/R-CMD-check-occasional.yaml | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 612ae0c064..8bc28e4580 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -22,15 +22,6 @@ jobs: # Latvian, Azeri, Hungarian, Faroese, Albanian: collate order (#3502, see also #7837) locale: ['en_US.utf8', 'zh_CN.utf8', 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8'] exclude: - # only run non-English locale CI on Ubuntu - - os: macOS-latest - locale: 'zh_CN.utf8' - - os: macOS-latest - locale: 'lv_LV.utf8' - - os: windows-latest - locale: 'zh_CN.utf8' - - os: windows-latest - locale: 'lv_LV.utf8' # macOS/arm64 only available for R>=4.1.0 - os: macOS-latest r: '3.5' @@ -47,24 +38,11 @@ jobs: steps: - name: Set locale - if: matrix.os == 'ubuntu-latest' && matrix.locale == 'en_US.utf8' - run: | - sudo locale-gen en_US - echo "LC_ALL=en_US.utf8" >> $GITHUB_ENV - - - name: Set locale - if: matrix.locale == 'zh_CN.utf8' - run: | - sudo locale-gen 'zh_CN.utf8' - echo "LC_ALL=zh_CN.utf8" >> $GITHUB_ENV - echo "LANGUAGE=zh_CN" >> $GITHUB_ENV - - - name: Set locale - if: matrix.locale == 'lv_LV.utf8' + if: matrix.os == 'ubuntu-latest' run: | - sudo locale-gen 'lv_LV.utf8' - echo "LC_ALL=lv_LV.utf8" >> $GITHUB_ENV - echo "LANGUAGE=lv_LV" >> $GITHUB_ENV + sudo locale-gen "${{ matrix.locale }}" + echo "LC_ALL=${{ matrix.locale }}" >> $GITHUB_ENV + echo "LANGUAGE=$(echo '${{ matrix.locale }}' | cut -d'.' -f1)" >> $GITHUB_ENV - uses: actions/checkout@v7 From 8d8ae7da095fc6a7528b9412412708db6e5ac5b6 Mon Sep 17 00:00:00 2001 From: chiricom Date: Thu, 30 Jul 2026 23:05:11 +0000 Subject: [PATCH 03/23] better comment style --- .github/workflows/R-CMD-check-occasional.yaml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 8bc28e4580..2616b656d0 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -21,6 +21,28 @@ jobs: # Mandarin: multibyte characters # Latvian, Azeri, Hungarian, Faroese, Albanian: collate order (#3502, see also #7837) locale: ['en_US.utf8', 'zh_CN.utf8', 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8'] + # Only run non-English-locale CI runs on Ubuntu + include: + # For multibyte characters + - os: ubuntu-latest + r: 'devel' + locale: 'zh_CN.utf8' # Mandarin + # For collate order (#3502, see also #7837) + - os: ubuntu-latest + r: 'devel' + locale: 'lv_LV.utf8' # Latvian + - os: ubuntu-latest + r: 'devel' + locale: 'az_AZ.utf8' # Azeri + - os: ubuntu-latest + r: 'devel' + locale: 'hu_HU.utf8' # Hungarian + - os: ubuntu-latest + r: 'devel' + locale: 'fo_FO.utf8' # Faroese + - os: ubuntu-latest + r: 'devel' + locale: 'sq_MK.utf8' # Albanian (in North Macedonia) exclude: # macOS/arm64 only available for R>=4.1.0 - os: macOS-latest From 5304a902cf9b75810578e142efcc60e5d88f6e55 Mon Sep 17 00:00:00 2001 From: chiricom Date: Thu, 30 Jul 2026 23:15:42 +0000 Subject: [PATCH 04/23] Gemini: back to `exclude` --- .github/workflows/R-CMD-check-occasional.yaml | 58 +++++++++++-------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 2616b656d0..e5daede46f 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -18,32 +18,40 @@ jobs: matrix: os: [macOS-latest, windows-latest, ubuntu-latest] r: ['devel', 'release', '3.5', '3.6', '4.0', '4.1', '4.2', '4.3', '4.4', '4.5'] - # Mandarin: multibyte characters - # Latvian, Azeri, Hungarian, Faroese, Albanian: collate order (#3502, see also #7837) - locale: ['en_US.utf8', 'zh_CN.utf8', 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8'] - # Only run non-English-locale CI runs on Ubuntu - include: - # For multibyte characters - - os: ubuntu-latest - r: 'devel' - locale: 'zh_CN.utf8' # Mandarin - # For collate order (#3502, see also #7837) - - os: ubuntu-latest - r: 'devel' - locale: 'lv_LV.utf8' # Latvian - - os: ubuntu-latest - r: 'devel' - locale: 'az_AZ.utf8' # Azeri - - os: ubuntu-latest - r: 'devel' - locale: 'hu_HU.utf8' # Hungarian - - os: ubuntu-latest - r: 'devel' - locale: 'fo_FO.utf8' # Faroese - - os: ubuntu-latest - r: 'devel' - locale: 'sq_MK.utf8' # Albanian (in North Macedonia) + locale: ['en_US.utf8', + # Multibyte characters: Mandarin + 'zh_CN.utf8', + # Collate order (#3502, see also #7837): Latvian, Azeri, Hungarian, Faroese, Albanian + 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8'] + # we're constrained by GHA inflexibility to do a tedious thing here with 'exclude' below. + # better would be for GHA to support multiple 'matrix' configs (one for ubuntu, one for other OS); + # an approach with multiple jobs would tediously require copy-pasting the _rest_ of the steps exclude: + # only run non-English locale CI on Ubuntu + - os: macOS-latest + locale: 'zh_CN.utf8' + - os: macOS-latest + locale: 'lv_LV.utf8' + - os: macOS-latest + locale: 'az_AZ.utf8' + - os: macOS-latest + locale: 'hu_HU.utf8' + - os: macOS-latest + locale: 'fo_FO.utf8' + - os: macOS-latest + locale: 'sq_MK.utf8' + - os: windows-latest + locale: 'zh_CN.utf8' + - os: windows-latest + locale: 'lv_LV.utf8' + - os: windows-latest + locale: 'az_AZ.utf8' + - os: windows-latest + locale: 'hu_HU.utf8' + - os: windows-latest + locale: 'fo_FO.utf8' + - os: windows-latest + locale: 'sq_MK.utf8' # macOS/arm64 only available for R>=4.1.0 - os: macOS-latest r: '3.5' From 9e858779ea89ca67255931c854a1683bd1464aa0 Mon Sep 17 00:00:00 2001 From: chiricom Date: Fri, 31 Jul 2026 03:47:25 +0000 Subject: [PATCH 05/23] Mark R.oo required for now --- inst/tests/other.Rraw | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/inst/tests/other.Rraw b/inst/tests/other.Rraw index 9ae3ffe38c..46bbce83d0 100644 --- a/inst/tests/other.Rraw +++ b/inst/tests/other.Rraw @@ -1,9 +1,11 @@ -pkgs = c("DBI", "RSQLite", "bit64", "ggplot2", "caret", "dplyr", "gdata", "hexbin", "knitr", "nanotime", "nlme", "parallel", "plyr", "R.utils", "sf", "vctrs", "zoo", "xts", "yaml") +pkgs = c("DBI", "RSQLite", "bit64", "ggplot2", "caret", "dplyr", "gdata", "hexbin", "knitr", "nanotime", "nlme", "parallel", "plyr", "R.oo", "R.utils", "sf", "vctrs", "zoo", "xts", "yaml") # First expression of this file must be as above: .gitlab-ci.yml uses parse(,n=1L) to read one expression from this file and installs pkgs. # So that these dependencies of other.Rraw are maintained in a single place. # TODO(R>=3.6.0): use attach.required=FALSE to let us keep pkgs= in alphabetical order (https://stat.ethz.ch/pipermail/r-devel/2026-July/084630.html) # TEST_DATA_TABLE_WITH_OTHER_PACKAGES is off by default so this other.Rraw doesn't run on CRAN. It is run by GLCI, locally in dev, and by # users running test.data.table("other.Rraw"). +# TODO(HenrikBengtsson/R.oo#31): I think we can remove 'R.oo' once it can install in certain locales; +# for now, we have to include it in 'pkgs' to ensure tests don't try to proceed when 'R.oo' is found missing. # Optional Suggest-ed package tests moved from tests.Rraw to here in #5516. Retaining their comments: # "xts", # we have xts methods in R/xts.R From e68dd143ae52b74584367304701dd22008d198e4 Mon Sep 17 00:00:00 2001 From: chiricom Date: Fri, 31 Jul 2026 16:32:35 +0000 Subject: [PATCH 06/23] Gemini: workarounds for R 3.5 --- .github/workflows/R-CMD-check-occasional.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index e5daede46f..943d70720c 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -132,7 +132,9 @@ jobs: other_pkgs = get(as.character(other_deps_expr[[1L]][[2L]])) # Many will not install on oldest R versions message("*** Installing fully optional packages ***") - try(install.packages(c(other_pkgs, "rcmdcheck"))) + base_pkgs = rownames(installed.packages(priority = "base")) + install_pkgs = setdiff(c(other_pkgs, "rcmdcheck"), base_pkgs) + try(install.packages(install_pkgs)) has_other_pkg = sapply(other_pkgs, requireNamespace, quietly=TRUE) run_other = all(has_other_pkg) @@ -144,7 +146,8 @@ jobs: } else { message(sprintf("Skipping other.Rraw since some required packages are not available: %s\n", toString(other_pkgs[!has_other_pkg]))) } - # IINM rcmdcheck isolates its env from the calling process', besides what's passed to env= + # Set env var in calling process for older rcmdcheck versions (<1.4.0) that do not support env= + Sys.setenv(TEST_DATA_TABLE_WITH_OTHER_PACKAGES = as.character(run_other)) env = c( TEST_DATA_TABLE_WITH_OTHER_PACKAGES=as.character(run_other) ) @@ -159,7 +162,9 @@ jobs: check_args = c(check_args, "--no-build-vignettes", "--ignore-vignettes") } if (requireNamespace("rcmdcheck", quietly=TRUE)) { - rcmdcheck::rcmdcheck(args = check_args, build_args = build_args, error_on = "warning", check_dir = "check", env=env) + rc_args = list(args = check_args, build_args = build_args, error_on = "warning", check_dir = "check") + if ("env" %in% names(formals(rcmdcheck::rcmdcheck))) rc_args$env = env + do.call(rcmdcheck::rcmdcheck, rc_args) } else { Rbin = if (.Platform$OS.type == "windows") "R.exe" else "R" system2(Rbin, c("CMD", "build", ".", build_args)) From e2059e5b6c28f4dc21a583b6ee8b6e1b9646508f Mon Sep 17 00:00:00 2001 From: chiricom Date: Fri, 31 Jul 2026 16:34:57 +0000 Subject: [PATCH 07/23] simplify --- .github/workflows/R-CMD-check-occasional.yaml | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 943d70720c..5bf445a1c7 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -129,12 +129,12 @@ jobs: other_deps_expr = parse('inst/tests/other.Rraw', n=1L) eval(other_deps_expr) - other_pkgs = get(as.character(other_deps_expr[[1L]][[2L]])) + other_pkgs = setdiff( + get(as.character(other_deps_expr[[1L]][[2L]])) + tools:::.get_standard_package_names()$base) # skip parallel # Many will not install on oldest R versions message("*** Installing fully optional packages ***") - base_pkgs = rownames(installed.packages(priority = "base")) - install_pkgs = setdiff(c(other_pkgs, "rcmdcheck"), base_pkgs) - try(install.packages(install_pkgs)) + try(install.packages(c(other_pkgs, "rcmdcheck")) has_other_pkg = sapply(other_pkgs, requireNamespace, quietly=TRUE) run_other = all(has_other_pkg) @@ -146,8 +146,7 @@ jobs: } else { message(sprintf("Skipping other.Rraw since some required packages are not available: %s\n", toString(other_pkgs[!has_other_pkg]))) } - # Set env var in calling process for older rcmdcheck versions (<1.4.0) that do not support env= - Sys.setenv(TEST_DATA_TABLE_WITH_OTHER_PACKAGES = as.character(run_other)) + # IINM rcmdcheck isolates its env from the calling process', besides what's passed to env= env = c( TEST_DATA_TABLE_WITH_OTHER_PACKAGES=as.character(run_other) ) @@ -162,9 +161,12 @@ jobs: check_args = c(check_args, "--no-build-vignettes", "--ignore-vignettes") } if (requireNamespace("rcmdcheck", quietly=TRUE)) { - rc_args = list(args = check_args, build_args = build_args, error_on = "warning", check_dir = "check") - if ("env" %in% names(formals(rcmdcheck::rcmdcheck))) rc_args$env = env - do.call(rcmdcheck::rcmdcheck, rc_args) + if ("env" %in% names(formals(rcmdcheck::rcmdcheck))) { + rcmdcheck::rcmdcheck(args=check_args, build_args=build_args, error_on="warning", check_dir="check", env=env) + } else { + do.call(Sys.setenv, as.list(env)) + rcmdcheck::rcmdcheck(args=check_args, build_args=build_args, error_on="warning", check_dir="check") + } } else { Rbin = if (.Platform$OS.type == "windows") "R.exe" else "R" system2(Rbin, c("CMD", "build", ".", build_args)) From 2eab6525317bfbfd0ac64456d528c1647995d3e7 Mon Sep 17 00:00:00 2001 From: chiricom Date: Fri, 31 Jul 2026 16:44:43 +0000 Subject: [PATCH 08/23] Gemini: simplify further, unify across branches & rcmdcheck versions --- .github/workflows/R-CMD-check-occasional.yaml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 5bf445a1c7..b32805fb1e 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -146,10 +146,7 @@ jobs: } else { message(sprintf("Skipping other.Rraw since some required packages are not available: %s\n", toString(other_pkgs[!has_other_pkg]))) } - # IINM rcmdcheck isolates its env from the calling process', besides what's passed to env= - env = c( - TEST_DATA_TABLE_WITH_OTHER_PACKAGES=as.character(run_other) - ) + Sys.setenv(TEST_DATA_TABLE_WITH_OTHER_PACKAGES=as.character(run_other)) do_vignettes = requireNamespace("litedown", quietly=TRUE) @@ -172,7 +169,7 @@ jobs: system2(Rbin, c("CMD", "build", ".", build_args)) dt_tar = list.files(pattern = "^data[.]table_.*[.]tar[.]gz$") if (!length(dt_tar)) stop("Built tar.gz not found among: ", toString(list.files())) - res = system2(Rbin, c("CMD", "check", dt_tar[1L], check_args), stdout=TRUE, stderr=TRUE, env=sprintf("%s=%s", names(env), env)) + res = system2(Rbin, c("CMD", "check", dt_tar[1L], check_args), stdout=TRUE, stderr=TRUE) if (!is.null(attr(res, "status")) || anyNA(res) || any(grepl("^Status:.*(ERROR|WARNING)", res))) { writeLines(as.character(res)) stop("R CMD check failed") From 7d78644eda4dc86e195112a87a92b1cb050e4da1 Mon Sep 17 00:00:00 2001 From: chiricom Date: Fri, 31 Jul 2026 16:55:43 +0000 Subject: [PATCH 09/23] Use tryCatch, for now, while R.oo cannot install --- inst/tests/tests.Rraw | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 2514547cff..3fa2957679 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -136,9 +136,11 @@ sugg = c( ) for (s in sugg) { assign(paste0("test_",s), loaded<-suppressWarnings(suppressMessages( - library(s, character.only=TRUE, logical.return=TRUE, quietly=TRUE, warn.conflicts=FALSE, pos="package:base") # attach at the end for #5101 + # tryCatch() here, not library(logical.return=), because of https://github.com/HenrikBengtsson/R.oo/issues/31; + # library(logical.return=) throws an error when R.utils doesn't find R.oo, not logical FALSE. + tryCatch(library(s, character.only=TRUE, quietly=TRUE, warn.conflicts=FALSE, pos="package:base"), error=identity) # attach at the end for #5101 ))) - if (!loaded) cat("\n**** Suggested package",s,"is not installed or has dependencies missing. Tests using it will be skipped.\n\n") + if (inherits(loaded, "error")) cat("\n**** Suggested package",s,"is not installed or has dependencies missing. Tests using it will be skipped.\n\n") } test_longdouble = isTRUE(capabilities()["long.double"]) && identical(as.integer(.Machine$longdouble.digits), 64L) From c38fbadc23bebd4c77c99edc9f31cc44b2338ef0 Mon Sep 17 00:00:00 2001 From: chiricom Date: Fri, 31 Jul 2026 17:48:01 +0000 Subject: [PATCH 10/23] restore is.logical(loaded) --- inst/tests/tests.Rraw | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 3fa2957679..b80fb2f227 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -135,12 +135,12 @@ sugg = c( "R.utils" # many fread test input files are compressed to save space; fundamental to test environment ) for (s in sugg) { - assign(paste0("test_",s), loaded<-suppressWarnings(suppressMessages( + assign(paste0("test_",s), loaded <- !inherits(what="error", suppressWarnings(suppressMessages( # tryCatch() here, not library(logical.return=), because of https://github.com/HenrikBengtsson/R.oo/issues/31; # library(logical.return=) throws an error when R.utils doesn't find R.oo, not logical FALSE. tryCatch(library(s, character.only=TRUE, quietly=TRUE, warn.conflicts=FALSE, pos="package:base"), error=identity) # attach at the end for #5101 - ))) - if (inherits(loaded, "error")) cat("\n**** Suggested package",s,"is not installed or has dependencies missing. Tests using it will be skipped.\n\n") + )))) + if (!loaded) cat("\n**** Suggested package",s,"is not installed or has dependencies missing. Tests using it will be skipped.\n\n") } test_longdouble = isTRUE(capabilities()["long.double"]) && identical(as.integer(.Machine$longdouble.digits), 64L) From 9c09f4c8b3a0c16cb092c3339bd6e142eb3e0b20 Mon Sep 17 00:00:00 2001 From: chiricom Date: Fri, 31 Jul 2026 18:42:07 +0000 Subject: [PATCH 11/23] missin g, simpler [[ --- .github/workflows/R-CMD-check-occasional.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index b32805fb1e..ee081fc405 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -130,7 +130,7 @@ jobs: other_deps_expr = parse('inst/tests/other.Rraw', n=1L) eval(other_deps_expr) other_pkgs = setdiff( - get(as.character(other_deps_expr[[1L]][[2L]])) + get(as.character(other_deps_expr[[1:2]])), tools:::.get_standard_package_names()$base) # skip parallel # Many will not install on oldest R versions message("*** Installing fully optional packages ***") From 6fa40207284cba149063290bddb0e574e3c9cb4b Mon Sep 17 00:00:00 2001 From: chiricom Date: Fri, 31 Jul 2026 20:51:19 +0000 Subject: [PATCH 12/23] missing ) --- .github/workflows/R-CMD-check-occasional.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index ee081fc405..288379b90d 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -134,7 +134,7 @@ jobs: tools:::.get_standard_package_names()$base) # skip parallel # Many will not install on oldest R versions message("*** Installing fully optional packages ***") - try(install.packages(c(other_pkgs, "rcmdcheck")) + try(install.packages(c(other_pkgs, "rcmdcheck"))) has_other_pkg = sapply(other_pkgs, requireNamespace, quietly=TRUE) run_other = all(has_other_pkg) From 27868eab605081deea7e05f666cf1da275e10bf4 Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 06:23:17 +0000 Subject: [PATCH 13/23] Avoid as.nanotime for ancient {nanotime} --- inst/tests/other.Rraw | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/inst/tests/other.Rraw b/inst/tests/other.Rraw index 46bbce83d0..617e9a2bec 100644 --- a/inst/tests/other.Rraw +++ b/inst/tests/other.Rraw @@ -718,13 +718,13 @@ if (loaded[["nanotime"]]) { test(27, na.omit(DT), DT[c(1,3)]) # rbind with vectors with class attributes #5309 - x = data.table(a=1L, b=as.nanotime(0)) + x = data.table(a=1L, b=nanotime(0)) y = data.table(a=2L, b=NA) - test(27.01, rbind(x,y), data.table(a = c(1L, 2L), b=as.nanotime(c(0, NA)))) - test(27.02, rbind(y,x), data.table(a = c(2L, 1L), b=as.nanotime(c(NA, 0)))) + test(27.01, rbind(x,y), data.table(a = c(1L, 2L), b=nanotime(c(0, NA)))) + test(27.02, rbind(y,x), data.table(a = c(2L, 1L), b=nanotime(c(NA, 0)))) y[, b := NULL] - test(27.03, rbind(x,y, fill = TRUE), data.table(a = c(1L, 2L), b=as.nanotime(c(0, NA)))) - test(27.04, rbind(y,x, fill = TRUE), data.table(a = c(2L, 1L), b=as.nanotime(c(NA, 0)))) + test(27.03, rbind(x,y, fill = TRUE), data.table(a = c(1L, 2L), b=nanotime(c(0, NA)))) + test(27.04, rbind(y,x, fill = TRUE), data.table(a = c(2L, 1L), b=nanotime(c(NA, 0)))) # Was 1.91-1.94 in nafill.Rraw, #6139 l = list(a=nanotime(c(1:2,NA,4:5)), b=nanotime(c(NA,2L,NA,4L,NA))) @@ -784,7 +784,7 @@ if (loaded[["dplyr"]]) { if (loaded[["nanotime"]]) { # respect dec=',' for nanotime, related to #6446, corresponding to tests 2281.* - test(31, fwrite(data.table(as.nanotime(.POSIXct(0))), dec=',', sep=';'), output="1970-01-01T00:00:00,000000000Z") + test(31, fwrite(data.table(nanotime(.POSIXct(0))), dec=',', sep=';'), output="1970-01-01T00:00:00,000000000Z") } # tables() with large environment #6607 From 8e9fa33819cc24695beaee3efeb4ed7fbaa77b5e Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 07:28:35 +0000 Subject: [PATCH 14/23] skip tests which fail on ancient versions of bit64 --- inst/tests/optimize.Rraw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inst/tests/optimize.Rraw b/inst/tests/optimize.Rraw index 2c835c2c15..4c25baee8b 100644 --- a/inst/tests/optimize.Rraw +++ b/inst/tests/optimize.Rraw @@ -192,7 +192,8 @@ dt = data.table(x = sample(letters, 300, TRUE), i2 = sample(c(-10:10, NA), 300, TRUE), d1 = as.numeric(sample(-10:10, 300, TRUE)), d2 = as.numeric(sample(c(NA, NaN, -10:10), 300, TRUE))) -if (test_bit64) { +# is.na() test for ancient {bit64} on ancient R +if (test_bit64 && is.na(integer64()[1L])) { dt[, `:=`(d3 = as.integer64(sample(-10:10, 300, TRUE)))] dt[, `:=`(d4 = as.integer64(sample(c(-10:10,NA), 300, TRUE)))] } From 5e45196a3fd83a26583b864e73fa649c161e0e06 Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 14:50:48 +0000 Subject: [PATCH 15/23] nullfile() from R 3.6.0 --- inst/tests/tests.Rraw | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index b80fb2f227..729225d339 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -20769,8 +20769,10 @@ DT[1, V1 := factor("a", levels = c("a", samelevel))] test(2311.3, nlevels(DT$V1), 2L) # used to be 3 # avoid translateChar*() in OpenMP threads, #6883 -DF = list(rep(iconv("\uf8", from = "UTF-8", to = "latin1"), 2e6)) -test(2312, fwrite(DF, nullfile(), encoding = "UTF-8", nThread = 2L), NULL) +DF = list(rep(iconv("\uf8", from="UTF-8", to="latin1"), 2e6)) +# TODO(R>=3.6.0): nullfile() added to base +if (!exists("nullfile")) nullfile <- function() if (.Platform$OS.type == "windows") "nul:" else "/dev/null" +test(2312, fwrite(DF, nullfile(), encoding="UTF-8", nThread=2L), check_value=FALSE) # avoid memcpy of 0-length inputs test(2313, From e937f88787d396678ef40f10e2e7ecf70fcf41d1 Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 14:52:36 +0000 Subject: [PATCH 16/23] a kludge for ancient knitr --- inst/tests/other.Rraw | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/inst/tests/other.Rraw b/inst/tests/other.Rraw index 617e9a2bec..f81a0d0da2 100644 --- a/inst/tests/other.Rraw +++ b/inst/tests/other.Rraw @@ -203,7 +203,9 @@ if (loaded[["knitr"]]) { tmp = tempfile() on.exit({unlink(tmp); options(old)}) invisible(knit(testDir("knitr.Rmd"), tmp, quiet=TRUE)) - test(11.2, tools::Rdiff(tmp, testDir("knitr.md.save")), 0L) + # TODO(R>=3.6.0): Try removing this kludge + if (packageVersion("knitr") > "1.45") + test(11.2, tools::Rdiff(tmp, testDir("knitr.md.save")), 0L) }) } From 3e2605780986dd799771f2ebbcd5bfb7fb413a80 Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 14:52:36 +0000 Subject: [PATCH 17/23] a kludge for ancient dplyr --- inst/tests/other.Rraw | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/inst/tests/other.Rraw b/inst/tests/other.Rraw index f81a0d0da2..7f45bd86e4 100644 --- a/inst/tests/other.Rraw +++ b/inst/tests/other.Rraw @@ -102,7 +102,9 @@ if (loaded[["dplyr"]]) { DT = data.table(A=c("b","c","a"), B=10:12) setindex(DT, A) DT2 = dplyr::arrange(DT, A) - test(2.2, DT2[A=="c"], data.table(A="c", B=11L)) + # TODO(R>=3.6.0): Old versions of dplyr might coerce to tbl or data.frame; try removing this + if (is.data.table(DT2)) + test(2.2, DT2[A=="c"], data.table(A="c", B=11L)) } if (FALSE) { # loaded[["reshape"]] From 425dd36e837280ad594cc0b15ccb9385c73d7f43 Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 18:35:11 +0000 Subject: [PATCH 18/23] Re-word test 168 to avoid R strptime bug; test in vi_VN --- .github/workflows/R-CMD-check-occasional.yaml | 4 +++- inst/tests/tests.Rraw | 15 ++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 288379b90d..007685df43 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -22,7 +22,9 @@ jobs: # Multibyte characters: Mandarin 'zh_CN.utf8', # Collate order (#3502, see also #7837): Latvian, Azeri, Hungarian, Faroese, Albanian - 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8'] + 'lv_LV.utf8', 'az_AZ.utf8', 'hu_HU.utf8', 'fo_FO.utf8', 'sq_MK.utf8', + # Local time formatting (for R bug #19117) + 'vi_VN.utf8'] # we're constrained by GHA inflexibility to do a tedious thing here with 'exclude' below. # better would be for GHA to support multiple 'matrix' configs (one for ubuntu, one for other OS); # an approach with multiple jobs would tediously require copy-pasting the _rest_ of the steps diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 729225d339..3942ed0214 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -627,15 +627,12 @@ test(166, suppressWarnings(split(DT,DT$grp)[[2]]), DT[grp==2]) # 167 tested graphics::plot, moved to other.Rraw 28 to save ram, #5517 # IDateTime conversion methods that ggplot2 uses (it calls as.data.frame method) -# Since %b is e.g. "nov." in LC_TIME=fr_FR.UTF-8 locale, we need to -# have the target/y value in these tests depend on the locale as well, #3450. -NOV = format(strptime("2000-11-01", "%Y-%m-%d"), "%b") -x = c("09:29:16","10:42:40","23:47:12","01:06:01","11:35:34","11:51:09") -datetimes = paste0("2011 ", NOV, c(18,18,18,19,19,19), " ", x) -DT = IDateTime(strptime(datetimes,"%Y %b%d %H:%M:%S")) -test(168.1, DT[,as.data.frame(itime)], data.frame(V1=as.ITime(x))) -test(168.2, as.character(DT[,as.POSIXct(itime,tz="UTC")]), paste(Sys.Date(), x)) -test(168.3, as.character(DT[,as.POSIXct(idate,tz="UTC")]), c("2011-11-18","2011-11-18","2011-11-18","2011-11-19","2011-11-19","2011-11-19")) +dates = paste0("2011-11-", rep(18:19, each=3L)) +times = c("09:29:16", "10:42:40", "23:47:12", "01:06:01", "11:35:34", "11:51:09") +DT = IDateTime(as.POSIXlt(paste(dates, times))) +test(168.1, DT[, as.data.frame(itime)], data.frame(V1=as.ITime(times))) +test(168.2, as.character(DT[, as.POSIXct(itime, tz="UTC")]), paste(Sys.Date(), times)) +test(168.3, as.character(DT[, as.POSIXct(idate, tz="UTC")]), dates) # test of . in formula, using inheritance DT = data.table(y=1:100,x=101:200,y=201:300,grp=1:5) From b124b49a98f357e17bc3f6a418ebde9bea18c29f Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 22:49:53 +0000 Subject: [PATCH 19/23] exclude vi_VN from macOS/windows --- .github/workflows/R-CMD-check-occasional.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 007685df43..84595374e7 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -42,6 +42,8 @@ jobs: locale: 'fo_FO.utf8' - os: macOS-latest locale: 'sq_MK.utf8' + - os: macOS-latest + locale: 'vi_VN.utf8' - os: windows-latest locale: 'zh_CN.utf8' - os: windows-latest @@ -54,6 +56,8 @@ jobs: locale: 'fo_FO.utf8' - os: windows-latest locale: 'sq_MK.utf8' + - os: windows-latest + locale: 'vi_VN.utf8' # macOS/arm64 only available for R>=4.1.0 - os: macOS-latest r: '3.5' From 819de1d7fab145162a1c4d6cac7a9ed992bb518d Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 23:58:39 +0000 Subject: [PATCH 20/23] make conditions on dplyr,knitr version-based --- inst/tests/other.Rraw | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/inst/tests/other.Rraw b/inst/tests/other.Rraw index 7f45bd86e4..77e03a7299 100644 --- a/inst/tests/other.Rraw +++ b/inst/tests/other.Rraw @@ -97,14 +97,13 @@ if (loaded[["plyr"]]) { test(2.1, plyr::arrange(DT,b), data.table(a=INT(1,3,5,7,9,2,4,6,8,10),b=INT(1,1,1,1,1,2,2,2,2,2))) } -if (loaded[["dplyr"]]) { +# in versions 0.7.0-0.8.5 of dplyr, arrange() returns a data.frame. +if (loaded[["dplyr"]] && packageVersion("dplyr") >= "1.0.0") { # dplyr::arrange uses vctrs::vec_slice which is implemented in C and bypasses `[` dispatch; #5042 DT = data.table(A=c("b","c","a"), B=10:12) setindex(DT, A) DT2 = dplyr::arrange(DT, A) - # TODO(R>=3.6.0): Old versions of dplyr might coerce to tbl or data.frame; try removing this - if (is.data.table(DT2)) - test(2.2, DT2[A=="c"], data.table(A="c", B=11L)) + test(2.2, DT2[A=="c"], data.table(A="c", B=11L)) } if (FALSE) { # loaded[["reshape"]] @@ -194,7 +193,8 @@ if (loaded[["gdata"]]) { unlink(f) } -if (loaded[["knitr"]]) { +# trivial '```r' vs '``` r' difference in older knitr +if (loaded[["knitr"]] && packageVersion("knitr") > "1.45") { # That data.table-unaware code in packages like knitr still work # kable in knitr v1.6 uses DF[...] syntax inside it but the user might have passed a data.table. # Which is fine and works thanks to cedta(). From ef748a3d459e2ae9d437044f4f5178ce39d797a7 Mon Sep 17 00:00:00 2001 From: chiricom Date: Tue, 4 Aug 2026 18:38:25 +0000 Subject: [PATCH 21/23] back to occasional testing --- .github/workflows/R-CMD-check-occasional.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 84595374e7..22571228d9 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -1,5 +1,4 @@ on: - push: schedule: - cron: '17 13 23 * *' # 23rd of month at 13:17 UTC workflow_dispatch: From 51d4cbb6d83d70c8f89126ec71957163114a92a5 Mon Sep 17 00:00:00 2001 From: chiricom Date: Wed, 5 Aug 2026 16:35:33 +0000 Subject: [PATCH 22/23] Fix-up botched merge --- .github/workflows/R-CMD-check-occasional.yaml | 7 +------ inst/tests/other.Rraw | 4 +--- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/R-CMD-check-occasional.yaml b/.github/workflows/R-CMD-check-occasional.yaml index 22571228d9..7f3dc36d89 100644 --- a/.github/workflows/R-CMD-check-occasional.yaml +++ b/.github/workflows/R-CMD-check-occasional.yaml @@ -163,12 +163,7 @@ jobs: check_args = c(check_args, "--no-build-vignettes", "--ignore-vignettes") } if (requireNamespace("rcmdcheck", quietly=TRUE)) { - if ("env" %in% names(formals(rcmdcheck::rcmdcheck))) { - rcmdcheck::rcmdcheck(args=check_args, build_args=build_args, error_on="warning", check_dir="check", env=env) - } else { - do.call(Sys.setenv, as.list(env)) - rcmdcheck::rcmdcheck(args=check_args, build_args=build_args, error_on="warning", check_dir="check") - } + rcmdcheck::rcmdcheck(args=check_args, build_args=build_args, error_on="warning", check_dir="check") } else { Rbin = if (.Platform$OS.type == "windows") "R.exe" else "R" system2(Rbin, c("CMD", "build", ".", build_args)) diff --git a/inst/tests/other.Rraw b/inst/tests/other.Rraw index 77e03a7299..928bc8e63e 100644 --- a/inst/tests/other.Rraw +++ b/inst/tests/other.Rraw @@ -205,9 +205,7 @@ if (loaded[["knitr"]] && packageVersion("knitr") > "1.45") { tmp = tempfile() on.exit({unlink(tmp); options(old)}) invisible(knit(testDir("knitr.Rmd"), tmp, quiet=TRUE)) - # TODO(R>=3.6.0): Try removing this kludge - if (packageVersion("knitr") > "1.45") - test(11.2, tools::Rdiff(tmp, testDir("knitr.md.save")), 0L) + test(11.2, tools::Rdiff(tmp, testDir("knitr.md.save")), 0L) }) } From 032548177be90b6cf32c2e8aeae71243f34eb198 Mon Sep 17 00:00:00 2001 From: chiricom Date: Wed, 5 Aug 2026 18:31:16 +0000 Subject: [PATCH 23/23] Fix make_c_sortable do delete the culprit strings, not random ones --- inst/tests/tests.Rraw | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 3942ed0214..ffadaa6c3f 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -253,7 +253,7 @@ make_c_sortable = function(x) { sorted_c = x[idx_c] sorted_r = x[idx_r] - x = x[-which(sorted_c != sorted_r)[1L]] + x = x[-idx_c[which(sorted_c != sorted_r)[1L]]] } x } @@ -4484,11 +4484,6 @@ d1 = as.numeric(sample(c(-100:100,Inf,-Inf), 1e3, TRUE)) d2 = as.numeric(rnorm(1e3)) c1 = sample(make_c_sortable(letters), 1e3, TRUE) c2 = sample(make_c_sortable(make_words(50L)), 1e3, TRUE) -# With some probability, in some locales (esp. az_AZ), c2 -# can be sorted leading forderv to give integer(). -if (identical(order(c2), seq_along(c2))) { - c2 = c(c2[-1L], "mmmmmmmmmmmmmmmmmmmmmmmmmmm") -} DT = data.table(i1, i2, d1, d2, c1, c2) # randomise col order as well