Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/fix-setup-python-version.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Pin Python version constraint in R wrapper setup_policyengine() to avoid failure on Python 3.14+ machines.
35 changes: 26 additions & 9 deletions r-package/policyenginetaxsim/R/setup.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# Python version constraint matching policyengine-us requirements.
# policyengine-us requires Python >=3.10,<3.14 (as of Feb 2026).
# Without this, setup_policyengine() fails on machines with only Python 3.14+.
.PE_PYTHON_VERSION <- ">=3.10,<3.14"

#' Set up PolicyEngine Python environment
#'
#' Installs Python (via Miniconda if needed) and the required Python packages
Expand Down Expand Up @@ -36,11 +41,18 @@ setup_policyengine <- function(envname = "policyengine-taxsim", force = FALSE,
return(invisible(TRUE))
}

# Step 1: Ensure Python is available
message("Checking for Python installation...")
# Step 1: Ensure a compatible Python is available
# policyengine-us requires Python >=3.10,<3.14
message("Checking for compatible Python installation (requires ", .PE_PYTHON_VERSION, ")...")

# Check if a compatible Python exists among available starters
compatible_python <- tryCatch(
reticulate::virtualenv_starter(version = .PE_PYTHON_VERSION, all = FALSE),
error = function(e) NULL
)

if (!reticulate::py_available(initialize = FALSE)) {
message("Python not found. Installing Miniconda...")
if (is.null(compatible_python) || length(compatible_python) == 0) {
message("No compatible Python found. Installing Miniconda with Python 3.12...")
message("This may take a few minutes...")

tryCatch({
Expand All @@ -49,15 +61,17 @@ setup_policyengine <- function(envname = "policyengine-taxsim", force = FALSE,
}, error = function(e) {
stop(
"Failed to install Miniconda. Error: ", e$message, "\n",
"You may need to install Python manually from https://www.python.org/",
"policyengine-us requires Python ", .PE_PYTHON_VERSION, ".\n",
"Please install Python 3.12 from https://www.python.org/downloads/\n",
"or via Homebrew: brew install python@3.12",
call. = FALSE
)
})
} else {
message("Python found.")
message("Compatible Python found.")
}

# Step 2: Create virtual environment
# Step 2: Create virtual environment with compatible Python version
message("Creating virtual environment '", envname, "'...")

# Check if virtualenv exists
Expand All @@ -77,11 +91,14 @@ setup_policyengine <- function(envname = "policyengine-taxsim", force = FALSE,

if (!(envname %in% existing_envs) || force) {
tryCatch({
reticulate::virtualenv_create(envname)
reticulate::virtualenv_create(envname, version = .PE_PYTHON_VERSION)
message("Virtual environment created.")
}, error = function(e) {
stop(
"Failed to create virtual environment. Error: ", e$message,
"Failed to create virtual environment. Error: ", e$message, "\n",
"policyengine-us requires Python ", .PE_PYTHON_VERSION, ".\n",
"Please install Python 3.12 from https://www.python.org/downloads/\n",
"or via Homebrew: brew install python@3.12",
call. = FALSE
)
})
Expand Down