-
-
Notifications
You must be signed in to change notification settings - Fork 18.5k
TYPING: check-untyped-defs for util._decorators #28128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,35 @@ | ||
from functools import wraps | ||
import inspect | ||
from textwrap import dedent | ||
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union | ||
from typing import ( | ||
Any, | ||
Callable, | ||
Dict, | ||
List, | ||
Optional, | ||
Tuple, | ||
Type, | ||
TypeVar, | ||
Union, | ||
cast, | ||
) | ||
import warnings | ||
|
||
from pandas._libs.properties import cache_readonly # noqa | ||
|
||
FuncType = Callable[..., Any] | ||
F = TypeVar("F", bound=FuncType) | ||
WillAyd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
def deprecate( | ||
name: str, | ||
alternative: Callable, | ||
alternative: Callable[..., Any], | ||
version: str, | ||
alt_name: Optional[str] = None, | ||
klass: Optional[Type[Warning]] = None, | ||
stacklevel: int = 2, | ||
msg: Optional[str] = None, | ||
) -> Callable: | ||
) -> Callable[..., Any]: | ||
""" | ||
Return a new function that emits a deprecation warning on use. | ||
|
||
|
@@ -47,7 +61,7 @@ def deprecate( | |
warning_msg = msg or "{} is deprecated, use {} instead".format(name, alt_name) | ||
|
||
@wraps(alternative) | ||
def wrapper(*args, **kwargs): | ||
def wrapper(*args, **kwargs) -> Callable[..., Any]: | ||
warnings.warn(warning_msg, klass, stacklevel=stacklevel) | ||
return alternative(*args, **kwargs) | ||
|
||
|
@@ -90,9 +104,9 @@ def wrapper(*args, **kwargs): | |
def deprecate_kwarg( | ||
old_arg_name: str, | ||
new_arg_name: Optional[str], | ||
mapping: Optional[Union[Dict, Callable[[Any], Any]]] = None, | ||
mapping: Optional[Union[Dict[Any, Any], Callable[[Any], Any]]] = None, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think OK just to do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is the same thing but would fail --disallow-any-generics check. although readability is important, i don't think the benefits of precise type checking can be understated. |
||
stacklevel: int = 2, | ||
) -> Callable: | ||
) -> Callable[..., Any]: | ||
""" | ||
Decorator to deprecate a keyword argument of a function. | ||
|
||
|
@@ -160,27 +174,27 @@ def deprecate_kwarg( | |
"mapping from old to new argument values " "must be dict or callable!" | ||
) | ||
|
||
def _deprecate_kwarg(func): | ||
def _deprecate_kwarg(func: F) -> F: | ||
@wraps(func) | ||
def wrapper(*args, **kwargs): | ||
def wrapper(*args, **kwargs) -> Callable[..., Any]: | ||
old_arg_value = kwargs.pop(old_arg_name, None) | ||
|
||
if new_arg_name is None and old_arg_value is not None: | ||
msg = ( | ||
"the '{old_name}' keyword is deprecated and will be " | ||
"removed in a future version. " | ||
"Please take steps to stop the use of '{old_name}'" | ||
).format(old_name=old_arg_name) | ||
warnings.warn(msg, FutureWarning, stacklevel=stacklevel) | ||
kwargs[old_arg_name] = old_arg_value | ||
return func(*args, **kwargs) | ||
|
||
if old_arg_value is not None: | ||
if mapping is not None: | ||
if hasattr(mapping, "get"): | ||
new_arg_value = mapping.get(old_arg_value, old_arg_value) | ||
else: | ||
if new_arg_name is None: | ||
msg = ( | ||
"the '{old_name}' keyword is deprecated and will be " | ||
"removed in a future version. " | ||
"Please take steps to stop the use of '{old_name}'" | ||
).format(old_name=old_arg_name) | ||
warnings.warn(msg, FutureWarning, stacklevel=stacklevel) | ||
kwargs[old_arg_name] = old_arg_value | ||
return func(*args, **kwargs) | ||
|
||
elif mapping is not None: | ||
if callable(mapping): | ||
new_arg_value = mapping(old_arg_value) | ||
else: | ||
new_arg_value = mapping.get(old_arg_value, old_arg_value) | ||
msg = ( | ||
"the {old_name}={old_val!r} keyword is deprecated, " | ||
"use {new_name}={new_val!r} instead" | ||
|
@@ -198,7 +212,7 @@ def wrapper(*args, **kwargs): | |
).format(old_name=old_arg_name, new_name=new_arg_name) | ||
|
||
warnings.warn(msg, FutureWarning, stacklevel=stacklevel) | ||
if kwargs.get(new_arg_name, None) is not None: | ||
if kwargs.get(new_arg_name) is not None: | ||
msg = ( | ||
"Can only specify '{old_name}' or '{new_name}', " "not both" | ||
).format(old_name=old_arg_name, new_name=new_arg_name) | ||
|
@@ -207,17 +221,17 @@ def wrapper(*args, **kwargs): | |
kwargs[new_arg_name] = new_arg_value | ||
return func(*args, **kwargs) | ||
|
||
return wrapper | ||
return cast(F, wrapper) | ||
|
||
return _deprecate_kwarg | ||
|
||
|
||
def rewrite_axis_style_signature( | ||
name: str, extra_params: List[Tuple[str, Any]] | ||
) -> Callable: | ||
def decorate(func): | ||
) -> Callable[..., Any]: | ||
def decorate(func: F) -> F: | ||
@wraps(func) | ||
def wrapper(*args, **kwargs): | ||
def wrapper(*args, **kwargs) -> Callable[..., Any]: | ||
return func(*args, **kwargs) | ||
|
||
kind = inspect.Parameter.POSITIONAL_OR_KEYWORD | ||
|
@@ -234,8 +248,9 @@ def wrapper(*args, **kwargs): | |
|
||
sig = inspect.Signature(params) | ||
|
||
func.__signature__ = sig | ||
return wrapper | ||
# https://github.com/python/typing/issues/598 | ||
func.__signature__ = sig # type: ignore | ||
return cast(F, wrapper) | ||
|
||
return decorate | ||
|
||
|
@@ -279,18 +294,17 @@ def __init__(self, *args, **kwargs): | |
|
||
self.params = args or kwargs | ||
|
||
def __call__(self, func: Callable) -> Callable: | ||
def __call__(self, func: F) -> F: | ||
func.__doc__ = func.__doc__ and func.__doc__ % self.params | ||
return func | ||
|
||
def update(self, *args, **kwargs) -> None: | ||
""" | ||
Update self.params with supplied args. | ||
|
||
If called, we assume self.params is a dict. | ||
""" | ||
|
||
self.params.update(*args, **kwargs) | ||
if isinstance(self.params, dict): | ||
self.params.update(*args, **kwargs) | ||
|
||
|
||
class Appender: | ||
|
@@ -320,7 +334,7 @@ def __init__(self, addendum: Optional[str], join: str = "", indents: int = 0): | |
self.addendum = addendum | ||
self.join = join | ||
|
||
def __call__(self, func: Callable) -> Callable: | ||
def __call__(self, func: F) -> F: | ||
func.__doc__ = func.__doc__ if func.__doc__ else "" | ||
self.addendum = self.addendum if self.addendum else "" | ||
docitems = [func.__doc__, self.addendum] | ||
|
Uh oh!
There was an error while loading. Please reload this page.