Skip to content

Commit fafaf36

Browse files
authored
QCSchema v2 and Py314 (#43)
* split computer for qcschema v1, v2 * separate computers and clean up * update for 3-way schema_versions testing * imitate qcel for v1/v2 imports * fix computer and BsseEnum imports * enable CI * try CI again with qcel 0.50 * CI with qcengine v0.50rc1 * qcng * min py310 * xtra dep * networkx * fix docs? * fix docs 2? * right py * to griffe * cleanup * fix pyd ver * fix docs * full docs * qcel rb2 * try py314 * changelog, all tests * respond to copilot review * more follow-up * more updates * finalize v0.6.0
1 parent 1029b58 commit fafaf36

39 files changed

Lines changed: 1784 additions & 785 deletions

.github/workflows/ci.yml

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
matrix:
2626
cfg:
2727
- label: Py-min
28-
python-version: "3.8"
28+
python-version: "3.10"
2929
runs-on: ubuntu-latest
3030
pytest: "-m 'not addon'"
3131

@@ -34,6 +34,11 @@ jobs:
3434
runs-on: ubuntu-latest
3535
pytest: "-k '(not (he4 and (3b or 4b) and not sio)) or supersys'"
3636

37+
- label: Py-314
38+
python-version: "3.14"
39+
runs-on: ubuntu-latest
40+
pytest: "-k '(not (he4 and (3b or 4b) and not sio)) or supersys'"
41+
3742
- label: Demo
3843
python-version: "3.11"
3944
runs-on: ubuntu-latest
@@ -58,13 +63,16 @@ jobs:
5863
name: test
5964
channels:
6065
- conda-forge
66+
- conda-forge/label/qcelemental_dev
67+
- conda-forge/label/qcengine_dev
6168
dependencies:
6269
# Build
6370
- setuptools
6471
- setuptools-scm
6572
# Core
6673
- python
67-
- qcelemental
74+
- qcelemental >=0.50.0rc2
75+
- qcengine >=0.50rc1 # TODO temp
6876
- pydantic
6977
# Testing
7078
- pytest
@@ -78,7 +86,8 @@ jobs:
7886
#- nwchem # lands on different he4 soln
7987
EOF
8088
if [[ "${{ matrix.cfg.label }}" == "Py-min" ]]; then
81-
sed -i "s;pydantic;pydantic=1;g" export.yaml
89+
:
90+
#sed -i "s;pydantic;pydantic=1;g" export.yaml
8291
fi
8392
if [[ "${{ matrix.cfg.label }}" == "Py-max" ]]; then
8493
sed -i "s;#- dummy1;- psi4;g" export.yaml
@@ -94,6 +103,11 @@ jobs:
94103
sed -i "s;#- dummy1;- psi4;g" export.yaml
95104
sed -i "s;#- dummy2;- pydantic-settings;g" export.yaml
96105
fi
106+
if [[ "${{ matrix.cfg.label }}" == "Py-314" ]]; then
107+
sed -i "s;#- nwchem;- nwchem;g" export.yaml
108+
sed -i "s;#- dummy1;- msgpack-python;g" export.yaml
109+
sed -i "s;#- dummy2;- networkx;g" export.yaml
110+
fi
97111
# model sed for L/W
98112
# sed -i "s;;;g" export.yaml
99113
# model sed for M
@@ -160,7 +174,7 @@ jobs:
160174
--color=yes --durations 50 --durations-min 20
161175
162176
- name: CodeCov
163-
uses: codecov/codecov-action@v4.0.1
177+
uses: codecov/codecov-action@v5
164178
with:
165179
token: ${{ secrets.CODECOV_TOKEN }}
166180
slug: loriab/QCManyBody
@@ -190,23 +204,25 @@ jobs:
190204
name: test
191205
channels:
192206
- conda-forge
207+
- conda-forge/label/qcelemental_dev
208+
- conda-forge/label/qcengine_dev
193209
dependencies:
194210
# Build
195211
- setuptools
196212
- setuptools-scm
197213
# Core
198214
- python
199-
- qcelemental
215+
- qcelemental >=0.50.0rc2
200216
# Docs
201217
- numpydoc
202218
- docutils
203-
- sphinx >=7.0.0,<8
219+
- sphinx >=7.0.0
204220
- sphinxcontrib-napoleon
205221
- sphinx-rtd-theme
206-
- autodoc-pydantic <2
222+
- autodoc-pydantic >=2
207223
- sphinx-automodapi
208224
- sphinx-autodoc-typehints
209-
- pydantic <2
225+
- pydantic >=2
210226
EOF
211227
cat export.yaml
212228

CITATION.cff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ keywords:
4444
- mbe
4545
- schema
4646
license: BSD-3-Clause
47-
version: 0.5.2
48-
date-released: '2026-02-16'
47+
version: 0.6.0
48+
date-released: '2026-02-24'
4949
preferred-citation:
5050
type: article
5151
authors:

docs/api.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ QCManyBody API
88
.. automodapi:: qcmanybody.core
99
:noindex:
1010

11-
.. automodapi:: qcmanybody.computer
11+
.. automodapi:: qcmanybody.v2.computer
1212

1313
.. automodapi:: qcmanybody.builder
1414

1515
.. automodapi:: qcmanybody.utils
1616

17-
.. automodapi:: qcmanybody.models
17+
.. automodapi:: qcmanybody.models.v2

docs/changelog.rst

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,75 @@
22
Changelog
33
=========
44

5+
.. .. _`sec:cl0x0`:
6+
..
7+
.. v0.x.0 / 2026-MM-DD (Unreleased)
8+
.. ===================
9+
..
10+
.. :docs:`v0.x.0` for current. :docs:`v0.5.2` for QCSchema v1.
11+
..
12+
.. Breaking Changes
13+
.. ----------------
14+
..
15+
.. New Features
16+
.. ------------
17+
..
18+
.. Enhancements
19+
.. ------------
20+
..
21+
.. Bug Fixes
22+
.. ---------
23+
..
24+
.. Misc.
25+
.. -----
26+
..
27+
.. MUST (Unmerged)
28+
.. ---------------
29+
..
30+
.. WIP (Unmerged)
31+
.. --------------
32+
33+
34+
:docs:`dev` for latest.
35+
36+
.. _`sec:cl060`:
37+
38+
v0.6.0 / 2026-02-24
39+
===================
40+
41+
:docs:`v0.6.0` for current. :docs:`v0.5.2` for QCSchema v1.
42+
43+
v0.6.0 introduces QCSchema v2 compatibility and requires Pydantic v2.
44+
45+
Breaking Changes
46+
----------------
47+
* :pr:`43` Deps -- require QCElemental `>=0.50.0rc2`. Package managers will not
48+
solve for this version unless prereleases are allowed. No longer compatible
49+
with pre-next QCElemental.
50+
* :pr:`43` Deps -- require Pydantic v2.
51+
* :pr:`43` Schema -- QCSchema v2 trial field renames updated:
52+
53+
* `component_results` → `cluster_results`
54+
* `component_properties` → `cluster_properties`
55+
* corresponding protocol name updates
56+
* `ManyBodyResultProperties` → `ManyBodyProperties`
57+
58+
New Features
59+
------------
60+
* :pr:`43` Schema -- add full QCSchema v2 compatibility, including QCManyBody schema and `Computer` interface.
61+
* :pr:`43` Deps -- allow Python 3.14+ insofar as supported by Pydantic.
62+
* :pr:`43` Models -- QCSchema v1 models are always importable (including on Python 3.14+), though instantiation will throw errors on 3.14+.
63+
* :pr:`43` Intf -- `Computer` reorganized into `v1/computer.py` and `v2/computer.py`.
64+
The v1 version is used when accessed through ``qcmanybody.compter`` (and <3.14)
65+
* :pr:`43` Testing -- expand test matrix to run combinations of v1 and v2 input/output models.
66+
67+
568
.. _`sec:cl052`:
669

770
v0.5.2 / 2026-02-16
871
===================
972

10-
`Docs <https://MolSSI.github.io/QCManyBody/v0.5.2/>`_
73+
:docs:`v0.5.2` (Sphinx)
1174

1275
Enhancements
1376
------------
@@ -17,6 +80,8 @@ Enhancements
1780
v0.5.1 / 2025-06-14
1881
===================
1982

83+
:docs:`v0.5.1` (Mkdocs)
84+
2085
Bug Fixes
2186
---------
2287

docs/conf.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import os
1717
import sys
1818

19+
os.environ["SPHINX_BUILD"] = "1"
20+
1921
sys.path.insert(0, os.path.abspath("../../"))
2022
import qcmanybody
2123

@@ -70,6 +72,7 @@
7072
autodoc_pydantic_model_hide_paramlist = True
7173
autodoc_pydantic_model_show_config_summary = False
7274
autodoc_pydantic_field_swap_name_and_alias = True
75+
typehints_use_signature_return = True
7376

7477
# Add any paths that contain templates here, relative to this directory.
7578
templates_path = ["_templates"]
@@ -213,6 +216,7 @@ def setup(app):
213216
extlinks = {
214217
"issue": ("https://github.com/MolSSI/QCManyBody/issues/%s", "GH#%s"),
215218
"pr": ("https://github.com/MolSSI/QCManyBody/pull/%s", "GH#%s"),
219+
"docs": ("https://MolSSI.github.io/QCManyBody/%s", "Docs %s"),
216220
}
217221

218222

@@ -224,9 +228,9 @@ def setup(app):
224228
"numpy": ("https://numpy.org/doc/stable/", None),
225229
"scipy": ("https://docs.scipy.org/doc/scipy/", None),
226230
"matplotlib": ("https://matplotlib.org/stable/", None),
227-
"qcelemental": ("https://molssi.github.io/QCElemental/dev/", None),
228-
"qcengine": ("https://molssi.github.io/QCEngine/dev/", None),
229-
"qcfractal": ("https://molssi.github.io/QCFractal/", None),
231+
"qcelemental": ("https://molssi.github.io/QCElemental/next/", None),
232+
"qcengine": ("https://molssi.github.io/QCEngine/next/", None),
233+
"qcfractal": ("https://docs.qcarchive.molssi.org/", None),
230234
}
231235

232236
# -- Options for todo extension ----------------------------------------------

docs/core-interface.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ class.
2020

2121
The first step is to create a molecule. This molecule is a
2222
`QCElemental molecule object <https://molssi.github.io/QCElemental/dev/model_molecule.html>`_, and must contain fragments.
23-
(see also: :ref:`molecule input <keywords:molecule>`)
23+
(see also: :ref:`molecule input <sec:keywords_molecule>`)
2424

2525
.. code-block:: python
2626
27-
from qcelemental.models import Molecule
27+
from qcelemental.models.v2 import Molecule
2828
2929
# Create a molecule with 3 neon atoms, each as its own fragment
3030
@@ -98,7 +98,7 @@ for a worked example or the below as a quick example of what ``run_calculation``
9898
basis = "def2-svp"
9999
program = "psi4"
100100
101-
mol = qcel.models.Molecule.from_data(p4_string)
101+
mol = qcel.models.v2.Molecule.from_data(p4_string)
102102
mbc = qcmb.ManyBodyCore(
103103
molecule=mol,
104104
bsse_type=[bsse_type],
@@ -113,8 +113,8 @@ for a worked example or the below as a quick example of what ``run_calculation``
113113
calculation_results = {}
114114
for chem, label, imol in mbc.iterate_molecules():
115115
mc, real, bas = qcmb.utils.delabeler(label)
116-
atin = qcel.models.AtomicInput(
117-
molecule=imol, driver="energy", model={"method": method, "basis": basis}
116+
atin = qcel.models.v2.AtomicInput(
117+
molecule=imol, specification={"driver": "energy", "model": {"method": method, "basis": basis}}
118118
)
119119
atres = qcng.compute(atin, program, raise_error=True)
120120
calculation_results[label] = {

docs/high-level-interface.rst

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,25 @@ The high-level interface takes advantage of :doc:`qcschema`
66
data structures for input and output and defines an easy way to run
77
the QC computations through QCEngine.
88
The high-level interface uses the core-interface under the hood.
9-
See the :class:`~qcmanybody.models.ManyBodyInput` QCSchema class for the input options :class:`~qcmanybody.models.ManyBodyKeywords`.
9+
See the :class:`~qcmanybody.models.v2.ManyBodyInput` QCSchema class for the input options :class:`~qcmanybody.models.v2.ManyBodyKeywords`.
1010
Details on forming fragmented ``Molecule`` s are at
11-
:ref:`molecule input <keywords:molecule>`
11+
:ref:`molecule input <sec:keywords_molecule>`
1212

13-
The high-level interface defines a :class:`~qcmanybody.computer.ManyBodyComputer` class in
14-
computer.py whose input is :class:`~qcmanybody.models.ManyBodyInput` schema and whose output is
15-
:class:`~qcmanybody.models.ManyBodyResult` schema.
16-
It provides :func:`qcmanybody.computer.ManyBodyComputer.from_manybodyinput()` to run through
13+
The high-level interface defines a :class:`~qcmanybody.v2.computer.ManyBodyComputer` class in
14+
computer.py whose input is :class:`~qcmanybody.models.v2.ManyBodyInput` schema and whose output is
15+
:class:`~qcmanybody.models.v2.ManyBodyResult` schema.
16+
It provides :func:`qcmanybody.v2.computer.ManyBodyComputer.from_manybodyinput()` to run through
1717
QCEngine.
1818
See ``test_highlevel_interface_example()`` in
1919
`test_example.py <https://github.com/MolSSI/QCManyBody/blob/main/qcmanybody/tests/test_examples.py>`_
2020
for a working example.
21-
The :class:`~qcmanybody.models.ManyBodyComputer` provides the missing link from the core interface
21+
The :class:`~qcmanybody.models.v2.ManyBodyComputer` provides the missing link from the core interface
2222
to run QC computations. A strategy that Psi4 uses is to define its own
2323
``ManyBodyComputer`` (inheriting from the high-level interface) that
2424
runs QC computations the way Psi4 wants to while still using all the
2525
validation and structure provided by the QCSchema I/O classes.
26+
27+
.. note:: QCManyBody import paths *without* QCSchema/Pydantic version specification (*i.e.*,
28+
``qcmanybody.models`` vs ``models.v1`` and ``models.v2`` and ``qcmanybody.computer`` vs. ``v1.computer`` and ``v2.computer)
29+
are *always* pointing to v1 for continuity. This will be true until QCManyBody depends on QCElemental >=v0.70.0.
30+
For technical constraints, these docs always reference v2 classes. See :docs:`v0.5.2` for QCSchema v1-based documentation.

docs/keywords.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ Keywords and Options
55
Required
66
========
77

8+
.. _`sec:keywords_molecule`:
9+
810
Molecule
911
--------
1012

@@ -16,7 +18,7 @@ Examples:
1618

1719
.. code-block:: python
1820
19-
from qcelemental.models import Molecule
21+
from qcelemental.models.v2 import Molecule
2022
2123
# Molecule with 3 neon atoms, each as its own fragment
2224
ne3 = Molecule(symbols=["ne", "ne", "ne"],

docs/qcschema.rst

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
QCSchema
33
========
44

5+
.. note:: QCManyBody import paths *without* QCSchema/Pydantic version specification (*i.e.*,
6+
``qcmanybody.models`` vs ``models.v1`` and ``models.v2`` and ``qcmanybody.computer`` vs. ``v1.computer`` and ``v2.computer)
7+
are *always* pointing to v1 for continuity. This will be true until QCManyBody depends on QCElemental >=v0.70.0.
8+
For technical constraints, these docs always reference v2 classes. See :docs:`v0.5.2` for QCSchema v1-based documentation.
9+
510
Inputs
611
======
712
8-
.. automodule:: qcmanybody.models.v1
13+
.. automodule:: qcmanybody.models.v2
914
:members: BsseEnum, ManyBodyKeywords, ManyBodyProtocols, ManyBodySpecification, ManyBodyInput
1015
:undoc-members:
1116
:show-inheritance:
@@ -26,15 +31,15 @@ Properties/Outputs
2631

2732
.. code-block:: python
2833
29-
python -c "import qcmanybody as qcmb;print(qcmb.models.MAX_NBODY)"
34+
python -c "import qcmanybody as qcmb;print(qcmb.models.v2.MAX_NBODY)"
3035
#> 5
3136
export QCMANYBODY_MAX_NBODY=9 # explicitly enumerates octamer properties
32-
python -c "import qcmanybody as qcmb;print(qcmb.models.MAX_NBODY)"
37+
python -c "import qcmanybody as qcmb;print(qcmb.models.v2.MAX_NBODY)"
3338
#> 9
3439
3540
36-
.. automodule:: qcmanybody.models.v1
37-
:members: ManyBodyResultProperties, ManyBodyResult
41+
.. automodule:: qcmanybody.models.v2
42+
:members: ManyBodyProperties, ManyBodyResult
3843
:undoc-members:
3944
:show-inheritance:
4045
:noindex:

0 commit comments

Comments
 (0)