Skip to content

Commit 20f3552

Browse files
committed
Upgrade most errors to expose appropriate call
Closes #255 I haven't done this to a 100% level, but I think I've covered the vast majority of errors that users are likely to bump into. Feels like an appropriate place to stop for now in terms of effort vs. payoff.
1 parent 4882b33 commit 20f3552

19 files changed

+273
-155
lines changed

R/ctype.R

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,16 @@ infer_ctype <- function(cell, na = "", trim_ws = TRUE) {
165165
string = "CELL_TEXT",
166166
boolean = "CELL_LOGICAL",
167167
formula = {
168-
warn("Internal warning: Cell has formula as effectiveValue. I thought impossible!")
168+
cli::cli_warn("
169+
Internal warning from googlesheets4: \\
170+
Cell has formula as effectiveValue. \\
171+
I thought this was impossible!")
169172
"CELL_TEXT"
170173
},
171-
gs4_abort("Unhandled effective_type: {.field {effective_type}}")
174+
gs4_abort(
175+
"Unhandled effective_type: {.field {effective_type}}",
176+
.internal = TRUE
177+
)
172178
))
173179
}
174180
# only numeric cells remain

R/get_cells.R

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ get_cells <- function(ss,
55
col_names_in_sheet = TRUE,
66
skip = 0, n_max = Inf,
77
detail_level = c("default", "full"),
8-
discard_empty = TRUE) {
8+
discard_empty = TRUE,
9+
call = caller_env()) {
910
ssid <- as_sheets_id(ss)
1011

11-
maybe_sheet(sheet)
12-
check_range(range)
13-
check_bool(col_names_in_sheet)
14-
check_non_negative_integer(skip)
15-
check_non_negative_integer(n_max)
12+
maybe_sheet(sheet, call = call)
13+
check_range(range, call = call)
14+
check_bool(col_names_in_sheet, call = call)
15+
check_non_negative_integer(skip, call = call)
16+
check_non_negative_integer(n_max, call = call)
1617
detail_level <- match.arg(detail_level)
17-
check_bool(discard_empty)
18+
check_bool(discard_empty, call = call)
1819

1920
## retrieve spreadsheet metadata --------------------------------------------
2021
x <- gs4_get(ssid)

R/gs4_example.R

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,30 +46,40 @@ gs4_example <- function(matches) {
4646
)
4747
}
4848

49-
many_sheets <- function(needle, haystack, adjective) {
49+
many_sheets <- function(needle, haystack, adjective, call = caller_env()) {
5050
out <- haystack
5151

5252
if (!missing(needle)) {
53-
check_string(needle)
53+
check_string(needle, call = call)
5454
sel <- grepl(needle, names(out), ignore.case = TRUE)
5555
if (!any(sel)) {
56-
gs4_abort("Can't find {adjective} Sheet that matches {.q {needle}}.")
56+
gs4_abort(
57+
"Can't find {adjective} Sheet that matches {.q {needle}}.",
58+
call = call)
5759
}
5860
out <- as_id(out[sel])
5961
}
6062

6163
out
6264
}
6365

64-
one_sheet <- function(needle, haystack, adjective) {
65-
check_string(needle)
66-
out <- many_sheets(needle = needle, haystack = haystack, adjective = adjective)
66+
one_sheet <- function(needle, haystack, adjective, call = caller_env()) {
67+
check_string(needle, call = call)
68+
out <- many_sheets(
69+
needle = needle,
70+
haystack = haystack,
71+
adjective = adjective,
72+
call = call
73+
)
6774
if (length(out) > 1) {
68-
gs4_abort(c(
69-
"Found multiple matching {adjective} Sheets:",
70-
bulletize(gargle_map_cli(names(out), template = "{.s_sheet <<x>>}")),
71-
i = "Make the {.arg matches} regular expression more specific."
72-
))
75+
gs4_abort(
76+
c(
77+
"Found multiple matching {adjective} Sheets:",
78+
bulletize(gargle_map_cli(names(out), template = "{.s_sheet <<x>>}")),
79+
i = "Make the {.arg matches} regular expression more specific."
80+
),
81+
call = call
82+
)
7383
}
7484
as_sheets_id(out)
7585
}

R/make_column.R

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ gs4_parse <- function(x, ctype, ...) {
4949
COL_CELL = as_cell,
5050
COL_LIST = as_list,
5151
## TODO: factor, duration
52-
gs4_abort("Not a recognized column type: {.field {ctype}}")
52+
gs4_abort(
53+
"Not a recognized column type: {.field {ctype}}",
54+
.internal = TRUE
55+
)
5356
)
5457
if (inherits(x, "SHEETS_CELL")) {
5558
x <- list(x)

R/range_add_validation.R

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,10 @@ new_BooleanCondition <- function(type = "NOT_BLANK", values = NULL) {
135135
"DATE_BEFORE", "DATE_AFTER", "DATE_ON_OR_BEFORE", "DATE_ON_OR_AFTER"
136136
)
137137
if (type %in% needs_relative_date) {
138-
gs4_abort("
139-
{.field relativeDate} not yet supported as a {.code conditionValue}.")
138+
gs4_abort(
139+
"{.field relativeDate} not yet supported as a {.code conditionValue}.",
140+
.internal = TRUE
141+
)
140142
}
141143
patch(out, values = map(values, ~ list(userEnteredValue = as.character(.x))))
142144
}

R/range_autofit.R

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ force_cell_limits <- function(x) {
119119
x
120120
}
121121

122-
check_only_one_dimension <- function(x) {
122+
check_only_one_dimension <- function(x, call = caller_env()) {
123123
limits <- x$cell_limits
124124

125125
if (is.na(limits$ul[1]) && is.na(limits$lr[1])) {
@@ -129,8 +129,10 @@ check_only_one_dimension <- function(x) {
129129
return(invisible(x))
130130
}
131131

132-
gs4_abort("
133-
The {.arg range} must target only columns or only rows, but not both.")
132+
gs4_abort(
133+
"The {.arg range} must target only columns or only rows, but not both.",
134+
call = call
135+
)
134136
}
135137

136138
determine_dimension <- function(x) {

R/range_delete.R

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ range_delete <- function(ss,
116116
invisible(ssid)
117117
}
118118

119-
determine_shift <- function(gr) {
119+
determine_shift <- function(gr, call = caller_env()) {
120120
stopifnot(inherits(gr, "googlesheets4_schema_GridRange"))
121121
bounded_on_bottom <- !is.null(gr$endRowIndex) && notNA(gr$endRowIndex)
122122
bounded_on_right <- !is.null(gr$endColumnIndex) && notNA(gr$endColumnIndex)
@@ -133,9 +133,12 @@ determine_shift <- function(gr) {
133133
return("COLUMNS")
134134
}
135135

136-
gs4_abort(c(
137-
"{.arg range} must be bounded on the bottom and/or on the right.",
138-
i = "Use {.fun sheet_delete} or {.fun sheet_resize} to delete or \\
139-
resize a (work)sheet."
140-
))
136+
gs4_abort(
137+
c(
138+
"{.arg range} must be bounded on the bottom and/or on the right.",
139+
i = "Use {.fun sheet_delete} or {.fun sheet_resize} to delete or \\
140+
resize a (work)sheet."
141+
),
142+
call = call
143+
)
141144
}

R/range_read.R

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ range_read <- function(ss,
9494
guess_max = min(1000, n_max),
9595
.name_repair = "unique") {
9696
# check these first, so we don't download cells in vain
97-
col_spec <- standardise_col_spec(col_names, col_types)
97+
col_spec <- standardise_col_spec(col_names, col_types, call = current_env())
9898
check_character(na)
9999
check_bool(trim_ws)
100100
check_non_negative_integer(guess_max)
@@ -150,7 +150,7 @@ spread_sheet <- function(df,
150150
na = "", trim_ws = TRUE,
151151
guess_max = min(1000, max(df$row)),
152152
.name_repair = "unique") {
153-
col_spec <- standardise_col_spec(col_names, col_types)
153+
col_spec <- standardise_col_spec(col_names, col_types, call = current_env())
154154
check_character(na)
155155
check_bool(trim_ws)
156156
check_non_negative_integer(guess_max)
@@ -168,7 +168,8 @@ spread_sheet_impl_ <- function(df,
168168
),
169169
na = "", trim_ws = TRUE,
170170
guess_max = min(1000, max(df$row)),
171-
.name_repair = "unique") {
171+
.name_repair = "unique",
172+
call = caller_env()) {
172173
if (nrow(df) == 0) {
173174
return(tibble::tibble())
174175
}
@@ -186,7 +187,12 @@ spread_sheet_impl_ <- function(df,
186187
if (is.logical(col_names)) {
187188
# if col_names is logical, this is first chance to check/set length of
188189
# ctypes, using the cell data
189-
ctypes <- rep_ctypes(max(df$col), ctypes, "column{?s} found in sheet")
190+
ctypes <- rep_ctypes(
191+
max(df$col),
192+
ctypes,
193+
"column{?s} found in sheet",
194+
call = call
195+
)
190196
}
191197

192198
# drop cells in skipped cols, update df$col and ctypes
@@ -201,11 +207,14 @@ spread_sheet_impl_ <- function(df,
201207
# if column names were provided explicitly, we need to check that length
202208
# of col_names (and, therefore, ctypes) == nc
203209
if (is.character(col_names) && length(col_names) != nc) {
204-
gs4_abort(c(
205-
"Length of {.arg col_names} is not compatible with the data:",
206-
"*" = "{.arg col_names} has length {length(col_names)}.",
207-
x = "But data has {nc} un-skipped column{?s}."
208-
))
210+
gs4_abort(
211+
c(
212+
"Length of {.arg col_names} is not compatible with the data:",
213+
"*" = "{.arg col_names} has length {length(col_names)}.",
214+
"x" = "But data has {nc} un-skipped column{?s}."
215+
),
216+
call = call
217+
)
209218
}
210219

211220
df$cell <- apply_ctype(df$cell, na = na, trim_ws = trim_ws)
@@ -236,58 +245,71 @@ spread_sheet_impl_ <- function(df,
236245

237246
## helpers ---------------------------------------------------------------------
238247

239-
standardise_col_spec <- function(col_names, col_types) {
240-
check_col_names(col_names)
241-
ctypes <- standardise_ctypes(col_types)
248+
standardise_col_spec <- function(col_names, col_types, call = caller_env()) {
249+
check_col_names(col_names, call = call)
250+
ctypes <- standardise_ctypes(col_types, call = call)
242251
if (is.character(col_names)) {
243-
ctypes <- rep_ctypes(length(col_names), ctypes, "column name{?s}")
252+
ctypes <- rep_ctypes(
253+
length(col_names),
254+
ctypes,
255+
"column name{?s}",
256+
call = call
257+
)
244258
col_names <- filter_col_names(col_names, ctypes)
245259
# if column names were provided explicitly, this is now true
246260
# length(col_names) == length(ctypes[ctypes != "COL_SKIP"])
247261
}
248262
list(col_names = col_names, ctypes = ctypes)
249263
}
250264

251-
check_col_names <- function(col_names) {
265+
check_col_names <- function(col_names, call = caller_env()) {
252266
if (is.logical(col_names)) {
253-
return(check_bool(col_names))
267+
return(check_bool(col_names, call = call))
254268
}
255-
check_character(col_names)
256-
check_has_length(col_names)
269+
check_character(col_names, call = call)
270+
check_has_length(col_names, call = call)
257271
}
258272

259273
# input: a string of readr-style shortcodes or NULL
260274
# output: a vector of col types of length >= 1
261-
standardise_ctypes <- function(col_types) {
275+
standardise_ctypes <- function(col_types, call = caller_env()) {
262276
col_types <- col_types %||% "?"
263-
check_string(col_types)
277+
check_string(col_types, call = call)
264278

265279
if (identical(col_types, "")) {
266280
gs4_abort("
267281
{.arg col_types}, when provided, must be a string that contains at \\
268-
least one readr-style shortcode.")
282+
least one readr-style shortcode.",
283+
call = call
284+
)
269285
}
270286

271287
accepted_codes <- keep(names(.ctypes), nzchar)
272288

273289
col_types_split <- strsplit(col_types, split = "")[[1]]
274290
ok <- col_types_split %in% accepted_codes
275291
if (!all(ok)) {
276-
gs4_abort(c(
277-
"{.arg col_types} must be a string of readr-style shortcodes. \\
278-
Unrecognized code{?s}{cli::qty(sum(!ok))}:",
279-
bulletize(gargle_map_cli(col_types_split[!ok]), bullet = "x")
280-
))
292+
gs4_abort(
293+
c(
294+
"{.arg col_types} must be a string of readr-style shortcodes. \\
295+
Unrecognized code{?s}{cli::qty(sum(!ok))}:",
296+
bulletize(gargle_map_cli(col_types_split[!ok]), bullet = "x")
297+
),
298+
call = call
299+
)
281300
}
282301
ctypes <- ctype(col_types_split)
283302
if (all(ctypes == "COL_SKIP")) {
284-
gs4_abort("{.arg col_types} can't request that all columns be skipped.")
303+
gs4_abort(
304+
"{.arg col_types} can't request that all columns be skipped.",
305+
call = call
306+
)
285307
}
286308
ctypes
287309
}
288310

289311
# makes sure there are n ctypes or n ctypes that are not COL_SKIP
290-
rep_ctypes <- function(n, ctypes, comparator = "n") {
312+
rep_ctypes <- function(n, ctypes, comparator = "n", call = caller_env()) {
291313
if (length(ctypes) == n) {
292314
return(ctypes)
293315
}
@@ -302,12 +324,15 @@ rep_ctypes <- function(n, ctypes, comparator = "n") {
302324
# column{?s} found in sheet
303325
# column name{?s}
304326
comparator <- cli::pluralize(sprintf("{cli::qty(n)}%s{?s}", comparator))
305-
gs4_abort(c(
306-
"Length of {.arg col_types} is not compatible with {comparator}:",
307-
x = "{length(ctypes)} column type{?s} specified.",
308-
x = "{n_col_types} un-skipped column type{?s} specified.",
309-
x = "But there {cli::qty(n)}{?is/are} {n} {comparator}."
310-
))
327+
gs4_abort(
328+
c(
329+
"Length of {.arg col_types} is not compatible with {comparator}:",
330+
x = "{length(ctypes)} column type{?s} specified.",
331+
x = "{n_col_types} un-skipped column type{?s} specified.",
332+
x = "But there {cli::qty(n)}{?is/are} {n} {comparator}."
333+
),
334+
call = call
335+
)
311336
}
312337

313338
# removes col_names for skipped columns

R/sheet_add.R

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,20 +95,23 @@ sheet_add_impl_ <- function(ssid,
9595
new_googlesheets4_spreadsheet(resp$updatedSpreadsheet)
9696
}
9797

98-
resolve_index <- function(sheets_df, .before = NULL, .after = NULL) {
98+
resolve_index <- function(sheets_df,
99+
.before = NULL,
100+
.after = NULL,
101+
call = caller_env()) {
99102
if (is.null(.before) && is.null(.after)) {
100103
return(NULL)
101104
}
102105

103106
if (is.null(.after)) {
104-
s <- lookup_sheet(.before, sheets_df = sheets_df)
107+
s <- lookup_sheet(.before, sheets_df = sheets_df, call = call)
105108
return(s$index)
106109
}
107110

108111
if (is.numeric(.after)) {
109112
.after <- min(.after, nrow(sheets_df))
110113
}
111-
s <- lookup_sheet(.after, sheets_df = sheets_df)
114+
s <- lookup_sheet(.after, sheets_df = sheets_df, call = call)
112115
s$index + 1
113116
}
114117

0 commit comments

Comments
 (0)