Created
March 18, 2026 14:10
-
-
Save Jerakin/9eaa9f415015216e9f6042f3f7c211e9 to your computer and use it in GitHub Desktop.
Deprecate method into a propery
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """Deprecation Property. | |
| Using the decorated function as a property `A().value` works as intended, | |
| while calling it `A().value()` will show the warning with the provided message. | |
| ```python | |
| class Test: | |
| @deprecation_property | |
| def b(self): | |
| return "b" | |
| ``` | |
| """ | |
| from __future__ import annotations | |
| import warnings | |
| from typing import Any, TypeVar | |
| T = TypeVar("T") | |
| class deprecation_property(property): # noqa: N801 | |
| """Property decorator warns if the user is calling the decorated as a method.""" | |
| def __get__(self, obj: T, obj_type: type[T] | None = None) -> Any: # noqa: ANN401 | |
| value: Any = super().__get__(obj, obj_type) | |
| _property = self | |
| class _Proxy(type(value)): | |
| def __call__(self) -> Any: # noqa: ANN401 | |
| name = _property.fget.__name__ if _property.fget else "unknown property" # ty:ignore[unresolved-attribute] | |
| warnings.warn( | |
| f"Calling '{name}' as method is deprecated." | |
| " Use it as a property instead.", | |
| DeprecationWarning, | |
| stacklevel=2, | |
| ) | |
| return value | |
| try: | |
| return _Proxy(value) | |
| except TypeError: | |
| return _Proxy(*value) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """Deprecation Property. | |
| Alternative version that supports a custom message. | |
| Using the decorated function as a property `A().value` works as intended, | |
| while calling it `A().value()` will show the warning with the provided message. | |
| ```python | |
| class Test: | |
| @deprecation_property | |
| def b(self): | |
| return "b" | |
| ``` | |
| """ | |
| from __future__ import annotations | |
| import warnings | |
| from typing import Any, TypeVar | |
| T = TypeVar("T") | |
| def deprecation_property( | |
| message: str, warning_type: type[Warning] = DeprecationWarning | |
| ) -> type[property]: | |
| class _Property(property): | |
| def __get__(self, obj: T, obj_type: type[T] | None = None) -> Any: # noqa: ANN401 | |
| value: Any = super().__get__(obj, obj_type) | |
| class _Proxy(type(value)): | |
| def __call__(self) -> Any: # noqa: ANN401 | |
| warnings.warn(message, warning_type, stacklevel=2) | |
| return value | |
| try: | |
| return _Proxy(value) | |
| except TypeError: | |
| return _Proxy(*value) | |
| return _Property |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Test: | |
| def __init__(self) -> None: | |
| self.value = "b" | |
| @deprecation_property | |
| def b(self) -> str: | |
| return self.value | |
| @b.setter | |
| def b(self, v: str) -> None: | |
| self.value = v | |
| def test_deprecated_property_works_as_property(): | |
| t = Test() | |
| p = t.b | |
| assert t.b == "b" | |
| def test_deprecated_property_works_as_method(): | |
| t = Test() | |
| assert t.b() == "b" | |
| def test_deprecated_property_calls_warning(): | |
| t = Test() | |
| with pytest.deprecated_call(): | |
| t.b() | |
| def test_deprecated_property_still_setter(): | |
| t = Test() | |
| assert t.b == "b" | |
| t.b = "c" | |
| assert t.b == "c" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Test: | |
| def __init__(self) -> None: | |
| self.value = "b" | |
| @deprecation_property("`.b()` is deprecated use `.b` instead") | |
| def b(self) -> str: | |
| return self.value | |
| @b.setter | |
| def b(self, v: str) -> None: | |
| self.value = v | |
| def test_deprecated_property_works_as_property(): | |
| t = Test() | |
| p = t.b | |
| assert t.b == "b" | |
| def test_deprecated_property_works_as_method(): | |
| t = Test() | |
| assert t.b() == "b" | |
| def test_deprecated_property_calls_warning(): | |
| t = Test() | |
| with pytest.deprecated_call(): | |
| t.b() | |
| def test_deprecated_property_still_setter(): | |
| t = Test() | |
| assert t.b == "b" | |
| t.b = "c" | |
| assert t.b == "c" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment