From f95e9221bb54d4115369dcae2e454cd2c3b7e29d Mon Sep 17 00:00:00 2001 From: Erik Wrede Date: Sun, 29 Sep 2024 13:31:24 +0200 Subject: [PATCH] refactor: replace @deprecated decorator with upcoming native support (via typing-extensions), bump mypy (#1578) * refactor: replace @deprecated decorator with upcoming native support (via typing-extensions) * chore: fix tests * chore: ruff fmt --- graphene/utils/deprecated.py | 68 +----------------- graphene/utils/resolve_only_args.py | 3 +- graphene/utils/tests/test_deprecated.py | 70 +------------------ .../utils/tests/test_resolve_only_args.py | 1 - setup.py | 1 + tox.ini | 2 +- 6 files changed, 8 insertions(+), 137 deletions(-) diff --git a/graphene/utils/deprecated.py b/graphene/utils/deprecated.py index 42c358fb..7138bf56 100644 --- a/graphene/utils/deprecated.py +++ b/graphene/utils/deprecated.py @@ -1,67 +1,5 @@ -import functools -import inspect -import warnings - -string_types = (type(b""), type("")) +from warnings import warn -def warn_deprecation(text): - warnings.warn(text, category=DeprecationWarning, stacklevel=2) - - -def deprecated(reason): - """ - This is a decorator which can be used to mark functions - as deprecated. It will result in a warning being emitted - when the function is used. - """ - - if isinstance(reason, string_types): - # The @deprecated is used with a 'reason'. - # - # .. code-block:: python - # - # @deprecated("please, use another function") - # def old_function(x, y): - # pass - - def decorator(func1): - if inspect.isclass(func1): - fmt1 = f"Call to deprecated class {func1.__name__} ({reason})." - else: - fmt1 = f"Call to deprecated function {func1.__name__} ({reason})." - - @functools.wraps(func1) - def new_func1(*args, **kwargs): - warn_deprecation(fmt1) - return func1(*args, **kwargs) - - return new_func1 - - return decorator - - elif inspect.isclass(reason) or inspect.isfunction(reason): - # The @deprecated is used without any 'reason'. - # - # .. code-block:: python - # - # @deprecated - # def old_function(x, y): - # pass - - func2 = reason - - if inspect.isclass(func2): - fmt2 = f"Call to deprecated class {func2.__name__}." - else: - fmt2 = f"Call to deprecated function {func2.__name__}." - - @functools.wraps(func2) - def new_func2(*args, **kwargs): - warn_deprecation(fmt2) - return func2(*args, **kwargs) - - return new_func2 - - else: - raise TypeError(repr(type(reason))) +def warn_deprecation(text: str): + warn(text, category=DeprecationWarning, stacklevel=2) diff --git a/graphene/utils/resolve_only_args.py b/graphene/utils/resolve_only_args.py index 5efff2ed..088e62ca 100644 --- a/graphene/utils/resolve_only_args.py +++ b/graphene/utils/resolve_only_args.py @@ -1,6 +1,5 @@ from functools import wraps - -from .deprecated import deprecated +from typing_extensions import deprecated @deprecated("This function is deprecated") diff --git a/graphene/utils/tests/test_deprecated.py b/graphene/utils/tests/test_deprecated.py index 8a14434b..3fe90ded 100644 --- a/graphene/utils/tests/test_deprecated.py +++ b/graphene/utils/tests/test_deprecated.py @@ -1,75 +1,9 @@ -from pytest import raises - from .. import deprecated -from ..deprecated import deprecated as deprecated_decorator from ..deprecated import warn_deprecation def test_warn_deprecation(mocker): - mocker.patch.object(deprecated.warnings, "warn") + mocker.patch.object(deprecated, "warn") warn_deprecation("OH!") - deprecated.warnings.warn.assert_called_with( - "OH!", stacklevel=2, category=DeprecationWarning - ) - - -def test_deprecated_decorator(mocker): - mocker.patch.object(deprecated, "warn_deprecation") - - @deprecated_decorator - def my_func(): - return True - - result = my_func() - assert result - deprecated.warn_deprecation.assert_called_with( - "Call to deprecated function my_func." - ) - - -def test_deprecated_class(mocker): - mocker.patch.object(deprecated, "warn_deprecation") - - @deprecated_decorator - class X: - pass - - result = X() - assert result - deprecated.warn_deprecation.assert_called_with("Call to deprecated class X.") - - -def test_deprecated_decorator_text(mocker): - mocker.patch.object(deprecated, "warn_deprecation") - - @deprecated_decorator("Deprecation text") - def my_func(): - return True - - result = my_func() - assert result - deprecated.warn_deprecation.assert_called_with( - "Call to deprecated function my_func (Deprecation text)." - ) - - -def test_deprecated_class_text(mocker): - mocker.patch.object(deprecated, "warn_deprecation") - - @deprecated_decorator("Deprecation text") - class X: - pass - - result = X() - assert result - deprecated.warn_deprecation.assert_called_with( - "Call to deprecated class X (Deprecation text)." - ) - - -def test_deprecated_other_object(mocker): - mocker.patch.object(deprecated, "warn_deprecation") - - with raises(TypeError): - deprecated_decorator({}) + deprecated.warn.assert_called_with("OH!", stacklevel=2, category=DeprecationWarning) diff --git a/graphene/utils/tests/test_resolve_only_args.py b/graphene/utils/tests/test_resolve_only_args.py index 4e44be9f..9b80e688 100644 --- a/graphene/utils/tests/test_resolve_only_args.py +++ b/graphene/utils/tests/test_resolve_only_args.py @@ -9,6 +9,5 @@ def test_resolve_only_args(mocker): return root, args wrapped_resolver = resolve_only_args(resolver) - assert deprecated.warn_deprecation.called result = wrapped_resolver(1, 2, a=3) assert result == (1, {"a": 3}) diff --git a/setup.py b/setup.py index c41a368a..33ceba50 100644 --- a/setup.py +++ b/setup.py @@ -83,6 +83,7 @@ setup( install_requires=[ "graphql-core>=3.1,<3.3", "graphql-relay>=3.1,<3.3", + "typing-extensions>=4.7.1,<5", ], tests_require=tests_require, extras_require={"test": tests_require, "dev": dev_requires}, diff --git a/tox.ini b/tox.ini index 00c10174..dc42a653 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ commands = [testenv:mypy] basepython = python3.10 deps = - mypy>=0.950,<1 + mypy>=1.10,<2 commands = mypy graphene