Skip to content

Commit cf2b801

Browse files
chore: use v1 timezones API (#315)
Co-authored-by: Neal Richardson <[email protected]>
1 parent 6085b53 commit cf2b801

File tree

16 files changed

+245
-64
lines changed

16 files changed

+245
-64
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
## Minor improvements and fixes
2222

2323
- Upgrade `pkgdown` to bootstrap 5 to enable search (@fh-mthomson, #275)
24+
- The `get_timezones()` function now uses the `v1/timezones` endpoint if
25+
available. (#300)
2426

2527
# connectapi 0.3.0
2628

R/connect.R

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ Connect <- R6::R6Class(
252252
#' @description Return all tags.
253253
#' @param use_cache Indicates that a cached set of tags is used.
254254
get_tags = function(use_cache = FALSE) {
255-
error_if_less_than(self, "1.8.6")
255+
error_if_less_than(self$version, "1.8.6")
256256
# TODO: check cache "age"?
257257
if (is.null(self$tags) || !use_cache) {
258258
self$tags <- self$tag()
@@ -305,7 +305,7 @@ Connect <- R6::R6Class(
305305
#' @param name The tag name.
306306
#' @param parent_id The parent identifier.
307307
tag_create = function(name, parent_id = NULL) {
308-
error_if_less_than(self, "1.8.6")
308+
error_if_less_than(self$version, "1.8.6")
309309
dat <- list(
310310
name = name
311311
)
@@ -328,7 +328,7 @@ Connect <- R6::R6Class(
328328
#' @description Get a tag.
329329
#' @param id The tag identifier.
330330
tag = function(id = NULL) {
331-
error_if_less_than(self, "1.8.6")
331+
error_if_less_than(self$version, "1.8.6")
332332
if (is.null(id)) {
333333
path <- v1_url("tags")
334334
} else {
@@ -833,6 +833,18 @@ Connect <- R6::R6Class(
833833
}
834834

835835
# end --------------------------------------------------------
836+
),
837+
private = list(
838+
.version = NULL
839+
),
840+
active = list(
841+
#' @field version The server version.
842+
version = function() {
843+
if (is.null(private$.version)) {
844+
private$.version <- safe_server_version(self)
845+
}
846+
private$.version
847+
}
836848
)
837849
)
838850

@@ -886,7 +898,7 @@ connect <- function(
886898
tryCatch(
887899
{
888900
check_connect_license(con)
889-
check_connect_version(using_version = safe_server_version(con))
901+
warn_untested_connect(using_version = safe_server_version(con))
890902
},
891903
error = function(err) {
892904
if (.check_is_fatal) {

R/content.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Content <- R6::R6Class(
6565
#' @param ... Content fields.
6666
update = function(...) {
6767
con <- self$get_connect()
68-
error_if_less_than(con, "1.8.6")
68+
error_if_less_than(con$version, "1.8.6")
6969
url <- v1_url("content", self$get_content()$guid)
7070
body <- rlang::list2(...)
7171
if (length(body)) {

R/deploy.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ deploy_current <- function(content) {
422422
set_vanity_url <- function(content, url, force = FALSE) {
423423
validate_R6_class(content, "Content")
424424
con <- content$get_connect()
425-
error_if_less_than(con, "1.8.6")
425+
error_if_less_than(con$version, "1.8.6")
426426
guid <- content$get_content()$guid
427427

428428
scoped_experimental_silence()
@@ -449,7 +449,7 @@ set_vanity_url <- function(content, url, force = FALSE) {
449449
#' @export
450450
delete_vanity_url <- function(content) {
451451
con <- content$get_connect()
452-
error_if_less_than(con, "1.8.6")
452+
error_if_less_than(con$version, "1.8.6")
453453
guid <- content$get_content()$guid
454454

455455
con$DELETE(v1_url("content", guid, "vanity"))
@@ -470,7 +470,7 @@ delete_vanity_url <- function(content) {
470470
get_vanity_url <- function(content) {
471471
validate_R6_class(content, "Content")
472472
con <- content$get_connect()
473-
error_if_less_than(con, "1.8.6")
473+
error_if_less_than(con$version, "1.8.6")
474474
guid <- content$get_content()$guid
475475

476476
van <- tryCatch(

R/schedule.R

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,13 @@ schedule_describe <- function(.schedule) {
337337
#' @family schedule functions
338338
#' @export
339339
get_timezones <- function(connect) {
340-
raw_tz <- connect$GET(unversioned_url("timezones"))
340+
raw_tz <- tryCatch(
341+
connect$GET(v1_url("timezones")),
342+
error = function(e) {
343+
connect$GET(unversioned_url("timezones"))
344+
}
345+
)
346+
341347
tz_values <- purrr::map_chr(raw_tz, ~ .x[["timezone"]])
342348
tz_display <- purrr::map_chr(raw_tz, ~ glue::glue("{.x[['timezone']]} ({.x[['offset']]})"))
343349

R/utils.R

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,20 +134,25 @@ safe_server_version <- function(client) {
134134
version <- safe_server_settings(client)$version
135135
if (is.null(version) || nchar(version) == 0) {
136136
message("Version information is not exposed by this Posit Connect instance.")
137-
# Return 0 so this will always show up as "too old"
138-
version <- "0"
137+
version <- NA
139138
}
140139
version
141140
}
142141

143-
error_if_less_than <- function(client, tested_version) {
144-
server_version <- safe_server_version(client)
145-
comp <- compare_connect_version(server_version, tested_version)
146-
if (comp < 0) {
147-
msg <- paste0(
148-
"ERROR: This API requires Posit Connect version ", tested_version,
149-
" but you are using", server_version, ". Please use a previous version",
150-
" of the `connectapi` package, upgrade Posit Connect, or review the API ",
142+
error_if_less_than <- function(using_version, tested_version) {
143+
comp <- compare_connect_version(using_version, tested_version)
144+
if (is.na(comp)) {
145+
msg <- glue::glue(
146+
"WARNING: This API requires Posit Connect version {tested_version} ",
147+
"but the server version is not exposed by this Posit Connect instance. ",
148+
"You may be experience errors when using this functionality."
149+
)
150+
warn_once(msg)
151+
} else if (comp < 0) {
152+
msg <- glue::glue(
153+
"ERROR: This API requires Posit Connect version {tested_version} ",
154+
"but you are using {using_version}. Please use a previous version ",
155+
"of the `connectapi` package, upgrade Posit Connect, or review the API ",
151156
"documentation corresponding to your version."
152157
)
153158
stop(msg)
@@ -156,12 +161,13 @@ error_if_less_than <- function(client, tested_version) {
156161
}
157162

158163
compare_connect_version <- function(using_version, tested_version) {
164+
if (is.na(using_version)) return(NA)
159165
compareVersion(simplify_version(using_version), simplify_version(tested_version))
160166
}
161167

162-
check_connect_version <- function(using_version, minimum_tested_version = "1.8.8.2") {
168+
warn_untested_connect <- function(using_version, minimum_tested_version = "1.8.8.2") {
163169
comp <- compare_connect_version(using_version, minimum_tested_version)
164-
if (comp < 0) {
170+
if (isTRUE(comp < 0)) {
165171
warn_once(glue::glue(
166172
"You are using an older version of Posit Connect ",
167173
"({using_version}) than is tested ({minimum_tested_version}). ",

man/PositConnect.Rd

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/integrated/test-schedule.R

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -80,26 +80,6 @@ test_that("schedule display works", {
8080
expect_snapshot_output(schedule_describe(tmp))
8181
})
8282

83-
# test_that("timezones helper works", {
84-
# tzs <- get_timezones(test_conn_1)
85-
# expect_snapshot(tzs)
86-
# })
87-
88-
# test_that("schedule timezone works", {
89-
# scoped_experimental_silence()
90-
#
91-
# tzs <- get_timezones(test_conn_1)
92-
# set_schedule_remove(d_var_sch)
93-
#
94-
# tmp <- set_schedule_minute(d_var_sch, n = 15, timezone = tzs$`America/New_York (-04:00)`)
95-
# expect_equal(tmp$schedule_data$timezone, tzs$`America/New_York (-04:00)`)
96-
#
97-
# tmp2 <- set_schedule_minute(d_var_sch, n = 10, timezone = tzs$`Universal (+00:00)`)
98-
# expect_equal(tmp$schedule_data$timezone, tzs$`Universal (+00:00)`)
99-
#
100-
# set_schedule_remove(d_var_sch)
101-
# })
102-
10383
test_that("get_schedules works", {
10484
scoped_experimental_silence()
10585
# TODO: add a helper that makes this prettier
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
{
2-
"version": "2024.06.0"
32
}

tests/testthat/2024.09.0/__api__/server_settings.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
{
2-
"hostname": "dogfood01",
3-
"version": "2024.09.0-dev+77-g9296f96ffb",
4-
"build": "v2024.08.0-77-g9296f96ffb",
5-
"about": "Posit Connect v2024.09.0-dev+77-g9296f96ffb",
2+
"hostname": "example",
3+
"version": "2024.09.0",
4+
"about": "Posit Connect v2024.09.0",
65
"authentication": {
76
"handles_credentials": false,
87
"handles_login": true,

tests/testthat/Rplots.pdf

-292 Bytes
Binary file not shown.

tests/testthat/_snaps/utils.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
# check_connect_version warning snapshot
1+
# warn_untested_connect warning snapshot
22

33
Code
4-
capture_warning(check_connect_version("2022.02", "2022.01"))
4+
capture_warning(warn_untested_connect("2022.02", "2022.01"))
55
Output
66
NULL
77

88
---
99

1010
Code
11-
capture_warning(check_connect_version("2022.01", "2022.02"))
11+
capture_warning(warn_untested_connect("2022.01", "2022.02"))
1212
Output
1313
<warning/rlang_warning>
1414
Warning:

tests/testthat/setup.R

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
library(httptest)
2+
library(R6)
23

34
set_requester(
45
function(r) {
@@ -35,3 +36,72 @@ set_redactor(
3536
# Mocks are in directories by Connect version. 2024.08.0 contains all mocks
3637
# created before 2024.09.0, and is the default mock path.
3738
.mockPaths("2024.08.0")
39+
40+
MockConnect <- R6Class(
41+
"MockConnect",
42+
inherit = Connect,
43+
public = list(
44+
initialize = function(version = NA) {
45+
self$server <- "https://connect.example"
46+
self$api_key <- "fake"
47+
private$.version <- version
48+
},
49+
request = function(method, url, ..., parser = "parsed") {
50+
route <- paste(method, url)
51+
print(route)
52+
53+
# Record call
54+
self$log_call(route)
55+
56+
# Look for response
57+
if (!(route %in% names(self$responses))) {
58+
stop("Unexpected route")
59+
}
60+
res <- self$responses[[route]]
61+
62+
if (is.null(parser)) {
63+
res
64+
} else {
65+
self$raise_error(res)
66+
httr::content(res, as = parser)
67+
}
68+
},
69+
responses = list(),
70+
mock_response = function(method, path, content, status_code = 200L, headers = c("Content-Type" = "application/json; charset=utf-8")) {
71+
url <- self$api_url(path)
72+
route <- paste(method, url)
73+
print(route)
74+
res <- new_mock_response(url, content, status_code, headers)
75+
self$responses[[route]] <- res
76+
},
77+
call_log = character(),
78+
log_call = function(route) {
79+
self$call_log <- c(self$call_log, route)
80+
}
81+
)
82+
)
83+
84+
new_mock_response <- function(url, content, status_code, headers = character()) {
85+
# Headers in responses are case-insensitive lists.
86+
names(headers) <- tolower(names(headers))
87+
headers <- as.list(headers)
88+
headers <- structure(as.list(headers), class = c("insensitive", class(headers)))
89+
90+
# Treat content similarly to httr::POST, with a subset of behaviors
91+
if (is.character(content) && length(content) == 1) {
92+
content <- charToRaw(content)
93+
} else if (is.list(content)) {
94+
content <- charToRaw(jsonlite::toJSON(content, auto_unbox = TRUE))
95+
}
96+
97+
structure(
98+
list(
99+
url = url,
100+
status_code = status_code,
101+
request = structure(list(url = url), class = "request"),
102+
headers = headers,
103+
content = content
104+
),
105+
class = "response"
106+
)
107+
}

tests/testthat/test-connect.R

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,18 @@ with_mock_api({
9797
"MY_MAGIC_HEADER: value"
9898
)
9999
})
100+
101+
102+
test_that("client$version is NA when server settings lacks version info", {
103+
con <- Connect$new(server = "https://connect.example", api_key = "fake")
104+
expect_message(v <- con$version, "Version information is not exposed by this Posit Connect instance")
105+
expect_true(is.na(v))
106+
})
107+
})
108+
109+
test_that("client$version is returns version when server settings exposes it", {
110+
with_mock_dir("2024.09.0", {
111+
con <- Connect$new(server = "https://connect.example", api_key = "fake")
112+
expect_equal(con$version, "2024.09.0")
113+
})
100114
})

0 commit comments

Comments
 (0)