Skip to content

Commit cab2dfc

Browse files
authored
chore(deps): add typing_extensions for py<3.13 to have a fallback for "deprecated" (jxmorris12#177)
1 parent b8b1162 commit cab2dfc

7 files changed

Lines changed: 31 additions & 56 deletions

File tree

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,16 @@
11
"""Provide a deprecated decorator for marking functions or classes as deprecated.
22
3-
It first attempts to import the deprecated decorator from the warnings module, available
4-
in Python 3.13 and later. If the import fails (indicating an earlier Python version), it
5-
defines a custom deprecated decorator. The decorator from warnings issues a
6-
DeprecationWarning when the decorated object is used during runtime, and triggers static
7-
linters to flag the usage as deprecated. The custom decorator also issues a
8-
DeprecationWarning when the decorated object is used, but does not trigger static
9-
linters.
3+
If the Python version is 3.13 or higher, it uses the
4+
built-in ``warnings.deprecated`` decorator.
5+
If the Python version is lower than 3.13, it falls back to using the
6+
``typing_extensions.deprecated`` decorator.
107
"""
118

12-
from __future__ import annotations
13-
14-
try:
15-
from warnings import deprecated # type: ignore [attr-defined, unused-ignore]
16-
except ImportError:
17-
import functools
18-
from collections.abc import Callable
19-
from typing import TypeVar, cast
20-
from warnings import warn
21-
22-
F = TypeVar("F", bound=Callable[..., object])
23-
24-
def deprecated( # type: ignore [no-redef, unused-ignore]
25-
message: str,
26-
/,
27-
*,
28-
category: type[Warning] | None = DeprecationWarning,
29-
stacklevel: int = 1,
30-
) -> Callable[[F], F]:
31-
"""Indicate that a function is deprecated."""
32-
33-
def decorator(func: F) -> F:
34-
@functools.wraps(func)
35-
def wrapper(*args: object, **kwargs: object) -> object:
36-
warn(message, category=category, stacklevel=stacklevel)
37-
return func(*args, **kwargs)
38-
39-
return cast("F", wrapper)
40-
41-
return decorator
9+
import sys
4210

11+
if sys.version_info >= (3, 13):
12+
from warnings import deprecated
13+
else:
14+
from typing_extensions import deprecated
4315

4416
__all__ = ["deprecated"]

language_tool_python/download_lt.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ def confirm_java_compatibility(
275275
@deprecated(
276276
"This function is no longer used internally and will be removed in 4.0.",
277277
stacklevel=2,
278-
) # type: ignore[untyped-decorator, unused-ignore]
278+
)
279279
def get_common_prefix(z: zipfile.ZipFile) -> str | None:
280280
"""Determine the common prefix of all file names in a zip archive.
281281
@@ -297,7 +297,7 @@ def get_common_prefix(z: zipfile.ZipFile) -> str | None:
297297
@deprecated(
298298
"This function is no longer used internally and will be removed in 4.0.",
299299
stacklevel=2,
300-
) # type: ignore[untyped-decorator, unused-ignore]
300+
)
301301
def http_get(
302302
url: str,
303303
out_file: IO[bytes],
@@ -329,7 +329,7 @@ def http_get(
329329
@deprecated(
330330
"This function is no longer used internally and will be removed in 4.0.",
331331
stacklevel=2,
332-
) # type: ignore[untyped-decorator, unused-ignore]
332+
)
333333
def unzip_file(temp_file_name: str, directory_to_extract_to: Path) -> None:
334334
"""Unzips a zip file to a specified directory.
335335
@@ -358,7 +358,7 @@ def unzip_file(temp_file_name: str, directory_to_extract_to: Path) -> None:
358358
@deprecated(
359359
"This function is no longer used internally and will be removed in 4.0.",
360360
stacklevel=2,
361-
) # type: ignore[untyped-decorator, unused-ignore]
361+
)
362362
def download_zip(url: str, directory: Path) -> None:
363363
"""Download a ZIP file from the given URL and extract it to the specified directory.
364364
@@ -389,7 +389,7 @@ def download_zip(url: str, directory: Path) -> None:
389389
"Use instead language_tool_python.download_lt.LocalLanguageTool.download."
390390
),
391391
stacklevel=2,
392-
) # type: ignore[untyped-decorator, unused-ignore]
392+
)
393393
def download_lt(language_tool_version: str = LTP_DOWNLOAD_VERSION) -> None:
394394
"""Download and extract the specified version of LanguageTool.
395395

language_tool_python/match.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def get_match_ordered_dict() -> OrderedDictType[str, type]:
6363
@deprecated(
6464
"This function is no longer used internally and will be removed in 4.0.",
6565
stacklevel=2,
66-
) # type: ignore[untyped-decorator, unused-ignore]
66+
)
6767
def auto_type(obj: SupportsInt | SupportsFloat | object) -> int | float | object:
6868
"""Attempt to automatically convert the input object to an integer or float.
6969

language_tool_python/utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ def get_language_tool_download_path() -> Path:
209209
"Replace its usage by an inline alternative."
210210
),
211211
stacklevel=2,
212-
) # type: ignore[untyped-decorator, unused-ignore]
212+
)
213213
def find_existing_language_tool_downloads(download_folder: Path) -> list[Path]:
214214
"""Find existing LanguageTool downloads in the specified folder.
215215
@@ -230,7 +230,7 @@ def find_existing_language_tool_downloads(download_folder: Path) -> list[Path]:
230230
@deprecated(
231231
"This function is no longer used internally and will be removed in 4.0.",
232232
stacklevel=2,
233-
) # type: ignore[untyped-decorator, unused-ignore]
233+
)
234234
def _extract_version(path: Path) -> version.Version:
235235
"""Extract the version number from a LanguageTool directory path.
236236
@@ -265,7 +265,7 @@ def _extract_version(path: Path) -> version.Version:
265265
"get_latest_installed_version."
266266
),
267267
stacklevel=2,
268-
) # type: ignore[untyped-decorator, unused-ignore]
268+
)
269269
def get_language_tool_directory() -> Path:
270270
"""Get the directory path of the LanguageTool installation.
271271
@@ -307,7 +307,7 @@ def get_language_tool_directory() -> Path:
307307
"Use instead language_tool_python.download_lt.LocalLanguageTool.get_server_cmd."
308308
),
309309
stacklevel=2,
310-
) # type: ignore[untyped-decorator, unused-ignore]
310+
)
311311
def get_server_cmd(
312312
port: int | None = None,
313313
config: LanguageToolConfig | None = None,
@@ -350,7 +350,7 @@ def get_server_cmd(
350350
@deprecated(
351351
"This function is no longer used internally and will be removed in 4.0.",
352352
stacklevel=2,
353-
) # type: ignore[untyped-decorator, unused-ignore]
353+
)
354354
def get_jar_info() -> tuple[Path, Path]:
355355
"""Retrieve the path to the Java executable and the LanguageTool JAR file.
356356
@@ -458,7 +458,7 @@ def __bool__(self) -> bool:
458458
@deprecated(
459459
"This protocol is no longer used internally and will be removed in 4.0.",
460460
stacklevel=2,
461-
) # type: ignore[untyped-decorator, unused-ignore]
461+
)
462462
@runtime_checkable
463463
class SupportsInt(Protocol):
464464
"""Protocol for types that can be converted to an integer value."""
@@ -471,7 +471,7 @@ def __int__(self) -> int:
471471
@deprecated(
472472
"This protocol is no longer used internally and will be removed in 4.0.",
473473
stacklevel=2,
474-
) # type: ignore[untyped-decorator, unused-ignore]
474+
)
475475
@runtime_checkable
476476
class SupportsFloat(Protocol):
477477
"""Protocol for types that can be converted to a float value."""

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ dependencies = [
3131
"tqdm",
3232
"packaging",
3333
"psutil",
34-
"toml"
34+
"toml",
35+
"typing_extensions; python_version < '3.13'", # only needed for py < 3.13 because warnings.deprecated added in 3.13 is used in the codebase
3536
]
3637

3738
[project.urls]

tests/test_deprecated.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
def test_deprecated_emits_warning() -> None:
1515
"""Test that the deprecated decorator emits a DeprecationWarning."""
1616

17-
@deprecated("This function is deprecated") # type: ignore[untyped-decorator, unused-ignore]
17+
@deprecated("This function is deprecated")
1818
def old_function() -> str:
1919
return "result"
2020

@@ -31,7 +31,7 @@ def old_function() -> str:
3131
def test_deprecated_with_custom_category() -> None:
3232
"""Test that the deprecated decorator can use a custom warning category."""
3333

34-
@deprecated("This is a user warning", category=UserWarning) # type: ignore[untyped-decorator, unused-ignore]
34+
@deprecated("This is a user warning", category=UserWarning)
3535
def old_function() -> int:
3636
return 42
3737

@@ -48,7 +48,7 @@ def old_function() -> int:
4848
def test_deprecated_preserves_function_signature() -> None:
4949
"""Test that the deprecated decorator preserves function metadata."""
5050

51-
@deprecated("Old function") # type: ignore[untyped-decorator, unused-ignore]
51+
@deprecated("Old function")
5252
def my_function(x: int, y: int) -> int:
5353
"""Add two numbers."""
5454
return x + y
@@ -63,7 +63,7 @@ def my_function(x: int, y: int) -> int:
6363
def test_deprecated_with_multiple_calls() -> None:
6464
"""Test that warning is emitted on each call."""
6565

66-
@deprecated("Deprecated function") # type: ignore[untyped-decorator, unused-ignore]
66+
@deprecated("Deprecated function")
6767
def func() -> str:
6868
return "value"
6969

@@ -80,7 +80,7 @@ def func() -> str:
8080
def test_deprecated_with_args_and_kwargs() -> None:
8181
"""Test that deprecated decorator works with functions that have args and kwargs."""
8282

83-
@deprecated("This function is obsolete") # type: ignore[untyped-decorator, unused-ignore]
83+
@deprecated("This function is obsolete")
8484
def complex_function(
8585
a: int,
8686
b: int,

uv.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)