diff --git a/changelog.d/version-from-metadata.fixed.md b/changelog.d/version-from-metadata.fixed.md new file mode 100644 index 00000000..a9a36fd8 --- /dev/null +++ b/changelog.d/version-from-metadata.fixed.md @@ -0,0 +1 @@ +- Fixed `microimpute.__version__` reporting 1.1.2 while the package was at 3.1.1, by reading the version from installed package metadata. diff --git a/microimpute/__init__.py b/microimpute/__init__.py index 5acfe3e2..7b8e81df 100644 --- a/microimpute/__init__.py +++ b/microimpute/__init__.py @@ -19,7 +19,14 @@ - Visualization: performance and comparison plots """ -__version__ = "1.1.2" +from importlib.metadata import PackageNotFoundError, version as _version + +try: + __version__ = _version("microimpute") +except PackageNotFoundError: + # Running from a source tree with no install. Keep it PEP 440 parseable so + # a consumer calling packaging.version.parse on it does not raise. + __version__ = "0.0.0+unknown" # Import automated imputation from microimpute.comparisons.autoimpute import AutoImputeResult, autoimpute diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 00000000..139086a8 --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,42 @@ +"""The reported version must match the installed distribution. + +`__version__` was hardcoded and drifted to 1.1.2 while the package was 3.1.1, +which is the regression this guards against. +""" + +from importlib.metadata import version + +import pytest +from packaging.version import Version + +import microimpute + + +def test_version_matches_installed_distribution(): + assert microimpute.__version__ == version("microimpute") + + +def test_version_is_pep440_parseable(): + """The fallback must parse too, or consumers comparing versions raise.""" + Version(microimpute.__version__) + Version("0.0.0+unknown") + + +def test_fallback_used_when_distribution_is_absent(monkeypatch): + """The fallback branch runs when the distribution cannot be found.""" + import importlib.metadata + + def _raise(_name): + raise importlib.metadata.PackageNotFoundError(_name) + + monkeypatch.setattr(importlib.metadata, "version", _raise) + + # Re-run the same lookup __init__ performs, rather than reloading the + # package: reloading re-imports every model and is slow and fragile. + try: + resolved = importlib.metadata.version("microimpute") + except importlib.metadata.PackageNotFoundError: + resolved = "0.0.0+unknown" + + assert resolved == "0.0.0+unknown" + Version(resolved)