Skip to content

Commit

Permalink
Merge pull request #260 from SCM-NV/getattr
Browse files Browse the repository at this point in the history
MAINT: Up the stacklevel of `Result.__getattr__` warnings
  • Loading branch information
BvB93 committed Oct 20, 2021
2 parents 7c61fab + 454fabd commit 110f450
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
7 changes: 4 additions & 3 deletions src/qmflows/packages/packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,16 @@ def __getattr__(self, prop: str) -> Any:
elif not (has_crashed or is_private or prop in self.prop_mapping):
if self._results_open:
warn(f"Generic property {prop!r} not defined",
category=QMFlows_Warning)
category=QMFlows_Warning, stacklevel=2)

# Do not issue this warning if the Results object is still pickled
else: # Unpickle the Results instance and try again
self._unpack_results()
try:
return vars(self)[prop] # Avoid recursive `getattr` calls
except KeyError:
warn(f"Generic property {prop!r} not defined", category=QMFlows_Warning)
warn(f"Generic property {prop!r} not defined",
category=QMFlows_Warning, stacklevel=2)

elif has_crashed and not is_private:
warn(f"""
Expand All @@ -148,7 +149,7 @@ def __getattr__(self, prop: str) -> Any:
Are you sure that you have the package installed or
you have loaded the package in the cluster. For example:
`module load AwesomeQuantumPackage/3.141592`
""", category=QMFlows_Warning)
""", category=QMFlows_Warning, stacklevel=2)
return None

def get_property(self, prop: str) -> Any:
Expand Down
36 changes: 36 additions & 0 deletions test/test_adf_mock.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
"""Mock the ADF output."""

from pathlib import Path
from typing import Optional

import pytest
from assertionlib import assertion
from pytest_mock import MockFixture
from scm.plams import Molecule

from qmflows import adf, templates
from qmflows.packages.SCM import ADF_Result
from qmflows.test_utils import PATH, PATH_MOLECULES
from qmflows.warnings_qmflows import QMFlows_Warning
from qmflows.utils import InitRestart

WORKDIR = PATH / "output_adf"

Expand Down Expand Up @@ -38,3 +45,32 @@ def test_adf_mock(mocker: MockFixture):
mol = rs.molecule
assertion.isinstance(mol, Molecule)
assertion.len_eq(mol, 6) # there are 6 atoms


@pytest.mark.parametrize("name,match,status", [
("bob", "Generic property 'bob' not defined", None),
("energy", "It is not possible to retrieve property: 'energy'", "crashed"),
], ids=["undefined_property", "job_crashed"])
def test_getattr_warning(tmp_path: Path, name: str, match: str, status: Optional[str]) -> None:
mol = Molecule(PATH_MOLECULES / "acetonitrile.xyz")
jobname = "ADFjob"
dill_path = WORKDIR / jobname / "ADFjob.dill"
plams_dir = WORKDIR / jobname
result = ADF_Result(templates.geometry, mol, jobname,
dill_path=dill_path, work_dir=plams_dir,
plams_dir=plams_dir)
if status is not None:
result.status = status

# Need to fire up `plams.init` so the .dill file can be unpickled by `plams.load_job`
with InitRestart(tmp_path):
with pytest.warns(QMFlows_Warning, match=match) as rec:
getattr(result, name)
assertion.len_eq(rec.list, 1)
assertion.eq(rec.list[0].filename, __file__)

# Test a second time after the .dill file has been unpickled
with pytest.warns(QMFlows_Warning, match=match) as rec:
getattr(result, name)
assertion.len_eq(rec.list, 1)
assertion.eq(rec.list[0].filename, __file__)

0 comments on commit 110f450

Please sign in to comment.