Skip to content

Commit a3ba3f9

Browse files
committed
fix: avoid embedding Windows paths in kaleido Python code
1 parent b669a19 commit a3ba3f9

2 files changed

Lines changed: 43 additions & 7 deletions

File tree

R/kaleido.R

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,10 @@ newKaleidoScope <- function(kaleido) {
133133
writeLines(fig, tmp_json)
134134

135135
# Import it as a fig (dict)
136-
load_json <- sprintf(
137-
"import json; fig = json.load(open('%s'))",
138-
tmp_json
136+
.py_run_string_with_context(
137+
"import json; fig = json.load(open(tmp_json_path))",
138+
context = list(tmp_json_path = tmp_json)
139139
)
140-
reticulate::py_run_string(load_json)
141140

142141
# Gather figure-level options
143142
opts <- list(
@@ -193,8 +192,9 @@ legacyKaleidoScope <- function(kaleido) {
193192
)
194193
# Write the base64 encoded string that transform() returns to disk
195194
# https://github.com/plotly/Kaleido/blame/master/README.md#L52
196-
reticulate::py_run_string(
197-
sprintf("import sys; open('%s', 'wb').write(%s)", file, transform_cmd)
195+
.py_run_string_with_context(
196+
sprintf("import sys; open(output_file, 'wb').write(%s)", transform_cmd),
197+
context = list(output_file = file)
198198
)
199199

200200
invisible(file)
@@ -216,6 +216,41 @@ legacyKaleidoScope <- function(kaleido) {
216216
res
217217
}
218218

219+
.py_run_string_with_context <- function(code, context = list(), convert = TRUE) {
220+
py <- reticulate::py
221+
context_names <- names(context)
222+
old_values <- vector("list", length(context))
223+
had_value <- logical(length(context))
224+
225+
if (length(context) > 0) {
226+
if (is.null(context_names) || any(context_names == "")) {
227+
rlang::abort("`context` must be a named list.")
228+
}
229+
230+
for (i in seq_along(context)) {
231+
name <- context_names[[i]]
232+
had_value[[i]] <- reticulate::py_has_attr(py, name)
233+
if (had_value[[i]]) {
234+
old_values[[i]] <- py[[name]]
235+
}
236+
py[[name]] <- context[[i]]
237+
}
238+
239+
on.exit({
240+
for (i in rev(seq_along(context))) {
241+
name <- context_names[[i]]
242+
if (had_value[[i]]) {
243+
py[[name]] <- old_values[[i]]
244+
} else {
245+
reticulate::py_run_string(paste("del", name))
246+
}
247+
}
248+
}, add = TRUE)
249+
}
250+
251+
reticulate::py_run_string(code, convert = convert)
252+
}
253+
219254

220255
#' Print method for kaleido
221256
#'

tests/testthat/test-kaleido.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ test_that("newKaleidoScope does not inline Windows temp paths into Python code",
3939
scope <- newKaleidoScope(kaleido)
4040
scope$transform(list(), "figure.png")
4141

42-
expect_identical(py_calls, "import json; fig = json.load(open(tmp_json_path))")
42+
expect_identical(py_calls[[1]], "import json; fig = json.load(open(tmp_json_path))")
43+
expect_identical(py_calls[[2]], "del tmp_json_path")
4344
expect_identical(write_fig_args$fig, "fake-fig")
4445
expect_identical(write_fig_args$file, "figure.png")
4546
})

0 commit comments

Comments
 (0)