From bfa664c8621350cb5df1280dcf7880580f2b57fe Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Mon, 29 Dec 2025 19:59:46 -0800
Subject: [PATCH 01/10] Restored full matrix of OS and Python versions.
---
.github/workflows/tests.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 232761b..cf7c1ab 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -13,8 +13,8 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ubuntu-22.04]
- python-version: ["3.9"]
+ os: [ubuntu-22.04, ubuntu24.04, macos-15-intel, macos-latest]
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v5
From 43b9db8755b73ba8071cae8639f4884b5d482255 Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Mon, 29 Dec 2025 20:20:46 -0800
Subject: [PATCH 02/10] Fix Python 3.11+ compatibility: Add -f flag to all
vspace subprocess calls
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Python 3.11+ has stricter error handling in subprocess.check_output() which
causes tests to fail when vspace prompts for directory override confirmation.
Solution: Add -f (force) flag to all subprocess.check_output(["vspace", ...])
calls to bypass interactive prompts in tests.
Fixed 15 test files:
- tests/FileOps/test_file_operations.py
- tests/GridMode/test_multi_parameter.py
- tests/Random/* (8 files)
- tests/Vspace_* (5 files)
This ensures tests run non-interactively on all Python versions (3.9-3.13).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5
---
tests/FileOps/test_file_operations.py | 8 ++++----
tests/GridMode/test_multi_parameter.py | 6 +++---
tests/Random/test_cosine.py | 4 ++--
tests/Random/test_gaussian.py | 4 ++--
tests/Random/test_gaussian_cutoffs.py | 6 +++---
tests/Random/test_lognormal.py | 4 ++--
tests/Random/test_loguniform.py | 4 ++--
tests/Random/test_seed_reproducibility.py | 8 ++++----
tests/Random/test_sine.py | 4 ++--
tests/Random/test_uniform.py | 2 +-
tests/Vspace_Explicit/test_vspace_explicit.py | 2 +-
tests/Vspace_Linear/test_vspace_linear.py | 2 +-
tests/Vspace_Log/test_vspace_log.py | 2 +-
.../Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py | 2 +-
.../Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py | 2 +-
15 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/tests/FileOps/test_file_operations.py b/tests/FileOps/test_file_operations.py
index 8d22032..bfe3ce0 100644
--- a/tests/FileOps/test_file_operations.py
+++ b/tests/FileOps/test_file_operations.py
@@ -23,7 +23,7 @@ def test_multiple_input_files():
shutil.rmtree(dir)
# Run vspace with earth.in and sun.in
- subprocess.check_output(["vspace", "vspace_multifile.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_multifile.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -70,7 +70,7 @@ def test_option_addition():
if dir.exists():
shutil.rmtree(dir)
- subprocess.check_output(["vspace", "vspace_option_add.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_option_add.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -106,7 +106,7 @@ def test_option_replacement():
if dir.exists():
shutil.rmtree(dir)
- subprocess.check_output(["vspace", "vspace_option_replace.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_option_replace.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
assert len(folders) == 2, "Should have 2 trials"
@@ -163,7 +163,7 @@ def test_source_folder_with_tilde():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "vspace_tilde_test.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_tilde_test.in"], cwd=path)
# Verify it worked
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
diff --git a/tests/GridMode/test_multi_parameter.py b/tests/GridMode/test_multi_parameter.py
index d0aa072..472b2f8 100644
--- a/tests/GridMode/test_multi_parameter.py
+++ b/tests/GridMode/test_multi_parameter.py
@@ -24,7 +24,7 @@ def test_two_parameters_cartesian_product():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "vspace_two_param.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_two_param.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -97,7 +97,7 @@ def test_three_parameters_cube():
if dir.exists():
shutil.rmtree(dir)
- subprocess.check_output(["vspace", "vspace_three_param.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_three_param.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -163,7 +163,7 @@ def test_mixed_spacing_types():
if dir.exists():
shutil.rmtree(dir)
- subprocess.check_output(["vspace", "vspace_mixed_spacing.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_mixed_spacing.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
diff --git a/tests/Random/test_cosine.py b/tests/Random/test_cosine.py
index 865e6b1..d204588 100644
--- a/tests/Random/test_cosine.py
+++ b/tests/Random/test_cosine.py
@@ -26,7 +26,7 @@ def test_cosine_degrees():
shutil.rmtree(dir)
# Run vspace with fixed seed for reproducibility
- subprocess.check_output(["vspace", "vspace_cosine_deg.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_cosine_deg.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -87,7 +87,7 @@ def test_cosine_radians():
if dir.exists():
shutil.rmtree(dir)
- subprocess.check_output(["vspace", "vspace_cosine_rad.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_cosine_rad.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
angles = []
diff --git a/tests/Random/test_gaussian.py b/tests/Random/test_gaussian.py
index 18454b9..c9977e0 100644
--- a/tests/Random/test_gaussian.py
+++ b/tests/Random/test_gaussian.py
@@ -26,7 +26,7 @@ def test_gaussian_basic():
shutil.rmtree(dir)
# Run vspace with fixed seed for reproducibility
- subprocess.check_output(["vspace", "vspace_gaussian.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_gaussian.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -93,7 +93,7 @@ def test_gaussian_nonstandard():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "vspace_gaussian_nonstandard.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_gaussian_nonstandard.in"], cwd=path)
# Extract values
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
diff --git a/tests/Random/test_gaussian_cutoffs.py b/tests/Random/test_gaussian_cutoffs.py
index 4330457..be339b9 100644
--- a/tests/Random/test_gaussian_cutoffs.py
+++ b/tests/Random/test_gaussian_cutoffs.py
@@ -24,7 +24,7 @@ def test_gaussian_min_cutoff():
shutil.rmtree(dir)
# Run vspace: Gaussian(0, 1) with min=-1.0
- subprocess.check_output(["vspace", "vspace_gaussian_min.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_gaussian_min.in"], cwd=path)
# Extract values
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -72,7 +72,7 @@ def test_gaussian_max_cutoff():
shutil.rmtree(dir)
# Run vspace: Gaussian(0, 1) with max=1.0
- subprocess.check_output(["vspace", "vspace_gaussian_max.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_gaussian_max.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
values = []
@@ -118,7 +118,7 @@ def test_gaussian_both_cutoffs():
shutil.rmtree(dir)
# Run vspace: Gaussian(0, 1) with min=-1.5, max=1.5
- subprocess.check_output(["vspace", "vspace_gaussian_both.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_gaussian_both.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
values = []
diff --git a/tests/Random/test_lognormal.py b/tests/Random/test_lognormal.py
index d24d524..5067cb6 100644
--- a/tests/Random/test_lognormal.py
+++ b/tests/Random/test_lognormal.py
@@ -25,7 +25,7 @@ def test_lognormal_basic():
# Run vspace with fixed seed
# Using mean=0, sigma=1 for standard log-normal
- subprocess.check_output(["vspace", "vspace_lognormal.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_lognormal.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -91,7 +91,7 @@ def test_lognormal_nonstandard():
if dir.exists():
shutil.rmtree(dir)
- subprocess.check_output(["vspace", "vspace_lognormal_nonstandard.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_lognormal_nonstandard.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
values = []
diff --git a/tests/Random/test_loguniform.py b/tests/Random/test_loguniform.py
index e5a6d95..80e00c4 100644
--- a/tests/Random/test_loguniform.py
+++ b/tests/Random/test_loguniform.py
@@ -27,7 +27,7 @@ def test_loguniform_positive():
shutil.rmtree(dir)
# Run vspace with fixed seed for reproducibility
- subprocess.check_output(["vspace", "vspace_loguniform.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_loguniform.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -102,7 +102,7 @@ def test_loguniform_negative():
shutil.rmtree(dir)
# Run vspace with fixed seed for reproducibility
- subprocess.check_output(["vspace", "vspace_loguniform_neg.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_loguniform_neg.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
diff --git a/tests/Random/test_seed_reproducibility.py b/tests/Random/test_seed_reproducibility.py
index bf58633..3b676a1 100644
--- a/tests/Random/test_seed_reproducibility.py
+++ b/tests/Random/test_seed_reproducibility.py
@@ -22,7 +22,7 @@ def test_seed_reproduces_identical_values():
if dir1.exists():
shutil.rmtree(dir1)
- subprocess.check_output(["vspace", "vspace_seed_test.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_seed_test.in"], cwd=path)
# Extract values from first run
folders1 = sorted([f.path for f in os.scandir(dir1) if f.is_dir()])
@@ -39,7 +39,7 @@ def test_seed_reproduces_identical_values():
shutil.rmtree(dir1)
# Second run with same seed=12345
- subprocess.check_output(["vspace", "vspace_seed_test.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_seed_test.in"], cwd=path)
# Extract values from second run
folders2 = sorted([f.path for f in os.scandir(dir1) if f.is_dir()])
@@ -85,7 +85,7 @@ def test_different_seeds_produce_different_values():
if dir1.exists():
shutil.rmtree(dir1)
- subprocess.check_output(["vspace", "vspace_seed_test.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_seed_test.in"], cwd=path)
folders1 = sorted([f.path for f in os.scandir(dir1) if f.is_dir()])
values1 = []
@@ -103,7 +103,7 @@ def test_different_seeds_produce_different_values():
if dir2.exists():
shutil.rmtree(dir2)
- subprocess.check_output(["vspace", "vspace_seed_test2.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_seed_test2.in"], cwd=path)
folders2 = sorted([f.path for f in os.scandir(dir2) if f.is_dir()])
values2 = []
diff --git a/tests/Random/test_sine.py b/tests/Random/test_sine.py
index 8f8f336..f5c15dc 100644
--- a/tests/Random/test_sine.py
+++ b/tests/Random/test_sine.py
@@ -26,7 +26,7 @@ def test_sine_degrees():
shutil.rmtree(dir)
# Run vspace with fixed seed for reproducibility
- subprocess.check_output(["vspace", "vspace_sine_deg.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_sine_deg.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -89,7 +89,7 @@ def test_sine_radians():
if dir.exists():
shutil.rmtree(dir)
- subprocess.check_output(["vspace", "vspace_sine_rad.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_sine_rad.in"], cwd=path)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
angles = []
diff --git a/tests/Random/test_uniform.py b/tests/Random/test_uniform.py
index ef2fd60..3db1bcf 100644
--- a/tests/Random/test_uniform.py
+++ b/tests/Random/test_uniform.py
@@ -28,7 +28,7 @@ def test_uniform_distribution():
shutil.rmtree(dir)
# Run vspace with fixed seed for reproducibility
- subprocess.check_output(["vspace", "vspace.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace.in"], cwd=path)
# Grab the output folders
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
diff --git a/tests/Vspace_Explicit/test_vspace_explicit.py b/tests/Vspace_Explicit/test_vspace_explicit.py
index 750debd..54e370a 100644
--- a/tests/Vspace_Explicit/test_vspace_explicit.py
+++ b/tests/Vspace_Explicit/test_vspace_explicit.py
@@ -17,7 +17,7 @@ def test_vspace_explicit():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "vspace.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace.in"], cwd=path)
# Grab the output
folders = sorted(
diff --git a/tests/Vspace_Linear/test_vspace_linear.py b/tests/Vspace_Linear/test_vspace_linear.py
index 816540f..a806a45 100644
--- a/tests/Vspace_Linear/test_vspace_linear.py
+++ b/tests/Vspace_Linear/test_vspace_linear.py
@@ -17,7 +17,7 @@ def test_vspace_linear():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "vspace.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace.in"], cwd=path)
# Grab the output
folders = sorted(
diff --git a/tests/Vspace_Log/test_vspace_log.py b/tests/Vspace_Log/test_vspace_log.py
index 469c890..932a832 100644
--- a/tests/Vspace_Log/test_vspace_log.py
+++ b/tests/Vspace_Log/test_vspace_log.py
@@ -18,7 +18,7 @@ def test_vspace_log():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "vspace.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace.in"], cwd=path)
# Grab the output
folders = sorted(
diff --git a/tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py b/tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py
index e3fca7d..86f5709 100644
--- a/tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py
+++ b/tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py
@@ -16,7 +16,7 @@ def test_vspace_predefprior_npy():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "vspace_npy.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_npy.in"], cwd=path)
# Grab the dat list of randomly selected priors
priors = ascii.read(str(dir)+'/rand_list.dat')
diff --git a/tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py b/tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py
index 1f832ce..1ec454a 100644
--- a/tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py
+++ b/tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py
@@ -16,7 +16,7 @@ def test_vspace_predefprior_txt():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "vspace_txt.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_txt.in"], cwd=path)
# Grab the dat list of randomly selected priors
priors = ascii.read(str(dir)+'/rand_list.dat')
From 2b40f935afb83f638d66a29016e67c5826063ae0 Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Mon, 29 Dec 2025 21:15:06 -0800
Subject: [PATCH 03/10] Add stderr capture to failing tests for better error
diagnostics
Modified test files to include stderr=subprocess.STDOUT in subprocess.check_output() calls to capture error messages from vspace when tests fail on Python 3.11+. This will help diagnose the root cause of failures in:
- test_gaussian_min_cutoff
- test_gaussian_max_cutoff
- test_gaussian_both_cutoffs
- test_vspace_predefprior_npy
- test_vspace_predefprior_txt
---
tests/Random/test_gaussian_cutoffs.py | 6 +++---
tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py | 2 +-
tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/tests/Random/test_gaussian_cutoffs.py b/tests/Random/test_gaussian_cutoffs.py
index be339b9..17f3455 100644
--- a/tests/Random/test_gaussian_cutoffs.py
+++ b/tests/Random/test_gaussian_cutoffs.py
@@ -24,7 +24,7 @@ def test_gaussian_min_cutoff():
shutil.rmtree(dir)
# Run vspace: Gaussian(0, 1) with min=-1.0
- subprocess.check_output(["vspace", "-f", "vspace_gaussian_min.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_gaussian_min.in"], cwd=path, stderr=subprocess.STDOUT)
# Extract values
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
@@ -72,7 +72,7 @@ def test_gaussian_max_cutoff():
shutil.rmtree(dir)
# Run vspace: Gaussian(0, 1) with max=1.0
- subprocess.check_output(["vspace", "-f", "vspace_gaussian_max.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_gaussian_max.in"], cwd=path, stderr=subprocess.STDOUT)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
values = []
@@ -118,7 +118,7 @@ def test_gaussian_both_cutoffs():
shutil.rmtree(dir)
# Run vspace: Gaussian(0, 1) with min=-1.5, max=1.5
- subprocess.check_output(["vspace", "-f", "vspace_gaussian_both.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_gaussian_both.in"], cwd=path, stderr=subprocess.STDOUT)
folders = sorted([f.path for f in os.scandir(dir) if f.is_dir()])
values = []
diff --git a/tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py b/tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py
index 86f5709..e79b7f0 100644
--- a/tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py
+++ b/tests/Vspace_PreDefPrior_npy/test_vspace_predefprior_npy.py
@@ -16,7 +16,7 @@ def test_vspace_predefprior_npy():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "-f", "vspace_npy.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_npy.in"], cwd=path, stderr=subprocess.STDOUT)
# Grab the dat list of randomly selected priors
priors = ascii.read(str(dir)+'/rand_list.dat')
diff --git a/tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py b/tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py
index 1ec454a..33af314 100644
--- a/tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py
+++ b/tests/Vspace_PreDefPrior_txt/test_vspace_predefprior_txt.py
@@ -16,7 +16,7 @@ def test_vspace_predefprior_txt():
shutil.rmtree(dir)
# Run vspace
- subprocess.check_output(["vspace", "-f", "vspace_txt.in"], cwd=path)
+ subprocess.check_output(["vspace", "-f", "vspace_txt.in"], cwd=path, stderr=subprocess.STDOUT)
# Grab the dat list of randomly selected priors
priors = ascii.read(str(dir)+'/rand_list.dat')
From 32f3ef8d83ec61f58c5ba91089944de79218d901 Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Mon, 29 Dec 2025 21:22:40 -0800
Subject: [PATCH 04/10] Fix NumPy 2.0 compatibility for array element
assignment
NumPy 2.0+ (used in Python 3.11+) no longer allows implicit conversion
of 1-element arrays to scalars when assigning to array elements. This
caused ValueError: 'setting an array element with a sequence' in the
Gaussian and log-normal cutoff resampling code.
Fixed by explicitly extracting the scalar value using [0] index for all
6 instances where np.random.normal() or np.random.lognormal() with
size=1 is assigned to an array element.
This resolves test failures on Python 3.11+ for:
- test_gaussian_min_cutoff
- test_gaussian_max_cutoff
- test_gaussian_both_cutoffs
- test_vspace_predefprior_npy
- test_vspace_predefprior_txt
All 48 tests now pass on both Python 3.9 and Python 3.11+.
---
vspace/vspace.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/vspace/vspace.py b/vspace/vspace.py
index 761f7c5..9832e06 100644
--- a/vspace/vspace.py
+++ b/vspace/vspace.py
@@ -399,7 +399,7 @@ def main():
loc=float(values[0]),
scale=float(values[1]),
size=1,
- )
+ )[0]
del min_cutoff # clean up so next parameter doesn't have spurious min_cutoff
elif "min_cutoff" not in vars() and "max_cutoff" in vars():
# user has set a max value for this parameter
@@ -410,7 +410,7 @@ def main():
loc=float(values[0]),
scale=float(values[1]),
size=1,
- )
+ )[0]
del max_cutoff # clean up so next parameter doesn't have spurious max_cutoff
elif "min_cutoff" in vars() and "max_cutoff" in vars():
# user has set min and max values for this parameter
@@ -424,7 +424,7 @@ def main():
loc=float(values[0]),
scale=float(values[1]),
size=1,
- )
+ )[0]
del max_cutoff # clean up so next parameter doesn't have spurious cutoffs
del min_cutoff
# elif "min_cutoff" not in vars() and "max_cutoff" not in vars():
@@ -475,7 +475,7 @@ def main():
mean=float(values[0]),
sigma=float(values[1]),
size=1,
- )
+ )[0]
del min_cutoff # clean up so next parameter doesn't have spurious min_cutoff
elif "min_cutoff" not in vars() and "max_cutoff" in vars():
# user has set a max value for this parameter
@@ -486,7 +486,7 @@ def main():
mean=float(values[0]),
sigma=float(values[1]),
size=1,
- )
+ )[0]
del max_cutoff # clean up so next parameter doesn't have spurious max_cutoff
elif "min_cutoff" in vars() and "max_cutoff" in vars():
# user has set min and max values for this parameter
@@ -500,7 +500,7 @@ def main():
mean=float(values[0]),
sigma=float(values[1]),
size=1,
- )
+ )[0]
del max_cutoff # clean up so next parameter doesn't have spurious cutoffs
del min_cutoff
# elif "min_cutoff" not in vars() and "max_cutoff" not in vars():
From 8de35f34e15a5f3c457a3370db4978c4842f7396 Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Tue, 30 Dec 2025 15:28:14 -0800
Subject: [PATCH 05/10] Updated number of unit tests in README.md.
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 3c73178..197bcde 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
-
+
From 973f2cf0fe15cbca4295567257717c7bdad22154 Mon Sep 17 00:00:00 2001
From: Rory Barnes
Date: Fri, 2 Jan 2026 13:00:02 -0800
Subject: [PATCH 06/10] Remove deprecated Hyak PBS integration details
Removed deprecated features section about Hyak PBS integration and updated recommendations for modern alternatives.
---
README.md | 8 --------
1 file changed, 8 deletions(-)
diff --git a/README.md b/README.md
index 197bcde..711990f 100644
--- a/README.md
+++ b/README.md
@@ -28,11 +28,3 @@
With `VSPACE` you can quickly and easily build input files with specific
parameters with different distributions, such as grids, normal distribution, sines and cosines, and even arbitrary distributions. After generating the trials, use the [`MultiPlanet` package](https://github.com/VirtualPlanetaryLaboratory/multi-planet) to run the simulations
on multi-core platforms, and use [`BigPlanet`](https://github.com/VirtualPlanetaryLaboratory/bigplanet) to store and quickly analyze the results. [Read the docs](https://VirtualPlanetaryLaboratory.github.io/vspace/) to learn how to generate VPLanet parameter sweeps.
-
-## Deprecated Features
-
-### Hyak PBS Integration (removed in v2.0)
-
-The `hyak.py` and `vspace_hyak.py` modules for PBS/Torque job submission have been removed. These were specific to UW's legacy Hyak cluster which migrated to Slurm in 2020.
-
-**Modern alternative:** Use [multiplanet](https://github.com/VirtualPlanetaryLaboratory/multi-planet) which provides superior parallel execution on any system without scheduler dependencies. For HPC clusters, we recommend using multiplanet in interactive sessions or developing Slurm job array workflows if needed.
From 3a2593698180cc826bab8f9f1edd05c63ee1bcb3 Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Fri, 2 Jan 2026 15:02:03 -0800
Subject: [PATCH 07/10] Updated tests.yml and README.
---
.github/workflows/tests.yml | 2 +-
README.md | 8 --------
2 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index cf7c1ab..53f4f15 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -14,7 +14,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu24.04, macos-15-intel, macos-latest]
- python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v5
diff --git a/README.md b/README.md
index 197bcde..711990f 100644
--- a/README.md
+++ b/README.md
@@ -28,11 +28,3 @@
With `VSPACE` you can quickly and easily build input files with specific
parameters with different distributions, such as grids, normal distribution, sines and cosines, and even arbitrary distributions. After generating the trials, use the [`MultiPlanet` package](https://github.com/VirtualPlanetaryLaboratory/multi-planet) to run the simulations
on multi-core platforms, and use [`BigPlanet`](https://github.com/VirtualPlanetaryLaboratory/bigplanet) to store and quickly analyze the results. [Read the docs](https://VirtualPlanetaryLaboratory.github.io/vspace/) to learn how to generate VPLanet parameter sweeps.
-
-## Deprecated Features
-
-### Hyak PBS Integration (removed in v2.0)
-
-The `hyak.py` and `vspace_hyak.py` modules for PBS/Torque job submission have been removed. These were specific to UW's legacy Hyak cluster which migrated to Slurm in 2020.
-
-**Modern alternative:** Use [multiplanet](https://github.com/VirtualPlanetaryLaboratory/multi-planet) which provides superior parallel execution on any system without scheduler dependencies. For HPC clusters, we recommend using multiplanet in interactive sessions or developing Slurm job array workflows if needed.
From 5584340e6aab7c7d10e1b0ab702af085a3d7e6cf Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Fri, 2 Jan 2026 15:03:26 -0800
Subject: [PATCH 08/10] Updated README.
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index d8d75ba..890f0c5 100644
--- a/README.md
+++ b/README.md
@@ -14,14 +14,14 @@
-
+
-
+
From 1fffc8bfd4fc1c1d7263f84941f0ffee7427093c Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Fri, 2 Jan 2026 17:23:30 -0800
Subject: [PATCH 09/10] Update pip-install.yml workflow to match BigPlanet
configuration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Modernize the pip-install workflow following the working BigPlanet template:
- Update Python versions from 3.7-3.9 to 3.9-3.14 (matching project requirements)
- Update OS matrix to use specific versions: macos-15-intel, macos-26, ubuntu-22.04, ubuntu-24.04
- Upgrade GitHub Actions versions:
- actions/checkout@v3 → v4
- actions/setup-python@v4 → v5
- actions/upload-artifact@v3 → v4
- actions/download-artifact@v3 → v4
- Add allow-prereleases flag for Python 3.14 support
- Replace deprecated pep517 with modern python -m build
- Update build dependencies: add build, setuptools, wheel
- Add artifact naming to prevent conflicts in multi-job builds
- Modernize PyPI upload:
- Use trusted publishing with id-token permissions
- Update to pypa/gh-action-pypi-publish@release/v1
- Remove deprecated password-based authentication
- Add merge-multiple for artifact downloads
This ensures the release workflow follows current GitHub Actions and PyPI best practices.
---
.github/workflows/pip-install.yml | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/.github/workflows/pip-install.yml b/.github/workflows/pip-install.yml
index c579dc1..eff6bf9 100644
--- a/.github/workflows/pip-install.yml
+++ b/.github/workflows/pip-install.yml
@@ -8,27 +8,28 @@ on:
jobs:
build:
- name: Build wheels on ${{ matrix.os }}
+ name: 'py${{ matrix.python }} on ${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
matrix:
- os: [ubuntu-latest, macos-latest]
- python: ['3.7', '3.8', '3.9']
+ os: [macos-15-intel, macos-26, ubuntu-22.04, ubuntu-24.04]
+ python: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- - uses: actions/setup-python@v4
+ - uses: actions/setup-python@v5
name: Install Python
with:
python-version: ${{ matrix.python }}
+ allow-prereleases: true
- name: Build
run: |
- python -m pip install -U pip pep517 twine setuptools_scm astropy
- python -m pep517.build .
+ python -m pip install -U pip build twine setuptools setuptools_scm wheel
+ python -m build
- name: Test the sdist
run: |
@@ -42,21 +43,22 @@ jobs:
venv-wheel/bin/python -m pip install dist/vspace*.whl
venv-wheel/bin/python -c "import vspace; print(vspace.__version__)"
- - uses: actions/upload-artifact@v3
+ - uses: actions/upload-artifact@v4
with:
+ name: dist-${{ matrix.os }}-${{ matrix.python }}
path: dist/*
upload_pypi:
needs: [build]
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'
+ permissions:
+ id-token: write
steps:
- - uses: actions/download-artifact@v3
+ - uses: actions/download-artifact@v4
with:
- name: artifact
+ pattern: dist-*
path: dist
+ merge-multiple: true
- - uses: pypa/gh-action-pypi-publish@master
- with:
- user: __token__
- password: ${{ secrets.pypi_password }}
+ - uses: pypa/gh-action-pypi-publish@release/v1
From fd515312f40e5eba073e27cbd0d17ae0c75f6119 Mon Sep 17 00:00:00 2001
From: RoryBarnes
Date: Fri, 2 Jan 2026 17:28:23 -0800
Subject: [PATCH 10/10] Fixed naming issue in test.yml.
---
.github/workflows/tests.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 53f4f15..b49c356 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -1,8 +1,6 @@
name: tests
on:
- push:
- branches: [main]
pull_request:
branches: [main]
@@ -13,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ubuntu-22.04, ubuntu24.04, macos-15-intel, macos-latest]
+ os: [ubuntu-22.04, ubuntu-24.04, macos-15-intel, macos-latest]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
steps: