8th day of python challenges 111-117
This commit is contained in:
3
venv/lib/python3.6/site-packages/pandas/util/__init__.py
Normal file
3
venv/lib/python3.6/site-packages/pandas/util/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from pandas.util._decorators import Appender, Substitution, cache_readonly # noqa
|
||||
|
||||
from pandas.core.util.hashing import hash_array, hash_pandas_object # noqa
|
335
venv/lib/python3.6/site-packages/pandas/util/_decorators.py
Normal file
335
venv/lib/python3.6/site-packages/pandas/util/_decorators.py
Normal file
@@ -0,0 +1,335 @@
|
||||
from functools import wraps
|
||||
import inspect
|
||||
from textwrap import dedent
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
|
||||
import warnings
|
||||
|
||||
from pandas._libs.properties import cache_readonly # noqa
|
||||
|
||||
|
||||
def deprecate(
|
||||
name: str,
|
||||
alternative: Callable,
|
||||
version: str,
|
||||
alt_name: Optional[str] = None,
|
||||
klass: Optional[Type[Warning]] = None,
|
||||
stacklevel: int = 2,
|
||||
msg: Optional[str] = None,
|
||||
) -> Callable:
|
||||
"""
|
||||
Return a new function that emits a deprecation warning on use.
|
||||
|
||||
To use this method for a deprecated function, another function
|
||||
`alternative` with the same signature must exist. The deprecated
|
||||
function will emit a deprecation warning, and in the docstring
|
||||
it will contain the deprecation directive with the provided version
|
||||
so it can be detected for future removal.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Name of function to deprecate.
|
||||
alternative : func
|
||||
Function to use instead.
|
||||
version : str
|
||||
Version of pandas in which the method has been deprecated.
|
||||
alt_name : str, optional
|
||||
Name to use in preference of alternative.__name__.
|
||||
klass : Warning, default FutureWarning
|
||||
stacklevel : int, default 2
|
||||
msg : str
|
||||
The message to display in the warning.
|
||||
Default is '{name} is deprecated. Use {alt_name} instead.'
|
||||
"""
|
||||
|
||||
alt_name = alt_name or alternative.__name__
|
||||
klass = klass or FutureWarning
|
||||
warning_msg = msg or "{} is deprecated, use {} instead".format(name, alt_name)
|
||||
|
||||
@wraps(alternative)
|
||||
def wrapper(*args, **kwargs):
|
||||
warnings.warn(warning_msg, klass, stacklevel=stacklevel)
|
||||
return alternative(*args, **kwargs)
|
||||
|
||||
# adding deprecated directive to the docstring
|
||||
msg = msg or "Use `{alt_name}` instead.".format(alt_name=alt_name)
|
||||
doc_error_msg = (
|
||||
"deprecate needs a correctly formatted docstring in "
|
||||
"the target function (should have a one liner short "
|
||||
"summary, and opening quotes should be in their own "
|
||||
"line). Found:\n{}".format(alternative.__doc__)
|
||||
)
|
||||
|
||||
# when python is running in optimized mode (i.e. `-OO`), docstrings are
|
||||
# removed, so we check that a docstring with correct formatting is used
|
||||
# but we allow empty docstrings
|
||||
if alternative.__doc__:
|
||||
if alternative.__doc__.count("\n") < 3:
|
||||
raise AssertionError(doc_error_msg)
|
||||
empty1, summary, empty2, doc = alternative.__doc__.split("\n", 3)
|
||||
if empty1 or empty2 and not summary:
|
||||
raise AssertionError(doc_error_msg)
|
||||
wrapper.__doc__ = dedent(
|
||||
"""
|
||||
{summary}
|
||||
|
||||
.. deprecated:: {depr_version}
|
||||
{depr_msg}
|
||||
|
||||
{rest_of_docstring}"""
|
||||
).format(
|
||||
summary=summary.strip(),
|
||||
depr_version=version,
|
||||
depr_msg=msg,
|
||||
rest_of_docstring=dedent(doc),
|
||||
)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def deprecate_kwarg(
|
||||
old_arg_name: str,
|
||||
new_arg_name: Optional[str],
|
||||
mapping: Optional[Union[Dict, Callable[[Any], Any]]] = None,
|
||||
stacklevel: int = 2,
|
||||
) -> Callable:
|
||||
"""
|
||||
Decorator to deprecate a keyword argument of a function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
old_arg_name : str
|
||||
Name of argument in function to deprecate
|
||||
new_arg_name : str or None
|
||||
Name of preferred argument in function. Use None to raise warning that
|
||||
``old_arg_name`` keyword is deprecated.
|
||||
mapping : dict or callable
|
||||
If mapping is present, use it to translate old arguments to
|
||||
new arguments. A callable must do its own value checking;
|
||||
values not found in a dict will be forwarded unchanged.
|
||||
|
||||
Examples
|
||||
--------
|
||||
The following deprecates 'cols', using 'columns' instead
|
||||
|
||||
>>> @deprecate_kwarg(old_arg_name='cols', new_arg_name='columns')
|
||||
... def f(columns=''):
|
||||
... print(columns)
|
||||
...
|
||||
>>> f(columns='should work ok')
|
||||
should work ok
|
||||
|
||||
>>> f(cols='should raise warning')
|
||||
FutureWarning: cols is deprecated, use columns instead
|
||||
warnings.warn(msg, FutureWarning)
|
||||
should raise warning
|
||||
|
||||
>>> f(cols='should error', columns="can\'t pass do both")
|
||||
TypeError: Can only specify 'cols' or 'columns', not both
|
||||
|
||||
>>> @deprecate_kwarg('old', 'new', {'yes': True, 'no': False})
|
||||
... def f(new=False):
|
||||
... print('yes!' if new else 'no!')
|
||||
...
|
||||
>>> f(old='yes')
|
||||
FutureWarning: old='yes' is deprecated, use new=True instead
|
||||
warnings.warn(msg, FutureWarning)
|
||||
yes!
|
||||
|
||||
To raise a warning that a keyword will be removed entirely in the future
|
||||
|
||||
>>> @deprecate_kwarg(old_arg_name='cols', new_arg_name=None)
|
||||
... def f(cols='', another_param=''):
|
||||
... print(cols)
|
||||
...
|
||||
>>> f(cols='should raise warning')
|
||||
FutureWarning: the 'cols' keyword is deprecated and will be removed in a
|
||||
future version please takes steps to stop use of 'cols'
|
||||
should raise warning
|
||||
>>> f(another_param='should not raise warning')
|
||||
should not raise warning
|
||||
|
||||
>>> f(cols='should raise warning', another_param='')
|
||||
FutureWarning: the 'cols' keyword is deprecated and will be removed in a
|
||||
future version please takes steps to stop use of 'cols'
|
||||
should raise warning
|
||||
"""
|
||||
|
||||
if mapping is not None and not hasattr(mapping, "get") and not callable(mapping):
|
||||
raise TypeError(
|
||||
"mapping from old to new argument values " "must be dict or callable!"
|
||||
)
|
||||
|
||||
def _deprecate_kwarg(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
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:
|
||||
new_arg_value = mapping(old_arg_value)
|
||||
msg = (
|
||||
"the {old_name}={old_val!r} keyword is deprecated, "
|
||||
"use {new_name}={new_val!r} instead"
|
||||
).format(
|
||||
old_name=old_arg_name,
|
||||
old_val=old_arg_value,
|
||||
new_name=new_arg_name,
|
||||
new_val=new_arg_value,
|
||||
)
|
||||
else:
|
||||
new_arg_value = old_arg_value
|
||||
msg = (
|
||||
"the '{old_name}' keyword is deprecated, "
|
||||
"use '{new_name}' instead"
|
||||
).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:
|
||||
msg = (
|
||||
"Can only specify '{old_name}' or '{new_name}', " "not both"
|
||||
).format(old_name=old_arg_name, new_name=new_arg_name)
|
||||
raise TypeError(msg)
|
||||
else:
|
||||
kwargs[new_arg_name] = new_arg_value
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return _deprecate_kwarg
|
||||
|
||||
|
||||
def rewrite_axis_style_signature(
|
||||
name: str, extra_params: List[Tuple[str, Any]]
|
||||
) -> Callable:
|
||||
def decorate(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
|
||||
kind = inspect.Parameter.POSITIONAL_OR_KEYWORD
|
||||
params = [
|
||||
inspect.Parameter("self", kind),
|
||||
inspect.Parameter(name, kind, default=None),
|
||||
inspect.Parameter("index", kind, default=None),
|
||||
inspect.Parameter("columns", kind, default=None),
|
||||
inspect.Parameter("axis", kind, default=None),
|
||||
]
|
||||
|
||||
for pname, default in extra_params:
|
||||
params.append(inspect.Parameter(pname, kind, default=default))
|
||||
|
||||
sig = inspect.Signature(params)
|
||||
|
||||
func.__signature__ = sig
|
||||
return wrapper
|
||||
|
||||
return decorate
|
||||
|
||||
|
||||
# Substitution and Appender are derived from matplotlib.docstring (1.1.0)
|
||||
# module http://matplotlib.org/users/license.html
|
||||
|
||||
|
||||
class Substitution:
|
||||
"""
|
||||
A decorator to take a function's docstring and perform string
|
||||
substitution on it.
|
||||
|
||||
This decorator should be robust even if func.__doc__ is None
|
||||
(for example, if -OO was passed to the interpreter)
|
||||
|
||||
Usage: construct a docstring.Substitution with a sequence or
|
||||
dictionary suitable for performing substitution; then
|
||||
decorate a suitable function with the constructed object. e.g.
|
||||
|
||||
sub_author_name = Substitution(author='Jason')
|
||||
|
||||
@sub_author_name
|
||||
def some_function(x):
|
||||
"%(author)s wrote this function"
|
||||
|
||||
# note that some_function.__doc__ is now "Jason wrote this function"
|
||||
|
||||
One can also use positional arguments.
|
||||
|
||||
sub_first_last_names = Substitution('Edgar Allen', 'Poe')
|
||||
|
||||
@sub_first_last_names
|
||||
def some_function(x):
|
||||
"%s %s wrote the Raven"
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if args and kwargs:
|
||||
raise AssertionError("Only positional or keyword args are allowed")
|
||||
|
||||
self.params = args or kwargs
|
||||
|
||||
def __call__(self, func: Callable) -> Callable:
|
||||
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)
|
||||
|
||||
|
||||
class Appender:
|
||||
"""
|
||||
A function decorator that will append an addendum to the docstring
|
||||
of the target function.
|
||||
|
||||
This decorator should be robust even if func.__doc__ is None
|
||||
(for example, if -OO was passed to the interpreter).
|
||||
|
||||
Usage: construct a docstring.Appender with a string to be joined to
|
||||
the original docstring. An optional 'join' parameter may be supplied
|
||||
which will be used to join the docstring and addendum. e.g.
|
||||
|
||||
add_copyright = Appender("Copyright (c) 2009", join='\n')
|
||||
|
||||
@add_copyright
|
||||
def my_dog(has='fleas'):
|
||||
"This docstring will have a copyright below"
|
||||
pass
|
||||
"""
|
||||
|
||||
def __init__(self, addendum: Optional[str], join: str = "", indents: int = 0):
|
||||
if indents > 0:
|
||||
self.addendum = indent(addendum, indents=indents) # type: Optional[str]
|
||||
else:
|
||||
self.addendum = addendum
|
||||
self.join = join
|
||||
|
||||
def __call__(self, func: Callable) -> Callable:
|
||||
func.__doc__ = func.__doc__ if func.__doc__ else ""
|
||||
self.addendum = self.addendum if self.addendum else ""
|
||||
docitems = [func.__doc__, self.addendum]
|
||||
func.__doc__ = dedent(self.join.join(docitems))
|
||||
return func
|
||||
|
||||
|
||||
def indent(text: Optional[str], indents: int = 1) -> str:
|
||||
if not text or not isinstance(text, str):
|
||||
return ""
|
||||
jointext = "".join(["\n"] + [" "] * indents)
|
||||
return jointext.join(text.split("\n"))
|
109
venv/lib/python3.6/site-packages/pandas/util/_depr_module.py
Normal file
109
venv/lib/python3.6/site-packages/pandas/util/_depr_module.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""
|
||||
This module houses a utility class for mocking deprecated modules.
|
||||
It is for internal use only and should not be used beyond this purpose.
|
||||
"""
|
||||
|
||||
import importlib
|
||||
import warnings
|
||||
|
||||
|
||||
class _DeprecatedModule:
|
||||
""" Class for mocking deprecated modules.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
deprmod : name of module to be deprecated.
|
||||
deprmodto : name of module as a replacement, optional.
|
||||
If not given, the __module__ attribute will
|
||||
be used when needed.
|
||||
removals : objects or methods in module that will no longer be
|
||||
accessible once module is removed.
|
||||
moved : dict, optional
|
||||
dictionary of function name -> new location for moved
|
||||
objects
|
||||
"""
|
||||
|
||||
def __init__(self, deprmod, deprmodto=None, removals=None, moved=None):
|
||||
self.deprmod = deprmod
|
||||
self.deprmodto = deprmodto
|
||||
self.removals = removals
|
||||
if self.removals is not None:
|
||||
self.removals = frozenset(self.removals)
|
||||
self.moved = moved
|
||||
|
||||
# For introspection purposes.
|
||||
self.self_dir = frozenset(dir(self.__class__))
|
||||
|
||||
def __dir__(self):
|
||||
deprmodule = self._import_deprmod()
|
||||
return dir(deprmodule)
|
||||
|
||||
def __repr__(self):
|
||||
deprmodule = self._import_deprmod()
|
||||
return repr(deprmodule)
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name in self.self_dir:
|
||||
return object.__getattribute__(self, name)
|
||||
|
||||
try:
|
||||
deprmodule = self._import_deprmod(self.deprmod)
|
||||
except ImportError:
|
||||
if self.deprmodto is None:
|
||||
raise
|
||||
|
||||
# a rename
|
||||
deprmodule = self._import_deprmod(self.deprmodto)
|
||||
|
||||
obj = getattr(deprmodule, name)
|
||||
|
||||
if self.removals is not None and name in self.removals:
|
||||
warnings.warn(
|
||||
"{deprmod}.{name} is deprecated and will be removed in "
|
||||
"a future version.".format(deprmod=self.deprmod, name=name),
|
||||
FutureWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
elif self.moved is not None and name in self.moved:
|
||||
warnings.warn(
|
||||
"{deprmod} is deprecated and will be removed in "
|
||||
"a future version.\nYou can access {name} as {moved}".format(
|
||||
deprmod=self.deprmod, name=name, moved=self.moved[name]
|
||||
),
|
||||
FutureWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
else:
|
||||
deprmodto = self.deprmodto
|
||||
if deprmodto is False:
|
||||
warnings.warn(
|
||||
"{deprmod}.{name} is deprecated and will be removed in "
|
||||
"a future version.".format(deprmod=self.deprmod, name=name),
|
||||
FutureWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
else:
|
||||
if deprmodto is None:
|
||||
deprmodto = obj.__module__
|
||||
# The object is actually located in another module.
|
||||
warnings.warn(
|
||||
"{deprmod}.{name} is deprecated. Please use "
|
||||
"{deprmodto}.{name} instead.".format(
|
||||
deprmod=self.deprmod, name=name, deprmodto=deprmodto
|
||||
),
|
||||
FutureWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
return obj
|
||||
|
||||
def _import_deprmod(self, mod=None):
|
||||
if mod is None:
|
||||
mod = self.deprmod
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", category=FutureWarning)
|
||||
deprmodule = importlib.import_module(mod)
|
||||
return deprmodule
|
186
venv/lib/python3.6/site-packages/pandas/util/_doctools.py
Normal file
186
venv/lib/python3.6/site-packages/pandas/util/_doctools.py
Normal file
@@ -0,0 +1,186 @@
|
||||
import numpy as np
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class TablePlotter:
|
||||
"""
|
||||
Layout some DataFrames in vertical/horizontal layout for explanation.
|
||||
Used in merging.rst
|
||||
"""
|
||||
|
||||
def __init__(self, cell_width=0.37, cell_height=0.25, font_size=7.5):
|
||||
self.cell_width = cell_width
|
||||
self.cell_height = cell_height
|
||||
self.font_size = font_size
|
||||
|
||||
def _shape(self, df):
|
||||
"""
|
||||
Calculate table chape considering index levels.
|
||||
"""
|
||||
|
||||
row, col = df.shape
|
||||
return row + df.columns.nlevels, col + df.index.nlevels
|
||||
|
||||
def _get_cells(self, left, right, vertical):
|
||||
"""
|
||||
Calculate appropriate figure size based on left and right data.
|
||||
"""
|
||||
|
||||
if vertical:
|
||||
# calculate required number of cells
|
||||
vcells = max(sum(self._shape(l)[0] for l in left), self._shape(right)[0])
|
||||
hcells = max(self._shape(l)[1] for l in left) + self._shape(right)[1]
|
||||
else:
|
||||
vcells = max([self._shape(l)[0] for l in left] + [self._shape(right)[0]])
|
||||
hcells = sum([self._shape(l)[1] for l in left] + [self._shape(right)[1]])
|
||||
return hcells, vcells
|
||||
|
||||
def plot(self, left, right, labels=None, vertical=True):
|
||||
"""
|
||||
Plot left / right DataFrames in specified layout.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
left : list of DataFrames before operation is applied
|
||||
right : DataFrame of operation result
|
||||
labels : list of str to be drawn as titles of left DataFrames
|
||||
vertical : bool
|
||||
If True, use vertical layout. If False, use horizontal layout.
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.gridspec as gridspec
|
||||
|
||||
if not isinstance(left, list):
|
||||
left = [left]
|
||||
left = [self._conv(l) for l in left]
|
||||
right = self._conv(right)
|
||||
|
||||
hcells, vcells = self._get_cells(left, right, vertical)
|
||||
|
||||
if vertical:
|
||||
figsize = self.cell_width * hcells, self.cell_height * vcells
|
||||
else:
|
||||
# include margin for titles
|
||||
figsize = self.cell_width * hcells, self.cell_height * vcells
|
||||
fig = plt.figure(figsize=figsize)
|
||||
|
||||
if vertical:
|
||||
gs = gridspec.GridSpec(len(left), hcells)
|
||||
# left
|
||||
max_left_cols = max(self._shape(l)[1] for l in left)
|
||||
max_left_rows = max(self._shape(l)[0] for l in left)
|
||||
for i, (l, label) in enumerate(zip(left, labels)):
|
||||
ax = fig.add_subplot(gs[i, 0:max_left_cols])
|
||||
self._make_table(ax, l, title=label, height=1.0 / max_left_rows)
|
||||
# right
|
||||
ax = plt.subplot(gs[:, max_left_cols:])
|
||||
self._make_table(ax, right, title="Result", height=1.05 / vcells)
|
||||
fig.subplots_adjust(top=0.9, bottom=0.05, left=0.05, right=0.95)
|
||||
else:
|
||||
max_rows = max(self._shape(df)[0] for df in left + [right])
|
||||
height = 1.0 / np.max(max_rows)
|
||||
gs = gridspec.GridSpec(1, hcells)
|
||||
# left
|
||||
i = 0
|
||||
for l, label in zip(left, labels):
|
||||
sp = self._shape(l)
|
||||
ax = fig.add_subplot(gs[0, i : i + sp[1]])
|
||||
self._make_table(ax, l, title=label, height=height)
|
||||
i += sp[1]
|
||||
# right
|
||||
ax = plt.subplot(gs[0, i:])
|
||||
self._make_table(ax, right, title="Result", height=height)
|
||||
fig.subplots_adjust(top=0.85, bottom=0.05, left=0.05, right=0.95)
|
||||
|
||||
return fig
|
||||
|
||||
def _conv(self, data):
|
||||
"""Convert each input to appropriate for table outplot"""
|
||||
if isinstance(data, pd.Series):
|
||||
if data.name is None:
|
||||
data = data.to_frame(name="")
|
||||
else:
|
||||
data = data.to_frame()
|
||||
data = data.fillna("NaN")
|
||||
return data
|
||||
|
||||
def _insert_index(self, data):
|
||||
# insert is destructive
|
||||
data = data.copy()
|
||||
idx_nlevels = data.index.nlevels
|
||||
if idx_nlevels == 1:
|
||||
data.insert(0, "Index", data.index)
|
||||
else:
|
||||
for i in range(idx_nlevels):
|
||||
data.insert(i, "Index{0}".format(i), data.index._get_level_values(i))
|
||||
|
||||
col_nlevels = data.columns.nlevels
|
||||
if col_nlevels > 1:
|
||||
col = data.columns._get_level_values(0)
|
||||
values = [
|
||||
data.columns._get_level_values(i).values for i in range(1, col_nlevels)
|
||||
]
|
||||
col_df = pd.DataFrame(values)
|
||||
data.columns = col_df.columns
|
||||
data = pd.concat([col_df, data])
|
||||
data.columns = col
|
||||
return data
|
||||
|
||||
def _make_table(self, ax, df, title, height=None):
|
||||
if df is None:
|
||||
ax.set_visible(False)
|
||||
return
|
||||
|
||||
import pandas.plotting as plotting
|
||||
|
||||
idx_nlevels = df.index.nlevels
|
||||
col_nlevels = df.columns.nlevels
|
||||
# must be convert here to get index levels for colorization
|
||||
df = self._insert_index(df)
|
||||
tb = plotting.table(ax, df, loc=9)
|
||||
tb.set_fontsize(self.font_size)
|
||||
|
||||
if height is None:
|
||||
height = 1.0 / (len(df) + 1)
|
||||
|
||||
props = tb.properties()
|
||||
for (r, c), cell in props["celld"].items():
|
||||
if c == -1:
|
||||
cell.set_visible(False)
|
||||
elif r < col_nlevels and c < idx_nlevels:
|
||||
cell.set_visible(False)
|
||||
elif r < col_nlevels or c < idx_nlevels:
|
||||
cell.set_facecolor("#AAAAAA")
|
||||
cell.set_height(height)
|
||||
|
||||
ax.set_title(title, size=self.font_size)
|
||||
ax.axis("off")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
p = TablePlotter()
|
||||
|
||||
df1 = pd.DataFrame({"A": [10, 11, 12], "B": [20, 21, 22], "C": [30, 31, 32]})
|
||||
df2 = pd.DataFrame({"A": [10, 12], "C": [30, 32]})
|
||||
|
||||
p.plot([df1, df2], pd.concat([df1, df2]), labels=["df1", "df2"], vertical=True)
|
||||
plt.show()
|
||||
|
||||
df3 = pd.DataFrame({"X": [10, 12], "Z": [30, 32]})
|
||||
|
||||
p.plot(
|
||||
[df1, df3], pd.concat([df1, df3], axis=1), labels=["df1", "df2"], vertical=False
|
||||
)
|
||||
plt.show()
|
||||
|
||||
idx = pd.MultiIndex.from_tuples(
|
||||
[(1, "A"), (1, "B"), (1, "C"), (2, "A"), (2, "B"), (2, "C")]
|
||||
)
|
||||
col = pd.MultiIndex.from_tuples([(1, "A"), (1, "B")])
|
||||
df3 = pd.DataFrame({"v1": [1, 2, 3, 4, 5, 6], "v2": [5, 6, 7, 8, 9, 10]}, index=idx)
|
||||
df3.columns = col
|
||||
p.plot(df3, df3, labels=["df3"])
|
||||
plt.show()
|
16
venv/lib/python3.6/site-packages/pandas/util/_exceptions.py
Normal file
16
venv/lib/python3.6/site-packages/pandas/util/_exceptions.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import contextlib
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def rewrite_exception(old_name, new_name):
|
||||
"""Rewrite the message of an exception."""
|
||||
try:
|
||||
yield
|
||||
except Exception as e:
|
||||
msg = e.args[0]
|
||||
msg = msg.replace(old_name, new_name)
|
||||
args = (msg,)
|
||||
if len(e.args) > 1:
|
||||
args = args + e.args[1:]
|
||||
e.args = args
|
||||
raise
|
Binary file not shown.
156
venv/lib/python3.6/site-packages/pandas/util/_print_versions.py
Normal file
156
venv/lib/python3.6/site-packages/pandas/util/_print_versions.py
Normal file
@@ -0,0 +1,156 @@
|
||||
import codecs
|
||||
import locale
|
||||
import os
|
||||
import platform
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from pandas.compat._optional import VERSIONS, _get_version, import_optional_dependency
|
||||
|
||||
|
||||
def get_sys_info():
|
||||
"Returns system information as a dict"
|
||||
|
||||
blob = []
|
||||
|
||||
# get full commit hash
|
||||
commit = None
|
||||
if os.path.isdir(".git") and os.path.isdir("pandas"):
|
||||
try:
|
||||
pipe = subprocess.Popen(
|
||||
'git log --format="%H" -n 1'.split(" "),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
so, serr = pipe.communicate()
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
else:
|
||||
if pipe.returncode == 0:
|
||||
commit = so
|
||||
try:
|
||||
commit = so.decode("utf-8")
|
||||
except ValueError:
|
||||
pass
|
||||
commit = commit.strip().strip('"')
|
||||
|
||||
blob.append(("commit", commit))
|
||||
|
||||
try:
|
||||
(sysname, nodename, release, version, machine, processor) = platform.uname()
|
||||
blob.extend(
|
||||
[
|
||||
("python", ".".join(map(str, sys.version_info))),
|
||||
("python-bits", struct.calcsize("P") * 8),
|
||||
("OS", "{sysname}".format(sysname=sysname)),
|
||||
("OS-release", "{release}".format(release=release)),
|
||||
# ("Version", "{version}".format(version=version)),
|
||||
("machine", "{machine}".format(machine=machine)),
|
||||
("processor", "{processor}".format(processor=processor)),
|
||||
("byteorder", "{byteorder}".format(byteorder=sys.byteorder)),
|
||||
("LC_ALL", "{lc}".format(lc=os.environ.get("LC_ALL", "None"))),
|
||||
("LANG", "{lang}".format(lang=os.environ.get("LANG", "None"))),
|
||||
("LOCALE", ".".join(map(str, locale.getlocale()))),
|
||||
]
|
||||
)
|
||||
except (KeyError, ValueError):
|
||||
pass
|
||||
|
||||
return blob
|
||||
|
||||
|
||||
def show_versions(as_json=False):
|
||||
sys_info = get_sys_info()
|
||||
deps = [
|
||||
"pandas",
|
||||
# required
|
||||
"numpy",
|
||||
"pytz",
|
||||
"dateutil",
|
||||
# install / build,
|
||||
"pip",
|
||||
"setuptools",
|
||||
"Cython",
|
||||
# test
|
||||
"pytest",
|
||||
"hypothesis",
|
||||
# docs
|
||||
"sphinx",
|
||||
# Other, need a min version
|
||||
"blosc",
|
||||
"feather",
|
||||
"xlsxwriter",
|
||||
"lxml.etree",
|
||||
"html5lib",
|
||||
"pymysql",
|
||||
"psycopg2",
|
||||
"jinja2",
|
||||
# Other, not imported.
|
||||
"IPython",
|
||||
"pandas_datareader",
|
||||
]
|
||||
|
||||
deps.extend(list(VERSIONS))
|
||||
deps_blob = []
|
||||
|
||||
for modname in deps:
|
||||
mod = import_optional_dependency(
|
||||
modname, raise_on_missing=False, on_version="ignore"
|
||||
)
|
||||
if mod:
|
||||
ver = _get_version(mod)
|
||||
else:
|
||||
ver = None
|
||||
deps_blob.append((modname, ver))
|
||||
|
||||
if as_json:
|
||||
try:
|
||||
import json
|
||||
except ImportError:
|
||||
import simplejson as json
|
||||
|
||||
j = dict(system=dict(sys_info), dependencies=dict(deps_blob))
|
||||
|
||||
if as_json is True:
|
||||
print(j)
|
||||
else:
|
||||
with codecs.open(as_json, "wb", encoding="utf8") as f:
|
||||
json.dump(j, f, indent=2)
|
||||
|
||||
else:
|
||||
maxlen = max(len(x) for x in deps)
|
||||
tpl = "{{k:<{maxlen}}}: {{stat}}".format(maxlen=maxlen)
|
||||
print("\nINSTALLED VERSIONS")
|
||||
print("------------------")
|
||||
for k, stat in sys_info:
|
||||
print(tpl.format(k=k, stat=stat))
|
||||
print("")
|
||||
for k, stat in deps_blob:
|
||||
print(tpl.format(k=k, stat=stat))
|
||||
|
||||
|
||||
def main():
|
||||
from optparse import OptionParser
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option(
|
||||
"-j",
|
||||
"--json",
|
||||
metavar="FILE",
|
||||
nargs=1,
|
||||
help="Save output as JSON into file, pass in " "'-' to output to stdout",
|
||||
)
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.json == "-":
|
||||
options.json = True
|
||||
|
||||
show_versions(as_json=options.json)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
217
venv/lib/python3.6/site-packages/pandas/util/_test_decorators.py
Normal file
217
venv/lib/python3.6/site-packages/pandas/util/_test_decorators.py
Normal file
@@ -0,0 +1,217 @@
|
||||
"""
|
||||
This module provides decorator functions which can be applied to test objects
|
||||
in order to skip those objects when certain conditions occur. A sample use case
|
||||
is to detect if the platform is missing ``matplotlib``. If so, any test objects
|
||||
which require ``matplotlib`` and decorated with ``@td.skip_if_no_mpl`` will be
|
||||
skipped by ``pytest`` during the execution of the test suite.
|
||||
|
||||
To illustrate, after importing this module:
|
||||
|
||||
import pandas.util._test_decorators as td
|
||||
|
||||
The decorators can be applied to classes:
|
||||
|
||||
@td.skip_if_some_reason
|
||||
class Foo:
|
||||
...
|
||||
|
||||
Or individual functions:
|
||||
|
||||
@td.skip_if_some_reason
|
||||
def test_foo():
|
||||
...
|
||||
|
||||
For more information, refer to the ``pytest`` documentation on ``skipif``.
|
||||
"""
|
||||
from distutils.version import LooseVersion
|
||||
import locale
|
||||
from typing import Optional
|
||||
|
||||
from _pytest.mark.structures import MarkDecorator
|
||||
import pytest
|
||||
|
||||
from pandas.compat import is_platform_32bit, is_platform_windows
|
||||
from pandas.compat.numpy import _np_version
|
||||
|
||||
from pandas.core.computation.expressions import _NUMEXPR_INSTALLED, _USE_NUMEXPR
|
||||
|
||||
|
||||
def safe_import(mod_name, min_version=None):
|
||||
"""
|
||||
Parameters:
|
||||
-----------
|
||||
mod_name : str
|
||||
Name of the module to be imported
|
||||
min_version : str, default None
|
||||
Minimum required version of the specified mod_name
|
||||
|
||||
Returns:
|
||||
--------
|
||||
object
|
||||
The imported module if successful, or False
|
||||
"""
|
||||
try:
|
||||
mod = __import__(mod_name)
|
||||
except ImportError:
|
||||
return False
|
||||
|
||||
if not min_version:
|
||||
return mod
|
||||
else:
|
||||
import sys
|
||||
|
||||
try:
|
||||
version = getattr(sys.modules[mod_name], "__version__")
|
||||
except AttributeError:
|
||||
# xlrd uses a capitalized attribute name
|
||||
version = getattr(sys.modules[mod_name], "__VERSION__")
|
||||
if version:
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
if LooseVersion(version) >= LooseVersion(min_version):
|
||||
return mod
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _skip_if_no_mpl():
|
||||
mod = safe_import("matplotlib")
|
||||
if mod:
|
||||
mod.use("Agg", warn=True)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def _skip_if_has_locale():
|
||||
lang, _ = locale.getlocale()
|
||||
if lang is not None:
|
||||
return True
|
||||
|
||||
|
||||
def _skip_if_not_us_locale():
|
||||
lang, _ = locale.getlocale()
|
||||
if lang != "en_US":
|
||||
return True
|
||||
|
||||
|
||||
def _skip_if_no_scipy():
|
||||
return not (
|
||||
safe_import("scipy.stats")
|
||||
and safe_import("scipy.sparse")
|
||||
and safe_import("scipy.interpolate")
|
||||
and safe_import("scipy.signal")
|
||||
)
|
||||
|
||||
|
||||
def skip_if_installed(package: str,) -> MarkDecorator:
|
||||
"""
|
||||
Skip a test if a package is installed.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
package : str
|
||||
The name of the package.
|
||||
"""
|
||||
return pytest.mark.skipif(
|
||||
safe_import(package), reason="Skipping because {} is installed.".format(package)
|
||||
)
|
||||
|
||||
|
||||
def skip_if_no(package: str, min_version: Optional[str] = None) -> MarkDecorator:
|
||||
"""
|
||||
Generic function to help skip tests when required packages are not
|
||||
present on the testing system.
|
||||
|
||||
This function returns a pytest mark with a skip condition that will be
|
||||
evaluated during test collection. An attempt will be made to import the
|
||||
specified ``package`` and optionally ensure it meets the ``min_version``
|
||||
|
||||
The mark can be used as either a decorator for a test function or to be
|
||||
applied to parameters in pytest.mark.parametrize calls or parametrized
|
||||
fixtures.
|
||||
|
||||
If the import and version check are unsuccessful, then the test function
|
||||
(or test case when used in conjunction with parametrization) will be
|
||||
skipped.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
package: str
|
||||
The name of the required package.
|
||||
min_version: str or None, default None
|
||||
Optional minimum version of the package.
|
||||
|
||||
Returns
|
||||
-------
|
||||
_pytest.mark.structures.MarkDecorator
|
||||
a pytest.mark.skipif to use as either a test decorator or a
|
||||
parametrization mark.
|
||||
"""
|
||||
msg = "Could not import '{}'".format(package)
|
||||
if min_version:
|
||||
msg += " satisfying a min_version of {}".format(min_version)
|
||||
return pytest.mark.skipif(
|
||||
not safe_import(package, min_version=min_version), reason=msg
|
||||
)
|
||||
|
||||
|
||||
skip_if_no_mpl = pytest.mark.skipif(
|
||||
_skip_if_no_mpl(), reason="Missing matplotlib dependency"
|
||||
)
|
||||
skip_if_mpl = pytest.mark.skipif(not _skip_if_no_mpl(), reason="matplotlib is present")
|
||||
skip_if_32bit = pytest.mark.skipif(is_platform_32bit(), reason="skipping for 32 bit")
|
||||
skip_if_windows = pytest.mark.skipif(is_platform_windows(), reason="Running on Windows")
|
||||
skip_if_windows_python_3 = pytest.mark.skipif(
|
||||
is_platform_windows(), reason="not used on win32"
|
||||
)
|
||||
skip_if_has_locale = pytest.mark.skipif(
|
||||
_skip_if_has_locale(),
|
||||
reason="Specific locale is set {lang}".format(lang=locale.getlocale()[0]),
|
||||
)
|
||||
skip_if_not_us_locale = pytest.mark.skipif(
|
||||
_skip_if_not_us_locale(),
|
||||
reason="Specific locale is set " "{lang}".format(lang=locale.getlocale()[0]),
|
||||
)
|
||||
skip_if_no_scipy = pytest.mark.skipif(
|
||||
_skip_if_no_scipy(), reason="Missing SciPy requirement"
|
||||
)
|
||||
skip_if_no_ne = pytest.mark.skipif(
|
||||
not _USE_NUMEXPR,
|
||||
reason="numexpr enabled->{enabled}, "
|
||||
"installed->{installed}".format(enabled=_USE_NUMEXPR, installed=_NUMEXPR_INSTALLED),
|
||||
)
|
||||
|
||||
|
||||
def skip_if_np_lt(ver_str, reason=None, *args, **kwds):
|
||||
if reason is None:
|
||||
reason = "NumPy %s or greater required" % ver_str
|
||||
return pytest.mark.skipif(
|
||||
_np_version < LooseVersion(ver_str), reason=reason, *args, **kwds
|
||||
)
|
||||
|
||||
|
||||
def parametrize_fixture_doc(*args):
|
||||
"""
|
||||
Intended for use as a decorator for parametrized fixture,
|
||||
this function will wrap the decorated function with a pytest
|
||||
``parametrize_fixture_doc`` mark. That mark will format
|
||||
initial fixture docstring by replacing placeholders {0}, {1} etc
|
||||
with parameters passed as arguments.
|
||||
|
||||
Parameters:
|
||||
----------
|
||||
args: iterable
|
||||
Positional arguments for docstring.
|
||||
|
||||
Returns:
|
||||
-------
|
||||
documented_fixture: function
|
||||
The decorated function wrapped within a pytest
|
||||
``parametrize_fixture_doc`` mark
|
||||
"""
|
||||
|
||||
def documented_fixture(fixture):
|
||||
fixture.__doc__ = fixture.__doc__.format(*args)
|
||||
return fixture
|
||||
|
||||
return documented_fixture
|
29
venv/lib/python3.6/site-packages/pandas/util/_tester.py
Normal file
29
venv/lib/python3.6/site-packages/pandas/util/_tester.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Entrypoint for testing from the top-level namespace
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
PKG = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def test(extra_args=None):
|
||||
try:
|
||||
import pytest
|
||||
except ImportError:
|
||||
raise ImportError("Need pytest>=4.0.2 to run tests")
|
||||
try:
|
||||
import hypothesis # noqa
|
||||
except ImportError:
|
||||
raise ImportError("Need hypothesis>=3.58 to run tests")
|
||||
cmd = ["--skip-slow", "--skip-network", "--skip-db"]
|
||||
if extra_args:
|
||||
if not isinstance(extra_args, list):
|
||||
extra_args = [extra_args]
|
||||
cmd = extra_args
|
||||
cmd += [PKG]
|
||||
print("running: pytest {}".format(" ".join(cmd)))
|
||||
sys.exit(pytest.main(cmd))
|
||||
|
||||
|
||||
__all__ = ["test"]
|
372
venv/lib/python3.6/site-packages/pandas/util/_validators.py
Normal file
372
venv/lib/python3.6/site-packages/pandas/util/_validators.py
Normal file
@@ -0,0 +1,372 @@
|
||||
"""
|
||||
Module that contains many useful utilities
|
||||
for validating data or function arguments
|
||||
"""
|
||||
import warnings
|
||||
|
||||
from pandas.core.dtypes.common import is_bool
|
||||
|
||||
|
||||
def _check_arg_length(fname, args, max_fname_arg_count, compat_args):
|
||||
"""
|
||||
Checks whether 'args' has length of at most 'compat_args'. Raises
|
||||
a TypeError if that is not the case, similar to in Python when a
|
||||
function is called with too many arguments.
|
||||
|
||||
"""
|
||||
if max_fname_arg_count < 0:
|
||||
raise ValueError("'max_fname_arg_count' must be non-negative")
|
||||
|
||||
if len(args) > len(compat_args):
|
||||
max_arg_count = len(compat_args) + max_fname_arg_count
|
||||
actual_arg_count = len(args) + max_fname_arg_count
|
||||
argument = "argument" if max_arg_count == 1 else "arguments"
|
||||
|
||||
raise TypeError(
|
||||
"{fname}() takes at most {max_arg} {argument} "
|
||||
"({given_arg} given)".format(
|
||||
fname=fname,
|
||||
max_arg=max_arg_count,
|
||||
argument=argument,
|
||||
given_arg=actual_arg_count,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _check_for_default_values(fname, arg_val_dict, compat_args):
|
||||
"""
|
||||
Check that the keys in `arg_val_dict` are mapped to their
|
||||
default values as specified in `compat_args`.
|
||||
|
||||
Note that this function is to be called only when it has been
|
||||
checked that arg_val_dict.keys() is a subset of compat_args
|
||||
|
||||
"""
|
||||
for key in arg_val_dict:
|
||||
# try checking equality directly with '=' operator,
|
||||
# as comparison may have been overridden for the left
|
||||
# hand object
|
||||
try:
|
||||
v1 = arg_val_dict[key]
|
||||
v2 = compat_args[key]
|
||||
|
||||
# check for None-ness otherwise we could end up
|
||||
# comparing a numpy array vs None
|
||||
if (v1 is not None and v2 is None) or (v1 is None and v2 is not None):
|
||||
match = False
|
||||
else:
|
||||
match = v1 == v2
|
||||
|
||||
if not is_bool(match):
|
||||
raise ValueError("'match' is not a boolean")
|
||||
|
||||
# could not compare them directly, so try comparison
|
||||
# using the 'is' operator
|
||||
except ValueError:
|
||||
match = arg_val_dict[key] is compat_args[key]
|
||||
|
||||
if not match:
|
||||
raise ValueError(
|
||||
(
|
||||
"the '{arg}' parameter is not "
|
||||
"supported in the pandas "
|
||||
"implementation of {fname}()".format(fname=fname, arg=key)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def validate_args(fname, args, max_fname_arg_count, compat_args):
|
||||
"""
|
||||
Checks whether the length of the `*args` argument passed into a function
|
||||
has at most `len(compat_args)` arguments and whether or not all of these
|
||||
elements in `args` are set to their default values.
|
||||
|
||||
fname: str
|
||||
The name of the function being passed the `*args` parameter
|
||||
|
||||
args: tuple
|
||||
The `*args` parameter passed into a function
|
||||
|
||||
max_fname_arg_count: int
|
||||
The maximum number of arguments that the function `fname`
|
||||
can accept, excluding those in `args`. Used for displaying
|
||||
appropriate error messages. Must be non-negative.
|
||||
|
||||
compat_args: OrderedDict
|
||||
A ordered dictionary of keys and their associated default values.
|
||||
In order to accommodate buggy behaviour in some versions of `numpy`,
|
||||
where a signature displayed keyword arguments but then passed those
|
||||
arguments **positionally** internally when calling downstream
|
||||
implementations, an ordered dictionary ensures that the original
|
||||
order of the keyword arguments is enforced. Note that if there is
|
||||
only one key, a generic dict can be passed in as well.
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError if `args` contains more values than there are `compat_args`
|
||||
ValueError if `args` contains values that do not correspond to those
|
||||
of the default values specified in `compat_args`
|
||||
|
||||
"""
|
||||
_check_arg_length(fname, args, max_fname_arg_count, compat_args)
|
||||
|
||||
# We do this so that we can provide a more informative
|
||||
# error message about the parameters that we are not
|
||||
# supporting in the pandas implementation of 'fname'
|
||||
kwargs = dict(zip(compat_args, args))
|
||||
_check_for_default_values(fname, kwargs, compat_args)
|
||||
|
||||
|
||||
def _check_for_invalid_keys(fname, kwargs, compat_args):
|
||||
"""
|
||||
Checks whether 'kwargs' contains any keys that are not
|
||||
in 'compat_args' and raises a TypeError if there is one.
|
||||
|
||||
"""
|
||||
# set(dict) --> set of the dictionary's keys
|
||||
diff = set(kwargs) - set(compat_args)
|
||||
|
||||
if diff:
|
||||
bad_arg = list(diff)[0]
|
||||
raise TypeError(
|
||||
(
|
||||
"{fname}() got an unexpected "
|
||||
"keyword argument '{arg}'".format(fname=fname, arg=bad_arg)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def validate_kwargs(fname, kwargs, compat_args):
|
||||
"""
|
||||
Checks whether parameters passed to the **kwargs argument in a
|
||||
function `fname` are valid parameters as specified in `*compat_args`
|
||||
and whether or not they are set to their default values.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fname: str
|
||||
The name of the function being passed the `**kwargs` parameter
|
||||
|
||||
kwargs: dict
|
||||
The `**kwargs` parameter passed into `fname`
|
||||
|
||||
compat_args: dict
|
||||
A dictionary of keys that `kwargs` is allowed to have and their
|
||||
associated default values
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError if `kwargs` contains keys not in `compat_args`
|
||||
ValueError if `kwargs` contains keys in `compat_args` that do not
|
||||
map to the default values specified in `compat_args`
|
||||
|
||||
"""
|
||||
kwds = kwargs.copy()
|
||||
_check_for_invalid_keys(fname, kwargs, compat_args)
|
||||
_check_for_default_values(fname, kwds, compat_args)
|
||||
|
||||
|
||||
def validate_args_and_kwargs(fname, args, kwargs, max_fname_arg_count, compat_args):
|
||||
"""
|
||||
Checks whether parameters passed to the *args and **kwargs argument in a
|
||||
function `fname` are valid parameters as specified in `*compat_args`
|
||||
and whether or not they are set to their default values.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fname: str
|
||||
The name of the function being passed the `**kwargs` parameter
|
||||
|
||||
args: tuple
|
||||
The `*args` parameter passed into a function
|
||||
|
||||
kwargs: dict
|
||||
The `**kwargs` parameter passed into `fname`
|
||||
|
||||
max_fname_arg_count: int
|
||||
The minimum number of arguments that the function `fname`
|
||||
requires, excluding those in `args`. Used for displaying
|
||||
appropriate error messages. Must be non-negative.
|
||||
|
||||
compat_args: OrderedDict
|
||||
A ordered dictionary of keys that `kwargs` is allowed to
|
||||
have and their associated default values. Note that if there
|
||||
is only one key, a generic dict can be passed in as well.
|
||||
|
||||
Raises
|
||||
------
|
||||
TypeError if `args` contains more values than there are
|
||||
`compat_args` OR `kwargs` contains keys not in `compat_args`
|
||||
ValueError if `args` contains values not at the default value (`None`)
|
||||
`kwargs` contains keys in `compat_args` that do not map to the default
|
||||
value as specified in `compat_args`
|
||||
|
||||
See Also
|
||||
--------
|
||||
validate_args : Purely args validation.
|
||||
validate_kwargs : Purely kwargs validation.
|
||||
|
||||
"""
|
||||
# Check that the total number of arguments passed in (i.e.
|
||||
# args and kwargs) does not exceed the length of compat_args
|
||||
_check_arg_length(
|
||||
fname, args + tuple(kwargs.values()), max_fname_arg_count, compat_args
|
||||
)
|
||||
|
||||
# Check there is no overlap with the positional and keyword
|
||||
# arguments, similar to what is done in actual Python functions
|
||||
args_dict = dict(zip(compat_args, args))
|
||||
|
||||
for key in args_dict:
|
||||
if key in kwargs:
|
||||
raise TypeError(
|
||||
"{fname}() got multiple values for keyword "
|
||||
"argument '{arg}'".format(fname=fname, arg=key)
|
||||
)
|
||||
|
||||
kwargs.update(args_dict)
|
||||
validate_kwargs(fname, kwargs, compat_args)
|
||||
|
||||
|
||||
def validate_bool_kwarg(value, arg_name):
|
||||
""" Ensures that argument passed in arg_name is of type bool. """
|
||||
if not (is_bool(value) or value is None):
|
||||
raise ValueError(
|
||||
'For argument "{arg}" expected type bool, received '
|
||||
"type {typ}.".format(arg=arg_name, typ=type(value).__name__)
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
def validate_axis_style_args(data, args, kwargs, arg_name, method_name):
|
||||
"""Argument handler for mixed index, columns / axis functions
|
||||
|
||||
In an attempt to handle both `.method(index, columns)`, and
|
||||
`.method(arg, axis=.)`, we have to do some bad things to argument
|
||||
parsing. This translates all arguments to `{index=., columns=.}` style.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
data : DataFrame
|
||||
args : tuple
|
||||
All positional arguments from the user
|
||||
kwargs : dict
|
||||
All keyword arguments from the user
|
||||
arg_name, method_name : str
|
||||
Used for better error messages
|
||||
|
||||
Returns
|
||||
-------
|
||||
kwargs : dict
|
||||
A dictionary of keyword arguments. Doesn't modify ``kwargs``
|
||||
inplace, so update them with the return value here.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> df._validate_axis_style_args((str.upper,), {'columns': id},
|
||||
... 'mapper', 'rename')
|
||||
{'columns': <function id>, 'index': <method 'upper' of 'str' objects>}
|
||||
|
||||
This emits a warning
|
||||
>>> df._validate_axis_style_args((str.upper, id), {},
|
||||
... 'mapper', 'rename')
|
||||
{'columns': <function id>, 'index': <method 'upper' of 'str' objects>}
|
||||
"""
|
||||
# TODO: Change to keyword-only args and remove all this
|
||||
|
||||
out = {}
|
||||
# Goal: fill 'out' with index/columns-style arguments
|
||||
# like out = {'index': foo, 'columns': bar}
|
||||
|
||||
# Start by validating for consistency
|
||||
if "axis" in kwargs and any(x in kwargs for x in data._AXIS_NUMBERS):
|
||||
msg = "Cannot specify both 'axis' and any of 'index' or 'columns'."
|
||||
raise TypeError(msg)
|
||||
|
||||
# First fill with explicit values provided by the user...
|
||||
if arg_name in kwargs:
|
||||
if args:
|
||||
msg = "{} got multiple values for argument " "'{}'".format(
|
||||
method_name, arg_name
|
||||
)
|
||||
raise TypeError(msg)
|
||||
|
||||
axis = data._get_axis_name(kwargs.get("axis", 0))
|
||||
out[axis] = kwargs[arg_name]
|
||||
|
||||
# More user-provided arguments, now from kwargs
|
||||
for k, v in kwargs.items():
|
||||
try:
|
||||
ax = data._get_axis_name(k)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
out[ax] = v
|
||||
|
||||
# All user-provided kwargs have been handled now.
|
||||
# Now we supplement with positional arguments, emitting warnings
|
||||
# when there's ambiguity and raising when there's conflicts
|
||||
|
||||
if len(args) == 0:
|
||||
pass # It's up to the function to decide if this is valid
|
||||
elif len(args) == 1:
|
||||
axis = data._get_axis_name(kwargs.get("axis", 0))
|
||||
out[axis] = args[0]
|
||||
elif len(args) == 2:
|
||||
if "axis" in kwargs:
|
||||
# Unambiguously wrong
|
||||
msg = "Cannot specify both 'axis' and any of 'index' " "or 'columns'"
|
||||
raise TypeError(msg)
|
||||
|
||||
msg = (
|
||||
"Interpreting call\n\t'.{method_name}(a, b)' as "
|
||||
"\n\t'.{method_name}(index=a, columns=b)'.\nUse named "
|
||||
"arguments to remove any ambiguity. In the future, using "
|
||||
"positional arguments for 'index' or 'columns' will raise "
|
||||
" a 'TypeError'."
|
||||
)
|
||||
warnings.warn(msg.format(method_name=method_name), FutureWarning, stacklevel=4)
|
||||
out[data._AXIS_NAMES[0]] = args[0]
|
||||
out[data._AXIS_NAMES[1]] = args[1]
|
||||
else:
|
||||
msg = "Cannot specify all of '{}', 'index', 'columns'."
|
||||
raise TypeError(msg.format(arg_name))
|
||||
return out
|
||||
|
||||
|
||||
def validate_fillna_kwargs(value, method, validate_scalar_dict_value=True):
|
||||
"""Validate the keyword arguments to 'fillna'.
|
||||
|
||||
This checks that exactly one of 'value' and 'method' is specified.
|
||||
If 'method' is specified, this validates that it's a valid method.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value, method : object
|
||||
The 'value' and 'method' keyword arguments for 'fillna'.
|
||||
validate_scalar_dict_value : bool, default True
|
||||
Whether to validate that 'value' is a scalar or dict. Specifically,
|
||||
validate that it is not a list or tuple.
|
||||
|
||||
Returns
|
||||
-------
|
||||
value, method : object
|
||||
"""
|
||||
from pandas.core.missing import clean_fill_method
|
||||
|
||||
if value is None and method is None:
|
||||
raise ValueError("Must specify a fill 'value' or 'method'.")
|
||||
elif value is None and method is not None:
|
||||
method = clean_fill_method(method)
|
||||
|
||||
elif value is not None and method is None:
|
||||
if validate_scalar_dict_value and isinstance(value, (list, tuple)):
|
||||
raise TypeError(
|
||||
'"value" parameter must be a scalar or dict, but '
|
||||
'you passed a "{0}"'.format(type(value).__name__)
|
||||
)
|
||||
|
||||
elif value is not None and method is not None:
|
||||
raise ValueError("Cannot specify both 'value' and 'method'.")
|
||||
|
||||
return value, method
|
2988
venv/lib/python3.6/site-packages/pandas/util/testing.py
Normal file
2988
venv/lib/python3.6/site-packages/pandas/util/testing.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user