From d0ce489b21ad750aea5c047435d25f62157f1173 Mon Sep 17 00:00:00 2001 From: Ed Rogers Date: Mon, 6 Oct 2025 13:23:20 -0500 Subject: [PATCH] fix: use stdlib override when possible (#2699) ## Description of changes Fixes #2698 This PR uses [`typing.override`](https://docs.python.org/3/library/typing.html#typing.override) in favor of the [`overrides`](https://pypi.org/project/overrides/) dependency when possible. As of Python 3.12, the standard library offers `typing.override` to perform a static check on overridden methods. ### Motivation Currently, `overrides` is incompatible with Python 3.14. As a result, any package that attempts to import `overrides` using Python 3.14+ will raise an `AttributeError`. An [issue](https://github.com/mkorpela/overrides/issues/127) has been raised and a [pull request](https://github.com/mkorpela/overrides/pull/133) has been submitted to the GitHub repo for the `overrides` project. But the maintainer has been unresponsive. To ensure readiness for Python 3.14, this package (and any other package directly depending on `overrides`) should consider using `typing.override` instead. ### Impact The standard library added `typing.override` as of 3.12. As a result, this change will affect only users of Python 3.12+. Previous versions will continue to rely on `overrides`. Notably, the standard library implementation is slightly different than that of `overrides`. A thorough discussion of those differences is shown in [PEP 698](https://peps.python.org/pep-0698/), and it is also summarized nicely by the maintainer of `overrides` [here](https://github.com/mkorpela/overrides/issues/126#issuecomment-2401327116). There are 2 main ways that switching from `overrides` to `typing.override` will have an impact on developers of this repo. 1. `typing.override` does not implement any runtime checking. Instead, it provides information to type checkers. 2. The stdlib does not provide a mixin class to enforce override decorators on child classes. (Their reasoning for this is explained in [the PEP](https://peps.python.org/pep-0698/).) This PR disables that behavior entirely by replacing the `EnforceOverrides`. --- python/pyproject.toml | 2 +- python/python/lancedb/db.py | 10 +++++++++- python/python/lancedb/namespace.py | 7 ++++++- python/python/lancedb/remote/db.py | 7 ++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/python/pyproject.toml b/python/pyproject.toml index e24dedf1..118b23dc 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -5,7 +5,7 @@ dynamic = ["version"] dependencies = [ "deprecation", "numpy", - "overrides>=0.7", + "overrides>=0.7; python_version<'3.12'", "packaging", "pyarrow>=16", "pydantic>=1.10", diff --git a/python/python/lancedb/db.py b/python/python/lancedb/db.py index d3aa1fe5..5d83c89e 100644 --- a/python/python/lancedb/db.py +++ b/python/python/lancedb/db.py @@ -6,10 +6,18 @@ from __future__ import annotations from abc import abstractmethod from pathlib import Path +import sys from typing import TYPE_CHECKING, Dict, Iterable, List, Literal, Optional, Union +if sys.version_info >= (3, 12): + from typing import override + + class EnforceOverrides: + pass +else: + from overrides import EnforceOverrides, override # type: ignore + from lancedb.embeddings.registry import EmbeddingFunctionRegistry -from overrides import EnforceOverrides, override # type: ignore from lancedb.common import data_to_reader, sanitize_uri, validate_schema from lancedb.background_loop import LOOP diff --git a/python/python/lancedb/namespace.py b/python/python/lancedb/namespace.py index b0c07d06..41968fff 100644 --- a/python/python/lancedb/namespace.py +++ b/python/python/lancedb/namespace.py @@ -12,13 +12,18 @@ from __future__ import annotations from typing import Dict, Iterable, List, Optional, Union import os +import sys + +if sys.version_info >= (3, 12): + from typing import override +else: + from overrides import override from lancedb.db import DBConnection from lancedb.table import LanceTable, Table from lancedb.util import validate_table_name from lancedb.common import validate_schema from lancedb.table import sanitize_create_table -from overrides import override from lance_namespace import LanceNamespace, connect as namespace_connect from lance_namespace_urllib3_client.models import ( diff --git a/python/python/lancedb/remote/db.py b/python/python/lancedb/remote/db.py index b839213e..10237446 100644 --- a/python/python/lancedb/remote/db.py +++ b/python/python/lancedb/remote/db.py @@ -5,15 +5,20 @@ from datetime import timedelta import logging from concurrent.futures import ThreadPoolExecutor +import sys from typing import Any, Dict, Iterable, List, Optional, Union from urllib.parse import urlparse import warnings +if sys.version_info >= (3, 12): + from typing import override +else: + from overrides import override + # Remove this import to fix circular dependency # from lancedb import connect_async from lancedb.remote import ClientConfig import pyarrow as pa -from overrides import override from ..common import DATA from ..db import DBConnection, LOOP