From 24dc1c76b592edebb440af3db8ab8f4155f15999 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 7 Nov 2019 20:17:34 -0800 Subject: [PATCH 1/4] typing in core.apply --- pandas/core/apply.py | 64 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/pandas/core/apply.py b/pandas/core/apply.py index d0093e5b697e1..f238cc74cce1a 100644 --- a/pandas/core/apply.py +++ b/pandas/core/apply.py @@ -1,8 +1,10 @@ import inspect +from typing import TYPE_CHECKING, Iterator, Type import numpy as np from pandas._libs import reduction as libreduction +from pandas.errors import AbstractMethodError from pandas.util._decorators import cache_readonly from pandas.core.dtypes.common import ( @@ -13,14 +15,17 @@ ) from pandas.core.dtypes.generic import ABCSeries +if TYPE_CHECKING: + from pandas import DataFrame, Series, Index + def frame_apply( - obj, + obj: "DataFrame", func, axis=0, - raw=False, + raw: bool = False, result_type=None, - ignore_failures=False, + ignore_failures: bool = False, args=None, kwds=None, ): @@ -28,7 +33,7 @@ def frame_apply( axis = obj._get_axis_number(axis) if axis == 0: - klass = FrameRowApply + klass = FrameRowApply # type: Type[FrameApply] elif axis == 1: klass = FrameColumnApply @@ -44,7 +49,38 @@ def frame_apply( class FrameApply: - def __init__(self, obj, func, raw, result_type, ignore_failures, args, kwds): + + # --------------------------------------------------------------- + # Abstract Methods + + @property + def axis(self) -> int: + raise AbstractMethodError(self) + + @property + def result_index(self) -> "Index": + raise AbstractMethodError(self) + + @property + def result_columns(self) -> "Index": + raise AbstractMethodError(self) + + @property + def series_generator(self) -> Iterator["Series"]: + raise AbstractMethodError(self) + + # --------------------------------------------------------------- + + def __init__( + self, + obj: "DataFrame", + func, + raw: bool, + result_type, + ignore_failures: bool, + args, + kwds, + ): self.obj = obj self.raw = raw self.ignore_failures = ignore_failures @@ -76,11 +112,11 @@ def f(x): self.res_columns = None @property - def columns(self): + def columns(self) -> "Index": return self.obj.columns @property - def index(self): + def index(self) -> "Index": return self.obj.index @cache_readonly @@ -88,11 +124,11 @@ def values(self): return self.obj.values @cache_readonly - def dtypes(self): + def dtypes(self) -> "Index": return self.obj.dtypes @property - def agg_axis(self): + def agg_axis(self) -> "Index": return self.obj._get_agg_axis(self.axis) def get_result(self): @@ -325,11 +361,11 @@ def series_generator(self): return (self.obj._ixs(i, axis=1) for i in range(len(self.columns))) @property - def result_index(self): + def result_index(self) -> "Index": return self.columns @property - def result_columns(self): + def result_columns(self) -> "Index": return self.index def wrap_results_for_axis(self): @@ -364,11 +400,11 @@ def series_generator(self): ) @property - def result_index(self): + def result_index(self) -> "Index": return self.index @property - def result_columns(self): + def result_columns(self) -> "Index": return self.columns def wrap_results_for_axis(self): @@ -392,7 +428,7 @@ def wrap_results_for_axis(self): return result - def infer_to_same_shape(self): + def infer_to_same_shape(self) -> "DataFrame": """ infer the results to the same shape as the input object """ results = self.results From ebd68a5892fecb4a75324c1a87e1ee603ea09964 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 7 Nov 2019 20:19:54 -0800 Subject: [PATCH 2/4] Make signature consisetntt --- pandas/core/apply.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pandas/core/apply.py b/pandas/core/apply.py index f238cc74cce1a..c7f70398cf3f1 100644 --- a/pandas/core/apply.py +++ b/pandas/core/apply.py @@ -163,7 +163,7 @@ def get_result(self): # broadcasting if self.result_type == "broadcast": - return self.apply_broadcast() + return self.apply_broadcast(self.obj) # one axis empty elif not all(self.obj.shape): @@ -227,7 +227,7 @@ def apply_raw(self): else: return self.obj._constructor_sliced(result, index=self.agg_axis) - def apply_broadcast(self, target): + def apply_broadcast(self, target: "DataFrame") -> "DataFrame": result_values = np.empty_like(target.values) # axis which we want to compare compliance @@ -353,8 +353,8 @@ def wrap_results(self): class FrameRowApply(FrameApply): axis = 0 - def apply_broadcast(self): - return super().apply_broadcast(self.obj) + def apply_broadcast(self, target: "DataFrame") -> "DataFrame": + return super().apply_broadcast(target) @property def series_generator(self): @@ -387,8 +387,8 @@ def wrap_results_for_axis(self): class FrameColumnApply(FrameApply): axis = 1 - def apply_broadcast(self): - result = super().apply_broadcast(self.obj.T) + def apply_broadcast(self, target: "DataFrame") -> "DataFrame": + result = super().apply_broadcast(target.T) return result.T @property From 92cbe831bd2613367330d847f32ebeb88ea49e9e Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 8 Nov 2019 08:36:33 -0800 Subject: [PATCH 3/4] fix Index->Series --- pandas/core/apply.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/apply.py b/pandas/core/apply.py index c7f70398cf3f1..86bec543c3e4c 100644 --- a/pandas/core/apply.py +++ b/pandas/core/apply.py @@ -124,7 +124,7 @@ def values(self): return self.obj.values @cache_readonly - def dtypes(self) -> "Index": + def dtypes(self) -> "Series": return self.obj.dtypes @property From 82479f492eb66054929aa159d00b08926f614268 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 11 Nov 2019 15:01:54 -0800 Subject: [PATCH 4/4] use abstractmethod --- pandas/core/apply.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/pandas/core/apply.py b/pandas/core/apply.py index 09a59d665fd9d..9c5806a3fe945 100644 --- a/pandas/core/apply.py +++ b/pandas/core/apply.py @@ -1,10 +1,10 @@ +import abc import inspect from typing import TYPE_CHECKING, Iterator, Type import numpy as np from pandas._libs import reduction as libreduction -from pandas.errors import AbstractMethodError from pandas.util._decorators import cache_readonly from pandas.core.dtypes.common import ( @@ -48,26 +48,25 @@ def frame_apply( ) -class FrameApply: +class FrameApply(metaclass=abc.ABCMeta): # --------------------------------------------------------------- # Abstract Methods + axis: int @property - def axis(self) -> int: - raise AbstractMethodError(self) - - @property + @abc.abstractmethod def result_index(self) -> "Index": - raise AbstractMethodError(self) + pass @property + @abc.abstractmethod def result_columns(self) -> "Index": - raise AbstractMethodError(self) + pass - @property + @abc.abstractmethod def series_generator(self) -> Iterator["Series"]: - raise AbstractMethodError(self) + pass # ---------------------------------------------------------------