Skip to content

TYP: _config/config.py && core/{apply,construction}.py #30734

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

Merged
merged 12 commits into from
Jan 16, 2020
135 changes: 70 additions & 65 deletions pandas/_config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
from collections import namedtuple
from contextlib import contextmanager
import re
from typing import Any, Dict, Iterable, List
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
import warnings

DeprecatedOption = namedtuple("DeprecatedOption", "key msg rkey removal_ver")
Expand Down Expand Up @@ -80,7 +80,7 @@ class OptionError(AttributeError, KeyError):
# User API


def _get_single_key(pat, silent):
def _get_single_key(pat: str, silent: bool) -> str:
keys = _select_options(pat)
if len(keys) == 0:
if not silent:
Expand All @@ -98,15 +98,15 @@ def _get_single_key(pat, silent):
return key


def _get_option(pat, silent=False):
def _get_option(pat: str, silent: bool = False):
key = _get_single_key(pat, silent)

# walk the nested dict
root, k = _get_root(key)
return root[k]


def _set_option(*args, **kwargs):
def _set_option(*args, **kwargs) -> None:
# must at least 1 arg deal with constraints later
nargs = len(args)
if not nargs or nargs % 2 != 0:
Expand Down Expand Up @@ -138,7 +138,7 @@ def _set_option(*args, **kwargs):
o.cb(key)


def _describe_option(pat="", _print_desc=True):
def _describe_option(pat: str = "", _print_desc: bool = True):

keys = _select_options(pat)
if len(keys) == 0:
Expand All @@ -154,7 +154,7 @@ def _describe_option(pat="", _print_desc=True):
return s


def _reset_option(pat, silent=False):
def _reset_option(pat: str, silent: bool = False) -> None:

keys = _select_options(pat)

Expand All @@ -173,19 +173,19 @@ def _reset_option(pat, silent=False):
_set_option(k, _registered_options[k].defval, silent=silent)


def get_default_val(pat):
def get_default_val(pat: str):
key = _get_single_key(pat, silent=True)
return _get_registered_option(key).defval


class DictWrapper:
""" provide attribute-style access to a nested dict"""

def __init__(self, d, prefix=""):
def __init__(self, d: Dict[str, Any], prefix: str = ""):
object.__setattr__(self, "d", d)
object.__setattr__(self, "prefix", prefix)

def __setattr__(self, key, val):
def __setattr__(self, key: str, val: Any) -> None:
prefix = object.__getattribute__(self, "prefix")
if prefix:
prefix += "."
Expand All @@ -211,7 +211,7 @@ def __getattr__(self, key: str):
else:
return _get_option(prefix)

def __dir__(self):
def __dir__(self) -> Iterable[str]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def __dir__(self) -> Iterable[str]:
def __dir__(self) -> List[str]:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vaguely recall this coming up elsewhere. Actually looks like this is inconsistent in typeshed though stdlib matches what's here:

https://github.com/python/typeshed/blob/a1331accbe98ae5f214b824121e5223e52a474f7/stdlib/2and3/builtins.pyi#L67

No strong preference on either, just adding for visibility

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vaguely recall this coming up elsewhere.

I got the same feeling while annotating this.
So I looked hard in my previous PR until I found it.
#30411 (comment)

return list(self.d.keys())


Expand Down Expand Up @@ -412,23 +412,31 @@ def __exit__(self, *args):
_set_option(pat, val, silent=True)


def register_option(key: str, defval: object, doc="", validator=None, cb=None):
"""Register an option in the package-wide pandas config object
def register_option(
key: str,
defval: object,
doc: str = "",
validator=None,
cb: Optional[Callable[[str], None]] = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to validator, restricting the return type to None may not be desirable.

) -> None:
"""
Register an option in the package-wide pandas config object

Parameters
----------
key - a fully-qualified key, e.g. "x.y.option - z".
defval - the default value of the option
doc - a string description of the option
validator - a function of a single argument, should raise `ValueError` if
called with a value which is not a legal value for the option.
cb - a function of a single argument "key", which is called
immediately after an option value is set/reset. key is
the full name of the option.

Returns
-------
Nothing.
key : str
Fully-qualified key, e.g. "x.y.option - z".
defval : object
Default value of the option.
doc : str
Description of the option.
validator : Callable, optional
Function of a single argument, should raise `ValueError` if
called with a value which is not a legal value for the option.
cb
a function of a single argument "key", which is called
immediately after an option value is set/reset. key is
the full name of the option.

Raises
------
Expand Down Expand Up @@ -481,7 +489,9 @@ def register_option(key: str, defval: object, doc="", validator=None, cb=None):
)


def deprecate_option(key, msg=None, rkey=None, removal_ver=None):
def deprecate_option(
key: str, msg: Optional[str] = None, rkey: Optional[str] = None, removal_ver=None
) -> None:
"""
Mark option `key` as deprecated, if code attempts to access this option,
a warning will be produced, using `msg` if given, or a default message
Expand All @@ -494,32 +504,27 @@ def deprecate_option(key, msg=None, rkey=None, removal_ver=None):

Parameters
----------
key - the name of the option to be deprecated. must be a fully-qualified
option name (e.g "x.y.z.rkey").

msg - (Optional) a warning message to output when the key is referenced.
if no message is given a default message will be emitted.

rkey - (Optional) the name of an option to reroute access to.
If specified, any referenced `key` will be re-routed to `rkey`
including set/get/reset.
rkey must be a fully-qualified option name (e.g "x.y.z.rkey").
used by the default message if no `msg` is specified.

removal_ver - (Optional) specifies the version in which this option will
be removed. used by the default message if no `msg`
is specified.

Returns
-------
Nothing
key : str
Name of the option to be deprecated.
must be a fully-qualified option name (e.g "x.y.z.rkey").
msg : str, optional
Warning message to output when the key is referenced.
if no message is given a default message will be emitted.
rkey : str, optional
Name of an option to reroute access to.
If specified, any referenced `key` will be
re-routed to `rkey` including set/get/reset.
rkey must be a fully-qualified option name (e.g "x.y.z.rkey").
used by the default message if no `msg` is specified.
removal_ver : optional
Specifies the version in which this option will
be removed. used by the default message if no `msg` is specified.

Raises
------
OptionError - if key has already been deprecated.

OptionError
If the specified key has already been deprecated.
"""

key = key.lower()

if key in _deprecated_options:
Expand All @@ -532,7 +537,7 @@ def deprecate_option(key, msg=None, rkey=None, removal_ver=None):
# functions internal to the module


def _select_options(pat):
def _select_options(pat: str) -> List[str]:
"""returns a list of keys matching `pat`

if pat=="all", returns all registered options
Expand All @@ -550,22 +555,22 @@ def _select_options(pat):
return [k for k in keys if re.search(pat, k, re.I)]


def _get_root(key):
def _get_root(key: str) -> Tuple[Dict[str, Any], str]:
path = key.split(".")
cursor = _global_config
for p in path[:-1]:
cursor = cursor[p]
return cursor, path[-1]


def _is_deprecated(key):
def _is_deprecated(key: str) -> bool:
""" Returns True if the given option has been deprecated """

key = key.lower()
return key in _deprecated_options


def _get_deprecated_option(key):
def _get_deprecated_option(key: str):
"""
Retrieves the metadata for a deprecated option, if `key` is deprecated.

Expand All @@ -582,7 +587,7 @@ def _get_deprecated_option(key):
return d


def _get_registered_option(key):
def _get_registered_option(key: str):
"""
Retrieves the option metadata if `key` is a registered option.

Expand All @@ -593,7 +598,7 @@ def _get_registered_option(key):
return _registered_options.get(key)


def _translate_key(key):
def _translate_key(key: str) -> str:
"""
if key id deprecated and a replacement key defined, will return the
replacement key, otherwise returns `key` as - is
Expand All @@ -606,7 +611,7 @@ def _translate_key(key):
return key


def _warn_if_deprecated(key):
def _warn_if_deprecated(key: str) -> bool:
"""
Checks if `key` is a deprecated option and if so, prints a warning.

Expand Down Expand Up @@ -634,7 +639,7 @@ def _warn_if_deprecated(key):
return False


def _build_option_description(k):
def _build_option_description(k: str) -> str:
""" Builds a formatted description of a registered option and prints it """

o = _get_registered_option(k)
Expand All @@ -659,7 +664,7 @@ def _build_option_description(k):
return s


def pp_options_list(keys, width=80, _print=False):
def pp_options_list(keys: Iterable[str], width=80, _print: bool = False):
""" Builds a concise listing of available options, grouped by prefix """

from textwrap import wrap
Expand Down Expand Up @@ -729,7 +734,7 @@ def config_prefix(prefix):
global register_option, get_option, set_option, reset_option

def wrap(func):
def inner(key, *args, **kwds):
def inner(key: str, *args, **kwds) -> Callable[[str, Any, Any], Any]:
pkey = f"{prefix}.{key}"
return func(pkey, *args, **kwds)

Expand All @@ -751,7 +756,7 @@ def inner(key, *args, **kwds):
# arg in register_option


def is_type_factory(_type):
def is_type_factory(_type) -> Callable[..., None]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the returned function accepts exactly one argument

Suggested change
def is_type_factory(_type) -> Callable[..., None]:
def is_type_factory(_type: Type[Any]) -> Callable[[Any], None]:

"""

Parameters
Expand All @@ -765,14 +770,14 @@ def is_type_factory(_type):

"""

def inner(x):
def inner(x) -> None:
if type(x) != _type:
raise ValueError(f"Value must have type '{_type}'")

return inner


def is_instance_factory(_type):
def is_instance_factory(_type) -> Callable[..., None]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the returned function accepts exactly one argument

Suggested change
def is_instance_factory(_type) -> Callable[..., None]:
def is_instance_factory(_type) -> Callable[[Any], None]:

"""

Parameters
Expand All @@ -792,19 +797,19 @@ def is_instance_factory(_type):
else:
type_repr = f"'{_type}'"

def inner(x):
def inner(x) -> None:
if not isinstance(x, _type):
raise ValueError(f"Value must be an instance of {type_repr}")

return inner


def is_one_of_factory(legal_values):
def is_one_of_factory(legal_values) -> Callable[..., None]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def is_one_of_factory(legal_values) -> Callable[..., None]:
def is_one_of_factory(legal_values) -> Callable[[Any] None]:


callables = [c for c in legal_values if callable(c)]
legal_values = [c for c in legal_values if not callable(c)]

def inner(x):
def inner(x) -> None:
if x not in legal_values:

if not any(c(x) for c in callables):
Expand All @@ -818,7 +823,7 @@ def inner(x):
return inner


def is_nonnegative_int(value):
def is_nonnegative_int(value: Optional[int]) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strange that this returns None. I would expect a function named is_* to return True/False.

Copy link
Member

@WillAyd WillAyd Jan 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think OK to rename this check_nonnegative_int in another PR

"""
Verify that value is None or a positive int.

Expand Down Expand Up @@ -853,7 +858,7 @@ def is_nonnegative_int(value):
is_text = is_instance_factory((str, bytes))


def is_callable(obj):
def is_callable(obj) -> bool:
"""

Parameters
Expand Down
9 changes: 5 additions & 4 deletions pandas/core/apply.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import abc
import inspect
from typing import TYPE_CHECKING, Any, Dict, Iterator, Tuple, Type, Union
from typing import TYPE_CHECKING, Any, Dict, Iterator, Optional, Tuple, Type, Union

import numpy as np

from pandas._libs import reduction as libreduction
from pandas._typing import Axis
from pandas.util._decorators import cache_readonly

from pandas.core.dtypes.common import (
Expand All @@ -26,9 +27,9 @@
def frame_apply(
obj: "DataFrame",
func,
axis=0,
axis: Axis = 0,
raw: bool = False,
result_type=None,
result_type: Optional[str] = None,
ignore_failures: bool = False,
args=None,
kwds=None,
Expand Down Expand Up @@ -87,7 +88,7 @@ def __init__(
obj: "DataFrame",
func,
raw: bool,
result_type,
result_type: Optional[str],
ignore_failures: bool,
args,
kwds,
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ def array(
return result


def extract_array(obj, extract_numpy=False):
def extract_array(obj, extract_numpy: bool = False):
"""
Extract the ndarray or ExtensionArray from a Series or Index.

Expand Down