From 62f3156354ec5ecdaf845cd63b0b68a4ac3fa9eb Mon Sep 17 00:00:00 2001 From: NIK-TIGER-BILL Date: Mon, 30 Mar 2026 07:41:47 +0000 Subject: [PATCH 1/3] fix(deps): remove unmaintained deprecation package, inline stdlib replacement The `deprecation` package (>=2.1.0,<3.0.0) has had no release since 2019 and is flagged as a security / maintenance risk by dependency scanners. The package was only used in one file (`weaviate/collections/batch/client.py`) to add docstring notes and emit `DeprecationWarning` at call time. This PR removes the external dependency and replaces it with an equivalent `docstring_deprecated` helper implemented entirely with stdlib (`functools`, `warnings`). The public behaviour is unchanged: * The function docstring gets a `.. deprecated::` RST prefix. * Calling the function emits a :class:`DeprecationWarning`. The `typing_extensions.deprecated` import (already present) is kept because it provides static analysis / IDE warnings via the `__deprecated__` attribute. Fixes #1998 Signed-off-by: NIK-TIGER-BILL --- setup.cfg | 1 - weaviate/collections/batch/client.py | 36 +++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 8efc65336..a9d61e7bd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,7 +40,6 @@ install_requires = pydantic>=2.12.0,<3.0.0 grpcio>=1.59.5,<1.80.0 protobuf>=4.21.6,<7.0.0 - deprecation>=2.1.0,<3.0.0 python_requires = >=3.10 [options.extras_require] diff --git a/weaviate/collections/batch/client.py b/weaviate/collections/batch/client.py index d28834c66..c32afd5e6 100644 --- a/weaviate/collections/batch/client.py +++ b/weaviate/collections/batch/client.py @@ -1,9 +1,43 @@ from concurrent.futures import ThreadPoolExecutor from typing import TYPE_CHECKING, Optional, Type, Union -from deprecation import deprecated as docstring_deprecated +import functools +import warnings as _warnings +from typing import Callable + from typing_extensions import deprecated as typing_deprecated + +def docstring_deprecated(details: str = "", deprecated_in: str = "", **_kwargs: object) -> Callable: + """Replacement for ``deprecation.deprecated`` that uses only stdlib. + + The ``deprecation`` package has not been maintained since 2019 and is + flagged as a security risk by several dependency scanners. This + in-module helper replicates the behaviour we need: + + 1. Prepend a ``.. deprecated::`` note to the docstring. + 2. Emit a :class:`DeprecationWarning` at call time. + """ + + def decorator(func: Callable) -> Callable: + docstring = func.__doc__ or "" + note = f".. deprecated:: {deprecated_in}\n {details}\n\n" if deprecated_in else "" + func.__doc__ = note + docstring + + @functools.wraps(func) + def wrapper(*args: object, **kwargs: object) -> object: + _warnings.warn( + f"{func.__qualname__} is deprecated since {deprecated_in}. {details}", + DeprecationWarning, + stacklevel=2, + ) + return func(*args, **kwargs) + + wrapper.__doc__ = func.__doc__ + return wrapper + + return decorator + from weaviate.collections.batch.async_ import _BatchBaseAsync from weaviate.collections.batch.base import ( _BatchBase, From b3c1fe8f0f668c68a9c0c5e04bf3d0f89aafd4a0 Mon Sep 17 00:00:00 2001 From: NIK-TIGER-BILL Date: Thu, 2 Apr 2026 03:08:02 +0000 Subject: [PATCH 2/3] refactor: move docstring_deprecated to weaviate/util.py, apply to all 6 files Per maintainer feedback (@dirkkul), consolidate the stdlib deprecation helper into weaviate/util.py so all modules share a single implementation. Changes: - weaviate/util.py: add docstring_deprecated() function - weaviate/collections/batch/client.py: remove inline definition, import from util - weaviate/collections/batch/collection.py: replace 'from deprecation import...' - weaviate/connect/helpers.py: replace 'from deprecation import...' - weaviate/collections/classes/config.py: replace 'from deprecation import...' - weaviate/collections/classes/config_vectorizers.py: replace 'from deprecation import...' - weaviate/collections/classes/config_named_vectors.py: replace 'from deprecation import...' The 'deprecation' package is now fully removed from the codebase. Signed-off-by: NIK-TIGER-BILL --- weaviate/collections/batch/client.py | 35 +------------------ weaviate/collections/batch/collection.py | 2 +- weaviate/collections/classes/config.py | 2 +- .../classes/config_named_vectors.py | 2 +- .../collections/classes/config_vectorizers.py | 2 +- weaviate/connect/helpers.py | 2 +- weaviate/util.py | 34 +++++++++++++++++- 7 files changed, 39 insertions(+), 40 deletions(-) diff --git a/weaviate/collections/batch/client.py b/weaviate/collections/batch/client.py index c32afd5e6..e733d3cfa 100644 --- a/weaviate/collections/batch/client.py +++ b/weaviate/collections/batch/client.py @@ -1,42 +1,9 @@ from concurrent.futures import ThreadPoolExecutor from typing import TYPE_CHECKING, Optional, Type, Union -import functools -import warnings as _warnings -from typing import Callable - from typing_extensions import deprecated as typing_deprecated - -def docstring_deprecated(details: str = "", deprecated_in: str = "", **_kwargs: object) -> Callable: - """Replacement for ``deprecation.deprecated`` that uses only stdlib. - - The ``deprecation`` package has not been maintained since 2019 and is - flagged as a security risk by several dependency scanners. This - in-module helper replicates the behaviour we need: - - 1. Prepend a ``.. deprecated::`` note to the docstring. - 2. Emit a :class:`DeprecationWarning` at call time. - """ - - def decorator(func: Callable) -> Callable: - docstring = func.__doc__ or "" - note = f".. deprecated:: {deprecated_in}\n {details}\n\n" if deprecated_in else "" - func.__doc__ = note + docstring - - @functools.wraps(func) - def wrapper(*args: object, **kwargs: object) -> object: - _warnings.warn( - f"{func.__qualname__} is deprecated since {deprecated_in}. {details}", - DeprecationWarning, - stacklevel=2, - ) - return func(*args, **kwargs) - - wrapper.__doc__ = func.__doc__ - return wrapper - - return decorator +from weaviate.util import docstring_deprecated from weaviate.collections.batch.async_ import _BatchBaseAsync from weaviate.collections.batch.base import ( diff --git a/weaviate/collections/batch/collection.py b/weaviate/collections/batch/collection.py index 7889db335..e2f9600d0 100644 --- a/weaviate/collections/batch/collection.py +++ b/weaviate/collections/batch/collection.py @@ -1,7 +1,7 @@ from concurrent.futures import ThreadPoolExecutor from typing import TYPE_CHECKING, Generic, List, Optional, Type, Union -from deprecation import deprecated as docstring_deprecated +from weaviate.util import docstring_deprecated from typing_extensions import deprecated as typing_deprecated from weaviate.collections.batch.async_ import _BatchBaseAsync diff --git a/weaviate/collections/classes/config.py b/weaviate/collections/classes/config.py index 2a8b8d600..1bd7e568c 100644 --- a/weaviate/collections/classes/config.py +++ b/weaviate/collections/classes/config.py @@ -14,7 +14,7 @@ cast, ) -from deprecation import deprecated as docstring_deprecated +from weaviate.util import docstring_deprecated from pydantic import AnyHttpUrl, Field, TypeAdapter, ValidationInfo, field_validator from typing_extensions import TypeAlias from typing_extensions import deprecated as typing_deprecated diff --git a/weaviate/collections/classes/config_named_vectors.py b/weaviate/collections/classes/config_named_vectors.py index 93445d0df..60fad6db3 100644 --- a/weaviate/collections/classes/config_named_vectors.py +++ b/weaviate/collections/classes/config_named_vectors.py @@ -1,6 +1,6 @@ from typing import Any, Dict, List, Literal, Optional, Union -from deprecation import deprecated as docstring_deprecated +from weaviate.util import docstring_deprecated from pydantic import AnyHttpUrl, Field from typing_extensions import deprecated as typing_deprecated diff --git a/weaviate/collections/classes/config_vectorizers.py b/weaviate/collections/classes/config_vectorizers.py index 1628f0d56..4237ee0b4 100644 --- a/weaviate/collections/classes/config_vectorizers.py +++ b/weaviate/collections/classes/config_vectorizers.py @@ -2,7 +2,7 @@ from enum import Enum from typing import Any, Dict, List, Literal, Optional, Union, cast -from deprecation import deprecated as docstring_deprecated +from weaviate.util import docstring_deprecated from pydantic import AnyHttpUrl, BaseModel, Field, field_validator from typing_extensions import TypeAlias from typing_extensions import deprecated as typing_deprecated diff --git a/weaviate/connect/helpers.py b/weaviate/connect/helpers.py index 5355903d5..9b54869c5 100644 --- a/weaviate/connect/helpers.py +++ b/weaviate/connect/helpers.py @@ -3,7 +3,7 @@ from typing import Dict, Optional, Tuple, Union from urllib.parse import urlparse -from deprecation import deprecated as docstring_deprecated +from weaviate.util import docstring_deprecated from typing_extensions import deprecated as typing_deprecated from weaviate.auth import ( diff --git a/weaviate/util.py b/weaviate/util.py index f9b8e9385..503bd7dc6 100644 --- a/weaviate/util.py +++ b/weaviate/util.py @@ -2,13 +2,15 @@ import base64 import datetime +import functools import io import json import os import re import uuid as uuid_lib +import warnings as _warnings from pathlib import Path -from typing import Any, Dict, Generator, List, Optional, Sequence, Tuple, Union, cast +from typing import Any, Callable, Dict, Generator, List, Optional, Sequence, Tuple, Union, cast from urllib.parse import quote import httpx @@ -32,6 +34,36 @@ BYTES_PER_CHUNK = 65535 # The number of bytes to read per chunk when encoding files ~ 64kb +def docstring_deprecated(details: str = "", deprecated_in: str = "", **_kwargs: object) -> Callable: + """Stdlib replacement for ``deprecation.deprecated``. + + The ``deprecation`` package has not been maintained since 2019 and is + flagged as a security risk by several dependency scanners. This helper + replicates the behaviour we need: + + 1. Prepend a ``.. deprecated::`` note to the function docstring. + 2. Emit a :class:`DeprecationWarning` at call time. + """ + + def decorator(func: Callable) -> Callable: + docstring = func.__doc__ or "" + note = f".. deprecated:: {deprecated_in}\n {details}\n\n" if deprecated_in else "" + func.__doc__ = note + docstring + + @functools.wraps(func) + def wrapper(*args: object, **kwargs: object) -> object: + _warnings.warn( + f"{func.__qualname__} is deprecated since {deprecated_in}. {details}", + DeprecationWarning, + stacklevel=2, + ) + return func(*args, **kwargs) + + return wrapper # type: ignore[return-value] + + return decorator + + def image_encoder_b64(image_or_image_path: Union[str, io.BufferedReader]) -> str: """Encode a image in a Weaviate understandable format from a binary read file or by providing the image path. From 91152ccd86f4414ab8c478bb04d37930a3d07882 Mon Sep 17 00:00:00 2001 From: NIK-TIGER-BILL Date: Tue, 7 Apr 2026 23:01:47 +0000 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20address=20review=20=E2=80=94=20remov?= =?UTF-8?q?e=20**=5Fkwargs,=20set=20docstring=20on=20wrapper,=20drop=20dep?= =?UTF-8?q?recation=20from=20dev=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove **_kwargs parameter from docstring_deprecated() since all call sites use only 'details' and 'deprecated_in' keyword args - Move docstring modification to wrapper instead of original func to preserve the original function's __doc__ - Remove deprecation==2.1.0 from requirements-devel.txt to fully eliminate the unmaintained dependency Signed-off-by: NIK-TIGER-BILL --- requirements-devel.txt | 1 - weaviate/util.py | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/requirements-devel.txt b/requirements-devel.txt index 03941d157..5e929631f 100644 --- a/requirements-devel.txt +++ b/requirements-devel.txt @@ -5,7 +5,6 @@ grpcio==1.75.1 grpcio-tools==1.75.1 grpcio-health-checking==1.75.1 pydantic==2.12.0 -deprecation==2.1.0 build twine diff --git a/weaviate/util.py b/weaviate/util.py index 503bd7dc6..7ee9e5566 100644 --- a/weaviate/util.py +++ b/weaviate/util.py @@ -34,7 +34,7 @@ BYTES_PER_CHUNK = 65535 # The number of bytes to read per chunk when encoding files ~ 64kb -def docstring_deprecated(details: str = "", deprecated_in: str = "", **_kwargs: object) -> Callable: +def docstring_deprecated(details: str = "", deprecated_in: str = "") -> Callable: """Stdlib replacement for ``deprecation.deprecated``. The ``deprecation`` package has not been maintained since 2019 and is @@ -46,10 +46,6 @@ def docstring_deprecated(details: str = "", deprecated_in: str = "", **_kwargs: """ def decorator(func: Callable) -> Callable: - docstring = func.__doc__ or "" - note = f".. deprecated:: {deprecated_in}\n {details}\n\n" if deprecated_in else "" - func.__doc__ = note + docstring - @functools.wraps(func) def wrapper(*args: object, **kwargs: object) -> object: _warnings.warn( @@ -59,6 +55,10 @@ def wrapper(*args: object, **kwargs: object) -> object: ) return func(*args, **kwargs) + docstring = func.__doc__ or "" + note = f".. deprecated:: {deprecated_in}\n {details}\n\n" if deprecated_in else "" + wrapper.__doc__ = note + docstring + return wrapper # type: ignore[return-value] return decorator