From d2cbd6cc29ed750f56f4d25923703000596325d2 Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Thu, 27 Oct 2022 10:17:26 -0400 Subject: [PATCH 1/7] MAINT: Update for Pint 0.20.0 --- openff/units/data/defaults.txt | 3 ++- openff/units/elements.py | 2 +- openff/units/units.py | 13 +++++-------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/openff/units/data/defaults.txt b/openff/units/data/defaults.txt index 050eb85..a978d67 100644 --- a/openff/units/data/defaults.txt +++ b/openff/units/data/defaults.txt @@ -109,7 +109,8 @@ hertz = 1 / second = Hz reciprocal_centimeter = 1 / cm = cm_1 = kayser # Velocity -[velocity] = [length] / [time] = [speed] +# As of 0.20, derived dimensions cannot have aliases +[velocity] = [length] / [time] # Acceleration [acceleration] = [velocity] / [time] diff --git a/openff/units/elements.py b/openff/units/elements.py index 29ee4e8..29b55b5 100644 --- a/openff/units/elements.py +++ b/openff/units/elements.py @@ -36,7 +36,7 @@ "SYMBOLS", ] -MASSES: Dict[int, Quantity[float]] = { +MASSES: Dict[int, Quantity] = { index + 1: Quantity(mass, unit.dalton) for index, mass in enumerate( [ diff --git a/openff/units/units.py b/openff/units/units.py index 30cabfa..bcbf7dd 100644 --- a/openff/units/units.py +++ b/openff/units/units.py @@ -4,13 +4,10 @@ import uuid import warnings -from typing import TYPE_CHECKING, TypeVar +from typing import TYPE_CHECKING import pint from openff.utilities import requires_package -from pint.measurement import _Measurement -from pint.quantity import _Quantity -from pint.unit import _Unit from openff.units.utilities import get_defaults_path @@ -43,7 +40,7 @@ def _unpickle_measurement(cls, *args): return pint._unpickle(DEFAULT_UNIT_REGISTRY.Measurement, *args) -class Unit(_Unit): +class Unit(DEFAULT_UNIT_REGISTRY.Unit): # type: ignore[name-defined] """A unit of measure.""" _REGISTRY = DEFAULT_UNIT_REGISTRY @@ -52,10 +49,10 @@ def __reduce__(self): return _unpickle_unit, (Unit, self._units) -_MagnitudeType = TypeVar("_MagnitudeType") +# _MagnitudeType = TypeVar("_MagnitudeType") -class Quantity(_Quantity[_MagnitudeType]): +class Quantity(DEFAULT_UNIT_REGISTRY.Quantity): # type: ignore[name-defined] """A value with associated units.""" _REGISTRY = DEFAULT_UNIT_REGISTRY @@ -85,7 +82,7 @@ def to_openmm(self) -> "OpenMMQuantity": return to_openmm(self) -class Measurement(_Measurement): +class Measurement(DEFAULT_UNIT_REGISTRY.Measurement): # type: ignore[name-defined] """A value with associated units and uncertainty.""" _REGISTRY = DEFAULT_UNIT_REGISTRY From 1e3e07fc8ab9b3f3315daa5f648cf0aef67da52a Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Thu, 27 Oct 2022 10:24:57 -0400 Subject: [PATCH 2/7] MAINT: Update Pint pins --- devtools/conda-envs/docs_env.yaml | 2 +- devtools/conda-envs/test_env.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/devtools/conda-envs/docs_env.yaml b/devtools/conda-envs/docs_env.yaml index 5926fc5..b9da8fe 100644 --- a/devtools/conda-envs/docs_env.yaml +++ b/devtools/conda-envs/docs_env.yaml @@ -5,7 +5,7 @@ dependencies: - python - pip - numpy - - pint >=0.19 + - pint >=0.20 - openff-utilities >=0.1.3 - sphinx >=4.5,<5 - myst-parser>=0.13.6 diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index 0898ac4..3dac041 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -6,7 +6,7 @@ dependencies: - python - pip - numpy - - pint >=0.19.0 + - pint >=0.20.0 - openff-utilities >=0.1.3 # Tests From 1d021af79d3cb7a9e0f57001a5bbc7da5679a082 Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Thu, 27 Oct 2022 13:18:48 -0400 Subject: [PATCH 3/7] REF: Refactor for Pint 0.20.0 internals --- openff/units/__init__.py | 10 ++-- openff/units/tests/test_units.py | 4 +- openff/units/units.py | 78 +++++++++++++++----------------- setup.cfg | 2 + 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/openff/units/__init__.py b/openff/units/__init__.py index 196a006..c459025 100644 --- a/openff/units/__init__.py +++ b/openff/units/__init__.py @@ -1,8 +1,12 @@ -from pint import UnitRegistry - from openff.units._version import get_versions # type: ignore from openff.units.openmm import ensure_quantity -from openff.units.units import DEFAULT_UNIT_REGISTRY, Measurement, Quantity, Unit +from openff.units.units import ( + DEFAULT_UNIT_REGISTRY, + Measurement, + Quantity, + Unit, + UnitRegistry, +) __all__ = [ "unit", diff --git a/openff/units/tests/test_units.py b/openff/units/tests/test_units.py index 9074ffe..b07cad2 100644 --- a/openff/units/tests/test_units.py +++ b/openff/units/tests/test_units.py @@ -36,14 +36,14 @@ def test_pickle_unit(self): assert x == y - def test_pick_quantity(self): + def test_pickle_quantity(self): x = 1.0 * unit.kelvin y = pickle.loads(pickle.dumps(x)) assert x == y @skip_if_missing("uncertainties") - def test_pickle_quantity(self): + def test_pickle_quantity_uncertainties(self): x = (1.0 * unit.kelvin).plus_minus(0.05) y = pickle.loads(pickle.dumps(x)) diff --git a/openff/units/units.py b/openff/units/units.py index bcbf7dd..1e36d17 100644 --- a/openff/units/units.py +++ b/openff/units/units.py @@ -1,13 +1,13 @@ """ Core classes for OpenFF Units """ - import uuid import warnings from typing import TYPE_CHECKING import pint from openff.utilities import requires_package +from pint import UnitRegistry as _UnitRegistry from openff.units.utilities import get_defaults_path @@ -21,44 +21,34 @@ "Unit", ] -DEFAULT_UNIT_REGISTRY = pint.UnitRegistry(get_defaults_path()) -"""The default unit registry provided by OpenFF Units""" - - -def _unpickle_quantity(cls, *args): - """Rebuild quantity upon unpickling using the application registry.""" - return pint._unpickle(DEFAULT_UNIT_REGISTRY.Quantity, *args) - - -def _unpickle_unit(cls, *args): - """Rebuild unit upon unpickling using the application registry.""" - return pint._unpickle(DEFAULT_UNIT_REGISTRY.Unit, *args) - - -def _unpickle_measurement(cls, *args): - """Rebuild measurement upon unpickling using the application registry.""" - return pint._unpickle(DEFAULT_UNIT_REGISTRY.Measurement, *args) - - -class Unit(DEFAULT_UNIT_REGISTRY.Unit): # type: ignore[name-defined] - """A unit of measure.""" - - _REGISTRY = DEFAULT_UNIT_REGISTRY - +# def _unpickle_quantity(cls, *args): +# """Rebuild quantity upon unpickling using the application registry.""" +# return pint._unpickle(Quantity, *args) +# +# +# def _unpickle_unit(cls, *args): +# """Rebuild unit upon unpickling using the application registry.""" +# return pint._unpickle(Unit, *args) +# +# +# def _unpickle_measurement(cls, *args): +# """Rebuild measurement upon unpickling using the application registry.""" +# return pint._unpickle(Measurement, *args) + + +class Unit: + pass + """ def __reduce__(self): return _unpickle_unit, (Unit, self._units) + """ -# _MagnitudeType = TypeVar("_MagnitudeType") - - -class Quantity(DEFAULT_UNIT_REGISTRY.Quantity): # type: ignore[name-defined] - """A value with associated units.""" - - _REGISTRY = DEFAULT_UNIT_REGISTRY - +class Quantity: + """ def __reduce__(self): return _unpickle_quantity, (Quantity, self.magnitude, self._units) + """ def __dask_tokenize__(self): return uuid.uuid4().hex @@ -82,13 +72,11 @@ def to_openmm(self) -> "OpenMMQuantity": return to_openmm(self) -class Measurement(DEFAULT_UNIT_REGISTRY.Measurement): # type: ignore[name-defined] - """A value with associated units and uncertainty.""" - - _REGISTRY = DEFAULT_UNIT_REGISTRY - +class Measurement: + """ def __reduce__(self): return _unpickle_measurement, (Measurement, self.magnitude, self._units) + """ def __dask_tokenize__(self): return uuid.uuid4().hex @@ -99,9 +87,17 @@ def _dask_finalize(results, func, args, units): return Measurement(values, units) -DEFAULT_UNIT_REGISTRY.Unit = Unit -DEFAULT_UNIT_REGISTRY.Quantity = Quantity -DEFAULT_UNIT_REGISTRY.Measurement = Measurement +class UnitRegistry(_UnitRegistry): + _quantity_class = Quantity + _unit_class = Quantity + _measurement_class = Measurement + + +DEFAULT_UNIT_REGISTRY = UnitRegistry(get_defaults_path()) + +Unit = DEFAULT_UNIT_REGISTRY.Unit +Quantity = DEFAULT_UNIT_REGISTRY.Quantity +Measurement = DEFAULT_UNIT_REGISTRY.Measurement pint.set_application_registry(DEFAULT_UNIT_REGISTRY) diff --git a/setup.cfg b/setup.cfg index 43ef0a5..aa04bb8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,6 +16,8 @@ exclude_lines = [flake8] max-line-length = 119 ignore = E203,W503 +per-file-ignores = + openff/units/units.py:F811 [isort] multi_line_output=3 From 36b50c14adb2010807391fb0db37bbb966e55c7a Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Thu, 27 Oct 2022 13:25:04 -0400 Subject: [PATCH 4/7] MAINT: Continue tests if Mypy fails --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0b849bc..8b05cc1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -74,6 +74,7 @@ jobs: - name: Run mypy if: ${{ matrix.python-version == 3.9 }} + continue-on-error: true run: | mypy --namespace-packages -p "openff.units" From d7621d27559102b5b1e0b80921a827cdf69a4ae4 Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Thu, 27 Oct 2022 13:43:12 -0400 Subject: [PATCH 5/7] REF: Privative custom classes --- openff/units/openmm.py | 2 ++ openff/units/units.py | 27 ++++++++++----------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/openff/units/openmm.py b/openff/units/openmm.py index 18c7236..79a3a47 100644 --- a/openff/units/openmm.py +++ b/openff/units/openmm.py @@ -211,6 +211,8 @@ def to_openmm_inner(quantity) -> "openmm_unit.Quantity": return value * openmm_unit_ + assert isinstance(quantity, Quantity) + try: return to_openmm_inner(quantity) except MissingOpenMMUnitError: diff --git a/openff/units/units.py b/openff/units/units.py index 1e36d17..37f9ef1 100644 --- a/openff/units/units.py +++ b/openff/units/units.py @@ -8,6 +8,8 @@ import pint from openff.utilities import requires_package from pint import UnitRegistry as _UnitRegistry +from pint.facets.measurement import Measurement as _BaseMeasurement +from pint.facets.plain import PlainQuantity, PlainUnit from openff.units.utilities import get_defaults_path @@ -36,27 +38,18 @@ # return pint._unpickle(Measurement, *args) -class Unit: +class _Unit(PlainUnit): pass - """ - def __reduce__(self): - return _unpickle_unit, (Unit, self._units) - """ - -class Quantity: - """ - def __reduce__(self): - return _unpickle_quantity, (Quantity, self.magnitude, self._units) - """ +class _Quantity(PlainQuantity): def __dask_tokenize__(self): return uuid.uuid4().hex @staticmethod def _dask_finalize(results, func, args, units): values = func(results, *args) - return Quantity(values, units) + return _Quantity(values, units) @requires_package("openmm") def to_openmm(self) -> "OpenMMQuantity": @@ -72,7 +65,7 @@ def to_openmm(self) -> "OpenMMQuantity": return to_openmm(self) -class Measurement: +class _Measurement(_BaseMeasurement): """ def __reduce__(self): return _unpickle_measurement, (Measurement, self.magnitude, self._units) @@ -84,13 +77,13 @@ def __dask_tokenize__(self): @staticmethod def _dask_finalize(results, func, args, units): values = func(results, *args) - return Measurement(values, units) + return _Measurement(values, units) class UnitRegistry(_UnitRegistry): - _quantity_class = Quantity - _unit_class = Quantity - _measurement_class = Measurement + _quantity_class = _Quantity + _unit_class = _Unit + _measurement_class = _Measurement DEFAULT_UNIT_REGISTRY = UnitRegistry(get_defaults_path()) From 02854ad7c7d6f91d860d7449d0431601faea55bd Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Thu, 27 Oct 2022 13:53:36 -0400 Subject: [PATCH 6/7] DEBUG: Update Pint version --- .github/workflows/ci.yaml | 6 +++--- devtools/conda-envs/docs_env.yaml | 2 +- devtools/conda-envs/test_env.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8b05cc1..b2d1f17 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -81,18 +81,18 @@ jobs: - name: Run unit tests with OpenMM if: ${{ matrix.openmm == 'true' }} run: | - pytest $PYTEST_ARGS $COV openff/units/tests/ + python -m pytest $PYTEST_ARGS $COV openff/units/tests/ - name: Run unit tests without OpenMM if: ${{ matrix.openmm == 'false' }} run: | - pytest $PYTEST_ARGS $COV openff/units/tests/ \ + python -m pytest $PYTEST_ARGS $COV openff/units/tests/ \ --ignore=openff/units/tests/test_openmm.py - name: Run docexamples if: ${{ matrix.openmm == 'true' }} run: | - pytest --doctest-modules $PYTEST_ARGS $COV openff + python -m pytest --doctest-modules $PYTEST_ARGS $COV openff --ignore=openff/units/tests - name: Codecov uses: codecov/codecov-action@v1 diff --git a/devtools/conda-envs/docs_env.yaml b/devtools/conda-envs/docs_env.yaml index b9da8fe..3393797 100644 --- a/devtools/conda-envs/docs_env.yaml +++ b/devtools/conda-envs/docs_env.yaml @@ -5,7 +5,7 @@ dependencies: - python - pip - numpy - - pint >=0.20 + - pint >=0.20.1 - openff-utilities >=0.1.3 - sphinx >=4.5,<5 - myst-parser>=0.13.6 diff --git a/devtools/conda-envs/test_env.yaml b/devtools/conda-envs/test_env.yaml index 3dac041..01b6853 100644 --- a/devtools/conda-envs/test_env.yaml +++ b/devtools/conda-envs/test_env.yaml @@ -6,7 +6,7 @@ dependencies: - python - pip - numpy - - pint >=0.20.0 + - pint >=0.20.1 - openff-utilities >=0.1.3 # Tests From 7b0d1872b491ddd49f992239db1fecad65cd0e21 Mon Sep 17 00:00:00 2001 From: "Matthew W. Thompson" Date: Tue, 1 Nov 2022 13:04:56 -0500 Subject: [PATCH 7/7] REF: Use direct subclasses, remove unused code --- .github/workflows/ci.yaml | 7 +++--- openff/units/openmm.py | 2 +- openff/units/units.py | 52 +++++++++++++++------------------------ setup.cfg | 6 ----- 4 files changed, 24 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b2d1f17..ccd55b2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -74,25 +74,24 @@ jobs: - name: Run mypy if: ${{ matrix.python-version == 3.9 }} - continue-on-error: true run: | mypy --namespace-packages -p "openff.units" - name: Run unit tests with OpenMM if: ${{ matrix.openmm == 'true' }} run: | - python -m pytest $PYTEST_ARGS $COV openff/units/tests/ + pytest $PYTEST_ARGS $COV openff/units/tests/ - name: Run unit tests without OpenMM if: ${{ matrix.openmm == 'false' }} run: | - python -m pytest $PYTEST_ARGS $COV openff/units/tests/ \ + pytest $PYTEST_ARGS $COV openff/units/tests/ \ --ignore=openff/units/tests/test_openmm.py - name: Run docexamples if: ${{ matrix.openmm == 'true' }} run: | - python -m pytest --doctest-modules $PYTEST_ARGS $COV openff --ignore=openff/units/tests + pytest --doctest-modules $PYTEST_ARGS $COV openff --ignore=openff/units/tests - name: Codecov uses: codecov/codecov-action@v1 diff --git a/openff/units/openmm.py b/openff/units/openmm.py index 79a3a47..b83b89a 100644 --- a/openff/units/openmm.py +++ b/openff/units/openmm.py @@ -264,7 +264,7 @@ def _ensure_openff_quantity( ) else: try: - return unit.Quantity( # type: ignore + return unit.Quantity( unknown_quantity, unit.dimensionless, ) diff --git a/openff/units/units.py b/openff/units/units.py index 37f9ef1..4ca257d 100644 --- a/openff/units/units.py +++ b/openff/units/units.py @@ -7,9 +7,10 @@ import pint from openff.utilities import requires_package +from pint import Measurement as _Measurement +from pint import Quantity as _Quantity +from pint import Unit as _Unit from pint import UnitRegistry as _UnitRegistry -from pint.facets.measurement import Measurement as _BaseMeasurement -from pint.facets.plain import PlainQuantity, PlainUnit from openff.units.utilities import get_defaults_path @@ -23,33 +24,23 @@ "Unit", ] -# def _unpickle_quantity(cls, *args): -# """Rebuild quantity upon unpickling using the application registry.""" -# return pint._unpickle(Quantity, *args) -# -# -# def _unpickle_unit(cls, *args): -# """Rebuild unit upon unpickling using the application registry.""" -# return pint._unpickle(Unit, *args) -# -# -# def _unpickle_measurement(cls, *args): -# """Rebuild measurement upon unpickling using the application registry.""" -# return pint._unpickle(Measurement, *args) - - -class _Unit(PlainUnit): + +class Unit(_Unit): + """A unit of measure.""" + pass -class _Quantity(PlainQuantity): +class Quantity(_Quantity): + """A value with associated units.""" + def __dask_tokenize__(self): return uuid.uuid4().hex @staticmethod def _dask_finalize(results, func, args, units): values = func(results, *args) - return _Quantity(values, units) + return Quantity(values, units) @requires_package("openmm") def to_openmm(self) -> "OpenMMQuantity": @@ -65,11 +56,8 @@ def to_openmm(self) -> "OpenMMQuantity": return to_openmm(self) -class _Measurement(_BaseMeasurement): - """ - def __reduce__(self): - return _unpickle_measurement, (Measurement, self.magnitude, self._units) - """ +class Measurement(_Measurement): + """A value with associated units and uncertainty.""" def __dask_tokenize__(self): return uuid.uuid4().hex @@ -77,20 +65,20 @@ def __dask_tokenize__(self): @staticmethod def _dask_finalize(results, func, args, units): values = func(results, *args) - return _Measurement(values, units) + return Measurement(values, units) class UnitRegistry(_UnitRegistry): - _quantity_class = _Quantity - _unit_class = _Unit - _measurement_class = _Measurement + _quantity_class = Quantity + _unit_class = Unit + _measurement_class = Measurement DEFAULT_UNIT_REGISTRY = UnitRegistry(get_defaults_path()) -Unit = DEFAULT_UNIT_REGISTRY.Unit -Quantity = DEFAULT_UNIT_REGISTRY.Quantity -Measurement = DEFAULT_UNIT_REGISTRY.Measurement +Unit: _Unit = DEFAULT_UNIT_REGISTRY.Unit # type: ignore[no-redef] +Quantity: _Quantity = DEFAULT_UNIT_REGISTRY.Quantity # type: ignore[no-redef] +Measurement: _Measurement = DEFAULT_UNIT_REGISTRY.Measurement # type: ignore[no-redef] pint.set_application_registry(DEFAULT_UNIT_REGISTRY) diff --git a/setup.cfg b/setup.cfg index aa04bb8..1d15025 100644 --- a/setup.cfg +++ b/setup.cfg @@ -49,14 +49,8 @@ ignore_missing_imports = True [mypy-pint.*] ignore_missing_imports = True -[mypy-openff.utilities.*] -ignore_missing_imports = True - [mypy-openmm] ignore_missing_imports = True [mypy-openmm.unit] ignore_missing_imports = True - -[mypy-openmm.app.element] -ignore_missing_imports = True