From 76c5b1071b2a8106ca5666598d9ac6a84609e5fa Mon Sep 17 00:00:00 2001 From: Lori Burns Date: Mon, 17 Aug 2020 15:41:24 -0400 Subject: [PATCH 01/43] fix a few mypy and linting complaints --- qcelemental/molparse/to_string.py | 2 +- qcelemental/tests/test_molecule.py | 8 ++++---- qcelemental/util/importing.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/qcelemental/molparse/to_string.py b/qcelemental/molparse/to_string.py index a83c83642..ff0b6d8d2 100644 --- a/qcelemental/molparse/to_string.py +++ b/qcelemental/molparse/to_string.py @@ -384,7 +384,7 @@ def to_dict(self) -> Dict: atom_format = "{elem}" ghost_format = "@{elem}" - umap = {"bohr": True, "angstrom": False} + umap = {"bohr": "True", "angstrom": "False"} atoms = _atoms_formatter(molrec, geom, atom_format, ghost_format, width, prec, 2) diff --git a/qcelemental/tests/test_molecule.py b/qcelemental/tests/test_molecule.py index 41e833602..aa56b0d79 100644 --- a/qcelemental/tests/test_molecule.py +++ b/qcelemental/tests/test_molecule.py @@ -651,14 +651,14 @@ def test_show(): def test_molecule_connectivity(): data = {"geometry": np.random.rand(5, 3), "symbols": ["he"] * 5, "validate": False} - mol = Molecule(**data, connectivity=None) + Molecule(**data, connectivity=None) connectivity = [[n, n + 1, 1] for n in range(4)] - mol = Molecule(**data, connectivity=connectivity) + Molecule(**data, connectivity=connectivity) connectivity[0][0] = -1 with pytest.raises(ValueError): - mol = Molecule(**data, connectivity=connectivity) + Molecule(**data, connectivity=connectivity) def test_orient_nomasses(): @@ -719,7 +719,7 @@ def test_sparse_molecule_connectivity(): def test_bad_isotope_spec(): - with pytest.raises(NotAnElementError) as e: + with pytest.raises(NotAnElementError): qcel.models.Molecule(symbols=["He3"], geometry=[0, 0, 0]) diff --git a/qcelemental/util/importing.py b/qcelemental/util/importing.py index 4bd120989..cacd3b81b 100644 --- a/qcelemental/util/importing.py +++ b/qcelemental/util/importing.py @@ -1,7 +1,7 @@ import os import shutil import sys -from typing import Union +from typing import List, Union def which_import( @@ -12,7 +12,7 @@ def which_import( raise_msg: str = None, package: str = None, namespace_ok: bool = False, -) -> Union[bool, None, str]: +) -> Union[bool, None, str, List[str]]: """Tests to see if a Python module is available. Returns From 29fbe5c6c527354f739b53418398123fdf258b10 Mon Sep 17 00:00:00 2001 From: Lori Burns Date: Mon, 17 Aug 2020 22:09:11 -0400 Subject: [PATCH 02/43] fix up mypy provenance --- qcelemental/models/__init__.py | 10 +++++++ qcelemental/models/basis.py | 2 +- qcelemental/models/molecule.py | 33 ++++++++++++++---------- qcelemental/models/results.py | 5 +++- qcelemental/molparse/chgmult.py | 4 +-- qcelemental/molutil/molecular_formula.py | 4 +-- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/qcelemental/models/__init__.py b/qcelemental/models/__init__.py index f2c6102ce..fe1420d98 100644 --- a/qcelemental/models/__init__.py +++ b/qcelemental/models/__init__.py @@ -14,3 +14,13 @@ from .molecule import Molecule from .procedures import Optimization, OptimizationInput, OptimizationResult from .results import AtomicInput, AtomicResult, AtomicResultProperties, Result, ResultInput, ResultProperties + + +def qcschema_models(): + return [ + AtomicInput, + AtomicResult, + BasisSet, + Molecule, + Provenance, + ] diff --git a/qcelemental/models/basis.py b/qcelemental/models/basis.py index 952bd9406..7621cf6a8 100644 --- a/qcelemental/models/basis.py +++ b/qcelemental/models/basis.py @@ -130,7 +130,7 @@ class BasisSet(ProtoModel): A quantum chemistry basis description. """ - schema_name: constr(strip_whitespace=True, regex="qcschema_basis") = "qcschema_basis" + schema_name: constr(strip_whitespace=True, regex="qcschema_basis") = "qcschema_basis" # type: ignore schema_version: int = 1 name: str = Field(..., description="A standard basis name if available (e.g., 'cc-pVDZ').") diff --git a/qcelemental/models/molecule.py b/qcelemental/models/molecule.py index a7ba80ba7..fb7fead98 100644 --- a/qcelemental/models/molecule.py +++ b/qcelemental/models/molecule.py @@ -5,13 +5,19 @@ import hashlib import json import warnings +from functools import partial from pathlib import Path -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, cast, Any, Dict, Iterable, List, Optional, Tuple, Union import numpy as np from pydantic import Field, constr, validator -from ..molparse import from_arrays, from_schema, from_string, to_schema, to_string +# molparse imports separated b/c https://github.com/python/mypy/issues/7203 +from ..molparse.from_arrays import from_arrays +from ..molparse.from_schema import from_schema +from ..molparse.from_string import from_string +from ..molparse.to_schema import to_schema +from ..molparse.to_string import to_string from ..periodic_table import periodictable from ..physical_constants import constants from ..testing import compare, compare_values @@ -23,7 +29,6 @@ if TYPE_CHECKING: from pydantic.typing import ReprArgs - # Rounding quantities for hashing GEOMETRY_NOISE = 8 MASS_NOISE = 6 @@ -225,8 +230,8 @@ class Molecule(ProtoModel): None, description="Maximal point group symmetry which ``geometry`` should be treated. Lowercase." ) # Extra - provenance: Provenance = Field( # type: ignore - provenance_stamp(__name__), + provenance: Provenance = Field( + default_factory=partial(provenance_stamp, __name__), description="The provenance information about how this Molecule (and its attributes) were generated, " "provided, and manipulated.", ) @@ -242,10 +247,10 @@ class Molecule(ProtoModel): class Config(ProtoModel.Config): serialize_skip_defaults = True - repr_style = lambda self: [ - ("name", self.name), - ("formula", self.get_molecular_formula()), - ("hash", self.get_hash()[:7]), + repr_style = lambda ins: [ + ("name", ins.name), + ("formula", ins.get_molecular_formula()), + ("hash", ins.get_hash()[:7]), ] fields = { "masses_": "masses", @@ -1042,7 +1047,7 @@ def nuclear_repulsion_energy(self, ifr: int = None) -> float: Nuclear repulsion energy in entire molecule or in fragment. """ - Zeff = [z * int(real) for z, real in zip(self.atomic_numbers, self.real)] + Zeff = [z * int(real) for z, real in zip(cast(Iterable[int], self.atomic_numbers), self.real)] atoms = list(range(self.geometry.shape[0])) if ifr is not None: @@ -1068,7 +1073,7 @@ def nelectrons(self, ifr: int = None) -> int: Number of electrons in entire molecule or in fragment. """ - Zeff = [z * int(real) for z, real in zip(self.atomic_numbers, self.real)] + Zeff = [z * int(real) for z, real in zip(cast(Iterable[int], self.atomic_numbers), self.real)] if ifr is None: nel = sum(Zeff) - self.molecular_charge @@ -1146,7 +1151,7 @@ def align( runiq = np.asarray( [ hashlib.sha1((sym + str(mas)).encode("utf-8")).hexdigest() - for sym, mas in zip(ref_mol.symbols, ref_mol.masses) + for sym, mas in zip(cast(Iterable[str], ref_mol.symbols), ref_mol.masses) ] ) concern_mol = self @@ -1157,7 +1162,7 @@ def align( cuniq = np.asarray( [ hashlib.sha1((sym + str(mas)).encode("utf-8")).hexdigest() - for sym, mas in zip(concern_mol.symbols, concern_mol.masses) + for sym, mas in zip(cast(Iterable[str], concern_mol.symbols), concern_mol.masses) ] ) @@ -1293,7 +1298,7 @@ def scramble( runiq = np.asarray( [ hashlib.sha1((sym + str(mas)).encode("utf-8")).hexdigest() - for sym, mas in zip(ref_mol.symbols, ref_mol.masses) + for sym, mas in zip(cast(Iterable[str], ref_mol.symbols), ref_mol.masses) ] ) nat = rgeom.shape[0] diff --git a/qcelemental/models/results.py b/qcelemental/models/results.py index 92bf46523..ca4398954 100644 --- a/qcelemental/models/results.py +++ b/qcelemental/models/results.py @@ -1,4 +1,5 @@ from enum import Enum +from functools import partial from typing import TYPE_CHECKING, Any, Dict, Optional, Set, Union import numpy as np @@ -347,7 +348,9 @@ class AtomicInput(ProtoModel): extras: Dict[str, Any] = Field({}, description="Extra fields that are not part of the schema.") - provenance: Provenance = Field(Provenance(**provenance_stamp(__name__)), description=str(Provenance.__base_doc__)) + provenance: Provenance = Field( + default_factory=partial(provenance_stamp, __name__), description=str(Provenance.__base_doc__) + ) def __repr_args__(self) -> "ReprArgs": return [ diff --git a/qcelemental/molparse/chgmult.py b/qcelemental/molparse/chgmult.py index 32d53d662..7d1ff4703 100644 --- a/qcelemental/molparse/chgmult.py +++ b/qcelemental/molparse/chgmult.py @@ -360,8 +360,8 @@ def validate_and_fill_chgmult( cgmp_rules.append("4") for ifr in range(nfr): cgmp_range.append( - lambda c, fc, m, fm, ifr=ifr: _sufficient_electrons_for_mult(fzel[ifr], fc[ifr], fm[ifr]) - ) # type: ignore + lambda c, fc, m, fm, ifr=ifr: _sufficient_electrons_for_mult(fzel[ifr], fc[ifr], fm[ifr]) # type: ignore + ) cgmp_rules.append("4-" + str(ifr)) # * (R5) require total parity consistent among neutral_electrons, chg, and mult diff --git a/qcelemental/molutil/molecular_formula.py b/qcelemental/molutil/molecular_formula.py index 3fee6ca40..7ff1d8fdb 100644 --- a/qcelemental/molutil/molecular_formula.py +++ b/qcelemental/molutil/molecular_formula.py @@ -1,6 +1,6 @@ import collections import re -from typing import List +from typing import Dict, List def order_molecular_formula(formula: str, order: str = "alphabetical") -> str: @@ -23,7 +23,7 @@ def order_molecular_formula(formula: str, order: str = "alphabetical") -> str: matches = re.findall(r"[A-Z][^A-Z]*", formula) if not "".join(matches) == formula: raise ValueError(f"{formula} is not a valid molecular formula.") - count = collections.defaultdict(int) + count: Dict[str, int] = collections.defaultdict(int) for match in matches: match_n = re.match(r"(\D+)(\d*)", match) assert match_n From c1af6bd0efc0567ba1302bcd6c3e3c1f3c68cae0 Mon Sep 17 00:00:00 2001 From: Lori Burns Date: Mon, 17 Aug 2020 23:45:47 -0400 Subject: [PATCH 03/43] incr min pydantic to 1.5 --- devtools/conda-envs/minimal.yaml | 2 +- qcelemental/models/molecule.py | 10 +++++----- setup.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/devtools/conda-envs/minimal.yaml b/devtools/conda-envs/minimal.yaml index bf609d50d..0d1b8f070 100644 --- a/devtools/conda-envs/minimal.yaml +++ b/devtools/conda-envs/minimal.yaml @@ -8,7 +8,7 @@ dependencies: - nomkl - python - pint=0.10.0 # technically, qcel has no lower bound for pint version for py36,37 but needs 0.10 for 38 - - pydantic=1.2.0 # technically, qcel works with 1.0.0 but c-f doesn't have py38 builds for it + - pydantic=1.5.0 # Testing - pytest=4.6.4 # technically, qcel works with 4.0.0 but c-f doesn't have py38 builds for it diff --git a/qcelemental/models/molecule.py b/qcelemental/models/molecule.py index fb7fead98..a22c78f4e 100644 --- a/qcelemental/models/molecule.py +++ b/qcelemental/models/molecule.py @@ -7,7 +7,7 @@ import warnings from functools import partial from pathlib import Path -from typing import TYPE_CHECKING, cast, Any, Dict, Iterable, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, Union, cast import numpy as np from pydantic import Field, constr, validator @@ -247,10 +247,10 @@ class Molecule(ProtoModel): class Config(ProtoModel.Config): serialize_skip_defaults = True - repr_style = lambda ins: [ - ("name", ins.name), - ("formula", ins.get_molecular_formula()), - ("hash", ins.get_hash()[:7]), + repr_style = lambda self: [ + ("name", self.name), + ("formula", self.get_molecular_formula()), + ("hash", self.get_hash()[:7]), ] fields = { "masses_": "masses", diff --git a/setup.py b/setup.py index b88ce62aa..345fc00e9 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ package_data={'': [os.path.join('qcelemental', 'data', '*.json')]}, setup_requires=[] + pytest_runner, python_requires='>=3.6', - install_requires=['numpy >= 1.12.0', 'pint >= 0.10.0', 'pydantic >= 1.0.0'], + install_requires=["numpy >= 1.12.0", "pint >= 0.10.0", "pydantic >= 1.5.0"], extras_require={ 'docs': [ 'numpydoc', From cb58b4edc64fa653af8592562177a56200ffb654 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 00:15:53 -0500 Subject: [PATCH 04/43] first stab at qcsk/qcel diff --- .github/workflows/QCSchema.yml | 68 ++++++++++++++++++++++++++++++++++ Makefile | 5 +++ 2 files changed, 73 insertions(+) create mode 100644 .github/workflows/QCSchema.yml diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml new file mode 100644 index 000000000..e0b2994cd --- /dev/null +++ b/.github/workflows/QCSchema.yml @@ -0,0 +1,68 @@ +name: QCSchema + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + conda-env: [base] + python-version: [3.7] + env: + PYVER: ${{ matrix.python-version }} + CONDA_ENV: ${{ matrix.conda-env }} + + steps: + - uses: actions/checkout@v1 + + - name: Python Setup + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + + - name: Create Environment + shell: bash + run: | + eval "$(conda shell.bash hook)" && conda activate + python devtools/scripts/create_conda_env.py -n=test -p=$PYVER devtools/conda-envs/$CONDA_ENV.yaml + + - name: Install + shell: bash + run: | + eval "$(conda shell.bash hook)" && conda activate test + python -m pip install . --no-deps + + - name: Environment Information + shell: bash + run: | + eval "$(conda shell.bash hook)" && conda activate test + conda list --show-channel-urls + + - name: QCSchema + shell: bash + run: | + eval "$(conda shell.bash hook)" && conda activate test + make qcschema + cd .. + git clone https://github.com/loriab/QCSchema.git + cd QCSchema + git checkout py2json + cd qcschema_json + ls -l + pwd + cp -p ../../qcschema/* . + git diff + +# - name: CodeCov +# uses: codecov/codecov-action@v1 +# with: +# token: ${{ secrets.CODECOV_TOKEN }} +# file: ./coverage.xml +# flags: unittests +# yml: ./.codecov.yml +# + +##### +# pull_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") +##### diff --git a/Makefile b/Makefile index 2bcb96c1b..6bfdd33c8 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,11 @@ data: cpu_data cpu_data: (cd raw_data/cpu_data; python build_cpu_data.py; mv cpu_data_blob.py ../../qcelemental/info/data/) +.PHONY: qcschema +qcschema: #install + mkdir -p qcschema + echo -e "import qcelemental as qcel\nfrom pathlib import Path\nfor md in [qcel.models.Provenance, qcel.models.AtomicResultProperties]:\n\tmfile = (Path('qcschema') / md.__name__).with_suffix('.json')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=4))" | python + .PHONY: clean clean: rm -rf `find . -name __pycache__` From 23d24cc5ba28b1881cc0e9725026a04990193c77 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 00:26:10 -0500 Subject: [PATCH 05/43] alt py cmd? --- .github/workflows/QCSchema.yml | 1 + Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index e0b2994cd..23950d5b9 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -38,6 +38,7 @@ jobs: run: | eval "$(conda shell.bash hook)" && conda activate test conda list --show-channel-urls + pwd - name: QCSchema shell: bash diff --git a/Makefile b/Makefile index 6bfdd33c8..3b1844cec 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ cpu_data: .PHONY: qcschema qcschema: #install mkdir -p qcschema - echo -e "import qcelemental as qcel\nfrom pathlib import Path\nfor md in [qcel.models.Provenance, qcel.models.AtomicResultProperties]:\n\tmfile = (Path('qcschema') / md.__name__).with_suffix('.json')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=4))" | python + python -c "exec(\"import qcelemental as qcel\nfrom pathlib import Path\nfor md in [qcel.models.Provenance, qcel.models.AtomicResultProperties]:\n\tmfile = (Path('qcschema') / md.__name__).with_suffix('.json')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=4))\")" .PHONY: clean clean: From a3343eb2a4c26656cf5bfca0853df191b6555e0c Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 00:31:53 -0500 Subject: [PATCH 06/43] count directories --- .github/workflows/QCSchema.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 23950d5b9..9007ff9e0 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -45,6 +45,7 @@ jobs: run: | eval "$(conda shell.bash hook)" && conda activate test make qcschema + ls -l qcschema cd .. git clone https://github.com/loriab/QCSchema.git cd QCSchema @@ -52,7 +53,7 @@ jobs: cd qcschema_json ls -l pwd - cp -p ../../qcschema/* . + cp -p ../../QCElemental/qcschema/* . git diff # - name: CodeCov From 04ed4a21d9d2a89c385af36c702e35bbf764c1e1 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 09:42:30 -0500 Subject: [PATCH 07/43] more actions --- .github/workflows/QCSchema.yml | 33 +++++++++++++++++++++++------ qcelemental/models/common_models.py | 2 +- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 9007ff9e0..0bb02954d 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -14,7 +14,19 @@ jobs: CONDA_ENV: ${{ matrix.conda-env }} steps: - - uses: actions/checkout@v1 + - name: Checkout + uses: actions/checkout@v2 + with: + path: qcel + + - name: Checkout schema repo + uses: actions/checkout@v2 + with: + repository: loriab/QCSchema + #repository: MolSSI/QCSchema + path: qcsk + ref: py2json + #ref: master - name: Python Setup uses: actions/setup-python@v1 @@ -39,23 +51,32 @@ jobs: eval "$(conda shell.bash hook)" && conda activate test conda list --show-channel-urls pwd + ls -l - name: QCSchema shell: bash run: | eval "$(conda shell.bash hook)" && conda activate test + pwd + ls -l + cd qcel make qcschema ls -l qcschema cd .. - git clone https://github.com/loriab/QCSchema.git - cd QCSchema - git checkout py2json - cd qcschema_json + #git clone https://github.com/loriab/QCSchema.git + #cd QCSchema + #git checkout py2json + #cd qcschema_json + #ls -l + #pwd + #cp -p ../../QCElemental/qcschema/* . + #git diff + cd qcsk ls -l - pwd cp -p ../../QCElemental/qcschema/* . git diff + # - name: CodeCov # uses: codecov/codecov-action@v1 # with: diff --git a/qcelemental/models/common_models.py b/qcelemental/models/common_models.py index 8c29df68f..ad475409e 100644 --- a/qcelemental/models/common_models.py +++ b/qcelemental/models/common_models.py @@ -20,7 +20,7 @@ class Provenance(ProtoModel): """ creator: str = Field(..., description="The creator of the object.") - version: Optional[str] = Field(None, description="The version of the creator.") + version: Optional[str] = Field(None, description="The version of the creator, which should be sortable by the very broad [PEP 440](https://www.python.org/dev/peps/pep-0440/).") routine: Optional[str] = Field(None, description="The routine of the creator.") class Config(ProtoModel.Config): From e0e1304bdc52c4a69df13690ca7ce1677a855445 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 09:49:05 -0500 Subject: [PATCH 08/43] working-dir --- .github/workflows/QCSchema.yml | 2 ++ qcelemental/models/common_models.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 0bb02954d..3a71a7195 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -35,12 +35,14 @@ jobs: - name: Create Environment shell: bash + working-directory: ./qcel run: | eval "$(conda shell.bash hook)" && conda activate python devtools/scripts/create_conda_env.py -n=test -p=$PYVER devtools/conda-envs/$CONDA_ENV.yaml - name: Install shell: bash + working-directory: ./qcel run: | eval "$(conda shell.bash hook)" && conda activate test python -m pip install . --no-deps diff --git a/qcelemental/models/common_models.py b/qcelemental/models/common_models.py index ad475409e..d52d83470 100644 --- a/qcelemental/models/common_models.py +++ b/qcelemental/models/common_models.py @@ -20,7 +20,10 @@ class Provenance(ProtoModel): """ creator: str = Field(..., description="The creator of the object.") - version: Optional[str] = Field(None, description="The version of the creator, which should be sortable by the very broad [PEP 440](https://www.python.org/dev/peps/pep-0440/).") + version: Optional[str] = Field( + None, + description="The version of the creator, which should be sortable by the very broad [PEP 440](https://www.python.org/dev/peps/pep-0440/).", + ) routine: Optional[str] = Field(None, description="The routine of the creator.") class Config(ProtoModel.Config): From 03ef7495fe41e9cdac19ff9b915d59a0c4ded5d6 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 10:00:46 -0500 Subject: [PATCH 09/43] chdir --- .github/workflows/QCSchema.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 3a71a7195..82645a850 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -64,7 +64,6 @@ jobs: cd qcel make qcschema ls -l qcschema - cd .. #git clone https://github.com/loriab/QCSchema.git #cd QCSchema #git checkout py2json @@ -73,10 +72,12 @@ jobs: #pwd #cp -p ../../QCElemental/qcschema/* . #git diff - cd qcsk + cd ../qcsk/qcschema_json ls -l - cp -p ../../QCElemental/qcschema/* . + cp -p ../../qcel/qcschema/* . git diff + # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, + # rather than the python module of the current repo # - name: CodeCov From 26ce029a7b63c12f676860e88da127107adf9484 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 10:21:32 -0500 Subject: [PATCH 10/43] get PR number --- .github/workflows/QCSchema.yml | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 82645a850..92392468b 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -52,33 +52,30 @@ jobs: run: | eval "$(conda shell.bash hook)" && conda activate test conda list --show-channel-urls - pwd - ls -l - - name: QCSchema + - name: QCSchema from QCElemental shell: bash + working-directory: ./qcel run: | eval "$(conda shell.bash hook)" && conda activate test - pwd - ls -l - cd qcel + #cd qcel make qcschema ls -l qcschema - #git clone https://github.com/loriab/QCSchema.git - #cd QCSchema - #git checkout py2json - #cd qcschema_json - #ls -l - #pwd - #cp -p ../../QCElemental/qcschema/* . + cp -p qcschema/* ../qcsk/qcschema_json/ + #cd ../qcsk/qcschema_json + #cp -p ../../qcel/qcschema/* . #git diff - cd ../qcsk/qcschema_json - ls -l - cp -p ../../qcel/qcschema/* . - git diff # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, # rather than the python module of the current repo + - name ASDF + shell: bash + working-directory: ./qcsk + run: | + git diff + echo ${GITHUB_REF} + pull_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") + echo ${pull_number} # - name: CodeCov # uses: codecov/codecov-action@v1 From 41b971e76481f743764e6e2d5dda305c346481af Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 10:24:19 -0500 Subject: [PATCH 11/43] colon --- .github/workflows/QCSchema.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 92392468b..16c7a2c3e 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -68,7 +68,7 @@ jobs: # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, # rather than the python module of the current repo - - name ASDF + - name: ASDF shell: bash working-directory: ./qcsk run: | From 3c014aea60cf0595a3f53895b3a4e0d6222603c9 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 10:43:29 -0500 Subject: [PATCH 12/43] try a branch --- .github/workflows/QCSchema.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 16c7a2c3e..5836bf1f1 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -58,13 +58,9 @@ jobs: working-directory: ./qcel run: | eval "$(conda shell.bash hook)" && conda activate test - #cd qcel make qcschema ls -l qcschema cp -p qcschema/* ../qcsk/qcschema_json/ - #cd ../qcsk/qcschema_json - #cp -p ../../qcel/qcschema/* . - #git diff # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, # rather than the python module of the current repo @@ -72,10 +68,15 @@ jobs: shell: bash working-directory: ./qcsk run: | - git diff - echo ${GITHUB_REF} + git diff --color-words pull_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") echo ${pull_number} + branch=qcel-${pull_number} + echo ${branch} + git checkout -b ${branch} + git add -A + git commit -m "auto-generated from QCElemental" + git push origin ${branch} # - name: CodeCov # uses: codecov/codecov-action@v1 From 4ae28ef1bba773209420abea2b564b6f40ecb139 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 28 Jan 2020 10:48:34 -0500 Subject: [PATCH 13/43] name --- .github/workflows/QCSchema.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 5836bf1f1..ccbf62be8 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -74,6 +74,9 @@ jobs: branch=qcel-${pull_number} echo ${branch} git checkout -b ${branch} + git remote -v + git config --global user.email "lori.burns@gmail.com" + git config --global user.name "Lori A. Burns" git add -A git commit -m "auto-generated from QCElemental" git push origin ${branch} From 67817e5cd12168ef5c3637a447d7907a25576854 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Sun, 9 Feb 2020 00:25:17 -0500 Subject: [PATCH 14/43] cleanup --- .github/workflows/QCSchema.yml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index ccbf62be8..274a18276 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -1,6 +1,6 @@ name: QCSchema -on: [push, pull_request] +on: [pull_request] jobs: build: @@ -70,9 +70,7 @@ jobs: run: | git diff --color-words pull_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") - echo ${pull_number} branch=qcel-${pull_number} - echo ${branch} git checkout -b ${branch} git remote -v git config --global user.email "lori.burns@gmail.com" @@ -81,15 +79,3 @@ jobs: git commit -m "auto-generated from QCElemental" git push origin ${branch} -# - name: CodeCov -# uses: codecov/codecov-action@v1 -# with: -# token: ${{ secrets.CODECOV_TOKEN }} -# file: ./coverage.xml -# flags: unittests -# yml: ./.codecov.yml -# - -##### -# pull_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") -##### From 703738b9a4cd2beb34745425bbdf7c53225f8a48 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 12:22:47 -0500 Subject: [PATCH 15/43] try a helper action --- .github/workflows/QCSchema.yml | 35 +++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 274a18276..ac69dbae0 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -77,5 +77,38 @@ jobs: git config --global user.name "Lori A. Burns" git add -A git commit -m "auto-generated from QCElemental" - git push origin ${branch} +# git push origin ${branch} + - name: Push changes + uses: ad-m/github-push-action@master + with: + directory: ./qcsk + repository: https://github.com/loriab/QCSchema.git + branch: ${branch} + github_token: ${{ secrets.GITHUB_TOKEN }} + +#github_token string Token for the repo. Can be passed in using ${{ secrets.GITHUB_TOKEN }}. +#branch string 'master' Destination branch to push changes. +#force boolean false Determines if force push is used. +#tags boolean false Determines if --tags is used. +#directory string '.' Directory to change to before pushing. +#repository string '' Repository name. Default or empty repository name represents current github repository. If you want to push to other repository, you should make a personal access token and use it as the github_token input. + + +#jobs: +# build: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@master +# - name: Create local changes +# run: | +# ... +# - name: Commit files +# run: | +# git config --local user.email "action@github.com" +# git config --local user.name "GitHub Action" +# git commit -m "Add changes" -a +# - name: Push changes +# uses: ad-m/github-push-action@master +# with: +# github_token: ${{ secrets.GITHUB_TOKEN }} From db76928db331ad4b18a6ce08822a31ef2e47a493 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 12:33:36 -0500 Subject: [PATCH 16/43] repo name --- .github/workflows/QCSchema.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index ac69dbae0..e4ad35d76 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -83,10 +83,16 @@ jobs: uses: ad-m/github-push-action@master with: directory: ./qcsk - repository: https://github.com/loriab/QCSchema.git - branch: ${branch} + repository: loriab/QCSchema +# branch: ${branch} + branch: "qcel-204" github_token: ${{ secrets.GITHUB_TOKEN }} + +#Push to branch ${branch} +#remote: Not Found +#fatal: repository 'https://github.com/https://github.com/loriab/QCSchema.git.git/' not found + #github_token string Token for the repo. Can be passed in using ${{ secrets.GITHUB_TOKEN }}. #branch string 'master' Destination branch to push changes. #force boolean false Determines if force push is used. From 7bbd7cbfe0b8d94abf1e6c60c7bcb0d18092c508 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 13:01:10 -0500 Subject: [PATCH 17/43] token --- .github/workflows/QCSchema.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index e4ad35d76..41e5c34a5 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -86,7 +86,7 @@ jobs: repository: loriab/QCSchema # branch: ${branch} branch: "qcel-204" - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.QCSK_TOKEN }} #Push to branch ${branch} From cb65f6d2fd458d10ab537add9e702ca1ae0c0111 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 13:15:35 -0500 Subject: [PATCH 18/43] persist --- .github/workflows/QCSchema.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 41e5c34a5..e7804c4a5 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -27,6 +27,8 @@ jobs: path: qcsk ref: py2json #ref: master + persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token + fetch-depth: 0 # otherwise, you will failed to push refs to dest repo - name: Python Setup uses: actions/setup-python@v1 From f6429046be28e48f9f2861280f607448f4b428f2 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 15:20:53 -0500 Subject: [PATCH 19/43] old way --- .github/workflows/QCSchema.yml | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index e7804c4a5..cf63dcaeb 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -79,17 +79,20 @@ jobs: git config --global user.name "Lori A. Burns" git add -A git commit -m "auto-generated from QCElemental" -# git push origin ${branch} + git push origin ${branch} - - name: Push changes - uses: ad-m/github-push-action@master - with: - directory: ./qcsk - repository: loriab/QCSchema -# branch: ${branch} - branch: "qcel-204" - github_token: ${{ secrets.QCSK_TOKEN }} + #- name: Push changes + # uses: ad-m/github-push-action@master + # with: + # directory: ./qcsk + # repository: loriab/QCSchema +# # branch: ${branch} + # branch: "qcel-204" + # github_token: ${{ secrets.QCSK_TOKEN }} + +#remote_repo="https://${GITHUB_ACTOR}:${INPUT_GITHUB_TOKEN}@github.com/${REPOSITORY}.git" +#git push "${remote_repo}" HEAD:${INPUT_BRANCH} --follow-tags $_FORCE_OPTION $_TAGS; #Push to branch ${branch} #remote: Not Found From 219a4e4d76cff74ded2d75739d14ad36876dfb45 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 17:25:01 -0500 Subject: [PATCH 20/43] checkout v1 --- .github/workflows/QCSchema.yml | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index cf63dcaeb..db79b55fc 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -15,12 +15,14 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + #uses: actions/checkout@v2 + uses: actions/checkout@v1 with: path: qcel - name: Checkout schema repo - uses: actions/checkout@v2 + #uses: actions/checkout@v2 + uses: actions/checkout@v1 with: repository: loriab/QCSchema #repository: MolSSI/QCSchema @@ -79,16 +81,25 @@ jobs: git config --global user.name "Lori A. Burns" git add -A git commit -m "auto-generated from QCElemental" - git push origin ${branch} +# git push origin ${branch} - #- name: Push changes - # uses: ad-m/github-push-action@master - # with: - # directory: ./qcsk - # repository: loriab/QCSchema + - name: Push changes + uses: ad-m/github-push-action@master + with: + directory: ./qcsk + repository: loriab/QCSchema # # branch: ${branch} - # branch: "qcel-204" - # github_token: ${{ secrets.QCSK_TOKEN }} + branch: "qcel-204" + github_token: ${{ secrets.QCSK_TOKEN }} + + +# git remote add github "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git" +#git pull github ${GITHUB_REF} --ff-only +# +#git add ... +# +#git commit -m "Update native model" +#git push github HEAD:${GITHUB_REF} #remote_repo="https://${GITHUB_ACTOR}:${INPUT_GITHUB_TOKEN}@github.com/${REPOSITORY}.git" From f658835900e9bef404182b1fae6ade6972a4e83b Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 17:30:48 -0500 Subject: [PATCH 21/43] v1v2 --- .github/workflows/QCSchema.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index db79b55fc..4a690b0a9 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -15,8 +15,7 @@ jobs: steps: - name: Checkout - #uses: actions/checkout@v2 - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: path: qcel From c9e2ca87bc45fe4ae578d35f1b3ea317eade55ef Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 17:45:12 -0500 Subject: [PATCH 22/43] alt token --- .github/workflows/QCSchema.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 4a690b0a9..f369cc23c 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -20,16 +20,16 @@ jobs: path: qcel - name: Checkout schema repo - #uses: actions/checkout@v2 - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: repository: loriab/QCSchema #repository: MolSSI/QCSchema path: qcsk ref: py2json #ref: master - persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token - fetch-depth: 0 # otherwise, you will failed to push refs to dest repo + #persist-credentials: false + fetch-depth: 0 + token: ${{ secrets.QCSK_TOKEN }} - name: Python Setup uses: actions/setup-python@v1 From bd7f02b8f08c211ca7df4bdde9bdc16bee7fd1df Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 2 Mar 2020 18:37:03 -0500 Subject: [PATCH 23/43] from branch --- .github/workflows/QCSchema.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index f369cc23c..beb189bd5 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -1,6 +1,6 @@ name: QCSchema -on: [pull_request] +on: [push, pull_request] jobs: build: @@ -27,9 +27,9 @@ jobs: path: qcsk ref: py2json #ref: master - #persist-credentials: false + persist-credentials: false fetch-depth: 0 - token: ${{ secrets.QCSK_TOKEN }} + #token: ${{ secrets.QCSK_TOKEN }} - name: Python Setup uses: actions/setup-python@v1 @@ -67,7 +67,7 @@ jobs: # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, # rather than the python module of the current repo - - name: ASDF + - name: Generated vs. Stable shell: bash working-directory: ./qcsk run: | From a47e47e89438f54f4bfb1274b2fce52c22df1382 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 3 Mar 2020 03:23:46 -0500 Subject: [PATCH 24/43] var branch --- .github/workflows/QCSchema.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index beb189bd5..13cafd4c5 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -80,18 +80,22 @@ jobs: git config --global user.name "Lori A. Burns" git add -A git commit -m "auto-generated from QCElemental" -# git push origin ${branch} + ::set-env name=branch::${branch} - name: Push changes uses: ad-m/github-push-action@master with: directory: ./qcsk repository: loriab/QCSchema -# # branch: ${branch} - branch: "qcel-204" + branch: ${branch} + #branch: "qcel-204" github_token: ${{ secrets.QCSK_TOKEN }} +#echo "::set-env name=action_state::yellow" + + + # git remote add github "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git" #git pull github ${GITHUB_REF} --ff-only # From 8e1a07fcb325d411f7fb4284136c0ba3a79ba8de Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 3 Mar 2020 03:32:20 -0500 Subject: [PATCH 25/43] echo? --- .github/workflows/QCSchema.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 13cafd4c5..016ee2c86 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -80,7 +80,7 @@ jobs: git config --global user.name "Lori A. Burns" git add -A git commit -m "auto-generated from QCElemental" - ::set-env name=branch::${branch} + echo "::set-env name=branch::${branch}" - name: Push changes uses: ad-m/github-push-action@master From 97ea4c098b92ff92fd367ff83ac725c4d41fd01d Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 3 Mar 2020 03:44:06 -0500 Subject: [PATCH 26/43] alt access --- .github/workflows/QCSchema.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 016ee2c86..a2febcaf1 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -87,7 +87,7 @@ jobs: with: directory: ./qcsk repository: loriab/QCSchema - branch: ${branch} + branch: ${{ env.branch }} #branch: "qcel-204" github_token: ${{ secrets.QCSK_TOKEN }} From aee7aeaada7bde85bccf072c1e9162918a26b805 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 3 Mar 2020 03:49:11 -0500 Subject: [PATCH 27/43] pr only --- .github/workflows/QCSchema.yml | 34 +++------------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index a2febcaf1..127643c02 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -1,6 +1,6 @@ name: QCSchema -on: [push, pull_request] +on: [pull_request] jobs: build: @@ -29,7 +29,6 @@ jobs: #ref: master persist-credentials: false fetch-depth: 0 - #token: ${{ secrets.QCSK_TOKEN }} - name: Python Setup uses: actions/setup-python@v1 @@ -76,8 +75,8 @@ jobs: branch=qcel-${pull_number} git checkout -b ${branch} git remote -v - git config --global user.email "lori.burns@gmail.com" - git config --global user.name "Lori A. Burns" + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" git add -A git commit -m "auto-generated from QCElemental" echo "::set-env name=branch::${branch}" @@ -88,36 +87,9 @@ jobs: directory: ./qcsk repository: loriab/QCSchema branch: ${{ env.branch }} - #branch: "qcel-204" github_token: ${{ secrets.QCSK_TOKEN }} -#echo "::set-env name=action_state::yellow" - - - -# git remote add github "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git" -#git pull github ${GITHUB_REF} --ff-only -# -#git add ... -# -#git commit -m "Update native model" -#git push github HEAD:${GITHUB_REF} - -#remote_repo="https://${GITHUB_ACTOR}:${INPUT_GITHUB_TOKEN}@github.com/${REPOSITORY}.git" - -#git push "${remote_repo}" HEAD:${INPUT_BRANCH} --follow-tags $_FORCE_OPTION $_TAGS; - -#Push to branch ${branch} -#remote: Not Found -#fatal: repository 'https://github.com/https://github.com/loriab/QCSchema.git.git/' not found - -#github_token string Token for the repo. Can be passed in using ${{ secrets.GITHUB_TOKEN }}. -#branch string 'master' Destination branch to push changes. -#force boolean false Determines if force push is used. -#tags boolean false Determines if --tags is used. -#directory string '.' Directory to change to before pushing. -#repository string '' Repository name. Default or empty repository name represents current github repository. If you want to push to other repository, you should make a personal access token and use it as the github_token input. #jobs: From 73855fef39e641dd6c0e75155ebad6da99b0e1ab Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 3 Mar 2020 11:55:56 -0500 Subject: [PATCH 28/43] define qcsk models --- Makefile | 2 +- qcelemental/models/__init__.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3b1844cec..a60f7740e 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ cpu_data: .PHONY: qcschema qcschema: #install mkdir -p qcschema - python -c "exec(\"import qcelemental as qcel\nfrom pathlib import Path\nfor md in [qcel.models.Provenance, qcel.models.AtomicResultProperties]:\n\tmfile = (Path('qcschema') / md.__name__).with_suffix('.json')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=4))\")" + python -c "exec(\"import qcelemental as qcel\nfrom pathlib import Path\nfor md in qcel.models.qcschema_models():\n\tmfile = (Path('qcschema') / md.__name__).with_suffix('.json')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=4))\")" .PHONY: clean clean: diff --git a/qcelemental/models/__init__.py b/qcelemental/models/__init__.py index fe1420d98..ca3399dfc 100644 --- a/qcelemental/models/__init__.py +++ b/qcelemental/models/__init__.py @@ -20,6 +20,7 @@ def qcschema_models(): return [ AtomicInput, AtomicResult, + AtomicResultProperties, BasisSet, Molecule, Provenance, From 12f3ebe4e23a1d6b561fe7c54b6f84ecd259f8cb Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 3 Mar 2020 12:00:33 -0500 Subject: [PATCH 29/43] clean gha --- .github/workflows/QCSchema.yml | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 127643c02..0c9c21ca7 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -66,7 +66,7 @@ jobs: # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, # rather than the python module of the current repo - - name: Generated vs. Stable + - name: Compare Schemas (generated vs. community) shell: bash working-directory: ./qcsk run: | @@ -79,33 +79,13 @@ jobs: git config --local user.name "GitHub Action" git add -A git commit -m "auto-generated from QCElemental" - echo "::set-env name=branch::${branch}" + echo "::set-env name=prbranch::${branch}" - - name: Push changes + - name: Propose changes uses: ad-m/github-push-action@master with: directory: ./qcsk repository: loriab/QCSchema - branch: ${{ env.branch }} + #repository: MolSSI/QCSchema + branch: ${{ env.prbranch }} github_token: ${{ secrets.QCSK_TOKEN }} - - - - -#jobs: -# build: -# runs-on: ubuntu-latest -# steps: -# - uses: actions/checkout@master -# - name: Create local changes -# run: | -# ... -# - name: Commit files -# run: | -# git config --local user.email "action@github.com" -# git config --local user.name "GitHub Action" -# git commit -m "Add changes" -a -# - name: Push changes -# uses: ad-m/github-push-action@master -# with: -# github_token: ${{ secrets.GITHUB_TOKEN }} From a9537c46cc2e531c88871168b4ab2d7541801402 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Tue, 3 Mar 2020 16:46:18 -0500 Subject: [PATCH 30/43] adapt to more schema --- .github/workflows/QCSchema.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 0c9c21ca7..434057082 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -25,7 +25,8 @@ jobs: repository: loriab/QCSchema #repository: MolSSI/QCSchema path: qcsk - ref: py2json + #ref: py2json + ref: json_files #ref: master persist-credentials: false fetch-depth: 0 @@ -62,7 +63,8 @@ jobs: eval "$(conda shell.bash hook)" && conda activate test make qcschema ls -l qcschema - cp -p qcschema/* ../qcsk/qcschema_json/ + #cp -p qcschema/* ../qcsk/qcschema_json/ + cp -p qcschema/* ../qcsk/qcschema/ # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, # rather than the python module of the current repo @@ -89,3 +91,4 @@ jobs: #repository: MolSSI/QCSchema branch: ${{ env.prbranch }} github_token: ${{ secrets.QCSK_TOKEN }} + force: true From 8d19d794dc0e7037b8400cc1946a49348d2284e5 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Sat, 29 Aug 2020 23:50:58 -0400 Subject: [PATCH 31/43] reconcile qcsk and qcel models, test gen schema, generate schema --- .github/workflows/CI.yml | 1 + .gitignore | 4 + Makefile | 5 +- qcelemental/conftest.py | 29 +++ qcelemental/models/__init__.py | 6 +- qcelemental/models/basemodels.py | 13 ++ qcelemental/models/basis.py | 76 +++++-- qcelemental/models/common_models.py | 42 ++-- qcelemental/models/molecule.py | 95 ++++++--- qcelemental/models/results.py | 189 ++++++++++++++---- qcelemental/molutil/test_molutil.py | 11 +- qcelemental/tests/addons.py | 19 ++ .../qcschema_instances/AtomicInput/dummy | 0 .../qcschema_instances/AtomicResult/dummy | 0 .../AtomicResultProperties/dummy | 0 .../tests/qcschema_instances/BasisSet/dummy | 0 .../tests/qcschema_instances/Molecule/dummy | 0 .../tests/qcschema_instances/Provenance/dummy | 0 .../tests/qcschema_instances/README.md | 3 + qcelemental/tests/test_model_general.py | 11 +- qcelemental/tests/test_model_results.py | 42 ++-- .../tests/test_molparse_from_schema.py | 5 +- qcelemental/tests/test_molparse_to_schema.py | 27 ++- qcelemental/tests/test_molparse_to_string.py | 5 +- qcelemental/tests/test_zqcschema.py | 35 ++++ 25 files changed, 485 insertions(+), 133 deletions(-) create mode 100644 qcelemental/conftest.py create mode 100644 qcelemental/tests/qcschema_instances/AtomicInput/dummy create mode 100644 qcelemental/tests/qcschema_instances/AtomicResult/dummy create mode 100644 qcelemental/tests/qcschema_instances/AtomicResultProperties/dummy create mode 100644 qcelemental/tests/qcschema_instances/BasisSet/dummy create mode 100644 qcelemental/tests/qcschema_instances/Molecule/dummy create mode 100644 qcelemental/tests/qcschema_instances/Provenance/dummy create mode 100644 qcelemental/tests/qcschema_instances/README.md create mode 100644 qcelemental/tests/test_zqcschema.py diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d6f1f0ff7..5af74f36b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -53,6 +53,7 @@ jobs: run: | eval "$(conda shell.bash hook)" && conda activate test pytest -rws -v --cov=qcelemental --color=yes --cov-report=xml qcelemental/ + pytest -rws -v qcelemental/ --validate - name: CodeCov uses: codecov/codecov-action@v1 diff --git a/.gitignore b/.gitignore index 666c74672..45f83e57e 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,7 @@ runinfo/* # VSCode .vscode/ raw_data/**/*_blob.py + +# autogen +qcschema/*.schema +qcelemental/tests/qcschema_instances/*/*.json diff --git a/Makefile b/Makefile index a60f7740e..46289e185 100644 --- a/Makefile +++ b/Makefile @@ -44,9 +44,10 @@ cpu_data: (cd raw_data/cpu_data; python build_cpu_data.py; mv cpu_data_blob.py ../../qcelemental/info/data/) .PHONY: qcschema -qcschema: #install +qcschema: mkdir -p qcschema - python -c "exec(\"import qcelemental as qcel\nfrom pathlib import Path\nfor md in qcel.models.qcschema_models():\n\tmfile = (Path('qcschema') / md.__name__).with_suffix('.json')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=4))\")" + python -c "exec(\"import pathlib, qcelemental\nfor md in qcelemental.models.qcschema_models():\n\tmfile = (pathlib.Path('qcschema') / md.__name__).with_suffix('.schema')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=4))\")" + python -c "exec(\"import json, pathlib, pydantic, qcelemental\nwith open((pathlib.Path('qcschema') / 'QCSchema').with_suffix('.schema'), 'w') as fp:\n\tjson.dump(pydantic.schema.schema(qcelemental.models.qcschema_models(), title='QCSchema'), fp, indent=4)\")" .PHONY: clean clean: diff --git a/qcelemental/conftest.py b/qcelemental/conftest.py new file mode 100644 index 000000000..67fb4a5b6 --- /dev/null +++ b/qcelemental/conftest.py @@ -0,0 +1,29 @@ +from pathlib import Path + +import pytest + + +def pytest_addoption(parser): + parser.addoption( + "--validate", action="store_true", help="validate JSON from previous test run against exported schema" + ) + + +@pytest.fixture(scope="session", autouse=True) +def set_up_overall(request): + # in all pytest runs except --validate (which uses the files), clear away the JSON examples and generate fresh + if not request.config.getoption("--validate", default=False): + _data_path = Path(__file__).parent.resolve() / "tests" / "qcschema_instances" + for fl in _data_path.rglob("*.json"): + fl.unlink() + + +def pytest_runtest_setup(item): + # there's a bug where can only set options if specify path in call, so needs to be ``pytest qcelemental/ --validate`` + + # skip the validate-generated-instances-against-exported-schema tests on most ``pytest`` runs. + # run only the validate-generated-instances-against-exported-schema tests on ``pytest --validate`` runs. + if not item.config.getoption("--validate", default=False) and item.name.startswith("test_qcschema"): + pytest.skip("can't run with --validate option") + elif item.config.getoption("--validate", default=False) and not item.name.startswith("test_qcschema"): + pytest.skip("need --validate option to run") diff --git a/qcelemental/models/__init__.py b/qcelemental/models/__init__.py index ca3399dfc..4a69f39a6 100644 --- a/qcelemental/models/__init__.py +++ b/qcelemental/models/__init__.py @@ -12,8 +12,10 @@ from .basis import BasisSet from .common_models import ComputeError, DriverEnum, FailedOperation, Provenance from .molecule import Molecule -from .procedures import Optimization, OptimizationInput, OptimizationResult -from .results import AtomicInput, AtomicResult, AtomicResultProperties, Result, ResultInput, ResultProperties +from .procedures import OptimizationInput, OptimizationResult +from .procedures import Optimization # scheduled for removal +from .results import AtomicInput, AtomicResult, AtomicResultProperties +from .results import Result, ResultInput, ResultProperties # scheduled for removal def qcschema_models(): diff --git a/qcelemental/models/basemodels.py b/qcelemental/models/basemodels.py index eb99a8451..1cd4328d6 100644 --- a/qcelemental/models/basemodels.py +++ b/qcelemental/models/basemodels.py @@ -125,6 +125,8 @@ def serialize( include: Optional[Set[str]] = None, exclude: Optional[Set[str]] = None, exclude_unset: Optional[bool] = None, + exclude_defaults: Optional[bool] = None, + exclude_none: Optional[bool] = None, ) -> Union[bytes, str]: """Generates a serialized representation of the model @@ -138,6 +140,10 @@ def serialize( Fields to be excluded in the serialization. exclude_unset : Optional[bool], optional If True, skips fields that have default values provided. + exclude_defaults: Optional[bool], optional + If True, skips fields that have set or defaulted values equal to the default. + exclude_none: Optional[bool], optional + If True, skips fields that have value ``None``. Returns ------- @@ -152,6 +158,10 @@ def serialize( kwargs["exclude"] = exclude if exclude_unset: kwargs["exclude_unset"] = exclude_unset + if exclude_defaults: + kwargs["exclude_defaults"] = exclude_defaults + if exclude_none: + kwargs["exclude_none"] = exclude_none data = self.dict(**kwargs) @@ -182,3 +192,6 @@ def compare(self, other: Union["ProtoModel", BaseModel], **kwargs) -> bool: class AutodocBaseSettings(BaseSettings): def __init_subclass__(cls) -> None: cls.__doc__ = AutoPydanticDocGenerator(cls, always_apply=True) + + +qcschema_draft = "http://json-schema.org/draft-04/schema#" diff --git a/qcelemental/models/basis.py b/qcelemental/models/basis.py index 7621cf6a8..528085ea8 100644 --- a/qcelemental/models/basis.py +++ b/qcelemental/models/basis.py @@ -1,10 +1,14 @@ from enum import Enum from typing import Dict, List, Optional -from pydantic import Field, constr, validator +from pydantic import ConstrainedInt, Field, constr, validator from ..exceptions import ValidationError -from .basemodels import ProtoModel +from .basemodels import ProtoModel, qcschema_draft + + +class NonnegativeInt(ConstrainedInt): + ge = 0 class HarmonicType(str, Enum): @@ -21,14 +25,26 @@ class ElectronShell(ProtoModel): Information for a single electronic shell """ - angular_momentum: List[int] = Field(..., description="Angular momentum for this shell.") + angular_momentum: List[NonnegativeInt] = Field( + ..., description="Angular momentum for the shell as an array of integers.", min_items=1 + ) + # function_type: FunctionType = Field(..., description=str(FunctionType.__doc__)) + # region: Region = Field(None, description=str(Region.__doc__)) harmonic_type: HarmonicType = Field(..., description=str(HarmonicType.__doc__)) - exponents: List[float] = Field(..., description="Exponents for this contracted shell.") + exponents: List[float] = Field(..., description="Exponents for the contracted shell.", min_items=1) coefficients: List[List[float]] = Field( ..., - description="General contraction coefficients for this shell, individual list components will be the individual segment contraction coefficients.", + description="General contraction coefficients for the shell, individual list components will be the individual segment contraction coefficients.", + min_items=1, ) + class Config(ProtoModel.Config): + def schema_extra(schema, model): + # edit to allow string storage of basis sets as BSE uses. alternately, could `Union[float, str]` above but that loses some validation + schema["properties"]["exponents"]["items"] = {"anyOf": [{"type": "number"}, {"type": "string"}]} + schema["properties"]["coefficients"]["items"]["items"] = {"anyOf": [{"type": "number"}, {"type": "string"}]} + schema["properties"]["angular_momentum"].update({"uniqueItems": True}) + @validator("coefficients") def _check_coefficient_length(cls, v, values): len_exp = len(values["exponents"]) @@ -89,14 +105,24 @@ class ECPPotential(ProtoModel): """ ecp_type: ECPType = Field(..., description=str(ECPType.__doc__)) - angular_momentum: List[int] = Field(..., description="Angular momentum for the ECPs.") - r_exponents: List[int] = Field(..., description="Exponents of the 'r' term.") - gaussian_exponents: List[float] = Field(..., description="Exponents of the 'gaussian' term.") + angular_momentum: List[NonnegativeInt] = Field( + ..., description="Angular momentum for the potential as an array of integers.", min_items=1 + ) + r_exponents: List[int] = Field(..., description="Exponents of the 'r' term.", min_items=1) + gaussian_exponents: List[float] = Field(..., description="Exponents of the 'gaussian' term.", min_items=1) coefficients: List[List[float]] = Field( ..., - description="General contraction coefficients for this shell, individual list components will be the individual segment contraction coefficients.", + description="General contraction coefficients for the potential, individual list components will be the individual segment contraction coefficients.", + min_items=1, ) + class Config(ProtoModel.Config): + def schema_extra(schema, model): + # edit to allow string storage of basis sets as BSE uses. alternately, could `Union[float, str]` above but that loses some validation + schema["properties"]["gaussian_exponents"]["items"] = {"anyOf": [{"type": "number"}, {"type": "string"}]} + schema["properties"]["coefficients"]["items"]["items"] = {"anyOf": [{"type": "number"}, {"type": "string"}]} + schema["properties"]["angular_momentum"].update({"uniqueItems": True}) + @validator("gaussian_exponents") def _check_gaussian_exponents_length(cls, v, values): len_exp = len(values["r_exponents"]) @@ -120,9 +146,16 @@ class BasisCenter(ProtoModel): Data for a single atom/center in a basis set. """ - electron_shells: List[ElectronShell] = Field(..., description="Electronic shells for this center.") - ecp_electrons: int = Field(0, description="Number of electrons replace by ECP potentials.") - ecp_potentials: Optional[List[ECPPotential]] = Field(None, description="ECPs for this center.") + electron_shells: List[ElectronShell] = Field(..., description="Electronic shells for this center.", min_items=1) + ecp_electrons: int = Field(0, description="Number of electrons replaced by ECP, MCP, or other field potentials.") + ecp_potentials: Optional[List[ECPPotential]] = Field( + None, description="ECPs, MCPs, or other field potentials for this center.", min_items=1 + ) + + class Config(ProtoModel.Config): + def schema_extra(schema, model): + schema["properties"]["electron_shells"].update({"uniqueItems": True}) + schema["properties"]["ecp_potentials"].update({"uniqueItems": True}) class BasisSet(ProtoModel): @@ -130,18 +163,29 @@ class BasisSet(ProtoModel): A quantum chemistry basis description. """ - schema_name: constr(strip_whitespace=True, regex="qcschema_basis") = "qcschema_basis" # type: ignore - schema_version: int = 1 + schema_name: constr(strip_whitespace=True, regex="^(qcschema_basis)$") = Field( # type: ignore + "qcschema_basis", + description=(f"The QCSchema specification to which this model conforms. Explicitly fixed as qcschema_basis."), + ) + schema_version: int = Field( # type: ignore + 1, description="The version number of ``schema_name`` to which this model conforms." + ) name: str = Field(..., description="A standard basis name if available (e.g., 'cc-pVDZ').") description: Optional[str] = Field(None, description="A brief description of the basis set.") - center_data: Dict[str, BasisCenter] = Field(..., description="A mapping of all types of centers available.") + center_data: Dict[str, BasisCenter] = Field( + ..., description="Shared basis data for all atoms/centers in the parent molecule" + ) atom_map: List[str] = Field( - ..., description="Mapping of all centers in the parent molecule to centers in `center_data`." + ..., description="Mapping of all atoms/centers in the parent molecule to centers in `center_data`." ) nbf: Optional[int] = Field(None, description="The number of basis functions.") + class Config(ProtoModel.Config): + def schema_extra(schema, model): + schema["$schema"] = qcschema_draft + @validator("atom_map") def _check_atom_map(cls, v, values): sv = set(v) diff --git a/qcelemental/models/common_models.py b/qcelemental/models/common_models.py index d52d83470..eb9b3c36a 100644 --- a/qcelemental/models/common_models.py +++ b/qcelemental/models/common_models.py @@ -1,10 +1,11 @@ from enum import Enum -from typing import TYPE_CHECKING, Any, Dict, Optional +from typing import TYPE_CHECKING, Any, Dict, Optional, Union import numpy as np from pydantic import Field -from .basemodels import ProtoModel +from .basemodels import ProtoModel, qcschema_draft +from .basis import BasisSet if TYPE_CHECKING: from pydantic.typing import ReprArgs @@ -19,41 +20,50 @@ class Provenance(ProtoModel): Provenance information. """ - creator: str = Field(..., description="The creator of the object.") - version: Optional[str] = Field( - None, - description="The version of the creator, which should be sortable by the very broad [PEP 440](https://www.python.org/dev/peps/pep-0440/).", + # compared to qcsk v2: + # this has defaults for version & routine, and those aren't required. + # this doesn't explicitly set `additionalProperties = True` + + creator: str = Field(..., description="The name of the program, library, or person who created the object.") + version: str = Field( + "", + description="The version of the creator, blank otherwise. This should be sortable by the very broad [PEP 440](https://www.python.org/dev/peps/pep-0440/).", ) - routine: Optional[str] = Field(None, description="The routine of the creator.") + routine: str = Field("", description="The name of the routine or function within the creator, blank otherwise.") class Config(ProtoModel.Config): canonical_repr = True - extra = "allow" + extra: str = "allow" + + def schema_extra(schema, model): + schema["$schema"] = qcschema_draft class Model(ProtoModel): """ - The quantum chemistry model specification for a given operation to compute against + The computational molecular sciences model to run. """ method: str = Field( # type: ignore - ..., description="The quantum chemistry method to evaluate (e.g., B3LYP, PBE, ...)." + ..., + description="The quantum chemistry method to evaluate (e.g., B3LYP, PBE, ...). " + "For MM, name of the force field.", ) - basis: Optional[str] = Field( # type: ignore + basis: Optional[Union[str, BasisSet]] = Field( # type: ignore None, description="The quantum chemistry basis set to evaluate (e.g., 6-31g, cc-pVDZ, ...). Can be ``None`` for " - "methods without basis sets.", + "methods without basis sets. For molecular mechanics, name of the atom-typer.", ) # basis_spec: BasisSpec = None # This should be exclusive with basis, but for now will be omitted class Config(ProtoModel.Config): canonical_repr = True - extra = "allow" + extra: str = "allow" class DriverEnum(str, Enum): - """Allowed quantum chemistry driver values. + """Allowed computation driver values. """ energy = "energy" @@ -74,7 +84,7 @@ class ComputeError(ProtoModel): error_type: str = Field( # type: ignore ..., # Error enumeration not yet strict - description="The type of error which was thrown. Restrict this field short classifiers e.g. 'input_error'.", + description="The type of error which was thrown. Restrict this field to short classifiers e.g. 'input_error'. Suggested classifiers: https://github.com/MolSSI/QCEngine/blob/master/qcengine/exceptions.py", ) error_message: str = Field( # type: ignore ..., @@ -82,7 +92,7 @@ class ComputeError(ProtoModel): "information as well.", ) extras: Optional[Dict[str, Any]] = Field( # type: ignore - None, description="Additional data to ship with the ComputeError object." + None, description="Additional data to ship with the error object." ) class Config: diff --git a/qcelemental/models/molecule.py b/qcelemental/models/molecule.py index a22c78f4e..5bd38ae1c 100644 --- a/qcelemental/models/molecule.py +++ b/qcelemental/models/molecule.py @@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, Union, cast import numpy as np -from pydantic import Field, constr, validator +from pydantic import ConstrainedFloat, ConstrainedInt, Field, constr, validator # molparse imports separated b/c https://github.com/python/mypy/issues/7203 from ..molparse.from_arrays import from_arrays @@ -22,7 +22,7 @@ from ..physical_constants import constants from ..testing import compare, compare_values from ..util import deserialize, measure_coordinates, msgpackext_loads, provenance_stamp, which_import -from .basemodels import ProtoModel +from .basemodels import ProtoModel, qcschema_draft from .common_models import Provenance, qcschema_molecule_default from .types import Array @@ -64,6 +64,15 @@ def float_prep(array, around): return array +class NonnegativeInt(ConstrainedInt): + ge = 0 + + +class BondOrderFloat(ConstrainedFloat): + ge = 0 + le = 5 + + class Identifiers(ProtoModel): """Canonical chemical identifiers""" @@ -87,20 +96,22 @@ class Config(ProtoModel.Config): class Molecule(ProtoModel): """ + The physical Cartesian representation of the molecular system. + A QCSchema representation of a Molecule. This model contains data for symbols, geometry, connectivity, charges, fragmentation, etc while also supporting a wide array of I/O and manipulation capabilities. Molecule objects geometry, masses, and charges are truncated to 8, 6, and 4 decimal places respectively to assist with duplicate detection. """ - schema_name: constr(strip_whitespace=True, regex=qcschema_molecule_default) = Field( # type: ignore + schema_name: constr(strip_whitespace=True, regex="^(qcschema_molecule)$") = Field( # type: ignore qcschema_molecule_default, description=( - f"The QCSchema specification this model conforms to. Explicitly fixed as " f"{qcschema_molecule_default}." + f"The QCSchema specification to which this model conforms. Explicitly fixed as {qcschema_molecule_default}." ), ) schema_version: int = Field( # type: ignore - 2, description="The version number of ``schema_name`` that this Molecule model conforms to." + 2, description="The version number of ``schema_name`` to which this model conforms." ) validated: bool = Field( # type: ignore False, @@ -114,10 +125,11 @@ class Molecule(ProtoModel): # Required data symbols: Array[str] = Field( # type: ignore ..., - description="An ordered (nat,) array-like object of atomic elemental symbols of shape (nat,). The index of " - "this attribute sets atomic order for all other per-atom setting like ``real`` and the first " - "dimension of ``geometry``. Ghost/Virtual atoms must have an entry in this array-like and are " - "indicated by the matching the 0-indexed indices in ``real`` field.", + description="An ordered (nat,) array-like object of atomic elemental symbols in title case. The index of " + "this attribute sets atomic order for all other per-atom fields like ``real`` and the first " + "dimension of ``geometry``. Ghost/Virtual atoms must have an entry here in ``symbols``; ghostedness is " + "indicated through the ``real`` field.", + shape=["nat"], ) geometry: Array[float] = Field( # type: ignore ..., @@ -127,9 +139,11 @@ class Molecule(ProtoModel): "(e.g., gradient). Index of the first dimension matches the 0-indexed indices of all other " "per-atom settings like ``symbols`` and ``real``." "\n" - "Can also accept array-likes which can be mapped to (nat,3) such as a 1-D list of length 3*nat, " + "Serialized storage is always flat, (3*nat,), but QCSchema implementations will want to reshape it. " + "QCElemental can also accept array-likes which can be mapped to (nat,3) such as a 1-D list of length 3*nat, " "or the serialized version of the array in (3*nat,) shape; all forms will be reshaped to " "(nat,3) for this attribute.", + shape=["nat", 3], ) # Molecule data @@ -143,19 +157,20 @@ class Molecule(ProtoModel): ) comment: Optional[str] = Field( # type: ignore None, - description="Additional comments for this Molecule. Intended for pure human/user consumption " "and clarity.", + description="Additional comments for this Molecule. Intended for pure human/user consumption and clarity.", ) - molecular_charge: float = Field(0.0, description="The net electrostatic charge of this Molecule.") # type: ignore - molecular_multiplicity: int = Field(1, description="The total multiplicity of this Molecule.") # type: ignore + molecular_charge: float = Field(0.0, description="The net electrostatic charge of the Molecule.") # type: ignore + molecular_multiplicity: int = Field(1, description="The total multiplicity of the Molecule.") # type: ignore # Atom data masses_: Optional[Array[float]] = Field( # type: ignore None, description="An ordered 1-D array-like object of atomic masses [u] of shape (nat,). Index order " - "matches the 0-indexed indices of all other per-atom settings like ``symbols`` and ``real``. If " + "matches the 0-indexed indices of all other per-atom fields like ``symbols`` and ``real``. If " "this is not provided, the mass of each atom is inferred from their most common isotope. If this " "is provided, it must be the same length as ``symbols`` but can accept ``None`` entries for " "standard masses to infer from the same index in the ``symbols`` field.", + shape=["nat"], ) real_: Optional[Array[bool]] = Field( # type: ignore None, @@ -163,68 +178,84 @@ class Molecule(ProtoModel): "ghost/virtual (``False``). Index " "matches the 0-indexed indices of all other per-atom settings like ``symbols`` and the first " "dimension of ``geometry``. If this is not provided, all atoms are assumed to be real (``True``)." - "If this is provided, the reality or ghostality of every atom must be specified.", + "If this is provided, the reality or ghostedness of every atom must be specified.", + shape=["nat"], ) atom_labels_: Optional[Array[str]] = Field( # type: ignore None, description="Additional per-atom labels as a 1-D array-like of of strings of shape (nat,). Typical use is in " "model conversions, such as Elemental <-> Molpro and not typically something which should be user " "assigned. See the ``comments`` field for general human-consumable text to affix to the Molecule.", + shape=["nat"], ) atomic_numbers_: Optional[Array[np.int16]] = Field( # type: ignore None, description="An optional ordered 1-D array-like object of atomic numbers of shape (nat,). Index " "matches the 0-indexed indices of all other per-atom settings like ``symbols`` and ``real``. " - "Values are inferred from the ``symbols`` list if not explicitly set.", + "Values are inferred from the ``symbols`` list if not explicitly set. " + "Ghostedness should be indicated through ``real`` field, not zeros here.", + shape=["nat"], ) mass_numbers_: Optional[Array[np.int16]] = Field( # type: ignore None, description="An optional ordered 1-D array-like object of atomic *mass* numbers of shape (nat). Index " "matches the 0-indexed indices of all other per-atom settings like ``symbols`` and ``real``. " - "Values are inferred from the most common isotopes of the ``symbols`` list if not explicitly set.", + "Values are inferred from the most common isotopes of the ``symbols`` list if not explicitly set. " + "If single isotope not (yet) known for an atom, -1 is placeholder.", + shape=["nat"], ) # Fragment and connection data - connectivity_: Optional[List[Tuple[int, int, float]]] = Field( # type: ignore + connectivity_: Optional[List[Tuple[NonnegativeInt, NonnegativeInt, BondOrderFloat]]] = Field( # type: ignore None, - description="The connectivity information between each atom in the ``symbols`` array. Each entry in this " - "list is a Tuple of ``(atom_index_A, atom_index_B, bond_order)`` where the ``atom_index`` " - "matches the 0-indexed indices of all other per-atom settings like ``symbols`` and ``real``.", + description="A list of bonds within the molecule. Each entry is a tuple " + "of ``(atom_index_A, atom_index_B, bond_order)`` where the ``atom_index`` " + "matches the 0-indexed indices of all other per-atom settings like ``symbols`` and ``real``. " + "Bonds may be freely reordered and inverted.", + min_items=1, ) fragments_: Optional[List[Array[np.int32]]] = Field( # type: ignore None, - description="An indication of which sets of atoms are fragments within the Molecule. This is a list of shape " + description="List of indices grouping atoms (0-indexed) into molecular fragments within the Molecule. This is a list of shape " "(nfr) of 1-D array-like objects of arbitrary length. Each entry in the list indicates a new " "fragment. The index " "of the list matches the 0-indexed indices of ``fragment_charges`` and " "``fragment_multiplicities``. The 1-D array-like objects are sets of atom indices indicating the " "atoms which compose the fragment. The atom indices match the 0-indexed indices of all other " - "per-atom settings like ``symbols`` and ``real``.", + "per-atom settings like ``symbols`` and ``real``. " + "Fragment ordering is fixed; that is, a consumer who shuffles fragments must not reattach the input (pre-shuffling) molecule schema instance to any output (post-shuffling) per-fragment results (e.g., n-body energy arrays).", + shape=["nfr", ""], ) fragment_charges_: Optional[List[float]] = Field( # type: ignore None, description="The total charge of each fragment in the ``fragments`` list of shape (nfr,). The index of this " - "list matches the 0-index indices of ``fragment`` list. Will be filled in based on a set of rules " + "list matches the 0-index indices of ``fragments`` list. Will be filled in based on a set of rules " "if not provided (and ``fragments`` are specified).", + shape=["nfr"], ) fragment_multiplicities_: Optional[List[int]] = Field( # type: ignore None, description="The multiplicity of each fragment in the ``fragments`` list of shape (nfr,). The index of this " - "list matches the 0-index indices of ``fragment`` list. Will be filled in based on a set of " + "list matches the 0-index indices of ``fragments`` list. Will be filled in based on a set of " "rules if not provided (and ``fragments`` are specified).", + shape=["nfr"], ) # Orientation fix_com: bool = Field( # type: ignore False, - description="An indicator which prevents pre-processing the Molecule object to translate the Center-of-Mass " - "to (0,0,0) in euclidean coordinate space. Will result in a different ``geometry`` than the " - "one provided if False.", + description="Whether translation of geometry is allowed (fix F) or disallowed (fix T)." + "When False, QCElemental will pre-process the Molecule object to translate the center of mass " + "to (0,0,0) in Euclidean coordinate space, resulting in a different ``geometry`` than the " + "one provided. " + "guidance: A consumer who translates the geometry must not reattach the input (pre-translation) molecule schema instance to any output (post-translation) origin-sensitive results (e.g., an ordinary energy when EFP present).", ) fix_orientation: bool = Field( # type: ignore False, - description="An indicator which prevents pre-processes the Molecule object to orient via the inertia tensor." - "Will result in a different ``geometry`` than the one provided if False.", + description="Whether rotation of geometry is allowed (fix F) or disallowed (fix T). " + "When False, QCElemental will pre-process the Molecule object to orient via the intertial tensor, " + "resulting in a different ``geometry`` than the one provided. " + "guidance: A consumer who rotates the geometry must not reattach the input (pre-rotation) molecule schema instance to any output (post-rotation) frame-sensitive results (e.g., molecular vibrations).", ) fix_symmetry: Optional[str] = Field( # type: ignore None, description="Maximal point group symmetry which ``geometry`` should be treated. Lowercase." @@ -264,6 +295,10 @@ class Config(ProtoModel.Config): "fragment_multiplicities_": "fragment_multiplicities", } + def schema_extra(schema, model): + # below addresses the draft-04 issue until https://github.com/samuelcolvin/pydantic/issues/1478 . + schema["$schema"] = qcschema_draft + def __init__(self, orient: bool = False, validate: Optional[bool] = None, **kwargs: Any) -> None: """Initializes the molecule object from dictionary-like values. diff --git a/qcelemental/models/results.py b/qcelemental/models/results.py index ca4398954..fd6b089a8 100644 --- a/qcelemental/models/results.py +++ b/qcelemental/models/results.py @@ -6,7 +6,7 @@ from pydantic import Field, constr, validator from ..util import provenance_stamp -from .basemodels import ProtoModel +from .basemodels import ProtoModel, qcschema_draft from .basis import BasisSet from .common_models import ComputeError, DriverEnum, Model, Provenance, qcschema_input_default, qcschema_output_default from .molecule import Molecule @@ -51,7 +51,7 @@ class AtomicResultProperties(ProtoModel): None, description="The dispersion correction appended to an underlying functional when a DFT-D method is requested.", ) - scf_dipole_moment: Optional[Array[float]] = Field(None, description="The X, Y, and Z dipole components.") + scf_dipole_moment: Optional[Array[float]] = Field(None, description="The SCF X, Y, and Z dipole components.") scf_quadrupole_moment: Optional[Array[float]] = Field( None, description="The (3, 3) quadrupole components (redundant; 6 unique)." ) @@ -62,11 +62,12 @@ class AtomicResultProperties(ProtoModel): # MP2 Keywords mp2_same_spin_correlation_energy: Optional[float] = Field( - None, description="The portion of MP2 doubles correlation energy from same-spin (i.e. triplet) correlations." + None, + description="The portion of MP2 doubles correlation energy from same-spin (i.e. triplet) correlations, without any user scaling.", ) mp2_opposite_spin_correlation_energy: Optional[float] = Field( None, - description="The portion of MP2 doubles correlation energy from opposite-spin (i.e. singlet) correlations.", + description="The portion of MP2 doubles correlation energy from opposite-spin (i.e. singlet) correlations, without any user scaling.", ) mp2_singles_energy: Optional[float] = Field( None, description="The singles portion of the MP2 correlation energy. Zero except in ROHF." @@ -86,11 +87,12 @@ class AtomicResultProperties(ProtoModel): # CCSD Keywords ccsd_same_spin_correlation_energy: Optional[float] = Field( - None, description="The portion of CCSD doubles correlation energy from same-spin (i.e. triplet) correlations." + None, + description="The portion of CCSD doubles correlation energy from same-spin (i.e. triplet) correlations, without any user scaling.", ) ccsd_opposite_spin_correlation_energy: Optional[float] = Field( None, - description="The portion of CCSD doubles correlation energy from opposite-spin (i.e. singlet) correlations", + description="The portion of CCSD doubles correlation energy from opposite-spin (i.e. singlet) correlations, without any user scaling.", ) ccsd_singles_energy: Optional[float] = Field( None, description="The singles portion of the CCSD correlation energy. Zero except in ROHF." @@ -115,6 +117,26 @@ class AtomicResultProperties(ProtoModel): None, description="The CCSD(T) X, Y, and Z dipole components." ) + # CCSDT keywords + ccsdt_correlation_energy: Optional[float] = Field(None, description="The CCSDT correlation energy.") + ccsdt_total_energy: Optional[float] = Field( + None, description="The total CCSDT energy (CCSDT correlation energy + HF energy)." + ) + ccsdt_dipole_moment: Optional[Array[float]] = Field(None, description="The CCSDT X, Y, and Z dipole components.") + ccsdt_iterations: Optional[int] = Field( + None, description="The number of CCSDT iterations taken before convergence." + ) + + # CCSDTQ keywords + ccsdtq_correlation_energy: Optional[float] = Field(None, description="The CCSDTQ correlation energy.") + ccsdtq_total_energy: Optional[float] = Field( + None, description="The total CCSDTQ energy (CCSDTQ correlation energy + HF energy)." + ) + ccsdtq_dipole_moment: Optional[Array[float]] = Field(None, description="The CCSDTQ X, Y, and Z dipole components.") + ccsdtq_iterations: Optional[int] = Field( + None, description="The number of CCSDTQ iterations taken before convergence." + ) + class Config(ProtoModel.Config): force_skip_defaults = True @@ -147,6 +169,7 @@ def dict(self, *args, **kwargs): class WavefunctionProperties(ProtoModel): + """Wavefunction properties resulting from a computation. Matrix quantities are stored in column-major order.""" # Class properties _return_results_names: Set[str] = { @@ -172,42 +195,119 @@ class WavefunctionProperties(ProtoModel): ) # Core Hamiltonian - h_core_a: Optional[Array[float]] = Field(None, description="Alpha-spin core (one-electron) Hamiltonian.") - h_core_b: Optional[Array[float]] = Field(None, description="Beta-spin core (one-electron) Hamiltonian.") + h_core_a: Optional[Array[float]] = Field( + None, description="Alpha-spin core (one-electron) Hamiltonian in the AO basis.", shape=["nao", "nao"] + ) + h_core_b: Optional[Array[float]] = Field( + None, description="Beta-spin core (one-electron) Hamiltonian in the AO basis.", shape=["nao", "nao"] + ) h_effective_a: Optional[Array[float]] = Field( - None, description="Alpha-spin effective core (one-electron) Hamiltonian." + None, description="Alpha-spin effective core (one-electron) Hamiltonian in the AO basis.", shape=["nao", "nao"] ) h_effective_b: Optional[Array[float]] = Field( - None, description="Beta-spin effective core (one-electron) Hamiltonian " + None, description="Beta-spin effective core (one-electron) Hamiltonian in the AO basis", shape=["nao", "nao"] ) # SCF Results - scf_orbitals_a: Optional[Array[float]] = Field(None, description="SCF alpha-spin orbitals.") - scf_orbitals_b: Optional[Array[float]] = Field(None, description="SCF beta-spin orbitals.") - scf_density_a: Optional[Array[float]] = Field(None, description="SCF alpha-spin density matrix.") - scf_density_b: Optional[Array[float]] = Field(None, description="SCF beta-spin density matrix.") - scf_fock_a: Optional[Array[float]] = Field(None, description="SCF alpha-spin Fock matrix.") - scf_fock_b: Optional[Array[float]] = Field(None, description="SCF beta-spin Fock matrix.") - scf_eigenvalues_a: Optional[Array[float]] = Field(None, description="SCF alpha-spin eigenvalues.") - scf_eigenvalues_b: Optional[Array[float]] = Field(None, description="SCF beta-spin eigenvalues.") - scf_occupations_a: Optional[Array[float]] = Field(None, description="SCF alpha-spin occupations.") - scf_occupations_b: Optional[Array[float]] = Field(None, description="SCF beta-spin occupations.") + scf_orbitals_a: Optional[Array[float]] = Field( + None, description="SCF alpha-spin orbitals in the AO basis.", shape=["nao", "nmo"] + ) + scf_orbitals_b: Optional[Array[float]] = Field( + None, description="SCF beta-spin orbitals in the AO basis.", shape=["nao", "nmo"] + ) + scf_density_a: Optional[Array[float]] = Field( + None, description="SCF alpha-spin density matrix in the AO basis.", shape=["nao", "nao"] + ) + scf_density_b: Optional[Array[float]] = Field( + None, description="SCF beta-spin density matrix in the AO basis.", shape=["nao", "nao"] + ) + scf_fock_a: Optional[Array[float]] = Field( + None, description="SCF alpha-spin Fock matrix in the AO basis.", shape=["nao", "nao"] + ) + scf_fock_b: Optional[Array[float]] = Field( + None, description="SCF beta-spin Fock matrix in the AO basis.", shape=["nao", "nao"] + ) + scf_eigenvalues_a: Optional[Array[float]] = Field( + None, description="SCF alpha-spin orbital eigenvalues.", shape=["nmo"] + ) + scf_eigenvalues_b: Optional[Array[float]] = Field( + None, description="SCF beta-spin orbital eigenvalues.", shape=["nmo"] + ) + scf_occupations_a: Optional[Array[float]] = Field( + None, description="SCF alpha-spin orbital occupations.", shape=["nmo"] + ) + scf_occupations_b: Optional[Array[float]] = Field( + None, description="SCF beta-spin orbital occupations.", shape=["nmo"] + ) + + # BELOW from qcsk + scf_coulomb_a: Optional[Array[float]] = Field( + None, description="SCF alpha-spin Coulomb matrix in the AO basis.", shape=["nao", "nao"] + ) + scf_coulomb_b: Optional[Array[float]] = Field( + None, description="SCF beta-spin Coulomb matrix in the AO basis.", shape=["nao", "nao"] + ) + scf_exchange_a: Optional[Array[float]] = Field( + None, description="SCF alpha-spin exchange matrix in the AO basis.", shape=["nao", "nao"] + ) + scf_exchange_b: Optional[Array[float]] = Field( + None, description="SCF beta-spin exchange matrix in the AO basis.", shape=["nao", "nao"] + ) + + # Localized-orbital SCF wavefunction quantities + localized_orbitals_a: Optional[Array[float]] = Field( + None, + description="Localized alpha-spin orbitals in the AO basis. All nmo orbitals are included, even if only a subset were localized.", + shape=["nao", "nmo"], + ) + localized_orbitals_b: Optional[Array[float]] = Field( + None, + description="Localized beta-spin orbitals in the AO basis. All nmo orbitals are included, even if only a subset were localized.", + shape=["nao", "nmo"], + ) + localized_fock_a: Optional[Array[float]] = Field( + None, + description="Alpha-spin Fock matrix in the localized molecular orbital basis. All nmo orbitals are included, even if only a subset were localized.", + shape=["nmo", "nmo"], + ) + localized_fock_b: Optional[Array[float]] = Field( + None, + description="Beta-spin Fock matrix in the localized molecular orbital basis. All nmo orbitals are included, even if only a subset were localized.", + shape=["nmo", "nmo"], + ) + # ABOVE from qcsk # Return results, must be defined last - orbitals_a: Optional[str] = Field(None, description="Index to the alpha-spin orbitals of the primary return.") - orbitals_b: Optional[str] = Field(None, description="Index to the beta-spin orbitals of the primary return.") - density_a: Optional[str] = Field(None, description="Index to the alpha-spin density of the primary return.") - density_b: Optional[str] = Field(None, description="Index to the beta-spin density of the primary return.") - fock_a: Optional[str] = Field(None, description="Index to the alpha-spin Fock matrix of the primary return.") - fock_b: Optional[str] = Field(None, description="Index to the beta-spin Fock matrix of the primary return.") - eigenvalues_a: Optional[str] = Field(None, description="Index to the alpha-spin eigenvalues of the primary return.") - eigenvalues_b: Optional[str] = Field(None, description="Index to the beta-spin eigenvalues of the primary return.") - occupations_a: Optional[str] = Field( + orbitals_a: Optional[str] = Field( + None, description="Index to the alpha-spin orbitals of the primary return in the AO basis." + ) + orbitals_b: Optional[str] = Field( + None, description="Index to the beta-spin orbitals of the primary return in the AO basis." + ) + density_a: Optional[str] = Field( + None, description="Index to the alpha-spin density of the primary return in the AO basis." + ) + density_b: Optional[str] = Field( + None, description="Index to the beta-spin density of the primary return in the AO basis." + ) + fock_a: Optional[str] = Field( + None, description="Index to the alpha-spin Fock matrix of the primary return in the AO basis." + ) + fock_b: Optional[str] = Field( + None, description="Index to the beta-spin Fock matrix of the primary return in the AO basis." + ) + eigenvalues_a: Optional[str] = Field( None, description="Index to the alpha-spin orbital eigenvalues of the primary return." ) - occupations_b: Optional[str] = Field( + eigenvalues_b: Optional[str] = Field( None, description="Index to the beta-spin orbital eigenvalues of the primary return." ) + occupations_a: Optional[str] = Field( + None, description="Index to the alpha-spin orbital occupations of the primary return." + ) + occupations_b: Optional[str] = Field( + None, description="Index to the beta-spin orbital occupations of the primary return." + ) class Config(ProtoModel.Config): force_skip_defaults = True @@ -335,23 +435,34 @@ class AtomicInput(ProtoModel): """The MolSSI Quantum Chemistry Schema""" id: Optional[str] = Field(None, description="An optional ID of the ResultInput object.") - schema_name: constr(strip_whitespace=True, regex=qcschema_input_default) = qcschema_input_default # type: ignore - schema_version: int = 1 + schema_name: constr(strip_whitespace=True, regex="^(qc_?schema_input)$") = Field( # type: ignore + qcschema_input_default, + description=( + f"The QCSchema specification this model conforms to. Explicitly fixed as {qcschema_input_default}." + ), + ) + schema_version: int = Field(1, description="The version number of ``schema_name`` to which this model conforms.") molecule: Molecule = Field(..., description="The molecule to use in the computation.") driver: DriverEnum = Field(..., description=str(DriverEnum.__doc__)) model: Model = Field(..., description=str(Model.__base_doc__)) - keywords: Dict[str, Any] = Field({}, description="The program specific keywords to be used.") + keywords: Dict[str, Any] = Field({}, description="The program-specific keywords to be used.") protocols: AtomicResultProtocols = Field( AtomicResultProtocols(), description=str(AtomicResultProtocols.__base_doc__) ) - extras: Dict[str, Any] = Field({}, description="Extra fields that are not part of the schema.") + extras: Dict[str, Any] = Field( + {}, description="Extra fields not part of the schema. Used for schema development and scratch space.", + ) provenance: Provenance = Field( default_factory=partial(provenance_stamp, __name__), description=str(Provenance.__base_doc__) ) + class Config(ProtoModel.Config): + def schema_extra(schema, model): + schema["$schema"] = qcschema_draft + def __repr_args__(self) -> "ReprArgs": return [ ("driver", self.driver.value), @@ -361,13 +472,17 @@ def __repr_args__(self) -> "ReprArgs": class AtomicResult(AtomicInput): - schema_name: constr(strip_whitespace=True, regex=qcschema_output_default) = qcschema_output_default # type: ignore - + schema_name: constr(strip_whitespace=True, regex="^(qc_?schema_output)$") = Field( # type: ignore + qcschema_output_default, + description=( + f"The QCSchema specification this model conforms to. Explicitly fixed as {qcschema_output_default}." + ), + ) properties: AtomicResultProperties = Field(..., description=str(AtomicResultProperties.__base_doc__)) wavefunction: Optional[WavefunctionProperties] = Field(None, description=str(WavefunctionProperties.__base_doc__)) return_result: Union[float, Array[float], Dict[str, Any]] = Field( - ..., description="The value requested by the 'driver' attribute." + ..., description="The primary specified return requested by the 'driver' attribute." ) # type: ignore stdout: Optional[str] = Field(None, description="The standard output of the program.") diff --git a/qcelemental/molutil/test_molutil.py b/qcelemental/molutil/test_molutil.py index 4b826f5e1..bf8cf0124 100644 --- a/qcelemental/molutil/test_molutil.py +++ b/qcelemental/molutil/test_molutil.py @@ -8,7 +8,7 @@ import qcelemental as qcel from qcelemental.testing import compare, compare_molrecs, compare_recursive, compare_values -from ..tests.addons import using_networkx +from ..tests.addons import drop_qcsk, using_networkx pp = pprint.PrettyPrinter(width=120) @@ -44,8 +44,9 @@ def test_scramble_descrambles_plain(): s22_12.scramble(do_shift=True, do_rotate=True, do_resort=True, do_plot=False, verbose=0, do_test=True) -def test_relative_geoms_align_free(): +def test_relative_geoms_align_free(request): s22_12 = qcel.models.Molecule.from_data(ss22_12) + drop_qcsk(s22_12, request.node.name) for trial in range(3): cmol, _ = s22_12.scramble( @@ -57,8 +58,9 @@ def test_relative_geoms_align_free(): assert compare_molrecs(rmolrec, cmolrec, atol=1.0e-4, relative_geoms="align") -def test_relative_geoms_align_fixed(): +def test_relative_geoms_align_fixed(request): s22_12 = qcel.models.Molecule.from_data(ss22_12 + "nocom\nnoreorient\n") + drop_qcsk(s22_12, request.node.name) for trial in range(3): cmol, _ = s22_12.scramble( @@ -344,7 +346,7 @@ def test_scramble_specific(): assert compare(mill_str, mill.pretty_print()) -def test_hessian_align(): +def test_hessian_align(request): # from Psi4 test test_hessian_vs_cfour[HOOH_TS-H_analytic] # fmt: off @@ -458,6 +460,7 @@ def test_hessian_align(): p4mol = qcel.models.Molecule.from_data(p4_hooh_xyz) c4mol = qcel.models.Molecule.from_data(c4_hooh_xyz) + drop_qcsk(c4mol, request.node.name) aqmol, data = p4mol.align(c4mol, atoms_map=True, mols_align=True, verbose=4) mill = data["mill"] diff --git a/qcelemental/tests/addons.py b/qcelemental/tests/addons.py index e400c5ea3..0a8821dc8 100644 --- a/qcelemental/tests/addons.py +++ b/qcelemental/tests/addons.py @@ -1,5 +1,7 @@ +import json import socket from contextlib import contextmanager +from pathlib import Path import pytest @@ -49,3 +51,20 @@ def xfail_on_pubchem_busy(): pytest.xfail("Pubchem server busy") else: raise e + + +_data_path = Path(__file__).parent.resolve() / "qcschema_instances" + + +def drop_qcsk(instance, tnm: str, schema_name: str = None): + if isinstance(instance, qcelemental.models.ProtoModel) and schema_name is None: + schema_name = type(instance).__name__ + drop = (_data_path / schema_name / tnm).with_suffix(".json") + + with open(drop, "w") as fp: + if isinstance(instance, qcelemental.models.ProtoModel): + fp.write(instance.json(exclude_none=True)) + elif isinstance(instance, dict): + json.dump(instance, fp, sort_keys=True, indent=2) + else: + raise TypeError diff --git a/qcelemental/tests/qcschema_instances/AtomicInput/dummy b/qcelemental/tests/qcschema_instances/AtomicInput/dummy new file mode 100644 index 000000000..e69de29bb diff --git a/qcelemental/tests/qcschema_instances/AtomicResult/dummy b/qcelemental/tests/qcschema_instances/AtomicResult/dummy new file mode 100644 index 000000000..e69de29bb diff --git a/qcelemental/tests/qcschema_instances/AtomicResultProperties/dummy b/qcelemental/tests/qcschema_instances/AtomicResultProperties/dummy new file mode 100644 index 000000000..e69de29bb diff --git a/qcelemental/tests/qcschema_instances/BasisSet/dummy b/qcelemental/tests/qcschema_instances/BasisSet/dummy new file mode 100644 index 000000000..e69de29bb diff --git a/qcelemental/tests/qcschema_instances/Molecule/dummy b/qcelemental/tests/qcschema_instances/Molecule/dummy new file mode 100644 index 000000000..e69de29bb diff --git a/qcelemental/tests/qcschema_instances/Provenance/dummy b/qcelemental/tests/qcschema_instances/Provenance/dummy new file mode 100644 index 000000000..e69de29bb diff --git a/qcelemental/tests/qcschema_instances/README.md b/qcelemental/tests/qcschema_instances/README.md new file mode 100644 index 000000000..40e34119f --- /dev/null +++ b/qcelemental/tests/qcschema_instances/README.md @@ -0,0 +1,3 @@ +These subdirectories are populated by running the QCElemental test suite. +Files are JSON representations of QCSchema instances stored or created in the course of testing. +These in turn are checked for compliance against the exported QCSchema models in test case ``test_qcschema``. diff --git a/qcelemental/tests/test_model_general.py b/qcelemental/tests/test_model_general.py index 5adee3fd3..f9f3b6585 100644 --- a/qcelemental/tests/test_model_general.py +++ b/qcelemental/tests/test_model_general.py @@ -13,10 +13,13 @@ Provenance, ) +from .addons import drop_qcsk -def test_result_properties_default_skip(): + +def test_result_properties_default_skip(request): obj = AtomicResultProperties(scf_one_electron_energy="-5.0") + drop_qcsk(obj, request.node.name) assert pytest.approx(obj.scf_one_electron_energy) == -5.0 @@ -31,9 +34,10 @@ def test_result_properties_default_repr(): assert len(repr(obj)) < 100 -def test_repr_provenance(): +def test_repr_provenance(request): prov = Provenance(creator="qcel", version="v0.3.2") + drop_qcsk(prov, request.node.name) assert "qcel" in str(prov) assert "qcel" in repr(prov) @@ -54,11 +58,12 @@ def test_repr_failed_op(): ) -def test_repr_result(): +def test_repr_result(request): result = AtomicInput( **{"driver": "gradient", "model": {"method": "UFF"}, "molecule": {"symbols": ["He"], "geometry": [0, 0, 0]}} ) + drop_qcsk(result, request.node.name) assert "molecule_hash" in str(result) assert "molecule_hash" in repr(result) assert "'gradient'" in str(result) diff --git a/qcelemental/tests/test_model_results.py b/qcelemental/tests/test_model_results.py index 01db8a0fb..2093c608c 100644 --- a/qcelemental/tests/test_model_results.py +++ b/qcelemental/tests/test_model_results.py @@ -4,6 +4,8 @@ import qcelemental as qcel from qcelemental.models import basis +from .addons import drop_qcsk + center_data = { "bs_sto3g_h": { "electron_shells": [ @@ -20,8 +22,8 @@ { "harmonic_type": "spherical", "angular_momentum": [0], - "exponents": [130.70939, 23.808861, 6.4436089], - "coefficients": [[0.15432899, 0.53532814, 0.44463454]], + "exponents": [130.70939, "23.808861", 6.4436089], + "coefficients": [[0.15432899, "0.53532814", 0.44463454]], }, { "harmonic_type": "cartesian", @@ -154,12 +156,13 @@ def test_basis_shell_centers(center_name): assert basis.BasisCenter(**center_data[center_name]) -def test_basis_set_build(): +def test_basis_set_build(request): bas = basis.BasisSet( name="custom_basis", center_data=center_data, atom_map=["bs_sto3g_o", "bs_sto3g_h", "bs_sto3g_h", "bs_def2tzvp_zr"], ) + drop_qcsk(bas, request.node.name) assert len(bas.center_data) == 3 assert len(bas.atom_map) == 4 @@ -170,6 +173,9 @@ def test_basis_set_build(): assert es[1].is_contracted() is False assert es[2].is_contracted() + assert es[0].exponents == [130.70939, 23.808861, 6.4436089] + assert es[0].coefficients == [[0.15432899, 0.53532814, 0.44463454]] + def test_basis_electron_center_raises(): data = center_data["bs_sto3g_h"]["electron_shells"][0].copy() @@ -213,19 +219,23 @@ def test_basis_map_raises(): assert basis.BasisSet(name="custom_basis", center_data=center_data, atom_map=["something_odd"]) -def test_result_build(result_data_fixture): +def test_result_build(result_data_fixture, request): ret = qcel.models.AtomicResult(**result_data_fixture) + drop_qcsk(ret, request.node.name) assert ret.wavefunction is None -def test_result_build_wavefunction_delete(wavefunction_data_fixture): +def test_result_build_wavefunction_delete(wavefunction_data_fixture, request): del wavefunction_data_fixture["protocols"] ret = qcel.models.AtomicResult(**wavefunction_data_fixture) + drop_qcsk(ret, request.node.name) assert ret.wavefunction is None -def test_wavefunction_build(wavefunction_data_fixture): - assert qcel.models.AtomicResult(**wavefunction_data_fixture) +def test_wavefunction_build(wavefunction_data_fixture, request): + ret = qcel.models.AtomicResult(**wavefunction_data_fixture) + drop_qcsk(ret, request.node.name) + assert ret def test_wavefunction_matrix_size_error(wavefunction_data_fixture): @@ -268,7 +278,7 @@ def test_wavefunction_return_result_pointer(wavefunction_data_fixture): ("return_results", True, ["orbitals_a", "fock_a", "fock_b"], ["orbitals_a", "fock_a"]), ], ) -def test_wavefunction_protocols(protocol, restricted, provided, expected, wavefunction_data_fixture): +def test_wavefunction_protocols(protocol, restricted, provided, expected, wavefunction_data_fixture, request): wfn_data = wavefunction_data_fixture["wavefunction"] @@ -289,6 +299,7 @@ def test_wavefunction_protocols(protocol, restricted, provided, expected, wavefu wfn_data[scf_name] = np.random.rand(bas.nbf, bas.nbf) wfn = qcel.models.AtomicResult(**wavefunction_data_fixture) + drop_qcsk(wfn, request.node.name) if len(expected) == 0: assert wfn.wavefunction is None @@ -316,7 +327,7 @@ def test_optimization_trajectory_protocol(keep, indices, optimization_data_fixtu "default, defined, default_result, defined_result", [(None, None, True, None), (False, {"a": True}, False, {"a": True})], ) -def test_error_correction_protocol(default, defined, default_result, defined_result, result_data_fixture): +def test_error_correction_protocol(default, defined, default_result, defined_result, result_data_fixture, request): policy = {} if default is not None: policy["default_policy"] = default @@ -324,6 +335,7 @@ def test_error_correction_protocol(default, defined, default_result, defined_res policy["policies"] = defined result_data_fixture["protocols"] = {"error_correction": policy} res = qcel.models.AtomicResult(**result_data_fixture) + drop_qcsk(res, request.node.name) assert res.protocols.error_correction.default_policy == default_result assert res.protocols.error_correction.policies == defined_result @@ -348,18 +360,20 @@ def test_error_correction_logic(): assert correction_policy.allows("a") -def test_result_build_stdout_delete(result_data_fixture): +def test_result_build_stdout_delete(result_data_fixture, request): result_data_fixture["protocols"] = {"stdout": False} ret = qcel.models.AtomicResult(**result_data_fixture) + drop_qcsk(ret, request.node.name) assert ret.stdout is None -def test_result_build_stdout(result_data_fixture): +def test_result_build_stdout(result_data_fixture, request): ret = qcel.models.AtomicResult(**result_data_fixture) + drop_qcsk(ret, request.node.name) assert ret.stdout == "I ran." -def test_failed_operation(result_data_fixture): +def test_failed_operation(result_data_fixture, request): water = qcel.models.Molecule.from_data( """ O 0 0 0 @@ -367,6 +381,7 @@ def test_failed_operation(result_data_fixture): H 0 2 0 """ ) + drop_qcsk(water, request.node.name) failed = qcel.models.FailedOperation( extras={"garbage": water}, @@ -380,12 +395,13 @@ def test_failed_operation(result_data_fixture): assert "its all good" in failed_json -def test_result_properties_array(): +def test_result_properties_array(request): lquad = [1, 2, 3, 2, 4, 5, 3, 5, 6] obj = qcel.models.AtomicResultProperties( scf_one_electron_energy="-5.0", scf_dipole_moment=[1, 2, 3], scf_quadrupole_moment=lquad ) + drop_qcsk(obj, request.node.name) assert pytest.approx(obj.scf_one_electron_energy) == -5.0 assert obj.scf_dipole_moment.shape == (3,) diff --git a/qcelemental/tests/test_molparse_from_schema.py b/qcelemental/tests/test_molparse_from_schema.py index c452509b1..5d65ce8b6 100644 --- a/qcelemental/tests/test_molparse_from_schema.py +++ b/qcelemental/tests/test_molparse_from_schema.py @@ -6,6 +6,8 @@ import qcelemental as qcel from qcelemental.testing import compare_molrecs +from .addons import drop_qcsk + _schema_prov_stamp = {"creator": "QCElemental", "version": "1.0", "routine": "qcelemental.molparse.from_schema"} @@ -131,9 +133,10 @@ def test_from_schema_1p5_14e(): assert compare_molrecs(schema14_psi4_np, ans, 4) -def test_from_schema_2_14e(): +def test_from_schema_2_14e(request): schema = copy.deepcopy(schema14_1) schema.update({"schema_name": "qcschema_molecule", "schema_version": 2}) + drop_qcsk(schema, request.node.name, "Molecule") ans = qcel.molparse.from_schema(schema) assert compare_molrecs(schema14_psi4_np, ans, 4) diff --git a/qcelemental/tests/test_molparse_to_schema.py b/qcelemental/tests/test_molparse_to_schema.py index c64c9653b..72cdc39a0 100644 --- a/qcelemental/tests/test_molparse_to_schema.py +++ b/qcelemental/tests/test_molparse_to_schema.py @@ -7,6 +7,8 @@ import qcelemental from qcelemental.testing import compare_molrecs +from .addons import drop_qcsk + _string_prov_stamp = {"creator": "QCElemental", "version": "1.0", "routine": "qcelemental.molparse.from_string"} _schema_prov_stamp = {"creator": "QCElemental", "version": "1.0", "routine": "qcelemental.molparse.from_schema"} @@ -58,12 +60,13 @@ } -def test_1_14a(): +def test_1_14a(request): fullans = copy.deepcopy(schema14_1) fullans["molecule"]["provenance"] = _string_prov_stamp final = qcelemental.molparse.from_string(subject14) kmol = qcelemental.molparse.to_schema(final["qm"], dtype=1) + drop_qcsk(kmol["molecule"], request.node.name, "Molecule") assert compare_molrecs(fullans["molecule"], kmol["molecule"]) fullans = copy.deepcopy(schema14_psi4) @@ -74,12 +77,13 @@ def test_1_14a(): assert compare_molrecs(fullans, molrec) -def test_2_14b(): +def test_2_14b(request): fullans = copy.deepcopy(schema14_2) fullans["provenance"] = _string_prov_stamp final = qcelemental.molparse.from_string(subject14) kmol = qcelemental.molparse.to_schema(final["qm"], dtype=2) + drop_qcsk(kmol, request.node.name, "Molecule") assert compare_molrecs(fullans, kmol) fullans = copy.deepcopy(schema14_psi4) @@ -109,7 +113,7 @@ def test_dtype_error(): @pytest.mark.parametrize("dtype", [1, 2]) -def test_qcschema_ang_error(dtype): +def test_atomic_units_qcschema_ang_error(dtype): final = qcelemental.molparse.from_string(subject14) with pytest.raises(qcelemental.ValidationError) as e: @@ -182,13 +186,14 @@ def test_psi4_nm_error(): } -def test_1_15a(): +def test_1_15a(request): fullans = copy.deepcopy(schema15_1) fullans["molecule"]["provenance"] = _string_prov_stamp final = qcelemental.molparse.from_string(subject15) final["qm"]["comment"] = "I has a comment" kmol = qcelemental.molparse.to_schema(final["qm"], dtype=1) + drop_qcsk(kmol["molecule"], request.node.name, "Molecule") assert compare_molrecs(fullans["molecule"], kmol["molecule"]) fullans = copy.deepcopy(schema15_psi4) @@ -201,13 +206,14 @@ def test_1_15a(): assert compare_molrecs(fullans, molrec) -def test_2_15b(): +def test_2_15b(request): fullans = copy.deepcopy(schema15_2) fullans["provenance"] = _string_prov_stamp final = qcelemental.molparse.from_string(subject15) final["qm"]["comment"] = "I has a comment" kmol = qcelemental.molparse.to_schema(final["qm"], dtype=2) + drop_qcsk(kmol, request.node.name, "Molecule") assert compare_molrecs(fullans, kmol) fullans = copy.deepcopy(schema15_psi4) @@ -280,7 +286,7 @@ def test_psi4_15c(): } -def test_froto_1_16a(): +def test_froto_1_16a(request): basic = { "schema_name": "qc_schema_output", "schema_version": 1, @@ -296,10 +302,11 @@ def test_froto_1_16a(): fullans["molecule"]["provenance"] = _schema_prov_stamp roundtrip = qcelemental.molparse.to_schema(qcelemental.molparse.from_schema(basic), dtype=1) + drop_qcsk(roundtrip["molecule"], request.node.name, "Molecule") assert compare_molrecs(fullans["molecule"], roundtrip["molecule"]) -def test_froto_2_16a(): +def test_froto_2_16a(request): basic = { "schema_name": "qcschema_molecule", "schema_version": 2, @@ -313,14 +320,18 @@ def test_froto_2_16a(): fullans["provenance"] = _schema_prov_stamp roundtrip = qcelemental.molparse.to_schema(qcelemental.molparse.from_schema(basic), dtype=2) + drop_qcsk(roundtrip, request.node.name, "Molecule") assert compare_molrecs(fullans, roundtrip) @pytest.mark.parametrize("dtype", [1, 2]) -def test_tofro_16b(dtype): +def test_tofro_16b(dtype, request): fullans = copy.deepcopy(schema16_psi4) fullans["provenance"] = _schema_prov_stamp roundtrip = qcelemental.molparse.from_schema(qcelemental.molparse.to_schema(schema16_psi4, dtype=dtype)) + qcsk = qcelemental.molparse.to_schema(schema16_psi4, dtype=dtype) + qcsk = qcsk["molecule"] if dtype == 1 else qcsk + drop_qcsk(qcsk, request.node.name, "Molecule") assert compare_molrecs(fullans, roundtrip) diff --git a/qcelemental/tests/test_molparse_to_string.py b/qcelemental/tests/test_molparse_to_string.py index 2653e3c42..bef3ece5f 100644 --- a/qcelemental/tests/test_molparse_to_string.py +++ b/qcelemental/tests/test_molparse_to_string.py @@ -3,6 +3,8 @@ import qcelemental as qcel from qcelemental.testing import compare +from .addons import drop_qcsk + # CODATA2014 = 1.05835442134 # CODATA2018 = 1.058354421806 au2 = 2.0 * qcel.constants.bohr2angstroms @@ -295,9 +297,10 @@ def test_to_string_xyz(inp, expected): ("subject2", {"dtype": "nglview-sdf"}, "ans2_ngslviewsdf"), ], ) -def test_molecule_to_string(inp, kwargs, expected): +def test_molecule_to_string(inp, kwargs, expected, request): smol = _molecule_inputs[inp].to_string(**kwargs) + drop_qcsk(_molecule_inputs[inp], request.node.name) assert compare(_molecule_outputs[expected], smol) diff --git a/qcelemental/tests/test_zqcschema.py b/qcelemental/tests/test_zqcschema.py new file mode 100644 index 000000000..b875c9009 --- /dev/null +++ b/qcelemental/tests/test_zqcschema.py @@ -0,0 +1,35 @@ +import json + +import jsonschema +import pytest + +import qcelemental as qcel + +from .addons import _data_path + + +@pytest.fixture(scope="module") +def qcschema_models(): + return {md.__name__: json.loads(md.schema_json()) for md in qcel.models.qcschema_models()} + + +files = sorted(_data_path.rglob("*.json")) +ids = [fl.parent.stem + "_" + fl.stem[5:] for fl in files] + + +@pytest.mark.parametrize("fl", files, ids=ids) +def test_qcschema(fl, qcschema_models): + model = fl.parent.stem + instance = json.loads(fl.read_text()) + + res = jsonschema.validate(instance, qcschema_models[model]) + assert res is None + + +# import pprint +# print("\n\n<<< SCHEMA") +# pprint.pprint(schemas["BasisSet"]) +# print("\n\n<<< INSTANCE") +# pprint.pprint(instance) + +# assert 0 From fecb6d974b4c26c8c2a6b24a0d14efa52f9be8ae Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Sun, 30 Aug 2020 00:03:18 -0400 Subject: [PATCH 32/43] install jsonschema --- devtools/conda-envs/base.yaml | 1 + devtools/conda-envs/minimal.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/devtools/conda-envs/base.yaml b/devtools/conda-envs/base.yaml index 0350c9f3f..ec43b74a1 100644 --- a/devtools/conda-envs/base.yaml +++ b/devtools/conda-envs/base.yaml @@ -20,3 +20,4 @@ dependencies: - pytest-cov - codecov - scipy # tests an aspect of a helper fn not used by qcel functionality + - jsonschema diff --git a/devtools/conda-envs/minimal.yaml b/devtools/conda-envs/minimal.yaml index 0d1b8f070..46591ed48 100644 --- a/devtools/conda-envs/minimal.yaml +++ b/devtools/conda-envs/minimal.yaml @@ -14,3 +14,4 @@ dependencies: - pytest=4.6.4 # technically, qcel works with 4.0.0 but c-f doesn't have py38 builds for it - pytest-cov - codecov + - jsonschema From 0c1930bd636bacc03b8ecc3120bf6eecc0fd8cef Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Sun, 30 Aug 2020 22:47:05 -0400 Subject: [PATCH 33/43] mostly black v20 formatting --- .github/workflows/QCSchema.yml | 3 +- Makefile | 2 +- qcelemental/info/cpu_info.py | 6 +-- qcelemental/models/align.py | 12 ++--- qcelemental/models/common_models.py | 3 +- qcelemental/models/results.py | 5 +- qcelemental/physical_constants/context.py | 3 +- qcelemental/physical_constants/ureg.py | 3 +- qcelemental/testing.py | 12 ++--- qcelemental/util/gph_uno_bipartite.py | 64 +++++++++++------------ 10 files changed, 49 insertions(+), 64 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 434057082..24f88cc58 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -64,7 +64,8 @@ jobs: make qcschema ls -l qcschema #cp -p qcschema/* ../qcsk/qcschema_json/ - cp -p qcschema/* ../qcsk/qcschema/ + cp -p qcschema/* ../qcsk/qcschema/data/vdev/ + mv ../qcsk/qcschema/data/vdev/QCSchema.schema ../qcsk/qcschema/dev/ # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, # rather than the python module of the current repo diff --git a/Makefile b/Makefile index 46289e185..386d0c205 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ cpu_data: .PHONY: qcschema qcschema: mkdir -p qcschema - python -c "exec(\"import pathlib, qcelemental\nfor md in qcelemental.models.qcschema_models():\n\tmfile = (pathlib.Path('qcschema') / md.__name__).with_suffix('.schema')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=4))\")" + python -c "exec(\"import pathlib, qcelemental\nfor md in qcelemental.models.qcschema_models():\n\tmfile = (pathlib.Path('qcschema') / md.__name__).with_suffix('.schema')\n\twith open(mfile, 'w') as fp:\n\t\tfp.write(md.schema_json(indent=None))\")" python -c "exec(\"import json, pathlib, pydantic, qcelemental\nwith open((pathlib.Path('qcschema') / 'QCSchema').with_suffix('.schema'), 'w') as fp:\n\tjson.dump(pydantic.schema.schema(qcelemental.models.qcschema_models(), title='QCSchema'), fp, indent=4)\")" .PHONY: clean diff --git a/qcelemental/info/cpu_info.py b/qcelemental/info/cpu_info.py index d2719db75..ce1c4a00c 100644 --- a/qcelemental/info/cpu_info.py +++ b/qcelemental/info/cpu_info.py @@ -14,8 +14,7 @@ class VendorEnum(str, Enum): - """Allowed processor vendors, used for validation. - """ + """Allowed processor vendors, used for validation.""" amd = "amd" intel = "intel" @@ -24,8 +23,7 @@ class VendorEnum(str, Enum): class InstructionSetEnum(int, Enum): - """Allowed instruction sets for CPUs in an ordinal enum. - """ + """Allowed instruction sets for CPUs in an ordinal enum.""" none = 0 sse = 1 diff --git a/qcelemental/models/align.py b/qcelemental/models/align.py index 6e21faeb3..e41d1a2f6 100644 --- a/qcelemental/models/align.py +++ b/qcelemental/models/align.py @@ -21,15 +21,9 @@ class AlignmentMill(ProtoModel): """ - shift: Optional[Array[float]] = Field( # type: ignore - None, description="Translation array (3,) for coordinates." - ) - rotation: Optional[Array[float]] = Field( # type: ignore - None, description="Rotation array (3, 3) for coordinates." - ) - atommap: Optional[Array[int]] = Field( # type: ignore - None, description="Atom exchange map (nat,) for coordinates." - ) + shift: Optional[Array[float]] = Field(None, description="Translation array (3,) for coordinates.") # type: ignore + rotation: Optional[Array[float]] = Field(None, description="Rotation array (3, 3) for coordinates.") # type: ignore + atommap: Optional[Array[int]] = Field(None, description="Atom exchange map (nat,) for coordinates.") # type: ignore mirror: bool = Field(False, description="Do mirror invert coordinates?") class Config: diff --git a/qcelemental/models/common_models.py b/qcelemental/models/common_models.py index eb9b3c36a..59e5a409a 100644 --- a/qcelemental/models/common_models.py +++ b/qcelemental/models/common_models.py @@ -63,8 +63,7 @@ class Config(ProtoModel.Config): class DriverEnum(str, Enum): - """Allowed computation driver values. - """ + """Allowed computation driver values.""" energy = "energy" gradient = "gradient" diff --git a/qcelemental/models/results.py b/qcelemental/models/results.py index fd6b089a8..7e032f546 100644 --- a/qcelemental/models/results.py +++ b/qcelemental/models/results.py @@ -391,7 +391,7 @@ class WavefunctionProtocolEnum(str, Enum): class ErrorCorrectionProtocol(ProtoModel): """Configuration for how QCEngine handles error correction - + WARNING: These protocols are currently experimental and only supported by NWChem tasks """ @@ -452,7 +452,8 @@ class AtomicInput(ProtoModel): ) extras: Dict[str, Any] = Field( - {}, description="Extra fields not part of the schema. Used for schema development and scratch space.", + {}, + description="Extra fields not part of the schema. Used for schema development and scratch space.", ) provenance: Provenance = Field( diff --git a/qcelemental/physical_constants/context.py b/qcelemental/physical_constants/context.py index 55896d435..c2c1ffb62 100644 --- a/qcelemental/physical_constants/context.py +++ b/qcelemental/physical_constants/context.py @@ -269,8 +269,7 @@ def get(self, physical_constant: str, return_tuple: bool = False) -> Union[float # me 'electron mass' = 9.10938215E-31 # Electron rest mass (in kg) def Quantity(self, data: str) -> "quantity._Quantity": - """Returns a Pint Quantity. - """ + """Returns a Pint Quantity.""" return self.ureg.Quantity(data) diff --git a/qcelemental/physical_constants/ureg.py b/qcelemental/physical_constants/ureg.py index 05d1727cf..f8106e0a6 100644 --- a/qcelemental/physical_constants/ureg.py +++ b/qcelemental/physical_constants/ureg.py @@ -129,8 +129,7 @@ def build_units_registry(context): # Add contexts def _find_nist_unit(unit): - """Converts pint datatypes to NIST datatypes - """ + """Converts pint datatypes to NIST datatypes""" for value in unit.to_tuple()[1]: if value[1] < 1: continue diff --git a/qcelemental/testing.py b/qcelemental/testing.py index 7899b7e4b..de6bc8215 100644 --- a/qcelemental/testing.py +++ b/qcelemental/testing.py @@ -11,8 +11,7 @@ def _handle_return(passfail: bool, label: str, message: str, return_message: bool, quiet: bool = False): - """Function to print a '*label*...PASSED' line to log. - """ + """Function to print a '*label*...PASSED' line to log.""" if not quiet: if passfail: @@ -28,8 +27,7 @@ def _handle_return(passfail: bool, label: str, message: str, return_message: boo def tnm() -> str: - """Returns the name of the calling function, usually name of test case. - """ + """Returns the name of the calling function, usually name of test case.""" return sys._getframe().f_back.f_code.co_name @@ -480,11 +478,7 @@ def compare_molrecs( return_message: bool = False, return_handler: Callable = None, ) -> bool: - """Function to compare Molecule dictionaries. Prints -# :py:func:`util.success` when elements of `computed` match elements of -# `expected` to `tol` number of digits (for float arrays). - - """ + """Function to compare Molecule dictionaries.""" # Need to manipulate the dictionaries a bit, so hold values xptd = copy.deepcopy(expected) cptd = copy.deepcopy(computed) diff --git a/qcelemental/util/gph_uno_bipartite.py b/qcelemental/util/gph_uno_bipartite.py index 4b7f28fb8..41f639b5a 100644 --- a/qcelemental/util/gph_uno_bipartite.py +++ b/qcelemental/util/gph_uno_bipartite.py @@ -45,10 +45,10 @@ def _formDirected(g, match): Returns ------- networkx.DiGraph - Directed graph, with edges in `match` pointing from set-0 - (bipartite attribute==0) to set-1 (bipartite attrbiute==1), and - the other edges in `g` but not in `match` pointing from set-1 to - set-0. + Directed graph, with edges in `match` pointing from set-0 + (bipartite attribute==0) to set-1 (bipartite attrbiute==1), and + the other edges in `g` but not in `match` pointing from set-1 to + set-0. """ import networkx as nx @@ -127,8 +127,8 @@ def _enumMaximumMatchingIter(g, match, all_matches, add_e=None): match : List of edges forming one maximum matching of `g`. all_matches : - List, each is a list of edges forming a maximum matching of `g`. - Newly found matchings will be appended into this list. + List, each is a list of edges forming a maximum matching of `g`. + Newly found matchings will be appended into this list. add_e : tuple, optional Edge used to form subproblems. If not `None`, will be added to each newly found matchings. @@ -335,32 +335,32 @@ def _enumMaximumMatching2(g): def _enumMaximumMatchingIter2(adj, matchadj, all_matches, n1, add_e=None, check_cycle=True): """Recurively search maximum matchings. - Similar to _enumMaximumMatching but implemented using adjacency matrix - of graph for a slight speed boost. - - Parameters - ---------- -# g : -# Undirected bipartite graph. Nodes are separated by their -# 'bipartite' attribute. -# match : -# List of edges forming one maximum matching of `g`. -# all_matches : -# List, each is a list of edges forming a maximum matching of `g`. -# Newly found matchings will be appended into this list. - add_e : tuple, optional - Edge used to form subproblems. If not `None`, will be added to each - newly found matchings. - - Returns - ------- - list - Updated list of all maximum matchings. - - Author - ------ - guangzhi XU (xugzhi1987@gmail.com; guangzhi.xu@outlook.com) - Update time: 2017-05-21 20:09:06. + Similar to _enumMaximumMatching but implemented using adjacency matrix + of graph for a slight speed boost. + + Parameters + ---------- + # g : + # Undirected bipartite graph. Nodes are separated by their + # 'bipartite' attribute. + # match : + # List of edges forming one maximum matching of `g`. + # all_matches : + # List, each is a list of edges forming a maximum matching of `g`. + # Newly found matchings will be appended into this list. + add_e : tuple, optional + Edge used to form subproblems. If not `None`, will be added to each + newly found matchings. + + Returns + ------- + list + Updated list of all maximum matchings. + + Author + ------ + guangzhi XU (xugzhi1987@gmail.com; guangzhi.xu@outlook.com) + Update time: 2017-05-21 20:09:06. """ import networkx as nx From bd917fef9a7ca7e417d46f5f3c79d7a9e75c6062 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 10:32:37 -0400 Subject: [PATCH 34/43] try alt init for ErrorCorrectionProtocol to appease schema generation --- .github/workflows/QCSchema.yml | 12 +++--------- qcelemental/models/results.py | 2 +- qcelemental/tests/test_zqcschema.py | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 24f88cc58..12feab242 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -22,11 +22,9 @@ jobs: - name: Checkout schema repo uses: actions/checkout@v2 with: - repository: loriab/QCSchema - #repository: MolSSI/QCSchema + repository: MolSSI/QCSchema path: qcsk - #ref: py2json - ref: json_files + ref: qcsk_export_2 #ref: master persist-credentials: false fetch-depth: 0 @@ -63,11 +61,8 @@ jobs: eval "$(conda shell.bash hook)" && conda activate test make qcschema ls -l qcschema - #cp -p qcschema/* ../qcsk/qcschema_json/ cp -p qcschema/* ../qcsk/qcschema/data/vdev/ mv ../qcsk/qcschema/data/vdev/QCSchema.schema ../qcsk/qcschema/dev/ - # Note: `qcschema_json` is a folder in the py2json branch containing plain JSON files of the schema, - # rather than the python module of the current repo - name: Compare Schemas (generated vs. community) shell: bash @@ -88,8 +83,7 @@ jobs: uses: ad-m/github-push-action@master with: directory: ./qcsk - repository: loriab/QCSchema - #repository: MolSSI/QCSchema + repository: MolSSI/QCSchema branch: ${{ env.prbranch }} github_token: ${{ secrets.QCSK_TOKEN }} force: true diff --git a/qcelemental/models/results.py b/qcelemental/models/results.py index 7e032f546..2f79a5ec0 100644 --- a/qcelemental/models/results.py +++ b/qcelemental/models/results.py @@ -421,7 +421,7 @@ class AtomicResultProtocols(ProtoModel): ) stdout: bool = Field(True, description="Primary output file to keep from a Result computation") error_correction: ErrorCorrectionProtocol = Field( - ErrorCorrectionProtocol(), description="Policies for error correction" + default_factory=ErrorCorrectionProtocol, description="Policies for error correction" ) class Config: diff --git a/qcelemental/tests/test_zqcschema.py b/qcelemental/tests/test_zqcschema.py index b875c9009..511fd22e9 100644 --- a/qcelemental/tests/test_zqcschema.py +++ b/qcelemental/tests/test_zqcschema.py @@ -1,6 +1,5 @@ import json -import jsonschema import pytest import qcelemental as qcel @@ -19,6 +18,7 @@ def qcschema_models(): @pytest.mark.parametrize("fl", files, ids=ids) def test_qcschema(fl, qcschema_models): + import jsonschema model = fl.parent.stem instance = json.loads(fl.read_text()) From 526b685dbd3b9c3d17aaf89a975df5e8e0cf4ee4 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 11:36:31 -0400 Subject: [PATCH 35/43] another schema fix try --- qcelemental/tests/addons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcelemental/tests/addons.py b/qcelemental/tests/addons.py index 0a8821dc8..fe2d9e4ec 100644 --- a/qcelemental/tests/addons.py +++ b/qcelemental/tests/addons.py @@ -63,7 +63,7 @@ def drop_qcsk(instance, tnm: str, schema_name: str = None): with open(drop, "w") as fp: if isinstance(instance, qcelemental.models.ProtoModel): - fp.write(instance.json(exclude_none=True)) + fp.write(instance.json(exclude_unset=True, exclude_none=True)) elif isinstance(instance, dict): json.dump(instance, fp, sort_keys=True, indent=2) else: From 347265072d42928505ee11382928b1e303a38bdc Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 15:39:06 -0400 Subject: [PATCH 36/43] CI try --- .github/workflows/CI.yml | 2 +- .github/workflows/QCSchema.yml | 3 ++- qcelemental/tests/test_zqcschema.py | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 5af74f36b..abdfa3906 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -53,7 +53,7 @@ jobs: run: | eval "$(conda shell.bash hook)" && conda activate test pytest -rws -v --cov=qcelemental --color=yes --cov-report=xml qcelemental/ - pytest -rws -v qcelemental/ --validate + pytest -rws -v --validate qcelemental/ - name: CodeCov uses: codecov/codecov-action@v1 diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 12feab242..156cd8c03 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -85,5 +85,6 @@ jobs: directory: ./qcsk repository: MolSSI/QCSchema branch: ${{ env.prbranch }} - github_token: ${{ secrets.QCSK_TOKEN }} + #github_token: ${{ secrets.QCSK_TOKEN }} + github_token: ${{ secrets.GITHUB_TOKEN }} force: true diff --git a/qcelemental/tests/test_zqcschema.py b/qcelemental/tests/test_zqcschema.py index 511fd22e9..b8dc32545 100644 --- a/qcelemental/tests/test_zqcschema.py +++ b/qcelemental/tests/test_zqcschema.py @@ -9,7 +9,12 @@ @pytest.fixture(scope="module") def qcschema_models(): - return {md.__name__: json.loads(md.schema_json()) for md in qcel.models.qcschema_models()} + #return {md.__name__: json.loads(md.schema_json()) for md in qcel.models.qcschema_models()} + models = {} + for md in qcel.models.qcschema_models(): + print(md) + models[md.__name__] = json.loads(md.schema_json()) + return models files = sorted(_data_path.rglob("*.json")) From cf89c3b7e9ea7c858fa5da559c0e9e94f3dd4798 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 16:56:47 -0400 Subject: [PATCH 37/43] CI try 2 --- .github/workflows/QCSchema.yml | 3 ++- qcelemental/tests/test_zqcschema.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 156cd8c03..8c33b53cc 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -86,5 +86,6 @@ jobs: repository: MolSSI/QCSchema branch: ${{ env.prbranch }} #github_token: ${{ secrets.QCSK_TOKEN }} - github_token: ${{ secrets.GITHUB_TOKEN }} + #github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.QCSCHEMA_FROM_QCELEMENTAL }} force: true diff --git a/qcelemental/tests/test_zqcschema.py b/qcelemental/tests/test_zqcschema.py index b8dc32545..925353528 100644 --- a/qcelemental/tests/test_zqcschema.py +++ b/qcelemental/tests/test_zqcschema.py @@ -9,7 +9,7 @@ @pytest.fixture(scope="module") def qcschema_models(): - #return {md.__name__: json.loads(md.schema_json()) for md in qcel.models.qcschema_models()} + # return {md.__name__: json.loads(md.schema_json()) for md in qcel.models.qcschema_models()} models = {} for md in qcel.models.qcschema_models(): print(md) @@ -24,6 +24,7 @@ def qcschema_models(): @pytest.mark.parametrize("fl", files, ids=ids) def test_qcschema(fl, qcschema_models): import jsonschema + model = fl.parent.stem instance = json.loads(fl.read_text()) From 0084c2320925f0015343998deab5294d3c2e9b4a Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 17:07:31 -0400 Subject: [PATCH 38/43] CI try 3 --- .github/workflows/CI.yml | 5 +++++ .github/workflows/QCSchema.yml | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index abdfa3906..0d67df41e 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -53,6 +53,11 @@ jobs: run: | eval "$(conda shell.bash hook)" && conda activate test pytest -rws -v --cov=qcelemental --color=yes --cov-report=xml qcelemental/ + + - name: PyTest B + shell: bash + run: | + eval "$(conda shell.bash hook)" && conda activate test pytest -rws -v --validate qcelemental/ - name: CodeCov diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 8c33b53cc..5fe63fdd0 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -85,7 +85,6 @@ jobs: directory: ./qcsk repository: MolSSI/QCSchema branch: ${{ env.prbranch }} - #github_token: ${{ secrets.QCSK_TOKEN }} - #github_token: ${{ secrets.GITHUB_TOKEN }} - github_token: ${{ secrets.QCSCHEMA_FROM_QCELEMENTAL }} + github_token: ${{ secrets.GITHUB_TOKEN }} +# github_token: ${{ secrets.QCSCHEMA_FROM_QCELEMENTAL }} force: true From e5ea3142d4f968b0b7c077280423dc020906c5c5 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 17:30:30 -0400 Subject: [PATCH 39/43] CI try 4 --- .github/workflows/CI.yml | 4 ++++ .github/workflows/QCSchema.yml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0d67df41e..1a9183b96 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -11,10 +11,13 @@ jobs: cfg: - conda-env: minimal python-version: 3.6 + id: mindep - conda-env: base python-version: 3.6 + id: minpy - conda-env: base python-version: 3.8 + id: fancy env: PYVER: ${{ matrix.cfg.python-version }} CONDA_ENV: ${{ matrix.cfg.conda-env }} @@ -56,6 +59,7 @@ jobs: - name: PyTest B shell: bash + if: matrix.cfg.id == "fancy" run: | eval "$(conda shell.bash hook)" && conda activate test pytest -rws -v --validate qcelemental/ diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 5fe63fdd0..595e19809 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -85,6 +85,6 @@ jobs: directory: ./qcsk repository: MolSSI/QCSchema branch: ${{ env.prbranch }} - github_token: ${{ secrets.GITHUB_TOKEN }} -# github_token: ${{ secrets.QCSCHEMA_FROM_QCELEMENTAL }} +# github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.qcschema_from_qcelemental }} force: true From e1efdba828b7e83729991d63f19f7a94e1059220 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 17:48:04 -0400 Subject: [PATCH 40/43] CI try 5 --- .github/workflows/CI.yml | 8 ++++---- .github/workflows/QCSchema.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1a9183b96..3f122b0f6 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -11,13 +11,13 @@ jobs: cfg: - conda-env: minimal python-version: 3.6 - id: mindep + id: "mindep" - conda-env: base python-version: 3.6 - id: minpy + id: "minpy" - conda-env: base python-version: 3.8 - id: fancy + id: "fancy" env: PYVER: ${{ matrix.cfg.python-version }} CONDA_ENV: ${{ matrix.cfg.conda-env }} @@ -59,7 +59,7 @@ jobs: - name: PyTest B shell: bash - if: matrix.cfg.id == "fancy" + if: ${{ matrix.cfg.id == "fancy" }} run: | eval "$(conda shell.bash hook)" && conda activate test pytest -rws -v --validate qcelemental/ diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index 595e19809..ee54a214e 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -26,8 +26,8 @@ jobs: path: qcsk ref: qcsk_export_2 #ref: master - persist-credentials: false - fetch-depth: 0 +# persist-credentials: false +# fetch-depth: 0 - name: Python Setup uses: actions/setup-python@v1 From 116c6c860ea7fde6cbe86c9f397304e3938f36f6 Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 18:34:37 -0400 Subject: [PATCH 41/43] CI try 6 --- .github/workflows/CI.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3f122b0f6..8f1f2ef58 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -11,13 +11,13 @@ jobs: cfg: - conda-env: minimal python-version: 3.6 - id: "mindep" + label: mindep - conda-env: base python-version: 3.6 - id: "minpy" + label: minpy - conda-env: base python-version: 3.8 - id: "fancy" + label: full env: PYVER: ${{ matrix.cfg.python-version }} CONDA_ENV: ${{ matrix.cfg.conda-env }} @@ -59,7 +59,7 @@ jobs: - name: PyTest B shell: bash - if: ${{ matrix.cfg.id == "fancy" }} + if: matrix.cfg.label == 'full' run: | eval "$(conda shell.bash hook)" && conda activate test pytest -rws -v --validate qcelemental/ From f957193f23d95edb9fda2b32e99f45e4c9b373bb Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 18:50:03 -0400 Subject: [PATCH 42/43] CI try 7 --- .github/workflows/CI.yml | 4 ++-- .github/workflows/QCSchema.yml | 8 ++++---- qcelemental/tests/test_zqcschema.py | 7 +------ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8f1f2ef58..40d1cb40b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -57,12 +57,12 @@ jobs: eval "$(conda shell.bash hook)" && conda activate test pytest -rws -v --cov=qcelemental --color=yes --cov-report=xml qcelemental/ - - name: PyTest B + - name: PyTest Validate shell: bash if: matrix.cfg.label == 'full' run: | eval "$(conda shell.bash hook)" && conda activate test - pytest -rws -v --validate qcelemental/ + pytest -rws -v --color=yes --validate qcelemental/ - name: CodeCov uses: codecov/codecov-action@v1 diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index ee54a214e..cd518a59e 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -26,8 +26,8 @@ jobs: path: qcsk ref: qcsk_export_2 #ref: master -# persist-credentials: false -# fetch-depth: 0 + persist-credentials: false + fetch-depth: 0 - name: Python Setup uses: actions/setup-python@v1 @@ -85,6 +85,6 @@ jobs: directory: ./qcsk repository: MolSSI/QCSchema branch: ${{ env.prbranch }} -# github_token: ${{ secrets.GITHUB_TOKEN }} - github_token: ${{ secrets.qcschema_from_qcelemental }} + github_token: ${{ secrets.GITHUB_TOKEN }} +# github_token: ${{ secrets.qcschema_from_qcelemental }} force: true diff --git a/qcelemental/tests/test_zqcschema.py b/qcelemental/tests/test_zqcschema.py index 925353528..6d314b8dc 100644 --- a/qcelemental/tests/test_zqcschema.py +++ b/qcelemental/tests/test_zqcschema.py @@ -9,12 +9,7 @@ @pytest.fixture(scope="module") def qcschema_models(): - # return {md.__name__: json.loads(md.schema_json()) for md in qcel.models.qcschema_models()} - models = {} - for md in qcel.models.qcschema_models(): - print(md) - models[md.__name__] = json.loads(md.schema_json()) - return models + return {md.__name__: json.loads(md.schema_json()) for md in qcel.models.qcschema_models()} files = sorted(_data_path.rglob("*.json")) From bdec27881b3dd472718137f1ddf662264438a1ea Mon Sep 17 00:00:00 2001 From: "Lori A. Burns" Date: Mon, 31 Aug 2020 21:25:45 -0400 Subject: [PATCH 43/43] CI try 8 --- .github/workflows/QCSchema.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/QCSchema.yml b/.github/workflows/QCSchema.yml index cd518a59e..44878bd33 100644 --- a/.github/workflows/QCSchema.yml +++ b/.github/workflows/QCSchema.yml @@ -26,8 +26,9 @@ jobs: path: qcsk ref: qcsk_export_2 #ref: master - persist-credentials: false +# persist-credentials: false fetch-depth: 0 + token: ${{ secrets.qcschema_from_qcelemental }} - name: Python Setup uses: actions/setup-python@v1 @@ -85,6 +86,6 @@ jobs: directory: ./qcsk repository: MolSSI/QCSchema branch: ${{ env.prbranch }} - github_token: ${{ secrets.GITHUB_TOKEN }} -# github_token: ${{ secrets.qcschema_from_qcelemental }} +# github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.qcschema_from_qcelemental }} force: true