-
Notifications
You must be signed in to change notification settings - Fork 1k
Add Classed error conditions for programmatic error handling #7139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
68cc421
7041d8d
0a583fa
42d63ad
0602e72
555fcc7
cc12e82
a210f23
21a3c51
99f5bff
71d2cbd
75d48d9
390fda6
88ce984
cf21327
404bd0a
6a3d11f
5244b56
7694219
1cd1600
71563f8
3508e73
e013435
6507f39
5be1427
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # Ensure that data.table condition classes in code match documentation | ||
| condition_classes_documentation_linter = function(rd_file) { | ||
| if (!grepl("\\name{datatable-condition-classes}", readChar(rd_file, 100L), fixed = TRUE)) return(invisible()) | ||
|
|
||
| # Find condition classes in R code | ||
| walk_r_ast_for_classes = function(expr) { | ||
| if (is.call(expr) && length(expr) >= 2L && identical(expr[[1L]], quote(stopf)) && "class" %in% names(expr) && is.character(class_arg <- expr[["class"]]) && startsWith(class_arg, "dt_") && endsWith(class_arg, "_error")) { | ||
| class_arg | ||
| } else if (is.recursive(expr)) { | ||
| unlist(lapply(expr, walk_r_ast_for_classes)) | ||
| } | ||
| } | ||
|
|
||
| # Find condition classes in documentation | ||
| walk_rd_ast_for_classes = function(rd_element) { | ||
| if (!is.list(rd_element)) return(character()) | ||
|
|
||
| result = character() | ||
| if (isTRUE(attr(rd_element, "Rd_tag") == "\\code") && length(rd_element) >= 1L) { | ||
| content = rd_element[[1L]] | ||
| if (is.character(content) && startsWith(content, "dt_") && endsWith(content, "_error")) { | ||
| result = content | ||
| } | ||
| } | ||
| c(result, unlist(lapply(rd_element, walk_rd_ast_for_classes))) | ||
| } | ||
|
|
||
| code_classes = list.files("R", pattern = "\\.R$", full.names = TRUE) |> | ||
| lapply(\(f) lapply(parse(f), walk_r_ast_for_classes)) |> | ||
| unlist() |> | ||
| unique() | ||
|
|
||
| doc_classes = rd_file |> | ||
| tools::parse_Rd() |> | ||
| walk_rd_ast_for_classes() |> | ||
| unique() | ||
|
|
||
| miss_in_doc = setdiff(code_classes, doc_classes) | ||
| miss_in_code = setdiff(doc_classes, code_classes) | ||
|
|
||
| if (length(miss_in_doc) > 0L || length(miss_in_code) > 0L) { | ||
| if (length(miss_in_doc) > 0L) { | ||
| cat(sprintf("Condition classes in code but missing from docs: %s\n", toString(miss_in_doc))) | ||
| } | ||
| if (length(miss_in_code) > 0L) { | ||
| cat(sprintf("Condition classes in docs but not in code: %s\n", toString(miss_in_code))) | ||
| } | ||
| stop("Please sync man/datatable-condition-classes.Rd with code condition classes") | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,37 @@ | ||||
| \name{data.table-error-handling} | ||||
| \alias{data.table-error-handling} | ||||
| \title{Error Handling with Classed Conditions} | ||||
|
MichaelChirico marked this conversation as resolved.
Outdated
|
||||
| \description{ | ||||
| \code{data.table} provides specific condition classes for common operations, making it easier to handle errors programmatically. This is particularly useful when writing robust code or packages that use \code{data.table}. Relying on the exact text of error messages is fragile (it is not uncommon to change the wording slightly, or for the user's session not to be in English); prefer using the signal class where possible. | ||||
| } | ||||
| \details{ | ||||
| \subsection{Available Error Classes}{ | ||||
| \code{data.table} provides four specific error classes: | ||||
|
|
||||
| \itemize{ | ||||
| \item \code{dt_missing_column_error}: When referencing columns that don't exist | ||||
| \item \code{dt_invalid_input_error}: When providing invalid input types or empty required arguments | ||||
| \item \code{dt_unsortable_type_error}: When trying to sort/key unsupported types | ||||
| \item \code{dt_join_type_mismatch_error}: When column types are incompatible in joins/set operations | ||||
| } | ||||
| } | ||||
|
|
||||
| \subsection{Backward Compatibility}{ | ||||
| All error classes inherit from base R's condition system, so existing \code{tryCatch(..., error = ...)} code continues to work unchanged. The new classes simply provide more specific handling options when needed. | ||||
| } | ||||
| } | ||||
| \examples{ | ||||
|
|
||||
| # Handle missing column errors specifically | ||||
| DT <- data.table(a = 1:3, b = 4:6) | ||||
| tryCatch({ | ||||
| setkey(DT, nonexistent_col) | ||||
| }, dt_missing_column_error = function(e) { | ||||
| cat("Missing column detected:", conditionMessage(e), "\n") | ||||
| }, error = function(e) { | ||||
| cat("Other error:", conditionMessage(e), "\n") | ||||
| }) | ||||
| } | ||||
| \seealso{ | ||||
| \code{\link{tryCatch}}, \url{https://adv-r.hadley.nz/conditions.html} | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While this reference is not bad, it unnecessarily uses third party packages. If there is an alternative that uses base R packages only, then I would prefer to use that one.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would using ?warning and ?signalCondition be appropriate here?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Haven't read them. data.table/R/test.data.table.R Line 435 in 2f0d12f
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a good idea to link our
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the first edition of Advanced R? There are mentions of |
||||
| } | ||||
Uh oh!
There was an error while loading. Please reload this page.