diff --git a/DESCRIPTION b/DESCRIPTION index 8f36240..3c53326 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: audit.workbench Title: RStudio/Workbench User Acceptance Tests -Version: 0.6.25 +Version: 0.6.26 Authors@R: person("Jumping", "Rivers", , "info@jumpingrivers.com", role = c("aut", "cre")) Description: Testing whether data scientists can do what they expect in diff --git a/NEWS.md b/NEWS.md index 07b2c14..a936121 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +# audit.workbench 0.6.26 + +## Bug fixes and minor improvements + +* The pip check installs numpy into a temporary virtual environment, so it no longer changes the user's own Python. It also works where system pip is externally managed (PEP 668), and finds Python in `/opt/python` when `python3` isn't on the `PATH` (#39). + # audit.workbench 0.6.25 ## Bug fixes and minor improvements diff --git a/R/check_python.R b/R/check_python.R index f5c1cd2..8dd0650 100644 --- a/R/check_python.R +++ b/R/check_python.R @@ -44,24 +44,23 @@ check_python_reticulate = R6::R6Class( ) ) -python_pip_tests = function() { - system('python3 -c "print(2+2)"', intern = TRUE) +# Installs numpy into a temporary venv, so the user's own Python is never changed +python_pip_tests = function(python = find_python()) { + if (!nzchar(python)) { + cli::cli_abort("Can't find Python: looked for python3 on the PATH and in /opt/python") + } + venv = withr::local_tempdir(pattern = "pip-venv-") + processx::run(python, c("-m", "venv", venv)) + venv_python = file.path(venv, "bin", "python") - pip_version = processx::run("pip", "--version")$stdout - min_version = grepl("pip [2-3][0-9]", pip_version) - stopifnot("Pip failed to install " = min_version) + pip_version = processx::run(venv_python, c("-m", "pip", "--version"))$stdout + stopifnot("pip is older than version 20" = grepl("pip [2-9][0-9]", pip_version)) - numpy = processx::run( - "pip", - args = c("install", "numpy", "--force-reinstall") - ) - withr::defer(processx::run("pip", args = c("uninstall", "numpy", "--yes"))) - has_installed = grepl( - numpy$stdout, - pattern = "Successfully installed", - fixed = TRUE + processx::run( + venv_python, + c("-m", "pip", "install", "--quiet", "--disable-pip-version-check", "numpy") ) - stopifnot("Pip failed to install " = has_installed) + processx::run(venv_python, c("-c", "import numpy")) invisible(TRUE) } diff --git a/tests/testthat/test-check_python.R b/tests/testthat/test-check_python.R new file mode 100644 index 0000000..aa48f58 --- /dev/null +++ b/tests/testthat/test-check_python.R @@ -0,0 +1,13 @@ +test_that("python_pip_tests() installs numpy in a venv and leaves the user's Python alone", { + expect_error(python_pip_tests(python = ""), "Can't find Python") + + python = find_python() + skip_if_not(nzchar(python), "No Python 3") + skip_if_offline() + has_numpy = function() { + processx::run(python, c("-c", "import numpy"), error_on_status = FALSE)$status == 0L + } + before = has_numpy() + expect_true(python_pip_tests(python)) + expect_identical(has_numpy(), before) +})