Skip to content

Commit

Permalink
Merge branch 'main' into python-3-13-compat
Browse files Browse the repository at this point in the history
  • Loading branch information
t-kalinowski authored Oct 24, 2024
2 parents 96ba79e + 65e17a3 commit fd5d148
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ inst/doc
rchk
.cache
compile_commands.json
*.Dockerfile
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

- Added preliminary support for Python 3.13 (#1686)

- `py_is_null_xptr()` and `[[` now load delayed modules (#1688).

- Fixed error when attempting to use a python venv created with `uv` (#1678)

- Fixed error where `py_discover_config()` attempted to detect
Expand Down
7 changes: 2 additions & 5 deletions R/array.R
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,7 @@ length.numpy.ndarray <- function(x) {
#' }
#' @export
array_reshape <- function(x, dim, order = c("C", "F")) {
np <- import("numpy", convert = FALSE)
order <- match.arg(order)
reshaped <- np$reshape(x, as.integer(dim), order = order)
if (!is_py_object(x))
reshaped <- py_to_r(reshaped)
reshaped
np <- import("numpy", convert = !is_py_object(x))
np$reshape(x, as.integer(dim), order = order)
}
5 changes: 5 additions & 0 deletions R/thread.R
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ py_run_file_on_thread <- function(file, ..., args = NULL) {
if (launching_lsp) {
main_dict <- py_eval("__import__('__main__').__dict__.copy()", FALSE)
py_get_attr(main_dict, "pop")("__annotations__")
# IPykernel will create a thread that redirects all output from fileno of
# the current sys.stdout and sys.stderr to its IO channels.
# This is not correctly cleaned up when IPykernel closes.
# To fix that, we set the IO streams to /dev/null before launching the kernel.
import("rpytools.run")$set_blank_io_streams()
}

import("rpytools.run")$run_file_on_thread(file, args, ...)
Expand Down
7 changes: 7 additions & 0 deletions inst/python/rpytools/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ def _launch_lsp_server_on_thread(path, args):
return run_file_on_thread(path, args)


def set_blank_io_streams():
import sys
import os
sys.stdout = open(os.devnull, "w")
sys.stderr = open(os.devnull, "w")


def run_file_on_thread(path, argv=None, init_globals=None, run_name="__main__"):
# for now, leave sys.argv and sys.path permanently modified.
# Later, revisit if it's desirable/safe to restore after the initial
Expand Down
6 changes: 4 additions & 2 deletions src/reticulate_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ class PyObjectRef: public Rcpp::RObject {
SEXP xptr = Rf_findVarInFrame(get_refenv(), sym_pyobj);
if(TYPEOF(xptr) == EXTPTRSXP)
return ((PyObject*) R_ExternalPtrAddr(xptr) == NULL);
if(xptr == R_UnboundValue || xptr == R_NilValue)
return true; // return true for lazy module proxy
if(xptr == R_UnboundValue)
return false; // return false for lazy module proxy
if(xptr == R_NilValue)
return true; // ??? manually finalized obj? ??? should never happen ???
return false; // should never happen
}

Expand Down
26 changes: 24 additions & 2 deletions tests/testthat/test-delay-load.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ test_that("imported module can be customized via delay_load", {
stopifnot(isTRUE(reticulate:::py_is_module_proxy(sys)))

print(sys)
stopifnot(isTRUE(reticulate::py_is_null_xptr(sys)))
stopifnot(isTRUE(reticulate:::py_is_module_proxy(sys)))
stopifnot(isFALSE(reticulate::py_available()))

out <- as.character(sys$byteorder)

stopifnot(isFALSE(reticulate::py_is_null_xptr(sys)))
stopifnot(isFALSE(reticulate:::py_is_module_proxy(sys)))
stopifnot(isTRUE(reticulate::py_available()))

out
})
Expand All @@ -35,3 +35,25 @@ test_that("imported module can be customized via delay_load", {
expect_true(result %in% c("little", "big"))

})


test_that("[[ loads delayed modules", {

# https://github.com/rstudio/reticulate/issues/1688
config <- py_config()
withr::local_envvar(RETICULATE_PYTHON = config$python)

result <- callr::r(function() {
time <- reticulate::import('time', delay_load = TRUE)
stopifnot(isFALSE(reticulate::py_available()))

result <- time[['time']]()
stopifnot(isTRUE(reticulate::py_available()))
result
})

# validate expected result
expect_true(typeof(result) %in% c("double", "integer"))
expect_true((result - import("time")$time()) < 10)

})

0 comments on commit fd5d148

Please sign in to comment.