From a4f71b857a8edd23684956dbee042a42f6c3c9d6 Mon Sep 17 00:00:00 2001 From: AlexWaygood Date: Sun, 29 Oct 2023 10:43:55 +0000 Subject: [PATCH] Raise if a non-`str` is passed as the first parameter to `@deprecated` --- CHANGELOG.md | 2 ++ src/test_typing_extensions.py | 15 +++++++++++++++ src/typing_extensions.py | 5 +++++ 3 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ecde9cf..43838db0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ - All parameters on `NewType.__call__` are now positional-only. This means that the signature of `typing_extensions.NewType.__call__` now exactly matches the signature of `typing.NewType.__call__`. Patch by Alex Waygood. +- `typing.deprecated` now gives a better error message if you pass a non-`str` + argument to the `msg` parameter. Patch by Alex Waygood. # Release 4.8.0 (September 17, 2023) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 7d8e2553..151d44c6 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -480,6 +480,21 @@ def d(): warnings.simplefilter("error") d() + def test_only_strings_allowed(self): + with self.assertRaisesRegex( + TypeError, + "Expected an object of type str for 'msg', not 'type'" + ): + @deprecated + class Foo: ... + + with self.assertRaisesRegex( + TypeError, + "Expected an object of type str for 'msg', not 'function'" + ): + @deprecated + def foo(): ... + class AnyTests(BaseTestCase): def test_can_subclass(self): diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 58706dc9..34affa97 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -2331,6 +2331,11 @@ def g(x: str) -> int: ... See PEP 702 for details. """ + if not isinstance(msg, str): + raise TypeError( + f"Expected an object of type str for 'msg', not {type(msg).__name__!r}" + ) + def decorator(arg: _T, /) -> _T: if category is None: arg.__deprecated__ = msg