diff --git a/cfa/dataops/utils.py b/cfa/dataops/utils.py index e1b6883..1c29829 100644 --- a/cfa/dataops/utils.py +++ b/cfa/dataops/utils.py @@ -193,6 +193,25 @@ def normalize(version: str) -> str: return version.replace("T", ".").replace("-", ".") +def construct_version_spec(version: str | None) -> str | None: + """Normalize a version string into a packaging specifier. + + If the input already starts with a specifier operator (e.g. ``>``, ``<``, ``=``, ``~``, or ``!``), + it is returned unchanged (after stripping whitespace). Otherwise, an exact-match specifier is created + by prepending ``==``. + """ + if version is None: + return None + + version = version.strip() + if version == "": + return "" + + if version.startswith((">", "<", "=", "~", "!")): + return version + return f"=={version}" + + def version_matcher( version_spec: str | None, available_versions: list[str], @@ -223,7 +242,7 @@ def version_matcher( versions = sorted( (Version(normalize(version)), version) for version in available_versions ) - + version_spec = construct_version_spec(version_spec) if version_spec is not None: specset = SpecifierSet(normalize(version_spec)) versions = [ diff --git a/changelog.md b/changelog.md index 4c0a806..f413958 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,10 @@ and this project adheres to [Calendar Versioning](https://calver.org/). The versioning pattern is `YYYY.MM.DD.micro(a/b/{none if release}) --- +## [2026.07.21.0] + +- adds function to translate bare versions to version_spec + ## [2026.07.20.0] - change most print statements to logging diff --git a/pyproject.toml b/pyproject.toml index fa74eec..7e9dca5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cfa.dataops" -version = "2026.07.20.0" +version = "2026.07.21.0" description = "Data cataloging, ETL, modeling, verification, and validation for CFA" authors = [ { name = "Phil Rogers", email = "ap66@cdc.gov" }, diff --git a/tests/test_utils_version_matcher.py b/tests/test_utils_version_matcher.py index a2021ff..5bc5b30 100644 --- a/tests/test_utils_version_matcher.py +++ b/tests/test_utils_version_matcher.py @@ -2,7 +2,38 @@ import pytest -from cfa.dataops.utils import version_matcher +from cfa.dataops.utils import construct_version_spec, version_matcher + + +class TestConstructVersionSpec: + """Tests for construct_version_spec helper.""" + + @pytest.mark.parametrize( + "raw_version,expected", + [ + ("2025-12-15T00-00-00", "==2025-12-15T00-00-00"), + (">2025-12-15T00-00-00", ">2025-12-15T00-00-00"), + ("<2025-12-15T00-00-00", "<2025-12-15T00-00-00"), + ("==2025-12-15T00-00-00", "==2025-12-15T00-00-00"), + ("~=2025-12-15T00-00-00", "~=2025-12-15T00-00-00"), + ("!=2025-12-15T00-00-00", "!=2025-12-15T00-00-00"), + ("", ""), + (" ", ""), + ], + ) + def test_construct_version_spec(self, raw_version, expected): + assert construct_version_spec(raw_version) == expected + + def test_version_matcher_accepts_raw_version(self): + available_versions = [ + "2025-12-15T00-00-00", + "2025-12-16T00-00-00", + "2025-12-17T00-00-00", + ] + assert ( + version_matcher("2025-12-16T00-00-00", available_versions) + == "2025-12-16T00-00-00" + ) class TestVersionMatcher: diff --git a/uv.lock b/uv.lock index f46fcb3..e01cbfa 100644 --- a/uv.lock +++ b/uv.lock @@ -655,7 +655,7 @@ dependencies = [ [[package]] name = "cfa-dataops" -version = "2026.6.30.0" +version = "2026.7.20.0" source = { editable = "." } dependencies = [ { name = "altair" },