From d1ac7107d2352a439ce4584de0fe4346cfa821fe Mon Sep 17 00:00:00 2001 From: mhucka Date: Mon, 27 Apr 2026 22:33:14 +0000 Subject: [PATCH 1/8] Change how random seed is initialized Setting the seed in conftest.py like this makes it possible to run pytest in parallel with the `-n` option from pytest-xdist. --- src/openfermion/conftest.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/openfermion/conftest.py b/src/openfermion/conftest.py index ac3ed7d30..11e8bd1ef 100644 --- a/src/openfermion/conftest.py +++ b/src/openfermion/conftest.py @@ -12,17 +12,14 @@ import os import random -import pytest import numpy as np +# Set random seeds at top level to ensure deterministic test collection. +# This makes it possible to run pytest in parallel (with pytest-xdist). +random.seed(31) +np.random.seed(31) + def pytest_configure(config): # fail tests when using deprecated cirq functionality os.environ['CIRQ_TESTING'] = "true" - - -@pytest.fixture(autouse=True) -def set_random_seed(): - """Set a fixed random seed when testing.""" - random.seed(0) - np.random.seed(0) From cf1b95c7e31ccbcd04755496f162db938486028d Mon Sep 17 00:00:00 2001 From: mhucka Date: Mon, 27 Apr 2026 23:25:55 +0000 Subject: [PATCH 2/8] Use isolated temp dirs and data files during testing Some of the test code did not work with parallel pytest execution because it attempted to write to and delete the same files in the shared `src/openfermion/testing/data` directory. Specifically, `SaveLoadOperatorTest` and `MolecularDataTest` used fixed filenames:(like `test_file.data` and `dummy_molecule.hdf5`) which led to collisions and errors during parallel execution. The changes implemented here are: * Refactor `SaveLoadOperatorTest` in `operator_utils_test.py` to use a unique temporary directory for each test instance through the use of `tempfile.mkdtemp()`. * Refactor `MolecularDataTest` in `molecular_data_test.py` to use a temporary directory for tests that perform disk writes (`test_dummy_save` and `test_abstract_molecule`). --- src/openfermion/chem/molecular_data_test.py | 14 ++- src/openfermion/utils/operator_utils_test.py | 107 ++++++++++++------- 2 files changed, 78 insertions(+), 43 deletions(-) diff --git a/src/openfermion/chem/molecular_data_test.py b/src/openfermion/chem/molecular_data_test.py index 7e12f328e..56c6d9237 100644 --- a/src/openfermion/chem/molecular_data_test.py +++ b/src/openfermion/chem/molecular_data_test.py @@ -12,6 +12,7 @@ """Tests for molecular_data.""" import os +import shutil import tempfile import unittest import h5py @@ -39,6 +40,7 @@ class MolecularDataTest(unittest.TestCase): def setUp(self): + self.test_dir = tempfile.mkdtemp() self.geometry = [('H', (0.0, 0.0, 0.0)), ('H', (0.0, 0.0, 0.7414))] self.basis = 'sto-3g' self.multiplicity = 1 @@ -48,6 +50,9 @@ def setUp(self): ) self.molecule.load() + def tearDown(self): + shutil.rmtree(self.test_dir) + def testUnitConversion(self): """Test the unit conversion routines""" unit_angstrom = 1.0 @@ -126,7 +131,7 @@ def test_save_load(self): def test_dummy_save(self): # Make fake molecule. - filename = os.path.join(DATA_DIRECTORY, 'dummy_molecule') + filename = os.path.join(self.test_dir, 'dummy_molecule') geometry = [('H', (0.0, 0.0, 0.0)), ('H', (0.0, 0.0, 0.7414))] basis = '6-31g*' multiplicity = 7 @@ -194,7 +199,8 @@ def test_dummy_save(self): self.assertAlmostEqual(new_molecule.ccsd_energy, molecule.ccsd_energy) self.assertAlmostEqual(molecule.ccsd_energy, 88.0) finally: - os.remove(filename + '.hdf5') + if os.path.isfile(filename + '.hdf5'): + os.remove(filename + '.hdf5') def test_file_loads(self): """Test different filename specs""" @@ -284,6 +290,7 @@ def test_abstract_molecule(self): basis="PlaneWave22", multiplicity=1, n_electrons=4, + data_directory=self.test_dir, ) jellium_filename = jellium_molecule.filename @@ -291,7 +298,8 @@ def test_abstract_molecule(self): jellium_molecule.load() correct_name = "Jellium_PlaneWave22_singlet" self.assertEqual(jellium_molecule.name, correct_name) - os.remove("{}.hdf5".format(jellium_filename)) + if os.path.isfile("{}.hdf5".format(jellium_filename)): + os.remove("{}.hdf5".format(jellium_filename)) def test_load_molecular_hamiltonian(self): bond_length = 1.45 diff --git a/src/openfermion/utils/operator_utils_test.py b/src/openfermion/utils/operator_utils_test.py index 95b7d32cb..015cb0cfc 100644 --- a/src/openfermion/utils/operator_utils_test.py +++ b/src/openfermion/utils/operator_utils_test.py @@ -14,7 +14,8 @@ import os import itertools - +import shutil +import tempfile import unittest import numpy @@ -458,6 +459,7 @@ def test_exceptions(self): class SaveLoadOperatorTest(unittest.TestCase): def setUp(self): + self.test_dir = tempfile.mkdtemp() self.n_qubits = 5 self.fermion_term = FermionOperator('1^ 2^ 3 4', -3.17) self.fermion_operator = self.fermion_term + hermitian_conjugated(self.fermion_term) @@ -470,30 +472,27 @@ def setUp(self): self.bad_operator_filename = 'bad_file.data' bad_op = "A:\nB" - with open(os.path.join(DATA_DIRECTORY, self.bad_operator_filename), 'w') as fid: + with open(os.path.join(self.test_dir, self.bad_operator_filename), 'w') as fid: fid.write(bad_op) + shutil.copy(os.path.join(DATA_DIRECTORY, 'bad_type_operator.data'), self.test_dir) + def tearDown(self): - file_path = os.path.join(DATA_DIRECTORY, self.file_name + '.data') - if os.path.isfile(file_path): - os.remove(file_path) - file_path = os.path.join(DATA_DIRECTORY, self.bad_operator_filename) - if os.path.isfile(file_path): - os.remove(file_path) + shutil.rmtree(self.test_dir) def test_save_sympy_plaintext(self): operator = FermionOperator('1^', sympy.Symbol('x')) with self.assertRaises(TypeError): - save_operator(operator, self.file_name, plain_text=True) + save_operator(operator, self.file_name, data_directory=self.test_dir, plain_text=True) def test_raises_error_sympy(self): operator = FermionOperator('1^', sympy.Symbol('x')) with self.assertRaises(TypeError): - save_operator(operator, self.file_name, plain_text=False) + save_operator(operator, self.file_name, data_directory=self.test_dir, plain_text=False) def test_save_and_load_fermion_operators(self): - save_operator(self.fermion_operator, self.file_name) - loaded_fermion_operator = load_operator(self.file_name) + save_operator(self.fermion_operator, self.file_name, data_directory=self.test_dir) + loaded_fermion_operator = load_operator(self.file_name, data_directory=self.test_dir) self.assertEqual( self.fermion_operator, loaded_fermion_operator, @@ -501,13 +500,17 @@ def test_save_and_load_fermion_operators(self): ) def test_save_and_load_fermion_operators_readably(self): - save_operator(self.fermion_operator, self.file_name, plain_text=True) - loaded_fermion_operator = load_operator(self.file_name, plain_text=True) + save_operator( + self.fermion_operator, self.file_name, data_directory=self.test_dir, plain_text=True + ) + loaded_fermion_operator = load_operator( + self.file_name, data_directory=self.test_dir, plain_text=True + ) self.assertTrue(self.fermion_operator == loaded_fermion_operator) def test_save_and_load_boson_operators(self): - save_operator(self.boson_operator, self.file_name) - loaded_boson_operator = load_operator(self.file_name) + save_operator(self.boson_operator, self.file_name, data_directory=self.test_dir) + loaded_boson_operator = load_operator(self.file_name, data_directory=self.test_dir) self.assertEqual( self.boson_operator.terms, loaded_boson_operator.terms, @@ -515,37 +518,51 @@ def test_save_and_load_boson_operators(self): ) def test_save_and_load_boson_operators_readably(self): - save_operator(self.boson_operator, self.file_name, plain_text=True) - loaded_boson_operator = load_operator(self.file_name, plain_text=True) + save_operator( + self.boson_operator, self.file_name, data_directory=self.test_dir, plain_text=True + ) + loaded_boson_operator = load_operator( + self.file_name, data_directory=self.test_dir, plain_text=True + ) self.assertTrue(self.boson_operator == loaded_boson_operator) def test_save_and_load_quad_operators(self): - save_operator(self.quad_operator, self.file_name) - loaded_quad_operator = load_operator(self.file_name) + save_operator(self.quad_operator, self.file_name, data_directory=self.test_dir) + loaded_quad_operator = load_operator(self.file_name, data_directory=self.test_dir) self.assertEqual(self.quad_operator.terms, loaded_quad_operator.terms) def test_save_and_load_quad_operators_readably(self): - save_operator(self.quad_operator, self.file_name, plain_text=True) - loaded_quad_operator = load_operator(self.file_name, plain_text=True) + save_operator( + self.quad_operator, self.file_name, data_directory=self.test_dir, plain_text=True + ) + loaded_quad_operator = load_operator( + self.file_name, data_directory=self.test_dir, plain_text=True + ) self.assertTrue(self.quad_operator == loaded_quad_operator) def test_save_and_load_qubit_operators(self): - save_operator(self.qubit_operator, self.file_name) - loaded_qubit_operator = load_operator(self.file_name) + save_operator(self.qubit_operator, self.file_name, data_directory=self.test_dir) + loaded_qubit_operator = load_operator(self.file_name, data_directory=self.test_dir) self.assertTrue(self.qubit_operator == loaded_qubit_operator) def test_save_and_load_qubit_operators_readably(self): - save_operator(self.qubit_operator, self.file_name, plain_text=True) - loaded_qubit_operator = load_operator(self.file_name, plain_text=True) + save_operator( + self.qubit_operator, self.file_name, data_directory=self.test_dir, plain_text=True + ) + loaded_qubit_operator = load_operator( + self.file_name, data_directory=self.test_dir, plain_text=True + ) self.assertEqual(self.qubit_operator, loaded_qubit_operator) def test_load_bad_operator(self): with self.assertRaises(TypeError): - load_operator(self.bad_operator_filename, plain_text=True) + load_operator(self.bad_operator_filename, data_directory=self.test_dir, plain_text=True) def test_save_readably(self): - save_operator(self.fermion_operator, self.file_name, plain_text=True) - file_path = os.path.join(DATA_DIRECTORY, self.file_name + '.data') + save_operator( + self.fermion_operator, self.file_name, data_directory=self.test_dir, plain_text=True + ) + file_path = os.path.join(self.test_dir, self.file_name + '.data') with open(file_path, "r") as f: self.assertEqual( f.read(), @@ -557,7 +574,7 @@ def test_save_no_filename_operator_utils_error(self): save_operator(self.fermion_operator) def test_basic_save(self): - save_operator(self.fermion_operator, self.file_name) + save_operator(self.fermion_operator, self.file_name, data_directory=self.test_dir) def test_save_interaction_operator_not_implemented(self): constant = 100.0 @@ -567,32 +584,42 @@ def test_save_interaction_operator_not_implemented(self): two_body[1, 2, 3, 4] = 12.0 interaction_operator = InteractionOperator(constant, one_body, two_body) with self.assertRaises(NotImplementedError): - save_operator(interaction_operator, self.file_name) + save_operator(interaction_operator, self.file_name, data_directory=self.test_dir) def test_save_on_top_of_existing_operator_utils_error(self): - save_operator(self.fermion_operator, self.file_name) + save_operator(self.fermion_operator, self.file_name, data_directory=self.test_dir) with self.assertRaises(OperatorUtilsError): - save_operator(self.fermion_operator, self.file_name) + save_operator(self.fermion_operator, self.file_name, data_directory=self.test_dir) def test_save_on_top_of_existing_operator_error_with_explicit_flag(self): - save_operator(self.fermion_operator, self.file_name) + save_operator(self.fermion_operator, self.file_name, data_directory=self.test_dir) with self.assertRaises(OperatorUtilsError): - save_operator(self.fermion_operator, self.file_name, allow_overwrite=False) + save_operator( + self.fermion_operator, + self.file_name, + data_directory=self.test_dir, + allow_overwrite=False, + ) def test_overwrite_flag_save_on_top_of_existing_operator(self): - save_operator(self.fermion_operator, self.file_name) - save_operator(self.fermion_operator, self.file_name, allow_overwrite=True) - fermion_operator = load_operator(self.file_name) + save_operator(self.fermion_operator, self.file_name, data_directory=self.test_dir) + save_operator( + self.fermion_operator, + self.file_name, + data_directory=self.test_dir, + allow_overwrite=True, + ) + fermion_operator = load_operator(self.file_name, data_directory=self.test_dir) self.assertEqual(fermion_operator, self.fermion_operator) def test_load_bad_type(self): with self.assertRaises(TypeError): - _ = load_operator('bad_type_operator') + _ = load_operator('bad_type_operator', data_directory=self.test_dir) def test_save_bad_type(self): with self.assertRaises(TypeError): - save_operator('ping', 'somewhere') + save_operator('ping', 'somewhere', data_directory=self.test_dir) class GetFileDirTest(unittest.TestCase): From f6a97cee4526d3c10b6d195757befa7f78bacf91 Mon Sep 17 00:00:00 2001 From: mhucka Date: Mon, 27 Apr 2026 23:29:30 +0000 Subject: [PATCH 3/8] Add `-n auto` to `pytest-and-incremental-coverage` Although `check/pytest` accepts command line arguments, `pytest-and-incremental-coverage` does not, so we can't instruct contributors to add `-n auto` to it to run it in parallel. Since it's something that is less commonly run by contributors, I took the more expedient route of simply adding the parallelism flag directly to the script. --- check/pytest-and-incremental-coverage | 1 + 1 file changed, 1 insertion(+) diff --git a/check/pytest-and-incremental-coverage b/check/pytest-and-incremental-coverage index 7536f729c..c26081bb1 100755 --- a/check/pytest-and-incremental-coverage +++ b/check/pytest-and-incremental-coverage @@ -68,6 +68,7 @@ fi # Run tests while producing coverage files. check/pytest . \ + -n auto \ --actually-quiet \ --cov \ --cov-report=annotate \ From a38a954cf0ce4981e0dd4c02e7bc293f178073ad Mon Sep 17 00:00:00 2001 From: mhucka Date: Mon, 27 Apr 2026 23:29:51 +0000 Subject: [PATCH 4/8] Update CI workflows to pass `-n auto` to Pytest --- .github/workflows/ci.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e7fdd0a31..8bd464786 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -342,7 +342,7 @@ jobs: run: echo '::add-matcher::.github/problem-matchers/pytest.json' - name: Run pytest - run: check/pytest -m "not slow" + run: check/pytest -n auto -m "not slow" pytest: if: needs.changes.outputs.python == 'true' && (success() || failure()) @@ -391,7 +391,7 @@ jobs: run: echo '::add-matcher::.github/problem-matchers/pytest.json' - name: Run pytest - run: check/pytest -m "not slow" src/openfermion/resource_estimates + run: check/pytest -n auto -m "not slow" src/openfermion/resource_estimates pytest-extra: if: needs.changes.outputs.python == 'true' && (success() || failure()) @@ -433,7 +433,7 @@ jobs: run: echo '::add-matcher::.github/problem-matchers/pytest.json' - name: Run pytest - run: check/pytest -m "not slow" + run: check/pytest -n auto -m "not slow" coverage: if: needs.changes.outputs.python == 'true' From 3af8a305fb9064b749cdbb1eed666806e960092f Mon Sep 17 00:00:00 2001 From: mhucka Date: Mon, 27 Apr 2026 23:42:59 +0000 Subject: [PATCH 5/8] Update `CONTRIBUTING.md` to suggest using parallelism Now that parallel Pytest execution works for OpenFermion, we can tell users about it. --- CONTRIBUTING.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9ac22d4ca..941214ac7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -217,6 +217,10 @@ to run it: check/mypy ``` +If your computer has multiple processor cores, you can add the option `-j 0` to the command above to +make Mypy run in parallel for a substantial speed increase. + + ### Linting and formatting Code should meet common style standards for Python and be free of error-prone constructs. We use @@ -259,7 +263,9 @@ We use [pytest](https://docs.pytest.org) to run our tests and * While developing, periodically check that changes do not break anything. For fast checks, use `pytest -c dev_tools/conf/pytest.ini PATH`, where `PATH` is a directory or pytest file to test. -* After finishing a task, run `check/pytest` to test all of the OpenFermion code. +* After finishing a task, run `check/pytest` to test all of the OpenFermion code. If your system + has multiple processor cores, you can add the option `-n auto` to make it run in parallel for a + substantial speed increase. (Beware, though, that this is resource-intensive.) We don't require 100% coverage, but coverage should be very high, and any uncovered code must be annotated with `# pragma: no cover`. To ignore coverage of a single line, place `# pragma: no cover` @@ -271,9 +277,9 @@ cover` comment on its own line. Note, however, that these annotations should be After a task is finished, run each of the following to make sure everything passes all the tests: * `check/format-incremental` -* `check/pylint` +* `check/pylint -j 0` * `check/mypy` -* `check/pytest` +* `check/pytest -n auto` * `check/pytest-and-incremental-coverage` ### Pull requests and code reviews From 8c1f29e7093351cecb02d53a89625c2f58918411 Mon Sep 17 00:00:00 2001 From: mhucka Date: Tue, 28 Apr 2026 00:01:30 +0000 Subject: [PATCH 6/8] Go back to using a fixture for setting the random seed Turns out the use of the `pytest-randomly` plugin and using `np.random.default_rng` seems to make it possible to run pytest in parallel. Evidently, that seeds every test individually based on a master seed, and this solves the xdist collection issue automatically without creating inter-test dependencies. --- src/openfermion/conftest.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/openfermion/conftest.py b/src/openfermion/conftest.py index 11e8bd1ef..b99547e0e 100644 --- a/src/openfermion/conftest.py +++ b/src/openfermion/conftest.py @@ -12,14 +12,17 @@ import os import random +import pytest import numpy as np -# Set random seeds at top level to ensure deterministic test collection. -# This makes it possible to run pytest in parallel (with pytest-xdist). -random.seed(31) -np.random.seed(31) - def pytest_configure(config): # fail tests when using deprecated cirq functionality os.environ['CIRQ_TESTING'] = "true" + + +@pytest.fixture(autouse=True) +def set_random_seed(): + """Set a fixed random seed when testing.""" + random.seed(0) + np.random.default_rng(0) From ae3ff0e4b35dd73ce131172004f6df614e3ccaf2 Mon Sep 17 00:00:00 2001 From: mhucka Date: Tue, 28 Apr 2026 00:55:12 +0000 Subject: [PATCH 7/8] Add pytest-randomly as a dependency --- dev_tools/requirements/deps/pytest.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev_tools/requirements/deps/pytest.txt b/dev_tools/requirements/deps/pytest.txt index 5ee378fbf..e6d43b3d5 100644 --- a/dev_tools/requirements/deps/pytest.txt +++ b/dev_tools/requirements/deps/pytest.txt @@ -1,6 +1,7 @@ pytest pytest-asyncio pytest-cov +pytest-randomly pytest-retry pytest-xdist From 91fdc3c9679870070464aca94b77c408136f1299 Mon Sep 17 00:00:00 2001 From: mhucka Date: Tue, 28 Apr 2026 00:58:52 +0000 Subject: [PATCH 8/8] Run `re-pip-compile-in-docker.sh` Regenerate dependency files after adding pytest-randomly. --- dev_tools/requirements/envs/dev.env.txt | 39 ++++++++++--------- dev_tools/requirements/envs/format.env.txt | 16 ++++---- dev_tools/requirements/envs/mypy.env.txt | 24 ++++++------ dev_tools/requirements/envs/pip-tools.env.txt | 8 ++-- dev_tools/requirements/envs/pylint.env.txt | 21 ++++++---- .../requirements/envs/pytest-extra.env.txt | 21 ++++++---- dev_tools/requirements/envs/pytest.env.txt | 19 +++++---- dev_tools/requirements/max_compat/dev.env.txt | 17 ++++---- .../max_compat/pytest-max-compat.env.txt | 19 +++++---- 9 files changed, 105 insertions(+), 79 deletions(-) diff --git a/dev_tools/requirements/envs/dev.env.txt b/dev_tools/requirements/envs/dev.env.txt index 38a1d3edf..896b79d39 100644 --- a/dev_tools/requirements/envs/dev.env.txt +++ b/dev_tools/requirements/envs/dev.env.txt @@ -19,15 +19,15 @@ backports-asyncio-runner==1.2.0 ; python_full_version < "3.11" # pytest-asyncio black==26.3.1 # via -r deps/format.txt -build==1.4.2 +build==1.4.4 # via pip-tools -certifi==2026.2.25 +certifi==2026.4.22 # via requests charset-normalizer==3.4.7 # via requests cirq-core==1.5.0 # via -r deps/runtime.txt -click==8.3.1 +click==8.3.3 # via # black # pip-tools @@ -57,7 +57,7 @@ h5py==3.16.0 # via # -r deps/runtime.txt # pyscf -idna==3.11 +idna==3.13 # via requests iniconfig==2.3.0 # via pytest @@ -77,9 +77,9 @@ jupyter-core==5.9.1 # via nbformat kiwisolver==1.5.0 # via matplotlib -librt==0.8.1 +librt==0.9.0 # via mypy -matplotlib==3.10.8 +matplotlib==3.10.9 # via # ase # cirq-core @@ -91,7 +91,7 @@ ml-dtypes==0.5.4 # jaxlib mpmath==1.3.0 # via sympy -mypy==1.20.0 +mypy==1.20.2 # via -r deps/mypy.txt mypy-extensions==1.1.0 # via @@ -121,7 +121,7 @@ numpy==2.2.6 # types-networkx opt-einsum==3.4.0 # via jax -packaging==26.0 +packaging==26.2 # via # black # build @@ -133,7 +133,7 @@ pandas==2.3.3 # via cirq-core pandas-stubs==2.3.3.260113 # via -r deps/mypy.txt -pathspec==1.0.4 +pathspec==1.1.1 # via # black # mypy @@ -141,7 +141,7 @@ pillow==12.2.0 # via matplotlib pip-tools==7.5.3 # via -r deps/pip-tools.txt -platformdirs==4.9.4 +platformdirs==4.9.6 # via # black # jupyter-core @@ -162,19 +162,22 @@ pyproject-hooks==1.2.0 # via # build # pip-tools -pyscf==2.12.1 +pyscf==2.13.0 # via -r deps/resource_estimates_runtime.txt -pytest==9.0.2 +pytest==9.0.3 # via # -r deps/pytest.txt # pytest-asyncio # pytest-cov + # pytest-randomly # pytest-retry # pytest-xdist pytest-asyncio==1.3.0 # via -r deps/pytest.txt pytest-cov==7.1.0 # via -r deps/pytest.txt +pytest-randomly==4.1.0 + # via -r deps/pytest.txt pytest-retry==1.7.0 # via -r deps/pytest.txt pytest-xdist==3.8.0 @@ -230,13 +233,13 @@ traitlets==5.14.3 # via # jupyter-core # nbformat -types-networkx==3.6.1.20260402 +types-networkx==3.6.1.20260408 # via -r deps/mypy.txt -types-pytz==2026.1.1.20260402 +types-pytz==2026.1.1.20260408 # via pandas-stubs -types-requests==2.33.0.20260402 +types-requests==2.33.0.20260408 # via -r deps/mypy.txt -types-setuptools==82.0.0.20260402 +types-setuptools==82.0.0.20260408 # via -r deps/mypy.txt typing-extensions==4.15.0 # via @@ -247,13 +250,13 @@ typing-extensions==4.15.0 # mypy # pytest-asyncio # referencing -tzdata==2025.3 +tzdata==2026.2 # via pandas urllib3==2.6.3 # via # requests # types-requests -wheel==0.46.3 +wheel==0.47.0 # via pip-tools # The following packages are considered to be unsafe in a requirements file: diff --git a/dev_tools/requirements/envs/format.env.txt b/dev_tools/requirements/envs/format.env.txt index 313d35d7a..5ddf25422 100644 --- a/dev_tools/requirements/envs/format.env.txt +++ b/dev_tools/requirements/envs/format.env.txt @@ -16,7 +16,7 @@ black==26.3.1 # via # -c envs/dev.env.txt # -r deps/format.txt -certifi==2026.2.25 +certifi==2026.4.22 # via # -c envs/dev.env.txt # requests @@ -28,7 +28,7 @@ cirq-core==1.5.0 # via # -c envs/dev.env.txt # -r deps/runtime.txt -click==8.3.1 +click==8.3.3 # via # -c envs/dev.env.txt # black @@ -57,7 +57,7 @@ h5py==3.16.0 # via # -c envs/dev.env.txt # -r deps/runtime.txt -idna==3.11 +idna==3.13 # via # -c envs/dev.env.txt # requests @@ -65,7 +65,7 @@ kiwisolver==1.5.0 # via # -c envs/dev.env.txt # matplotlib -matplotlib==3.10.8 +matplotlib==3.10.9 # via # -c envs/dev.env.txt # cirq-core @@ -92,7 +92,7 @@ numpy==2.2.6 # matplotlib # pandas # scipy -packaging==26.0 +packaging==26.2 # via # -c envs/dev.env.txt # black @@ -102,7 +102,7 @@ pandas==2.3.3 # via # -c envs/dev.env.txt # cirq-core -pathspec==1.0.4 +pathspec==1.1.1 # via # -c envs/dev.env.txt # black @@ -110,7 +110,7 @@ pillow==12.2.0 # via # -c envs/dev.env.txt # matplotlib -platformdirs==4.9.4 +platformdirs==4.9.6 # via # -c envs/dev.env.txt # black @@ -170,7 +170,7 @@ typing-extensions==4.15.0 # -c envs/dev.env.txt # black # cirq-core -tzdata==2025.3 +tzdata==2026.2 # via # -c envs/dev.env.txt # pandas diff --git a/dev_tools/requirements/envs/mypy.env.txt b/dev_tools/requirements/envs/mypy.env.txt index 499ced234..9c61c6163 100644 --- a/dev_tools/requirements/envs/mypy.env.txt +++ b/dev_tools/requirements/envs/mypy.env.txt @@ -12,7 +12,7 @@ backports-asyncio-runner==1.2.0 ; python_full_version < "3.11" # via # -c envs/dev.env.txt # -r deps/runtime.txt -certifi==2026.2.25 +certifi==2026.4.22 # via # -c envs/dev.env.txt # requests @@ -49,7 +49,7 @@ h5py==3.16.0 # via # -c envs/dev.env.txt # -r deps/runtime.txt -idna==3.11 +idna==3.13 # via # -c envs/dev.env.txt # requests @@ -57,11 +57,11 @@ kiwisolver==1.5.0 # via # -c envs/dev.env.txt # matplotlib -librt==0.8.1 +librt==0.9.0 # via # -c envs/dev.env.txt # mypy -matplotlib==3.10.8 +matplotlib==3.10.9 # via # -c envs/dev.env.txt # cirq-core @@ -69,7 +69,7 @@ mpmath==1.3.0 # via # -c envs/dev.env.txt # sympy -mypy==1.20.0 +mypy==1.20.2 # via # -c envs/dev.env.txt # -r deps/mypy.txt @@ -94,7 +94,7 @@ numpy==2.2.6 # pandas-stubs # scipy # types-networkx -packaging==26.0 +packaging==26.2 # via # -c envs/dev.env.txt # deprecation @@ -107,7 +107,7 @@ pandas-stubs==2.3.3.260113 # via # -c envs/dev.env.txt # -r deps/mypy.txt -pathspec==1.0.4 +pathspec==1.1.1 # via # -c envs/dev.env.txt # mypy @@ -162,19 +162,19 @@ tqdm==4.67.3 # via # -c envs/dev.env.txt # cirq-core -types-networkx==3.6.1.20260402 +types-networkx==3.6.1.20260408 # via # -c envs/dev.env.txt # -r deps/mypy.txt -types-pytz==2026.1.1.20260402 +types-pytz==2026.1.1.20260408 # via # -c envs/dev.env.txt # pandas-stubs -types-requests==2.33.0.20260402 +types-requests==2.33.0.20260408 # via # -c envs/dev.env.txt # -r deps/mypy.txt -types-setuptools==82.0.0.20260402 +types-setuptools==82.0.0.20260408 # via # -c envs/dev.env.txt # -r deps/mypy.txt @@ -183,7 +183,7 @@ typing-extensions==4.15.0 # -c envs/dev.env.txt # cirq-core # mypy -tzdata==2025.3 +tzdata==2026.2 # via # -c envs/dev.env.txt # pandas diff --git a/dev_tools/requirements/envs/pip-tools.env.txt b/dev_tools/requirements/envs/pip-tools.env.txt index 6b7167b2a..8383cb8c0 100644 --- a/dev_tools/requirements/envs/pip-tools.env.txt +++ b/dev_tools/requirements/envs/pip-tools.env.txt @@ -4,15 +4,15 @@ # # pip-compile --constraint=envs/dev.env.txt --output-file=envs/pip-tools.env.txt deps/pip-tools.txt # -build==1.4.2 +build==1.4.4 # via # -c envs/dev.env.txt # pip-tools -click==8.3.1 +click==8.3.3 # via # -c envs/dev.env.txt # pip-tools -packaging==26.0 +packaging==26.2 # via # -c envs/dev.env.txt # build @@ -31,7 +31,7 @@ tomli==2.4.1 # -c envs/dev.env.txt # build # pip-tools -wheel==0.46.3 +wheel==0.47.0 # via # -c envs/dev.env.txt # pip-tools diff --git a/dev_tools/requirements/envs/pylint.env.txt b/dev_tools/requirements/envs/pylint.env.txt index c729dcbc9..44db3c43d 100644 --- a/dev_tools/requirements/envs/pylint.env.txt +++ b/dev_tools/requirements/envs/pylint.env.txt @@ -23,7 +23,7 @@ backports-asyncio-runner==1.2.0 ; python_full_version < "3.11" # -c envs/dev.env.txt # -r deps/runtime.txt # pytest-asyncio -certifi==2026.2.25 +certifi==2026.4.22 # via # -c envs/dev.env.txt # requests @@ -81,7 +81,7 @@ h5py==3.16.0 # -c envs/dev.env.txt # -r deps/runtime.txt # pyscf -idna==3.11 +idna==3.13 # via # -c envs/dev.env.txt # requests @@ -118,7 +118,7 @@ kiwisolver==1.5.0 # via # -c envs/dev.env.txt # matplotlib -matplotlib==3.10.8 +matplotlib==3.10.9 # via # -c envs/dev.env.txt # ase @@ -164,7 +164,7 @@ opt-einsum==3.4.0 # via # -c envs/dev.env.txt # jax -packaging==26.0 +packaging==26.2 # via # -c envs/dev.env.txt # deprecation @@ -178,7 +178,7 @@ pillow==12.2.0 # via # -c envs/dev.env.txt # matplotlib -platformdirs==4.9.4 +platformdirs==4.9.6 # via # -c envs/dev.env.txt # jupyter-core @@ -204,16 +204,17 @@ pyparsing==3.3.2 # via # -c envs/dev.env.txt # matplotlib -pyscf==2.12.1 +pyscf==2.13.0 # via # -c envs/dev.env.txt # -r deps/resource_estimates_runtime.txt -pytest==9.0.2 +pytest==9.0.3 # via # -c envs/dev.env.txt # -r deps/pytest.txt # pytest-asyncio # pytest-cov + # pytest-randomly # pytest-retry # pytest-xdist pytest-asyncio==1.3.0 @@ -224,6 +225,10 @@ pytest-cov==7.1.0 # via # -c envs/dev.env.txt # -r deps/pytest.txt +pytest-randomly==4.1.0 + # via + # -c envs/dev.env.txt + # -r deps/pytest.txt pytest-retry==1.7.0 # via # -c envs/dev.env.txt @@ -304,7 +309,7 @@ typing-extensions==4.15.0 # exceptiongroup # pytest-asyncio # referencing -tzdata==2025.3 +tzdata==2026.2 # via # -c envs/dev.env.txt # pandas diff --git a/dev_tools/requirements/envs/pytest-extra.env.txt b/dev_tools/requirements/envs/pytest-extra.env.txt index 3fd3eb5ae..83d6e6b09 100644 --- a/dev_tools/requirements/envs/pytest-extra.env.txt +++ b/dev_tools/requirements/envs/pytest-extra.env.txt @@ -19,7 +19,7 @@ backports-asyncio-runner==1.2.0 ; python_full_version < "3.11" # -c envs/dev.env.txt # -r deps/runtime.txt # pytest-asyncio -certifi==2026.2.25 +certifi==2026.4.22 # via # -c envs/dev.env.txt # requests @@ -73,7 +73,7 @@ h5py==3.16.0 # -c envs/dev.env.txt # -r deps/runtime.txt # pyscf -idna==3.11 +idna==3.13 # via # -c envs/dev.env.txt # requests @@ -106,7 +106,7 @@ kiwisolver==1.5.0 # via # -c envs/dev.env.txt # matplotlib -matplotlib==3.10.8 +matplotlib==3.10.9 # via # -c envs/dev.env.txt # ase @@ -148,7 +148,7 @@ opt-einsum==3.4.0 # via # -c envs/dev.env.txt # jax -packaging==26.0 +packaging==26.2 # via # -c envs/dev.env.txt # deprecation @@ -162,7 +162,7 @@ pillow==12.2.0 # via # -c envs/dev.env.txt # matplotlib -platformdirs==4.9.4 +platformdirs==4.9.6 # via # -c envs/dev.env.txt # jupyter-core @@ -183,16 +183,17 @@ pyparsing==3.3.2 # via # -c envs/dev.env.txt # matplotlib -pyscf==2.12.1 +pyscf==2.13.0 # via # -c envs/dev.env.txt # -r deps/resource_estimates_runtime.txt -pytest==9.0.2 +pytest==9.0.3 # via # -c envs/dev.env.txt # -r deps/pytest.txt # pytest-asyncio # pytest-cov + # pytest-randomly # pytest-retry # pytest-xdist pytest-asyncio==1.3.0 @@ -203,6 +204,10 @@ pytest-cov==7.1.0 # via # -c envs/dev.env.txt # -r deps/pytest.txt +pytest-randomly==4.1.0 + # via + # -c envs/dev.env.txt + # -r deps/pytest.txt pytest-retry==1.7.0 # via # -c envs/dev.env.txt @@ -277,7 +282,7 @@ typing-extensions==4.15.0 # exceptiongroup # pytest-asyncio # referencing -tzdata==2025.3 +tzdata==2026.2 # via # -c envs/dev.env.txt # pandas diff --git a/dev_tools/requirements/envs/pytest.env.txt b/dev_tools/requirements/envs/pytest.env.txt index 7a111ea1d..3fe3a730c 100644 --- a/dev_tools/requirements/envs/pytest.env.txt +++ b/dev_tools/requirements/envs/pytest.env.txt @@ -15,7 +15,7 @@ backports-asyncio-runner==1.2.0 ; python_full_version < "3.11" # -c envs/dev.env.txt # -r deps/runtime.txt # pytest-asyncio -certifi==2026.2.25 +certifi==2026.4.22 # via # -c envs/dev.env.txt # requests @@ -68,7 +68,7 @@ h5py==3.16.0 # via # -c envs/dev.env.txt # -r deps/runtime.txt -idna==3.11 +idna==3.13 # via # -c envs/dev.env.txt # requests @@ -92,7 +92,7 @@ kiwisolver==1.5.0 # via # -c envs/dev.env.txt # matplotlib -matplotlib==3.10.8 +matplotlib==3.10.9 # via # -c envs/dev.env.txt # cirq-core @@ -119,7 +119,7 @@ numpy==2.2.6 # matplotlib # pandas # scipy -packaging==26.0 +packaging==26.2 # via # -c envs/dev.env.txt # deprecation @@ -133,7 +133,7 @@ pillow==12.2.0 # via # -c envs/dev.env.txt # matplotlib -platformdirs==4.9.4 +platformdirs==4.9.6 # via # -c envs/dev.env.txt # jupyter-core @@ -154,12 +154,13 @@ pyparsing==3.3.2 # via # -c envs/dev.env.txt # matplotlib -pytest==9.0.2 +pytest==9.0.3 # via # -c envs/dev.env.txt # -r deps/pytest.txt # pytest-asyncio # pytest-cov + # pytest-randomly # pytest-retry # pytest-xdist pytest-asyncio==1.3.0 @@ -170,6 +171,10 @@ pytest-cov==7.1.0 # via # -c envs/dev.env.txt # -r deps/pytest.txt +pytest-randomly==4.1.0 + # via + # -c envs/dev.env.txt + # -r deps/pytest.txt pytest-retry==1.7.0 # via # -c envs/dev.env.txt @@ -240,7 +245,7 @@ typing-extensions==4.15.0 # exceptiongroup # pytest-asyncio # referencing -tzdata==2025.3 +tzdata==2026.2 # via # -c envs/dev.env.txt # pandas diff --git a/dev_tools/requirements/max_compat/dev.env.txt b/dev_tools/requirements/max_compat/dev.env.txt index 3a8cd7dc7..bec60f5cc 100644 --- a/dev_tools/requirements/max_compat/dev.env.txt +++ b/dev_tools/requirements/max_compat/dev.env.txt @@ -13,7 +13,7 @@ backports-asyncio-runner==1.2.0 ; python_full_version < "3.11" # via # -r deps/runtime.txt # pytest-asyncio -certifi==2026.2.25 +certifi==2026.4.22 # via requests charset-normalizer==3.4.7 # via requests @@ -43,7 +43,7 @@ fonttools==4.62.1 # via matplotlib h5py==3.16.0 # via -r deps/runtime.txt -idna==3.11 +idna==3.13 # via requests iniconfig==2.3.0 # via pytest @@ -55,7 +55,7 @@ jupyter-core==5.9.1 # via nbformat kiwisolver==1.5.0 # via matplotlib -matplotlib==3.10.8 +matplotlib==3.10.9 # via cirq-core mpmath==1.3.0 # via sympy @@ -74,7 +74,7 @@ numpy==1.26.4 # matplotlib # pandas # scipy -packaging==26.0 +packaging==26.2 # via # deprecation # matplotlib @@ -83,7 +83,7 @@ pandas==2.3.3 # via cirq-core pillow==12.2.0 # via matplotlib -platformdirs==4.9.4 +platformdirs==4.9.6 # via jupyter-core pluggy==1.6.0 # via @@ -95,17 +95,20 @@ pygments==2.20.0 # via pytest pyparsing==3.3.2 # via matplotlib -pytest==9.0.2 +pytest==9.0.3 # via # -r deps/pytest.txt # pytest-asyncio # pytest-cov + # pytest-randomly # pytest-retry # pytest-xdist pytest-asyncio==1.3.0 # via -r deps/pytest.txt pytest-cov==7.1.0 # via -r deps/pytest.txt +pytest-randomly==4.1.0 + # via -r deps/pytest.txt pytest-retry==1.7.0 # via -r deps/pytest.txt pytest-xdist==3.8.0 @@ -154,7 +157,7 @@ typing-extensions==4.15.0 # exceptiongroup # pytest-asyncio # referencing -tzdata==2025.3 +tzdata==2026.2 # via pandas urllib3==2.6.3 # via requests diff --git a/dev_tools/requirements/max_compat/pytest-max-compat.env.txt b/dev_tools/requirements/max_compat/pytest-max-compat.env.txt index 53ebc649d..5fc54b4e8 100644 --- a/dev_tools/requirements/max_compat/pytest-max-compat.env.txt +++ b/dev_tools/requirements/max_compat/pytest-max-compat.env.txt @@ -15,7 +15,7 @@ backports-asyncio-runner==1.2.0 ; python_full_version < "3.11" # -c max_compat/dev.env.txt # -r deps/runtime.txt # pytest-asyncio -certifi==2026.2.25 +certifi==2026.4.22 # via # -c max_compat/dev.env.txt # requests @@ -69,7 +69,7 @@ h5py==3.16.0 # via # -c max_compat/dev.env.txt # -r deps/runtime.txt -idna==3.11 +idna==3.13 # via # -c max_compat/dev.env.txt # requests @@ -93,7 +93,7 @@ kiwisolver==1.5.0 # via # -c max_compat/dev.env.txt # matplotlib -matplotlib==3.10.8 +matplotlib==3.10.9 # via # -c max_compat/dev.env.txt # cirq-core @@ -120,7 +120,7 @@ numpy==1.26.4 # matplotlib # pandas # scipy -packaging==26.0 +packaging==26.2 # via # -c max_compat/dev.env.txt # deprecation @@ -134,7 +134,7 @@ pillow==12.2.0 # via # -c max_compat/dev.env.txt # matplotlib -platformdirs==4.9.4 +platformdirs==4.9.6 # via # -c max_compat/dev.env.txt # jupyter-core @@ -155,12 +155,13 @@ pyparsing==3.3.2 # via # -c max_compat/dev.env.txt # matplotlib -pytest==9.0.2 +pytest==9.0.3 # via # -c max_compat/dev.env.txt # -r deps/pytest.txt # pytest-asyncio # pytest-cov + # pytest-randomly # pytest-retry # pytest-xdist pytest-asyncio==1.3.0 @@ -171,6 +172,10 @@ pytest-cov==7.1.0 # via # -c max_compat/dev.env.txt # -r deps/pytest.txt +pytest-randomly==4.1.0 + # via + # -c max_compat/dev.env.txt + # -r deps/pytest.txt pytest-retry==1.7.0 # via # -c max_compat/dev.env.txt @@ -241,7 +246,7 @@ typing-extensions==4.15.0 # exceptiongroup # pytest-asyncio # referencing -tzdata==2025.3 +tzdata==2026.2 # via # -c max_compat/dev.env.txt # pandas