Skip to content

Commit e9fc77c

Browse files
committed
Actaully import
1 parent 0c83ab5 commit e9fc77c

File tree

4 files changed

+962
-93
lines changed

4 files changed

+962
-93
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Imports:
2424
magrittr,
2525
pillar (>= 1.9.0),
2626
purrr (>= 1.0.1),
27-
rlang (>= 1.0.2),
27+
rlang (>= 1.1.0),
2828
tibble (>= 2.0.0),
2929
utils,
3030
uuid,

R/import-standalone-obj-type.R

Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
# Standalone file: do not edit by hand
2+
# Source: https://github.com/r-lib/rlang/blob/HEAD/R/standalone-obj-type.R
3+
# Generated by: usethis::use_standalone("r-lib/rlang", "obj-type")
4+
# ----------------------------------------------------------------------
5+
#
6+
# ---
7+
# repo: r-lib/rlang
8+
# file: standalone-obj-type.R
9+
# last-updated: 2024-02-14
10+
# license: https://unlicense.org
11+
# imports: rlang (>= 1.1.0)
12+
# ---
13+
#
14+
# ## Changelog
15+
#
16+
# 2024-02-14:
17+
# - `obj_type_friendly()` now works for S7 objects.
18+
#
19+
# 2023-05-01:
20+
# - `obj_type_friendly()` now only displays the first class of S3 objects.
21+
#
22+
# 2023-03-30:
23+
# - `stop_input_type()` now handles `I()` input literally in `arg`.
24+
#
25+
# 2022-10-04:
26+
# - `obj_type_friendly(value = TRUE)` now shows numeric scalars
27+
# literally.
28+
# - `stop_friendly_type()` now takes `show_value`, passed to
29+
# `obj_type_friendly()` as the `value` argument.
30+
#
31+
# 2022-10-03:
32+
# - Added `allow_na` and `allow_null` arguments.
33+
# - `NULL` is now backticked.
34+
# - Better friendly type for infinities and `NaN`.
35+
#
36+
# 2022-09-16:
37+
# - Unprefixed usage of rlang functions with `rlang::` to
38+
# avoid onLoad issues when called from rlang (#1482).
39+
#
40+
# 2022-08-11:
41+
# - Prefixed usage of rlang functions with `rlang::`.
42+
#
43+
# 2022-06-22:
44+
# - `friendly_type_of()` is now `obj_type_friendly()`.
45+
# - Added `obj_type_oo()`.
46+
#
47+
# 2021-12-20:
48+
# - Added support for scalar values and empty vectors.
49+
# - Added `stop_input_type()`
50+
#
51+
# 2021-06-30:
52+
# - Added support for missing arguments.
53+
#
54+
# 2021-04-19:
55+
# - Added support for matrices and arrays (#141).
56+
# - Added documentation.
57+
# - Added changelog.
58+
#
59+
# nocov start
60+
61+
#' Return English-friendly type
62+
#' @param x Any R object.
63+
#' @param value Whether to describe the value of `x`. Special values
64+
#' like `NA` or `""` are always described.
65+
#' @param length Whether to mention the length of vectors and lists.
66+
#' @return A string describing the type. Starts with an indefinite
67+
#' article, e.g. "an integer vector".
68+
#' @noRd
69+
obj_type_friendly <- function(x, value = TRUE) {
70+
if (is_missing(x)) {
71+
return("absent")
72+
}
73+
74+
if (is.object(x)) {
75+
if (inherits(x, "quosure")) {
76+
type <- "quosure"
77+
} else {
78+
type <- class(x)[[1L]]
79+
}
80+
return(sprintf("a <%s> object", type))
81+
}
82+
83+
if (!is_vector(x)) {
84+
return(.rlang_as_friendly_type(typeof(x)))
85+
}
86+
87+
n_dim <- length(dim(x))
88+
89+
if (!n_dim) {
90+
if (!is_list(x) && length(x) == 1) {
91+
if (is_na(x)) {
92+
return(switch(
93+
typeof(x),
94+
logical = "`NA`",
95+
integer = "an integer `NA`",
96+
double = if (is.nan(x)) {
97+
"`NaN`"
98+
} else {
99+
"a numeric `NA`"
100+
},
101+
complex = "a complex `NA`",
102+
character = "a character `NA`",
103+
.rlang_stop_unexpected_typeof(x)
104+
))
105+
}
106+
107+
show_infinites <- function(x) {
108+
if (x > 0) {
109+
"`Inf`"
110+
} else {
111+
"`-Inf`"
112+
}
113+
}
114+
str_encode <- function(x, width = 30, ...) {
115+
if (nchar(x) > width) {
116+
x <- substr(x, 1, width - 3)
117+
x <- paste0(x, "...")
118+
}
119+
encodeString(x, ...)
120+
}
121+
122+
if (value) {
123+
if (is.numeric(x) && is.infinite(x)) {
124+
return(show_infinites(x))
125+
}
126+
127+
if (is.numeric(x) || is.complex(x)) {
128+
number <- as.character(round(x, 2))
129+
what <- if (is.complex(x)) "the complex number" else "the number"
130+
return(paste(what, number))
131+
}
132+
133+
return(switch(
134+
typeof(x),
135+
logical = if (x) "`TRUE`" else "`FALSE`",
136+
character = {
137+
what <- if (nzchar(x)) "the string" else "the empty string"
138+
paste(what, str_encode(x, quote = "\""))
139+
},
140+
raw = paste("the raw value", as.character(x)),
141+
.rlang_stop_unexpected_typeof(x)
142+
))
143+
}
144+
145+
return(switch(
146+
typeof(x),
147+
logical = "a logical value",
148+
integer = "an integer",
149+
double = if (is.infinite(x)) show_infinites(x) else "a number",
150+
complex = "a complex number",
151+
character = if (nzchar(x)) "a string" else "\"\"",
152+
raw = "a raw value",
153+
.rlang_stop_unexpected_typeof(x)
154+
))
155+
}
156+
157+
if (length(x) == 0) {
158+
return(switch(
159+
typeof(x),
160+
logical = "an empty logical vector",
161+
integer = "an empty integer vector",
162+
double = "an empty numeric vector",
163+
complex = "an empty complex vector",
164+
character = "an empty character vector",
165+
raw = "an empty raw vector",
166+
list = "an empty list",
167+
.rlang_stop_unexpected_typeof(x)
168+
))
169+
}
170+
}
171+
172+
vec_type_friendly(x)
173+
}
174+
175+
vec_type_friendly <- function(x, length = FALSE) {
176+
if (!is_vector(x)) {
177+
abort("`x` must be a vector.")
178+
}
179+
type <- typeof(x)
180+
n_dim <- length(dim(x))
181+
182+
add_length <- function(type) {
183+
if (length && !n_dim) {
184+
paste0(type, sprintf(" of length %s", length(x)))
185+
} else {
186+
type
187+
}
188+
}
189+
190+
if (type == "list") {
191+
if (n_dim < 2) {
192+
return(add_length("a list"))
193+
} else if (is.data.frame(x)) {
194+
return("a data frame")
195+
} else if (n_dim == 2) {
196+
return("a list matrix")
197+
} else {
198+
return("a list array")
199+
}
200+
}
201+
202+
type <- switch(
203+
type,
204+
logical = "a logical %s",
205+
integer = "an integer %s",
206+
numeric = ,
207+
double = "a double %s",
208+
complex = "a complex %s",
209+
character = "a character %s",
210+
raw = "a raw %s",
211+
type = paste0("a ", type, " %s")
212+
)
213+
214+
if (n_dim < 2) {
215+
kind <- "vector"
216+
} else if (n_dim == 2) {
217+
kind <- "matrix"
218+
} else {
219+
kind <- "array"
220+
}
221+
out <- sprintf(type, kind)
222+
223+
if (n_dim >= 2) {
224+
out
225+
} else {
226+
add_length(out)
227+
}
228+
}
229+
230+
.rlang_as_friendly_type <- function(type) {
231+
switch(
232+
type,
233+
234+
list = "a list",
235+
236+
NULL = "`NULL`",
237+
environment = "an environment",
238+
externalptr = "a pointer",
239+
weakref = "a weak reference",
240+
S4 = "an S4 object",
241+
242+
name = ,
243+
symbol = "a symbol",
244+
language = "a call",
245+
pairlist = "a pairlist node",
246+
expression = "an expression vector",
247+
248+
char = "an internal string",
249+
promise = "an internal promise",
250+
... = "an internal dots object",
251+
any = "an internal `any` object",
252+
bytecode = "an internal bytecode object",
253+
254+
primitive = ,
255+
builtin = ,
256+
special = "a primitive function",
257+
closure = "a function",
258+
259+
type
260+
)
261+
}
262+
263+
.rlang_stop_unexpected_typeof <- function(x, call = caller_env()) {
264+
abort(
265+
sprintf("Unexpected type <%s>.", typeof(x)),
266+
call = call
267+
)
268+
}
269+
270+
#' Return OO type
271+
#' @param x Any R object.
272+
#' @return One of `"bare"` (for non-OO objects), `"S3"`, `"S4"`,
273+
#' `"R6"`, or `"S7"`.
274+
#' @noRd
275+
obj_type_oo <- function(x) {
276+
if (!is.object(x)) {
277+
return("bare")
278+
}
279+
280+
class <- inherits(x, c("R6", "S7_object"), which = TRUE)
281+
282+
if (class[[1]]) {
283+
"R6"
284+
} else if (class[[2]]) {
285+
"S7"
286+
} else if (isS4(x)) {
287+
"S4"
288+
} else {
289+
"S3"
290+
}
291+
}
292+
293+
#' @param x The object type which does not conform to `what`. Its
294+
#' `obj_type_friendly()` is taken and mentioned in the error message.
295+
#' @param what The friendly expected type as a string. Can be a
296+
#' character vector of expected types, in which case the error
297+
#' message mentions all of them in an "or" enumeration.
298+
#' @param show_value Passed to `value` argument of `obj_type_friendly()`.
299+
#' @param ... Arguments passed to [abort()].
300+
#' @inheritParams args_error_context
301+
#' @noRd
302+
stop_input_type <- function(
303+
x,
304+
what,
305+
...,
306+
allow_na = FALSE,
307+
allow_null = FALSE,
308+
show_value = TRUE,
309+
arg = caller_arg(x),
310+
call = caller_env()
311+
) {
312+
# From standalone-cli.R
313+
cli <- env_get_list(
314+
nms = c("format_arg", "format_code"),
315+
last = topenv(),
316+
default = function(x) sprintf("`%s`", x),
317+
inherit = TRUE
318+
)
319+
320+
if (allow_na) {
321+
what <- c(what, cli$format_code("NA"))
322+
}
323+
if (allow_null) {
324+
what <- c(what, cli$format_code("NULL"))
325+
}
326+
if (length(what)) {
327+
what <- oxford_comma(what)
328+
}
329+
if (inherits(arg, "AsIs")) {
330+
format_arg <- identity
331+
} else {
332+
format_arg <- cli$format_arg
333+
}
334+
335+
message <- sprintf(
336+
"%s must be %s, not %s.",
337+
format_arg(arg),
338+
what,
339+
obj_type_friendly(x, value = show_value)
340+
)
341+
342+
abort(message, ..., call = call, arg = arg)
343+
}
344+
345+
oxford_comma <- function(chr, sep = ", ", final = "or") {
346+
n <- length(chr)
347+
348+
if (n < 2) {
349+
return(chr)
350+
}
351+
352+
head <- chr[seq_len(n - 1)]
353+
last <- chr[n]
354+
355+
head <- paste(head, collapse = sep)
356+
357+
# Write a or b. But a, b, or c.
358+
if (n > 2) {
359+
paste0(head, sep, final, " ", last)
360+
} else {
361+
paste0(head, " ", final, " ", last)
362+
}
363+
}
364+
365+
# nocov end

0 commit comments

Comments
 (0)