Skip to content

Commit d9300ad

Browse files
committed
Merge branch 'master' into litedown
2 parents d01e83c + 84b0e32 commit d9300ad

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+3753
-703
lines changed

.ci/.lintr.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ linters = c(dt_linters, all_linters(
2121
message = "Use messagef to avoid fragmented translations.",
2222
warning = "Use warningf to avoid fragmented translations.",
2323
stop = "Use stopf to avoid fragmented translations.",
24+
rev = "Use frev internally, or setfrev if by-reference is safe.",
2425
NULL
2526
)),
2627
# undesirable_function_linter(modify_defaults(

.ci/atime/tests.R

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,5 +277,14 @@ test.list <- atime::atime_test_list(
277277
Slow = "73d79edf8ff8c55163e90631072192301056e336", # Parent of the first commit in the PR (https://github.com/Rdatatable/data.table/commit/8397dc3c993b61a07a81c786ca68c22bc589befc)
278278
Fast = "8397dc3c993b61a07a81c786ca68c22bc589befc"), # Commit in the PR (https://github.com/Rdatatable/data.table/pull/7019/commits) that removes inefficiency
279279

280+
"isoweek improved in #7144" = atime::atime_test(
281+
setup = {
282+
set.seed(349)
283+
x = sample(Sys.Date() - 0:5000, N, replace=TRUE)
284+
},
285+
expr = data.table::isoweek(x),
286+
Slow = "548410d23dd74b625e8ea9aeb1a5d2e9dddd2927", # Parent of the first commit in the PR (https://github.com/Rdatatable/data.table/commit/548410d23dd74b625e8ea9aeb1a5d2e9dddd2927)
287+
Fast = "c0b32a60466bed0e63420ec105bc75c34590865e"), # Commit in the PR (https://github.com/Rdatatable/data.table/pull/7144/commits) that uses a much faster implementation
288+
280289
tests=extra.test.list)
281290
# nolint end: undesirable_operator_linter.

.ci/linters/md/news_linter.R renamed to .ci/linters/md/news_github_link_mismatch_linter.R

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,6 @@
1-
# ensure that numbered list in each section is in sequence
2-
check_section_numbering = function(news) {
3-
if (!grepl("NEWS", news)) return(invisible())
4-
news = readLines(news)
5-
# plain '#' catches some examples; 'd' for 'data.table'
6-
sections = grep("^#+ [A-Zd]", news)
7-
entries = grep("^[0-9]+[.]", news)
8-
entry_value = as.integer(gsub("^([0-9]+)[.].*", "\\1", news[entries]))
9-
section_id = findInterval(entries, sections)
10-
11-
any_mismatch = FALSE
12-
for (id in unique(section_id)) {
13-
section_entries = entry_value[section_id == id]
14-
intended_value = seq_along(section_entries)
15-
matched = section_entries == intended_value
16-
if (all(matched)) next
17-
any_mismatch = TRUE
18-
section_header = news[sections[id]]
19-
cat(sprintf(
20-
"In section '%s' (line %d), bad numbering:\n%s\n",
21-
section_header, sections[id],
22-
paste0(" [", section_entries[!matched], " --> ", intended_value[!matched], "]", collapse="\n")
23-
))
24-
}
25-
stopifnot("Please fix the NEWS issues above" = !any_mismatch)
26-
}
27-
281
# ensure that GitHub link text & URL actually agree
29-
check_gh_links = function(news) {
2+
news_github_link_mismatch_linter = function(news) {
3+
if (!grepl("NEWS", news)) return(invisible())
304
news = readLines(news)
315
gh_links_info = gregexpr(
326
"\\[#(?<md_number>[0-9]+)\\]\\(https://github.com/Rdatatable/data.table/(?<link_type>[^/]+)/(?<link_number>[0-9]+)\\)",
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# ensure that numbered list in each section is in sequence
2+
news_section_numbering_linter = function(news) {
3+
if (!grepl("NEWS", news)) return(invisible())
4+
news = readLines(news)
5+
# plain '#' catches some examples; 'd' for 'data.table'
6+
sections = grep("^#+ [A-Zd]", news)
7+
entries = grep("^[0-9]+[.]", news)
8+
entry_value = as.integer(gsub("^([0-9]+)[.].*", "\\1", news[entries]))
9+
section_id = findInterval(entries, sections)
10+
11+
any_mismatch = FALSE
12+
for (id in unique(section_id)) {
13+
section_entries = entry_value[section_id == id]
14+
intended_value = seq_along(section_entries)
15+
matched = section_entries == intended_value
16+
if (all(matched)) next
17+
any_mismatch = TRUE
18+
section_header = news[sections[id]]
19+
cat(sprintf(
20+
"In section '%s' (line %d), bad numbering:\n%s\n",
21+
section_header, sections[id],
22+
paste0(" [", section_entries[!matched], " --> ", intended_value[!matched], "]", collapse="\n")
23+
))
24+
}
25+
stopifnot("Please fix the NEWS issues above" = !any_mismatch)
26+
}

.ci/linters/md/heading_id_linter.R renamed to .ci/linters/md/vignette_heading_id_linter.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ensure that ids are limited to alphanumerics and dashes
22
# (in particular, dots and underscores break the links)
3-
check_header_ids = function(md) {
3+
vignette_heading_id_linter = function(md) {
44
if (!grepl('[.]Rmd$', md)) return(invisible())
55
md = readLines(md)
66
# A bit surprisingly, some headings don't start with a letter.

.ci/linters/r/eval_parse_linter.R

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
eval_parse_linter = make_linter_from_xpath(
2+
"//SYMBOL_FUNCTION_CALL[text() = 'parse']
3+
/ancestor::expr
4+
/preceding-sibling::expr[SYMBOL_FUNCTION_CALL[text() = 'eval']]
5+
/parent::expr
6+
",
7+
"Avoid eval(parse()); build the language directly, possibly using substitute2()."
8+
)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Ensure that data.table condition classes in code match documentation
2+
condition_classes_documentation_linter = function(rd_file) {
3+
if (!grepl("\\name{data.table-condition-classes}", readChar(rd_file, 100L), fixed = TRUE)) return(invisible())
4+
5+
# Find condition classes in R code
6+
walk_r_ast_for_classes = function(expr) {
7+
if (is.call(expr) && is.name(e <- expr[[1L]]) && as.character(e) %in% c("stopf", "warningf", "messagef", "packageStartupMessagef") && is.character(class_arg <- expr[["class"]]) && startsWith(class_arg, "dt_")) {
8+
class_arg
9+
} else if (is.recursive(expr)) {
10+
unlist(lapply(expr, walk_r_ast_for_classes))
11+
}
12+
}
13+
14+
# Find condition classes in documentation
15+
walk_rd_ast_for_classes = function(rd_element) {
16+
if (!is.list(rd_element)) return(character())
17+
18+
result = character()
19+
if (isTRUE(attr(rd_element, "Rd_tag") == "\\code") && length(rd_element) >= 1L) {
20+
content = rd_element[[1L]]
21+
if (is.character(content) && startsWith(content, "dt_")) {
22+
result = content
23+
}
24+
}
25+
c(result, unlist(lapply(rd_element, walk_rd_ast_for_classes)))
26+
}
27+
28+
code_classes = list.files("R", pattern = "\\.R$", full.names = TRUE) |>
29+
lapply(\(f) lapply(parse(f), walk_r_ast_for_classes)) |>
30+
unlist() |>
31+
unique()
32+
33+
doc_classes = rd_file |>
34+
tools::parse_Rd() |>
35+
walk_rd_ast_for_classes() |>
36+
unique()
37+
38+
miss_in_doc = setdiff(code_classes, doc_classes)
39+
miss_in_code = setdiff(doc_classes, code_classes)
40+
41+
if (length(miss_in_doc) > 0L || length(miss_in_code) > 0L) {
42+
if (length(miss_in_doc) > 0L) {
43+
cat(sprintf("Condition classes in code but missing from docs: %s\n", toString(miss_in_doc)))
44+
}
45+
if (length(miss_in_code) > 0L) {
46+
cat(sprintf("Condition classes in docs but not in code: %s\n", toString(miss_in_code)))
47+
}
48+
stop("Please sync man/datatable-condition-classes.Rd with code condition classes")
49+
}
50+
}
51+

.dev/CRAN_Release.cmd

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -584,26 +584,29 @@ bunzip2 inst/tests/*.Rraw.bz2 # decompress *.Rraw again so as not to commit com
584584
# Many thanks!
585585
# Best, Tyson
586586
# ------------------------------------------------------------
587-
# DO NOT commit or push to GitHub. Leave 4 files (.dev/CRAN_Release.cmd, DESCRIPTION, NEWS and init.c) edited and not committed. Include these in a single and final bump commit below.
588-
# DO NOT even use a PR. Because PRs build binaries and we don't want any binary versions of even release numbers available from anywhere other than CRAN.
587+
589588
# Leave milestone open with a 'release checks' issue open. Keep updating status there.
590589
# ** If on EC2, shutdown instance. Otherwise get charged for potentially many days/weeks idle time with no alerts **
591590
# If it's evening, SLEEP.
592591
# It can take a few days for CRAN's checks to run. If any issues arise, backport locally. Resubmit the same even version to CRAN.
593592
# CRAN's first check is automatic and usually received within an hour. WAIT FOR THAT EMAIL.
594593
# When CRAN's email contains "Pretest results OK pending a manual inspection" (or similar), or if not and it is known why not and ok, then bump dev.
595594

596-
###### Bump dev for NON-PATCH RELEASE
597-
# 0. Close milestone to prevent new issues being tagged with it. The final 'release checks' issue can be left open in a closed milestone.
598-
# 1. Check that 'git status' shows 4 files in modified and uncommitted state: DESCRIPTION, NEWS.md, init.c and this .dev/CRAN_Release.cmd
599-
# 2. Bump minor version in DESCRIPTION to next odd number. Note that DESCRIPTION was in edited and uncommitted state so even number never appears in git.
600-
# 3. Add new heading in NEWS for the next dev version. Add "(submitted to CRAN on <today>)" on the released heading.
601-
# 4. Bump minor version in dllVersion() in init.c
602-
# 5. Bump 3 minor version numbers in Makefile
603-
# 6. Search and replace this .dev/CRAN_Release.cmd to update 1.16.99 to 1.16.99 inc below, 1.16.0 to 1.17.0 above, 1.15.0 to 1.16.0 below
604-
# 7. Another final gd to view all diffs using meld. (I have `alias gd='git difftool &> /dev/null'` and difftool meld: http://meldmerge.org/)
605-
# 8. Push to master with this consistent commit message: "1.17.0 on CRAN. Bump to 1.17.99"
606-
# 9. Take sha from the previous step and run `git tag 1.17.0 96c..sha..d77` then `git push origin 1.16.0` (not `git push --tags` according to https://stackoverflow.com/a/5195913/403310)
595+
###### After submission for NON-PATCH RELEASE
596+
# 0. Start a new branch `cran-x.y.0` with the code as submitted to CRAN
597+
# - Check that 'git status' shows 4 files in modified and uncommitted state: DESCRIPTION, NEWS.md, init.c and this .dev/CRAN_Release.cmd
598+
# - The branch should have one commit with precisely these 4 files being edited
599+
# 1. Follow up with a commit with this consistent commit message like: "1.17.0 on CRAN. Bump to 1.17.99" to this branch bumping to the next dev version
600+
# - Bump minor version in DESCRIPTION to next odd number. Note that DESCRIPTION was in edited and uncommitted state so even number never appears in git.
601+
# - Add new heading in NEWS for the next dev version. Add "(submitted to CRAN on <today>)" on the released heading.
602+
# - Bump minor version in dllVersion() in init.c
603+
# - Bump 3 minor version numbers in Makefile
604+
# - Search and replace this .dev/CRAN_Release.cmd to update 1.16.99 to 1.16.99 inc below, 1.16.0 to 1.17.0 above, 1.15.0 to 1.16.0 below
605+
# - Another final gd to view all diffs using meld. (I have `alias gd='git difftool &> /dev/null'` and difftool meld: http://meldmerge.org/)
606+
# 2. Ideally, no PRs are reviewed while a CRAN submission is pending. Any reviews that do happen MUST target this branch, NOT master!
607+
# 3. Once the submission lands on CRAN, merge this branch WITHOUT SQUASHING!
608+
# 4. Close milestone to prevent new issues being tagged with it. The final 'release checks' issue can be left open in a closed milestone.
609+
# 5. Take SHA from the "...on CRAN. Bump to ..." commit and run `git tag 1.17.0 96c..sha..d77` then `git push origin 1.17.0` (not `git push --tags` according to https://stackoverflow.com/a/5195913/403310)
607610
######
608611

609612
###### Branching policy for PATCH RELEASE
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
on:
2+
workflow_dispatch:
3+
schedule:
4+
- cron: '0 6 * * 1,3,5' # Runs at 06:00 on Mon/Wed/Fri
5+
6+
name: check-cran-status
7+
8+
jobs:
9+
fetch-deadlines:
10+
runs-on: ubuntu-latest
11+
env:
12+
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
13+
permissions:
14+
issues: write
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- uses: r-lib/actions/setup-r@v2
19+
with:
20+
use-public-rspm: true
21+
22+
- uses: r-lib/actions/setup-r-dependencies@v2
23+
with:
24+
packages: |
25+
gh
26+
glue
27+
28+
- name: Check for existing CRAN issues
29+
id: check-issues
30+
env:
31+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32+
run: |
33+
# Count open issues with CRAN-related labels
34+
ISSUE_COUNT=$(gh issue list --label "cran-deadline" --state open --json number | jq length)
35+
if [ $ISSUE_COUNT -eq 0 ]; then
36+
echo "should-run=true" >> $GITHUB_OUTPUT
37+
echo "✅ Will run CRAN check"
38+
else
39+
echo "should-run=false" >> $GITHUB_OUTPUT
40+
echo "⏭️ Skipping CRAN check - existing issues found"
41+
fi
42+
43+
- name: Fetch deadline for this package
44+
if: steps.check-issues.outputs.should-run == 'true'
45+
shell: Rscript {0}
46+
run: |
47+
pkgname <- drop(read.dcf("DESCRIPTION", "Package"))
48+
49+
deadline <- subset(tools::CRAN_package_db(), Package == pkgname, "Deadline", drop=TRUE)
50+
51+
if (is.na(deadline)) {
52+
quit()
53+
}
54+
55+
gh::gh(
56+
"POST /repos/{owner_repo}/issues",
57+
owner_repo = Sys.getenv("GITHUB_REPOSITORY"),
58+
title = paste("Fix CRAN R CMD check issues by", deadline),
59+
body = glue::glue(
60+
"This package is failing CRAN checks and is at risk of archival.",
61+
"https://cran.r-project.org/web/checks/check_results_{pkgname}.html",
62+
"This issue was opened by https://github.com/{Sys.getenv('GITHUB_REPOSITORY')}/actions/runs/{Sys.getenv('GITHUB_RUN_ID')}.",
63+
.sep = "\n\n"
64+
),
65+
labels = list("cran-deadline")
66+
)

.gitlab-ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ test-lin-rel:
114114
variables:
115115
_R_CHECK_FORCE_SUGGESTS_: "TRUE"
116116
OPENBLAS_MAIN_FREE: "1"
117+
_R_CHECK_RD_CHECKRD_MINLEVEL_: "-Inf"
117118
script:
118119
- *install-deps
119120
- echo 'CFLAGS=-g -O3 -flto=auto -fno-common -fopenmp -Wall -Wvla -pedantic -fstack-protector-strong -D_FORTIFY_SOURCE=2' > ~/.R/Makevars

0 commit comments

Comments
 (0)