From 5fb487bdb023a689b79912b1968d17d5b847a03f Mon Sep 17 00:00:00 2001 From: Benjamin Pritchard Date: Mon, 2 Mar 2026 14:02:47 -0500 Subject: [PATCH 1/5] Update version pins --- qcarchivetesting/pyproject.toml | 4 ++-- qcfractal/pyproject.toml | 2 +- qcfractalcompute/pyproject.toml | 3 ++- qcportal/pyproject.toml | 7 +++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/qcarchivetesting/pyproject.toml b/qcarchivetesting/pyproject.toml index 43aecebc1..3866dcb9b 100644 --- a/qcarchivetesting/pyproject.toml +++ b/qcarchivetesting/pyproject.toml @@ -13,7 +13,7 @@ description = "A distributed compute and database platform for quantum chemistry readme = "README.md" license = "BSD-3-Clause" license-files = ["LICENSE"] -requires-python = ">=3.10" +requires-python = ">=3.10,<3.14" classifiers = [ "Programming Language :: Python :: 3", "Development Status :: 4 - Beta", @@ -23,7 +23,7 @@ classifiers = [ ] dependencies = [ "qcfractal", - "qcengine<0.70a0", + "qcengine>=0.34,<0.70a0", "pytest", "deepdiff", ] diff --git a/qcfractal/pyproject.toml b/qcfractal/pyproject.toml index 1412474cb..c18389094 100644 --- a/qcfractal/pyproject.toml +++ b/qcfractal/pyproject.toml @@ -13,7 +13,7 @@ description = "A distributed compute and database platform for quantum chemistry readme = "README.md" license = "BSD-3-Clause" license-files = ["LICENSE"] -requires-python = ">=3.10" +requires-python = ">=3.10,<3.14" classifiers = [ "Programming Language :: Python :: 3", "Development Status :: 4 - Beta", diff --git a/qcfractalcompute/pyproject.toml b/qcfractalcompute/pyproject.toml index 64d55dbab..fdad0878d 100644 --- a/qcfractalcompute/pyproject.toml +++ b/qcfractalcompute/pyproject.toml @@ -13,7 +13,7 @@ description = "A distributed compute and database platform for quantum chemistry readme = "README.md" license = "BSD-3-Clause" license-files = ["LICENSE"] -requires-python = ">=3.10" +requires-python = ">=3.10,<3.14" classifiers = [ "Programming Language :: Python :: 3", "Development Status :: 4 - Beta", @@ -24,6 +24,7 @@ classifiers = [ dependencies = [ "qcportal", "parsl", + "qcengine>=0.34,<0.70a0", ] diff --git a/qcportal/pyproject.toml b/qcportal/pyproject.toml index 245683a13..6fdff84a2 100644 --- a/qcportal/pyproject.toml +++ b/qcportal/pyproject.toml @@ -13,7 +13,7 @@ description = "A distributed compute and database platform for quantum chemistry readme = "README.md" license = "BSD-3-Clause" license-files = ["LICENSE"] -requires-python = ">=3.10" +requires-python = ">=3.10,<3.14" classifiers = [ "Programming Language :: Python :: 3", "Development Status :: 4 - Beta", @@ -26,12 +26,11 @@ dependencies = [ "msgpack", "requests", "pyyaml", - "pydantic>2.10", + "pydantic>=2.11", "pydantic-settings", "zstandard", "apsw>=3.42", - "qcelemental<0.70a0", - "pint", # Required for qcelemental. Doesn't install with py3.13. REMOVE EVENTUALLY + "qcelemental>=0.30,<0.70a0", "tabulate", "tqdm", "pandas", From 2f4211c7f1df5e2317487940289437731c1b8165 Mon Sep 17 00:00:00 2001 From: Benjamin Pritchard Date: Mon, 2 Mar 2026 14:11:44 -0500 Subject: [PATCH 2/5] update changelog --- docs/source/release_notes.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/source/release_notes.rst b/docs/source/release_notes.rst index d59a5a213..c11a90fd5 100644 --- a/docs/source/release_notes.rst +++ b/docs/source/release_notes.rst @@ -1,6 +1,36 @@ Release Notes ============= +0.64 / 2026-03-03 +----------------- + +Some cleanup and some small bug fixes. Some old code and migrations were removed and some +incorrect endpoints were fixed. + +One bigger change is the improved use of upserts (ON CONFLICT DO NOTHING) in postgres, particularly +for the molecule table but also on specification tables. This should eliminate some deadlocks +that were happening due to the use of advisory locks. + +Some bugs found during the development of the web app were fixed. These related to the "/me" endpoint which +is not used by the PortalClient, but will be used by the web app. Also, we improved the performance +of dataset listing, which was getting slow on our large instances. + +This release also introduces pydantic v2 in a few isolated areas (configuration files), with more +coming the next version. + +Notable PRs: + +- (:pr:`977`) Adding & cleaning documentation +- (:pr:`978`) Update server and compute config to use pydantic v2 +- (:pr:`980`) Remove pre-v0.50 database migrations +- (:pr:`985`) Making dataset views should always include required record fields +- (:pr:`988`) Improve errors for exporting to qcschema with missing data +- (:pr:`991`, :pr:`992`) Fix /me endpoints and add tests +- (:pr:`993`) Add owner/user to project listing +- (:pr:`994`) Rework database locking to use upserts when possible +- (:pr:`995`) Faster record count in dataset list + + 0.63 / 2025-09-26 ----------------- From 48e31feeaf34327ffa40a7b3e13d66be55cc97c5 Mon Sep 17 00:00:00 2001 From: Benjamin Pritchard Date: Mon, 2 Mar 2026 14:26:37 -0500 Subject: [PATCH 3/5] Update conda env pins --- qcarchivetesting/conda-envs/fulltest_server.yaml | 2 +- qcarchivetesting/conda-envs/fulltest_snowflake.yaml | 4 ++-- qcarchivetesting/conda-envs/fulltest_testing.yaml | 2 +- qcarchivetesting/conda-envs/fulltest_worker.yaml | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/qcarchivetesting/conda-envs/fulltest_server.yaml b/qcarchivetesting/conda-envs/fulltest_server.yaml index 23b6da6f9..2833e7eb5 100644 --- a/qcarchivetesting/conda-envs/fulltest_server.yaml +++ b/qcarchivetesting/conda-envs/fulltest_server.yaml @@ -16,7 +16,7 @@ dependencies: - pydantic-settings - zstandard - apsw>=3.42 - - qcelemental<0.70a0 + - qcelemental>=0.30,<0.70a0 - tabulate - tqdm - pandas diff --git a/qcarchivetesting/conda-envs/fulltest_snowflake.yaml b/qcarchivetesting/conda-envs/fulltest_snowflake.yaml index 25bbd8011..5f8338fab 100644 --- a/qcarchivetesting/conda-envs/fulltest_snowflake.yaml +++ b/qcarchivetesting/conda-envs/fulltest_snowflake.yaml @@ -16,7 +16,7 @@ dependencies: - pydantic-settings - zstandard - apsw>=3.42 - - qcelemental<0.70a0 + - qcelemental>=0.30,<0.70a0 - tabulate - tqdm - pandas @@ -47,7 +47,7 @@ dependencies: - scipy # TODO Required for geometric REMOVE EVENTUALLY # Worker codes below - - qcengine<0.70a0 + - qcengine>=0.34,<0.70a0 - psi4>=1.9.1 - rdkit diff --git a/qcarchivetesting/conda-envs/fulltest_testing.yaml b/qcarchivetesting/conda-envs/fulltest_testing.yaml index 2c02904f1..f7ca9b15c 100644 --- a/qcarchivetesting/conda-envs/fulltest_testing.yaml +++ b/qcarchivetesting/conda-envs/fulltest_testing.yaml @@ -16,7 +16,7 @@ dependencies: - pydantic-settings - zstandard - apsw>=3.42 - - qcelemental<0.70a0 + - qcelemental>=0.30,<0.70a0 - tabulate - tqdm - pandas diff --git a/qcarchivetesting/conda-envs/fulltest_worker.yaml b/qcarchivetesting/conda-envs/fulltest_worker.yaml index 63e96bc11..fd79fea43 100644 --- a/qcarchivetesting/conda-envs/fulltest_worker.yaml +++ b/qcarchivetesting/conda-envs/fulltest_worker.yaml @@ -14,7 +14,7 @@ dependencies: - pydantic-settings - zstandard - apsw>=3.42 - - qcelemental<0.70a0 + - qcelemental>=0.30,<0.70a0 - tabulate - tqdm - pandas @@ -28,7 +28,7 @@ dependencies: - parsl # Worker codes below - - qcengine<0.70a0 + - qcengine>=0.34,<0.70a0 - psi4>=1.9.1 - rdkit - geometric From 3a58a553982c035b4f487933eb0560b985075089 Mon Sep 17 00:00:00 2001 From: Benjamin Pritchard Date: Mon, 2 Mar 2026 20:07:57 -0500 Subject: [PATCH 4/5] Fix migration for unique constraints on specs --- ...dd_postgres_nulls_not_distinct_to_specs.py | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/qcfractal/qcfractal/alembic/versions/2026-02-27-83127ad1a00e_add_postgres_nulls_not_distinct_to_specs.py b/qcfractal/qcfractal/alembic/versions/2026-02-27-83127ad1a00e_add_postgres_nulls_not_distinct_to_specs.py index 9aae5b554..a62c81c93 100644 --- a/qcfractal/qcfractal/alembic/versions/2026-02-27-83127ad1a00e_add_postgres_nulls_not_distinct_to_specs.py +++ b/qcfractal/qcfractal/alembic/versions/2026-02-27-83127ad1a00e_add_postgres_nulls_not_distinct_to_specs.py @@ -6,6 +6,7 @@ """ +import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. @@ -19,6 +20,122 @@ def upgrade(): op.drop_constraint("ux_neb_specification_keys", "neb_specification", type_="unique") op.drop_constraint("ux_reaction_specification_keys", "reaction_specification", type_="unique") + # We need to find duplicates due to a NULL optimization_specification_id + # then update references and delete + op.execute(sa.text(""" + WITH ranked AS ( + SELECT + id, + MIN(id) OVER ( + PARTITION BY specification_hash, singlepoint_specification_id + ) AS canonical_id + FROM neb_specification + WHERE optimization_specification_id IS NULL + ), + dupes AS ( + SELECT id AS duplicate_id, canonical_id + FROM ranked + WHERE id <> canonical_id + ) + UPDATE neb_record r + SET specification_id = d.canonical_id + FROM dupes d + WHERE r.specification_id = d.duplicate_id; + """)) + + op.execute(sa.text(""" + WITH ranked AS ( + SELECT + id, + MIN(id) OVER ( + PARTITION BY specification_hash, singlepoint_specification_id + ) AS canonical_id + FROM neb_specification + WHERE optimization_specification_id IS NULL + ), + dupes AS ( + SELECT id AS duplicate_id, canonical_id + FROM ranked + WHERE id <> canonical_id + ) + UPDATE neb_dataset_specification rds + SET specification_id = d.canonical_id + FROM dupes d + WHERE rds.specification_id = d.duplicate_id; + """)) + + op.execute(sa.text(""" + WITH ranked AS ( + SELECT + id, + MIN(id) OVER ( + PARTITION BY specification_hash, singlepoint_specification_id + ) AS canonical_id + FROM neb_specification + WHERE optimization_specification_id IS NULL + ) + DELETE FROM neb_specification r + USING ranked d + WHERE r.id = d.id + AND d.id <> d.canonical_id; + """)) + + # Now for reactions, which can have singlepoint or optimization specification ids be null + op.execute(sa.text(""" + WITH ranked AS ( + SELECT + id, + MIN(id) OVER ( + PARTITION BY specification_hash, singlepoint_specification_id, optimization_specification_id + ) AS canonical_id + FROM reaction_specification + ), + dupes AS ( + SELECT id AS duplicate_id, canonical_id + FROM ranked + WHERE id <> canonical_id + ) + UPDATE reaction_record r + SET specification_id = d.canonical_id + FROM dupes d + WHERE r.specification_id = d.duplicate_id; + """)) + + op.execute(sa.text(""" + WITH ranked AS ( + SELECT + id, + MIN(id) OVER ( + PARTITION BY specification_hash, singlepoint_specification_id, optimization_specification_id + ) AS canonical_id + FROM reaction_specification + ), + dupes AS ( + SELECT id AS duplicate_id, canonical_id + FROM ranked + WHERE id <> canonical_id + ) + UPDATE reaction_dataset_specification rds + SET specification_id = d.canonical_id + FROM dupes d + WHERE rds.specification_id = d.duplicate_id; + """)) + + op.execute(sa.text(""" + WITH ranked AS ( + SELECT + id, + MIN(id) OVER ( + PARTITION BY specification_hash, singlepoint_specification_id, optimization_specification_id + ) AS canonical_id + FROM reaction_specification + ) + DELETE FROM reaction_specification r + USING ranked d + WHERE r.id = d.id + AND d.id <> d.canonical_id; + """)) + op.create_unique_constraint( "ux_neb_specification_keys", "neb_specification", From 07bea7cdd9b007d61fb5c40f16805aeb106af055 Mon Sep 17 00:00:00 2001 From: Benjamin Pritchard Date: Wed, 4 Mar 2026 08:48:47 -0500 Subject: [PATCH 5/5] Update release date --- docs/source/release_notes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/release_notes.rst b/docs/source/release_notes.rst index c11a90fd5..1ec26c457 100644 --- a/docs/source/release_notes.rst +++ b/docs/source/release_notes.rst @@ -1,7 +1,7 @@ Release Notes ============= -0.64 / 2026-03-03 +0.64 / 2026-03-04 ----------------- Some cleanup and some small bug fixes. Some old code and migrations were removed and some