-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
COMPAT: Expand compatibility with fromnumeric.py #12810
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
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
""" | ||
For compatibility with numpy libraries, pandas functions or | ||
methods have to accept '*args' and '**kwargs' parameters to | ||
accommodate numpy arguments that are not actually used or | ||
respected in the pandas implementation. | ||
|
||
To ensure that users do not abuse these parameters, validation | ||
is performed in 'validators.py' to make sure that any extra | ||
parameters passed correspond ONLY to those in the numpy signature. | ||
Part of that validation includes whether or not the user attempted | ||
to pass in non-default values for these extraneous parameters. As we | ||
want to discourage users from relying on these parameters when calling | ||
the pandas implementation, we want them only to pass in the default values | ||
for these parameters. | ||
|
||
This module provides a set of commonly used default arguments for functions | ||
and methods that are spread throughout the codebase. This module will make it | ||
easier to adjust to future upstream changes in the analogous numpy signatures. | ||
""" | ||
|
||
from numpy import ndarray | ||
from pandas.util.validators import (validate_args, validate_kwargs, | ||
validate_args_and_kwargs) | ||
from pandas.core.common import is_integer | ||
from pandas.compat import OrderedDict | ||
|
||
|
||
class CompatValidator(object): | ||
def __init__(self, defaults, fname=None, method=None, | ||
max_fname_arg_count=None): | ||
self.fname = fname | ||
self.method = method | ||
self.defaults = defaults | ||
self.max_fname_arg_count = max_fname_arg_count | ||
|
||
def __call__(self, args, kwargs, fname=None, | ||
max_fname_arg_count=None, method=None): | ||
fname = self.fname if fname is None else fname | ||
max_fname_arg_count = (self.max_fname_arg_count if | ||
max_fname_arg_count is None | ||
else max_fname_arg_count) | ||
method = self.method if method is None else method | ||
|
||
if method == 'args': | ||
validate_args(fname, args, max_fname_arg_count, self.defaults) | ||
elif method == 'kwargs': | ||
validate_kwargs(fname, kwargs, self.defaults) | ||
elif method == 'both': | ||
validate_args_and_kwargs(fname, args, kwargs, | ||
max_fname_arg_count, | ||
self.defaults) | ||
else: | ||
raise ValueError("invalid validation method " | ||
"'{method}'".format(method=method)) | ||
|
||
ARGMINMAX_DEFAULTS = dict(out=None) | ||
validate_argmin = CompatValidator(ARGMINMAX_DEFAULTS, fname='argmin', | ||
method='both', max_fname_arg_count=1) | ||
validate_argmax = CompatValidator(ARGMINMAX_DEFAULTS, fname='argmax', | ||
method='both', max_fname_arg_count=1) | ||
|
||
|
||
def process_skipna(skipna, args): | ||
if isinstance(skipna, ndarray) or skipna is None: | ||
args = (skipna,) + args | ||
skipna = True | ||
|
||
return skipna, args | ||
|
||
|
||
def validate_argmin_with_skipna(skipna, args, kwargs): | ||
""" | ||
If 'Series.argmin' is called via the 'numpy' library, | ||
the third parameter in its signature is 'out', which | ||
takes either an ndarray or 'None', so check if the | ||
'skipna' parameter is either an instance of ndarray or | ||
is None, since 'skipna' itself should be a boolean | ||
""" | ||
|
||
skipna, args = process_skipna(skipna, args) | ||
validate_argmin(args, kwargs) | ||
return skipna | ||
|
||
|
||
def validate_argmax_with_skipna(skipna, args, kwargs): | ||
""" | ||
If 'Series.argmax' is called via the 'numpy' library, | ||
the third parameter in its signature is 'out', which | ||
takes either an ndarray or 'None', so check if the | ||
'skipna' parameter is either an instance of ndarray or | ||
is None, since 'skipna' itself should be a boolean | ||
""" | ||
|
||
skipna, args = process_skipna(skipna, args) | ||
validate_argmax(args, kwargs) | ||
return skipna | ||
|
||
ARGSORT_DEFAULTS = OrderedDict() | ||
ARGSORT_DEFAULTS['axis'] = -1 | ||
ARGSORT_DEFAULTS['kind'] = 'quicksort' | ||
ARGSORT_DEFAULTS['order'] = None | ||
validate_argsort = CompatValidator(ARGSORT_DEFAULTS, fname='argsort', | ||
max_fname_arg_count=0, method='both') | ||
|
||
|
||
def validate_argsort_with_ascending(ascending, args, kwargs): | ||
""" | ||
If 'Categorical.argsort' is called via the 'numpy' library, the | ||
first parameter in its signature is 'axis', which takes either | ||
an integer or 'None', so check if the 'ascending' parameter has | ||
either integer type or is None, since 'ascending' itself should | ||
be a boolean | ||
""" | ||
|
||
if is_integer(ascending) or ascending is None: | ||
args = (ascending,) + args | ||
ascending = True | ||
|
||
validate_argsort(args, kwargs, max_fname_arg_count=1) | ||
return ascending | ||
|
||
CLIP_DEFAULTS = dict(out=None) | ||
validate_clip = CompatValidator(CLIP_DEFAULTS, fname='clip', | ||
method='both', max_fname_arg_count=3) | ||
|
||
|
||
def validate_clip_with_axis(axis, args, kwargs): | ||
""" | ||
If 'NDFrame.clip' is called via the numpy library, the third | ||
parameter in its signature is 'out', which can takes an ndarray, | ||
so check if the 'axis' parameter is an instance of ndarray, since | ||
'axis' itself should either be an integer or None | ||
""" | ||
|
||
if isinstance(axis, ndarray): | ||
args = (axis,) + args | ||
axis = None | ||
|
||
validate_clip(args, kwargs) | ||
return axis | ||
|
||
COMPRESS_DEFAULTS = OrderedDict() | ||
COMPRESS_DEFAULTS['axis'] = None | ||
COMPRESS_DEFAULTS['out'] = None | ||
validate_compress = CompatValidator(COMPRESS_DEFAULTS, fname='compress', | ||
method='both', max_fname_arg_count=1) | ||
|
||
CUM_FUNC_DEFAULTS = OrderedDict() | ||
CUM_FUNC_DEFAULTS['dtype'] = None | ||
CUM_FUNC_DEFAULTS['out'] = None | ||
validate_cum_func = CompatValidator(CUM_FUNC_DEFAULTS, method='kwargs') | ||
validate_cumsum = CompatValidator(CUM_FUNC_DEFAULTS, fname='cumsum', | ||
method='both', max_fname_arg_count=1) | ||
|
||
LOGICAL_FUNC_DEFAULTS = dict(out=None) | ||
validate_logical_func = CompatValidator(LOGICAL_FUNC_DEFAULTS, method='kwargs') | ||
|
||
MINMAX_DEFAULTS = dict(out=None) | ||
validate_min = CompatValidator(MINMAX_DEFAULTS, fname='min', | ||
method='both', max_fname_arg_count=1) | ||
validate_max = CompatValidator(MINMAX_DEFAULTS, fname='max', | ||
method='both', max_fname_arg_count=1) | ||
|
||
RESHAPE_DEFAULTS = dict(order='C') | ||
validate_reshape = CompatValidator(RESHAPE_DEFAULTS, fname='reshape', | ||
method='both', max_fname_arg_count=1) | ||
|
||
REPEAT_DEFAULTS = dict(axis=None) | ||
validate_repeat = CompatValidator(REPEAT_DEFAULTS, fname='repeat', | ||
method='both', max_fname_arg_count=1) | ||
|
||
ROUND_DEFAULTS = dict(out=None) | ||
validate_round = CompatValidator(ROUND_DEFAULTS, fname='round', | ||
method='both', max_fname_arg_count=1) | ||
|
||
SORT_DEFAULTS = OrderedDict() | ||
SORT_DEFAULTS['axis'] = -1 | ||
SORT_DEFAULTS['kind'] = 'quicksort' | ||
SORT_DEFAULTS['order'] = None | ||
validate_sort = CompatValidator(SORT_DEFAULTS, fname='sort', | ||
method='kwargs') | ||
|
||
STAT_FUNC_DEFAULTS = OrderedDict() | ||
STAT_FUNC_DEFAULTS['dtype'] = None | ||
STAT_FUNC_DEFAULTS['out'] = None | ||
validate_stat_func = CompatValidator(STAT_FUNC_DEFAULTS, | ||
method='kwargs') | ||
validate_sum = CompatValidator(STAT_FUNC_DEFAULTS, fname='sort', | ||
method='both', max_fname_arg_count=1) | ||
validate_mean = CompatValidator(STAT_FUNC_DEFAULTS, fname='mean', | ||
method='both', max_fname_arg_count=1) | ||
|
||
STAT_DDOF_FUNC_DEFAULTS = OrderedDict() | ||
STAT_DDOF_FUNC_DEFAULTS['dtype'] = None | ||
STAT_DDOF_FUNC_DEFAULTS['out'] = None | ||
validate_stat_ddof_func = CompatValidator(STAT_DDOF_FUNC_DEFAULTS, | ||
method='kwargs') | ||
|
||
# Currently, numpy (v1.11) has backwards compatibility checks | ||
# in place so that this 'kwargs' parameter is technically | ||
# unnecessary, but in the long-run, this will be needed. | ||
SQUEEZE_DEFAULTS = dict(axis=None) | ||
validate_squeeze = CompatValidator(SQUEEZE_DEFAULTS, fname='squeeze', | ||
method='kwargs') | ||
|
||
TAKE_DEFAULTS = OrderedDict() | ||
TAKE_DEFAULTS['out'] = None | ||
TAKE_DEFAULTS['mode'] = 'raise' | ||
validate_take = CompatValidator(TAKE_DEFAULTS, fname='take', | ||
method='kwargs') | ||
|
||
|
||
def validate_take_with_convert(convert, args, kwargs): | ||
""" | ||
If this function is called via the 'numpy' library, the third | ||
parameter in its signature is 'axis', which takes either an | ||
ndarray or 'None', so check if the 'convert' parameter is either | ||
an instance of ndarray or is None | ||
""" | ||
|
||
if isinstance(convert, ndarray) or convert is None: | ||
args = (convert,) + args | ||
convert = True | ||
|
||
validate_take(args, kwargs, max_fname_arg_count=3, method='both') | ||
return convert | ||
|
||
TRANSPOSE_DEFAULTS = dict(axes=None) | ||
validate_transpose = CompatValidator(TRANSPOSE_DEFAULTS, fname='transpose', | ||
method='both', max_fname_arg_count=0) | ||
|
||
|
||
def validate_transpose_for_generic(inst, kwargs): | ||
try: | ||
validate_transpose(tuple(), kwargs) | ||
except ValueError as e: | ||
klass = type(inst).__name__ | ||
msg = str(e) | ||
|
||
# the Panel class actual relies on the 'axes' parameter if called | ||
# via the 'numpy' library, so let's make sure the error is specific | ||
# about saying that the parameter is not supported for particular | ||
# implementations of 'transpose' | ||
if "the 'axes' parameter is not supported" in msg: | ||
msg += " for {klass} instances".format(klass=klass) | ||
|
||
raise ValueError(msg) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,6 @@ | |
# flake8: noqa | ||
|
||
import sys | ||
import numpy as np | ||
import pandas | ||
import copy | ||
import pickle as pkl | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make this an
ipython-block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this didn't update, did you push?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub is being buggy here. You can see for yourself below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah weird.