From 34a6644ab025d9ecd327ca3836ccbee47a90160f Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Thu, 3 Dec 2020 00:10:40 +0700 Subject: [PATCH 01/11] TYP: handle mypy ignore in SelectionMixin --- pandas/core/base.py | 65 +++++++++-------------------------- pandas/core/window/rolling.py | 1 - 2 files changed, 17 insertions(+), 49 deletions(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index f333ee0f71e46..21d493ceeb0be 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -10,7 +10,9 @@ Callable, Dict, FrozenSet, + Hashable, Optional, + Set, TypeVar, Union, cast, @@ -152,6 +154,9 @@ class SelectionMixin: object sub-classes need to define: obj, exclusions """ + obj: Any + exclusions: Set[Optional[Hashable]] = set() + _selection: Optional[IndexLabel] = None _internal_names = ["_cache", "__setstate__"] _internal_names_set = set(_internal_names) @@ -206,18 +211,9 @@ def _selection_list(self): @cache_readonly def _selected_obj(self): - # pandas\core\base.py:195: error: "SelectionMixin" has no attribute - # "obj" [attr-defined] - if self._selection is None or isinstance( - self.obj, ABCSeries # type: ignore[attr-defined] - ): - # pandas\core\base.py:194: error: "SelectionMixin" has no attribute - # "obj" [attr-defined] - return self.obj # type: ignore[attr-defined] - else: - # pandas\core\base.py:204: error: "SelectionMixin" has no attribute - # "obj" [attr-defined] - return self.obj[self._selection] # type: ignore[attr-defined] + if self._selection is None or isinstance(self.obj, ABCSeries): + return self.obj + return self.obj[self._selection] @cache_readonly def ndim(self) -> int: @@ -225,58 +221,31 @@ def ndim(self) -> int: @cache_readonly def _obj_with_exclusions(self): - # pandas\core\base.py:209: error: "SelectionMixin" has no attribute - # "obj" [attr-defined] - if self._selection is not None and isinstance( - self.obj, ABCDataFrame # type: ignore[attr-defined] - ): - # pandas\core\base.py:217: error: "SelectionMixin" has no attribute - # "obj" [attr-defined] - return self.obj.reindex( # type: ignore[attr-defined] - columns=self._selection_list - ) - - # pandas\core\base.py:207: error: "SelectionMixin" has no attribute - # "exclusions" [attr-defined] - if len(self.exclusions) > 0: # type: ignore[attr-defined] - # pandas\core\base.py:208: error: "SelectionMixin" has no attribute - # "obj" [attr-defined] + if self._selection is not None and isinstance(self.obj, ABCDataFrame): + return self.obj.reindex(columns=self._selection_list) - # pandas\core\base.py:208: error: "SelectionMixin" has no attribute - # "exclusions" [attr-defined] - return self.obj.drop(self.exclusions, axis=1) # type: ignore[attr-defined] + if len(self.exclusions) > 0: + return self.obj.drop(self.exclusions, axis=1) else: - # pandas\core\base.py:210: error: "SelectionMixin" has no attribute - # "obj" [attr-defined] - return self.obj # type: ignore[attr-defined] + return self.obj def __getitem__(self, key): if self._selection is not None: raise IndexError(f"Column(s) {self._selection} already selected") if isinstance(key, (list, tuple, ABCSeries, ABCIndexClass, np.ndarray)): - # pandas\core\base.py:217: error: "SelectionMixin" has no attribute - # "obj" [attr-defined] - if len( - self.obj.columns.intersection(key) # type: ignore[attr-defined] - ) != len(key): - # pandas\core\base.py:218: error: "SelectionMixin" has no - # attribute "obj" [attr-defined] - bad_keys = list( - set(key).difference(self.obj.columns) # type: ignore[attr-defined] - ) + if len(self.obj.columns.intersection(key)) != len(key): + bad_keys = list(set(key).difference(self.obj.columns)) raise KeyError(f"Columns not found: {str(bad_keys)[1:-1]}") return self._gotitem(list(key), ndim=2) elif not getattr(self, "as_index", False): - # error: "SelectionMixin" has no attribute "obj" [attr-defined] - if key not in self.obj.columns: # type: ignore[attr-defined] + if key not in self.obj.columns: raise KeyError(f"Column not found: {key}") return self._gotitem(key, ndim=2) else: - # error: "SelectionMixin" has no attribute "obj" [attr-defined] - if key not in self.obj: # type: ignore[attr-defined] + if key not in self.obj: raise KeyError(f"Column not found: {key}") return self._gotitem(key, ndim=1) diff --git a/pandas/core/window/rolling.py b/pandas/core/window/rolling.py index e6185f8ae0679..eb2b0027b74b1 100644 --- a/pandas/core/window/rolling.py +++ b/pandas/core/window/rolling.py @@ -85,7 +85,6 @@ class BaseWindow(ShallowMixin, SelectionMixin): "on", "closed", ] - exclusions: Set[str] = set() def __init__( self, From 19f0db3c343dd37893c70ced909a1533d7950b78 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Thu, 3 Dec 2020 00:50:53 +0700 Subject: [PATCH 02/11] FIX: remove unnecessary import --- pandas/core/window/rolling.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/core/window/rolling.py b/pandas/core/window/rolling.py index eb2b0027b74b1..b3d2f984f811b 100644 --- a/pandas/core/window/rolling.py +++ b/pandas/core/window/rolling.py @@ -13,7 +13,6 @@ Dict, List, Optional, - Set, Tuple, Type, Union, From d4a8a7e201e97b90d52dd61cbaaaef9680165306 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Thu, 3 Dec 2020 00:52:51 +0700 Subject: [PATCH 03/11] TYP: use Label instead of Optional[Hashable] --- pandas/core/base.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index 21d493ceeb0be..add5abc41feed 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -10,7 +10,6 @@ Callable, Dict, FrozenSet, - Hashable, Optional, Set, TypeVar, @@ -21,7 +20,7 @@ import numpy as np import pandas._libs.lib as lib -from pandas._typing import DtypeObj, IndexLabel +from pandas._typing import DtypeObj, IndexLabel, Label from pandas.compat import PYPY from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError @@ -155,7 +154,7 @@ class SelectionMixin: """ obj: Any - exclusions: Set[Optional[Hashable]] = set() + exclusions: Set[Label] = set() _selection: Optional[IndexLabel] = None _internal_names = ["_cache", "__setstate__"] From bc5157dd9ce1bad85fc0feee0c6465b67cd45e0d Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Thu, 10 Dec 2020 15:28:39 +0700 Subject: [PATCH 04/11] DOC: document public attributes in SelectionMixin --- pandas/core/base.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index add5abc41feed..ae461aea412d5 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -149,8 +149,13 @@ class SpecificationError(Exception): class SelectionMixin: """ - mixin implementing the selection & aggregation interface on a group-like + Mixin implementing the selection & aggregation interface on a group-like object sub-classes need to define: obj, exclusions + + obj : FrameOrSeries + Target object for the selection and aggregation. + exclusions : set, optional + Columns to exclude. """ obj: Any From a99be9763428183cf19ed9e91256c70a351cdb06 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Mon, 11 Jan 2021 19:05:53 +0700 Subject: [PATCH 05/11] REF: initialize exclusions in derived class --- pandas/core/base.py | 2 +- pandas/core/window/rolling.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index 4b8ec992d36d8..75cdd8e1b8cc1 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -159,7 +159,7 @@ class SelectionMixin: """ obj: Any - exclusions: Set[Label] = set() + exclusions: Set[Label] _selection: Optional[IndexLabel] = None _internal_names = ["_cache", "__setstate__"] diff --git a/pandas/core/window/rolling.py b/pandas/core/window/rolling.py index 24732d1e643e5..201ae1dc201a3 100644 --- a/pandas/core/window/rolling.py +++ b/pandas/core/window/rolling.py @@ -106,6 +106,7 @@ def __init__( self.__dict__.update(kwargs) self.obj = obj + self.exclusions = set() self.on = on self.closed = closed self.window = window From dcc6885de282664dd00fe34e9d6a82c737b66337 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Thu, 11 Feb 2021 18:52:23 +0700 Subject: [PATCH 06/11] TYP: TODO on typing obj as FrameOrSeriesUnion --- pandas/core/base.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index 75cdd8e1b8cc1..0be0d5817bd8a 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -152,13 +152,17 @@ class SelectionMixin: Mixin implementing the selection & aggregation interface on a group-like object sub-classes need to define: obj, exclusions - obj : FrameOrSeries + obj : DataFrame or Series Target object for the selection and aggregation. exclusions : set, optional Columns to exclude. """ obj: Any + # GH 38239 + # TODO obj here must be typed as FrameOrSeriesUnion, + # however this creates multiple mypy errors elsewhere. + # Those have to be addressed in a separate PR. exclusions: Set[Label] _selection: Optional[IndexLabel] = None From a56f7b9846e8b6b2a3f9b112ec53d32e3c586ee5 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Thu, 11 Feb 2021 18:55:15 +0700 Subject: [PATCH 07/11] DOC: doc attributes inside class body --- pandas/core/base.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index 3b45f75646adf..7ef260f1c26fe 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -149,21 +149,19 @@ class SpecificationError(Exception): class SelectionMixin: """ - Mixin implementing the selection & aggregation interface on a group-like - object sub-classes need to define: obj, exclusions + Mixin for the selection & aggregation interface on a group-like object. - obj : DataFrame or Series - Target object for the selection and aggregation. - exclusions : set, optional - Columns to exclude. + Sub-classes need to define: obj, exclusions """ obj: Any + """Target object for the selection and aggregation.""" # GH 38239 # TODO obj here must be typed as FrameOrSeriesUnion, # however this creates multiple mypy errors elsewhere. # Those have to be addressed in a separate PR. exclusions: Set[Label] + """Columns to exclude.""" _selection: Optional[IndexLabel] = None _internal_names = ["_cache", "__setstate__"] From e0b16571ee436e4134ca1345f3de78cfe0bfce50 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Thu, 11 Feb 2021 20:52:09 +0700 Subject: [PATCH 08/11] TYP: replace Label with Hashable --- pandas/core/base.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index 7ef260f1c26fe..c7abaa117c88f 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -10,6 +10,7 @@ Callable, Dict, FrozenSet, + Hashable, Optional, Set, TypeVar, @@ -20,7 +21,7 @@ import numpy as np import pandas._libs.lib as lib -from pandas._typing import Dtype, DtypeObj, IndexLabel, Label +from pandas._typing import Dtype, DtypeObj, IndexLabel from pandas.compat import PYPY from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError @@ -160,7 +161,7 @@ class SelectionMixin: # TODO obj here must be typed as FrameOrSeriesUnion, # however this creates multiple mypy errors elsewhere. # Those have to be addressed in a separate PR. - exclusions: Set[Label] + exclusions: Set[Hashable] """Columns to exclude.""" _selection: Optional[IndexLabel] = None From 4222c83402008f87b3ca10d9002f966f3d9337d1 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov <41443370+ivanovmg@users.noreply.github.com> Date: Fri, 12 Feb 2021 02:23:34 +0700 Subject: [PATCH 09/11] Update pandas/core/base.py Co-authored-by: Simon Hawkins --- pandas/core/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index c7abaa117c88f..9975383f68583 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -155,7 +155,7 @@ class SelectionMixin: Sub-classes need to define: obj, exclusions """ - obj: Any + obj: Any # TODO: refine this type, should NOT be Any """Target object for the selection and aggregation.""" # GH 38239 # TODO obj here must be typed as FrameOrSeriesUnion, From 954a2a3d37ee8d101dad8ce988fdce9d6ed65f6f Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Tue, 16 Feb 2021 10:43:21 +0700 Subject: [PATCH 10/11] TYP: change to FrameOrSeriesUnion --- pandas/core/base.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index a4bd58f26e21e..fc2702f4f4b53 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -21,7 +21,7 @@ import numpy as np import pandas._libs.lib as lib -from pandas._typing import Dtype, DtypeObj, IndexLabel +from pandas._typing import Dtype, DtypeObj, FrameOrSeriesUnion, IndexLabel from pandas.compat import PYPY from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError @@ -154,14 +154,8 @@ class SelectionMixin: Sub-classes need to define: obj, exclusions """ - obj: Any # TODO: refine this type, should NOT be Any - """Target object for the selection and aggregation.""" - # GH 38239 - # TODO obj here must be typed as FrameOrSeriesUnion, - # however this creates multiple mypy errors elsewhere. - # Those have to be addressed in a separate PR. + obj: FrameOrSeriesUnion exclusions: Set[Hashable] - """Columns to exclude.""" _selection: Optional[IndexLabel] = None _internal_names = ["_cache", "__setstate__"] From e7f9028e29582f337f2faa18c00c528ac3728836 Mon Sep 17 00:00:00 2001 From: Maxim Ivanov Date: Wed, 17 Feb 2021 16:19:49 +0700 Subject: [PATCH 11/11] LINT: fix trailing whitespace --- pandas/core/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/base.py b/pandas/core/base.py index 4150f655c4c97..2dc1d32b44828 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -24,7 +24,7 @@ from pandas._typing import ( Dtype, DtypeObj, - FrameOrSeriesUnion, + FrameOrSeriesUnion, IndexLabel, ) from pandas.compat import PYPY