@@ -2292,15 +2292,12 @@ def method(self) -> None:
22922292else :
22932293 _T = typing .TypeVar ("_T" )
22942294
2295- def deprecated (
2296- msg : str ,
2297- / ,
2298- * ,
2299- category : typing .Optional [typing .Type [Warning ]] = DeprecationWarning ,
2300- stacklevel : int = 1 ,
2301- ) -> typing .Callable [[_T ], _T ]:
2295+ class deprecated :
23022296 """Indicate that a class, function or overload is deprecated.
23032297
2298+ When this decorator is applied to an object, the type checker
2299+ will generate a diagnostic on usage of the deprecated object.
2300+
23042301 Usage:
23052302
23062303 @deprecated("Use B instead")
@@ -2317,36 +2314,56 @@ def g(x: int) -> int: ...
23172314 @overload
23182315 def g(x: str) -> int: ...
23192316
2320- When this decorator is applied to an object, the type checker
2321- will generate a diagnostic on usage of the deprecated object.
2322-
2323- The warning specified by ``category`` will be emitted on use
2324- of deprecated objects. For functions, that happens on calls;
2325- for classes, on instantiation. If the ``category`` is ``None``,
2326- no warning is emitted. The ``stacklevel`` determines where the
2317+ The warning specified by *category* will be emitted at runtime
2318+ on use of deprecated objects. For functions, that happens on calls;
2319+ for classes, on instantiation and on creation of subclasses.
2320+ If the *category* is ``None``, no warning is emitted at runtime.
2321+ The *stacklevel* determines where the
23272322 warning is emitted. If it is ``1`` (the default), the warning
23282323 is emitted at the direct caller of the deprecated object; if it
23292324 is higher, it is emitted further up the stack.
2325+ Static type checker behavior is not affected by the *category*
2326+ and *stacklevel* arguments.
23302327
2331- The decorator sets the ``__deprecated__``
2332- attribute on the decorated object to the deprecation message
2333- passed to the decorator. If applied to an overload, the decorator
2328+ The deprecation message passed to the decorator is saved in the
2329+ ``__deprecated__`` attribute on the decorated object.
2330+ If applied to an overload, the decorator
23342331 must be after the ``@overload`` decorator for the attribute to
23352332 exist on the overload as returned by ``get_overloads()``.
23362333
23372334 See PEP 702 for details.
23382335
23392336 """
2340- if not isinstance (msg , str ):
2341- raise TypeError (
2342- f"Expected an object of type str for 'msg', not { type (msg ).__name__ !r} "
2343- )
2344-
2345- def decorator (arg : _T , / ) -> _T :
2337+ def __init__ (
2338+ self ,
2339+ message : str ,
2340+ / ,
2341+ * ,
2342+ category : typing .Optional [typing .Type [Warning ]] = DeprecationWarning ,
2343+ stacklevel : int = 1 ,
2344+ ) -> None :
2345+ if not isinstance (message , str ):
2346+ raise TypeError (
2347+ "Expected an object of type str for 'message', not "
2348+ f"{ type (message ).__name__ !r} "
2349+ )
2350+ self .message = message
2351+ self .category = category
2352+ self .stacklevel = stacklevel
2353+
2354+ def __call__ (self , arg : _T , / ) -> _T :
2355+ # Make sure the inner functions created below don't
2356+ # retain a reference to self.
2357+ msg = self .message
2358+ category = self .category
2359+ stacklevel = self .stacklevel
23462360 if category is None :
23472361 arg .__deprecated__ = msg
23482362 return arg
23492363 elif isinstance (arg , type ):
2364+ import functools
2365+ from types import MethodType
2366+
23502367 original_new = arg .__new__
23512368
23522369 @functools .wraps (original_new )
@@ -2366,7 +2383,7 @@ def __new__(cls, *args, **kwargs):
23662383 original_init_subclass = arg .__init_subclass__
23672384 # We need slightly different behavior if __init_subclass__
23682385 # is a bound method (likely if it was implemented in Python)
2369- if isinstance (original_init_subclass , _types . MethodType ):
2386+ if isinstance (original_init_subclass , MethodType ):
23702387 original_init_subclass = original_init_subclass .__func__
23712388
23722389 @functools .wraps (original_init_subclass )
@@ -2389,6 +2406,8 @@ def __init_subclass__(*args, **kwargs):
23892406 __init_subclass__ .__deprecated__ = msg
23902407 return arg
23912408 elif callable (arg ):
2409+ import functools
2410+
23922411 @functools .wraps (arg )
23932412 def wrapper (* args , ** kwargs ):
23942413 warnings .warn (msg , category = category , stacklevel = stacklevel + 1 )
@@ -2402,8 +2421,6 @@ def wrapper(*args, **kwargs):
24022421 f"a class or callable, not { arg !r} "
24032422 )
24042423
2405- return decorator
2406-
24072424
24082425# We have to do some monkey patching to deal with the dual nature of
24092426# Unpack/TypeVarTuple:
0 commit comments