diff --git a/pyproject.toml b/pyproject.toml index 76c8526712..8398c63ec2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,8 @@ dependencies = [ "tenacity>=8.2.3", "pyroaring>=1.0.0", "cachetools>=5.5", - "zstandard>=0.13.0" + "zstandard>=0.13.0", + "typing-extensions>=4.4.0" # Self/override are imported at runtime on Python < 3.12 ] [project.urls] diff --git a/tests/test_version.py b/tests/test_version.py index dcaa3f0735..1fa0c6a527 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -28,3 +28,22 @@ def test_version_format() -> None: "This failure could be due to a recent version bump in the Pyiceberg library. " "Please ensure you have the latest version installed by rerunning `make install` command." ) + + +def test_typing_extensions_is_a_core_dependency() -> None: + # typing_extensions is imported unconditionally at import time (e.g. Self in + # pyiceberg/typedef.py, override in the catalog and IO modules), so it must be a + # core runtime dependency rather than only a development one. + from importlib import metadata + + from packaging.requirements import Requirement + from packaging.utils import canonicalize_name + + requirements = [Requirement(requirement) for requirement in metadata.requires("pyiceberg") or []] + # Core dependencies carry no environment marker; optional extras add "; extra == ...". + core_dependencies = {canonicalize_name(requirement.name) for requirement in requirements if requirement.marker is None} + + assert canonicalize_name("typing-extensions") in core_dependencies, ( + "typing-extensions must be declared in [project.dependencies] because it is imported at runtime; " + "found only these core dependencies: " + ", ".join(sorted(core_dependencies)) + ) diff --git a/uv.lock b/uv.lock index 0aea046671..1b34be6687 100644 --- a/uv.lock +++ b/uv.lock @@ -1408,7 +1408,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -4901,6 +4901,7 @@ dependencies = [ { name = "rich" }, { name = "strictyaml" }, { name = "tenacity" }, + { name = "typing-extensions" }, { name = "zstandard" }, ] @@ -5078,6 +5079,7 @@ requires-dist = [ { name = "thrift", marker = "extra == 'hive'", specifier = ">=0.13.0" }, { name = "thrift", marker = "extra == 'hive-kerberos'", specifier = ">=0.13.0" }, { name = "thrift-sasl", marker = "extra == 'hive-kerberos'", specifier = ">=0.4.3" }, + { name = "typing-extensions", specifier = ">=4.4.0" }, { name = "zstandard", specifier = ">=0.13.0" }, ] provides-extras = ["pyarrow", "pandas", "duckdb", "ray", "bodo", "daft", "polars", "snappy", "hive", "hive-kerberos", "s3fs", "glue", "adlfs", "dynamodb", "bigquery", "sql-postgres", "sql-sqlite", "gcsfs", "rest-sigv4", "hf", "pyiceberg-core", "datafusion", "gcp-auth", "entra-auth", "geoarrow"]