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/2] 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/2] 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.