diff --git a/python/python/lancedb/__init__.py b/python/python/lancedb/__init__.py index 623279bf0..9cc1db0d5 100644 --- a/python/python/lancedb/__init__.py +++ b/python/python/lancedb/__init__.py @@ -7,7 +7,13 @@ from concurrent.futures import ThreadPoolExecutor from datetime import timedelta from typing import Dict, Optional, Union, Any, List, Iterable, TYPE_CHECKING -from ._lancedb import __version__ as __version__ +from packaging.version import Version as _Version + +from ._lancedb import __version__ as _native_version + +# Match Python package metadata without requiring the lancedb distribution. +__version__ = str(_Version(_native_version)) + from ._lancedb import connect as lancedb_connect from ._lancedb import FtsToken from ._lancedb import FunctionErrorFragment as FunctionErrorFragment diff --git a/python/python/tests/test_import.py b/python/python/tests/test_import.py index e8373b03b..6f9b00e5d 100644 --- a/python/python/tests/test_import.py +++ b/python/python/tests/test_import.py @@ -34,9 +34,23 @@ def test_native_extension_does_not_link_openssl(): ) -def test_top_level_version_comes_from_native_module(): +@pytest.mark.parametrize( + "native_version, expected_version", + [ + ("0.41.0", "0.41.0"), + ("0.41.0-alpha.1", "0.41.0a1"), + ("0.41.0-beta.17", "0.41.0b17"), + ("0.41.0-rc.1", "0.41.0rc1"), + ("0.41.0-dev.1", "0.41.0.dev1"), + ], +) +def test_top_level_version_comes_from_native_module(native_version, expected_version): child_code = """ +import importlib import importlib.metadata +import sys + +from packaging.version import Version orig_version = importlib.metadata.version @@ -51,13 +65,17 @@ import lancedb import lancedb._lancedb as native_module import lancedb.db -assert lancedb.__version__ == native_module.__version__ +assert lancedb.__version__ == str(Version(native_module.__version__)) + +native_module.__version__ = sys.argv[1] +importlib.reload(lancedb) +assert lancedb.__version__ == sys.argv[2] """ env = os.environ.copy() env["PYTHONPATH"] = os.pathsep.join(path for path in sys.path if path) result = subprocess.run( - [sys.executable, "-c", child_code], + [sys.executable, "-c", child_code, native_version, expected_version], check=False, capture_output=True, text=True, diff --git a/python/python/tests/test_package_metadata.py b/python/python/tests/test_package_metadata.py index 58f4e7267..9bdcbb3b0 100644 --- a/python/python/tests/test_package_metadata.py +++ b/python/python/tests/test_package_metadata.py @@ -2,6 +2,7 @@ # SPDX-FileCopyrightText: Copyright The LanceDB Authors import importlib +import importlib.metadata import re import sys from pathlib import Path @@ -9,6 +10,18 @@ from pathlib import Path import pytest +@pytest.mark.parametrize("distribution", ["lancedb", "lancedb-compat"]) +def test_version_matches_package_metadata(distribution): + import lancedb + + try: + package_version = importlib.metadata.version(distribution) + except importlib.metadata.PackageNotFoundError: + pytest.skip(f"{distribution} is not installed") + + assert lancedb.__version__ == package_version + + @pytest.mark.parametrize("name", ["JobInfo", "JobDescription", "JobFailureInfo"]) def test_job_metadata_types_have_resolvable_modules(name): """Documentation tools resolve re-exports through each type's module."""