From 64d43fbaf5b72d4208c3091e57dce93c48908c28 Mon Sep 17 00:00:00 2001 From: tp Date: Tue, 29 Dec 2020 16:28:00 +0000 Subject: [PATCH 1/9] TST: test inspect.getmembers(Series) --- pandas/core/frame.py | 7 +++---- pandas/core/generic.py | 8 -------- pandas/tests/series/test_api.py | 9 +++++++++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 6357b8feb348b..16630e971edd3 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -490,15 +490,14 @@ class DataFrame(NDFrame, OpsMixin): _internal_names_set = {"columns", "index"} | NDFrame._internal_names_set _typ = "dataframe" _HANDLED_TYPES = (Series, Index, ExtensionArray, np.ndarray) + _accessors: Set[str] = {"sparse"} + _hidden_attrs: FrozenSet[str] = NDFrame._hidden_attrs | frozenset([]) + _constructor_sliced: Type[Series] = Series @property def _constructor(self) -> Type[DataFrame]: return DataFrame - _constructor_sliced: Type[Series] = Series - _hidden_attrs: FrozenSet[str] = NDFrame._hidden_attrs | frozenset([]) - _accessors: Set[str] = {"sparse"} - @property def _constructor_expanddim(self): # GH#31549 raising NotImplementedError on a property causes trouble diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 96b35f1aaab9c..c711e26d619fa 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -375,14 +375,6 @@ def _constructor(self: FrameOrSeries) -> Type[FrameOrSeries]: """ raise AbstractMethodError(self) - @property - def _constructor_sliced(self): - """ - Used when a manipulation result has one lower dimension(s) as the - original, such as DataFrame single columns slicing. - """ - raise AbstractMethodError(self) - @property def _constructor_expanddim(self): """ diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index 2f255d92d86e3..01ce1be21768e 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -1,9 +1,11 @@ import pydoc +import inspect import numpy as np import pytest import pandas as pd +from pandas.util._test_decorators import skip_if_no from pandas import DataFrame, Index, Series, date_range import pandas._testing as tm @@ -167,3 +169,10 @@ def test_attrs(self): s.attrs["version"] = 1 result = s + 1 assert result.attrs == {"version": 1} + + @skip_if_no("jinja2") + def test_inspect_getmembers(self): + # GH38740 + ser = Series() + with tm.assert_produces_warning(None): + inspect.getmembers(ser) From fac0e8ce2405d68112fbccfef0599527cc6f84e4 Mon Sep 17 00:00:00 2001 From: tp Date: Tue, 29 Dec 2020 16:34:18 +0000 Subject: [PATCH 2/9] add whatsnew --- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/tests/series/test_api.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 17d8c79994dbe..627fbb4983413 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -445,11 +445,11 @@ Other - Bug in :class:`Index` constructor sometimes silently ignorning a specified ``dtype`` (:issue:`38879`) - Bug in constructing a :class:`Series` from a list and a :class:`PandasDtype` (:issue:`39357`) - Bug in :class:`Styler` which caused CSS to duplicate on multiple renders. (:issue:`39395`) +- ``inspect.getmembers(Series)`` no longer raises an ``AbstractMethodError`` (:issue:`38782`) - :meth:`Index.where` behavior now mirrors :meth:`Index.putmask` behavior, i.e. ``index.where(mask, other)`` matches ``index.putmask(~mask, other)`` (:issue:`39412`) - Bug in :func:`pandas.testing.assert_series_equal`, :func:`pandas.testing.assert_frame_equal`, :func:`pandas.testing.assert_index_equal` and :func:`pandas.testing.assert_extension_array_equal` incorrectly raising when an attribute has an unrecognized NA type (:issue:`39461`) - Bug in :class:`Styler` where ``subset`` arg in methods raised an error for some valid multiindex slices (:issue:`33562`) - -- .. --------------------------------------------------------------------------- diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index 01ce1be21768e..63c674c9dc334 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -172,7 +172,7 @@ def test_attrs(self): @skip_if_no("jinja2") def test_inspect_getmembers(self): - # GH38740 + # GH38782 ser = Series() with tm.assert_produces_warning(None): inspect.getmembers(ser) From 940c325327d650c2c6ce8337d00c46f7c165a2aa Mon Sep 17 00:00:00 2001 From: tp Date: Tue, 29 Dec 2020 16:38:43 +0000 Subject: [PATCH 3/9] isoer fixup --- pandas/tests/series/test_api.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index 63c674c9dc334..4dd91b942474a 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -1,11 +1,12 @@ -import pydoc import inspect +import pydoc import numpy as np import pytest -import pandas as pd from pandas.util._test_decorators import skip_if_no + +import pandas as pd from pandas import DataFrame, Index, Series, date_range import pandas._testing as tm From 59b49e1c368d696c898a529f1d8ce05c15a9c122 Mon Sep 17 00:00:00 2001 From: tp Date: Wed, 30 Dec 2020 00:16:47 +0000 Subject: [PATCH 4/9] Remove NDFrame.__constructor_expanddim --- doc/source/development/extending.rst | 18 ++++-------------- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/core/frame.py | 10 +--------- pandas/core/generic.py | 8 -------- pandas/core/series.py | 4 ++++ pandas/tests/frame/test_api.py | 8 +++++--- 6 files changed, 15 insertions(+), 35 deletions(-) diff --git a/doc/source/development/extending.rst b/doc/source/development/extending.rst index d4219296f5795..5476aeedfb6f9 100644 --- a/doc/source/development/extending.rst +++ b/doc/source/development/extending.rst @@ -329,21 +329,11 @@ Each data structure has several *constructor properties* for returning a new data structure as the result of an operation. By overriding these properties, you can retain subclasses through ``pandas`` data manipulations. -There are 3 constructor properties to be defined: +There are 3 possible constructor properties to be defined on a subclass: -* ``_constructor``: Used when a manipulation result has the same dimensions as the original. -* ``_constructor_sliced``: Used when a manipulation result has one lower dimension(s) as the original, such as ``DataFrame`` single columns slicing. -* ``_constructor_expanddim``: Used when a manipulation result has one higher dimension as the original, such as ``Series.to_frame()``. - -Following table shows how ``pandas`` data structures define constructor properties by default. - -=========================== ======================= ============= -Property Attributes ``Series`` ``DataFrame`` -=========================== ======================= ============= -``_constructor`` ``Series`` ``DataFrame`` -``_constructor_sliced`` ``NotImplementedError`` ``Series`` -``_constructor_expanddim`` ``DataFrame`` ``NotImplementedError`` -=========================== ======================= ============= +* ``DataFrame/Series._constructor``: Used when a manipulation result has the same (sub-)class as the original. +* ``DataFrame._constructor_sliced``: Used when a ``DataFrame`` (sub-)class manipulation result should be a ``Series`` (sub-)class. +* ``Series._constructor_expanddim``: Used when a ``Series`` (sub-)class manipulation result should be a ``DataFrame`` (sub-)class, e.g. ``Series.to_frame()``. Below example shows how to define ``SubclassedSeries`` and ``SubclassedDataFrame`` overriding constructor properties. diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 627fbb4983413..ebacc7e70edb7 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -219,7 +219,7 @@ See :ref:`install.dependencies` and :ref:`install.optional_dependencies` for mor Other API changes ^^^^^^^^^^^^^^^^^ - Partially initialized :class:`CategoricalDtype` (i.e. those with ``categories=None`` objects will no longer compare as equal to fully initialized dtype objects. -- +- Accessing ``_constructor_expanddim`` on a :class:`DataFrame` and ``_constructor_sliced`` on a :class:`Series` now raise an ``AttributeError``. Previously a ``NotImplementedError`` was raised (:issue:`38782`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 16630e971edd3..7136e42c4f638 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -492,20 +492,12 @@ class DataFrame(NDFrame, OpsMixin): _HANDLED_TYPES = (Series, Index, ExtensionArray, np.ndarray) _accessors: Set[str] = {"sparse"} _hidden_attrs: FrozenSet[str] = NDFrame._hidden_attrs | frozenset([]) - _constructor_sliced: Type[Series] = Series @property def _constructor(self) -> Type[DataFrame]: return DataFrame - @property - def _constructor_expanddim(self): - # GH#31549 raising NotImplementedError on a property causes trouble - # for `inspect` - def constructor(*args, **kwargs): - raise NotImplementedError("Not supported for DataFrames!") - - return constructor + _constructor_sliced: Type[Series] = Series # ---------------------------------------------------------------------- # Constructors diff --git a/pandas/core/generic.py b/pandas/core/generic.py index c711e26d619fa..330c945ef19cb 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -375,14 +375,6 @@ def _constructor(self: FrameOrSeries) -> Type[FrameOrSeries]: """ raise AbstractMethodError(self) - @property - def _constructor_expanddim(self): - """ - Used when a manipulation result has one higher dimension as the - original, such as Series.to_frame() - """ - raise NotImplementedError - # ---------------------------------------------------------------------- # Internals diff --git a/pandas/core/series.py b/pandas/core/series.py index 8bd325beede65..cb161a1a717cc 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -403,6 +403,10 @@ def _constructor(self) -> Type[Series]: @property def _constructor_expanddim(self) -> Type[DataFrame]: + """ + Used when a manipulation result has one higher dimension as the + original, such as Series.to_frame() + """ from pandas.core.frame import DataFrame return DataFrame diff --git a/pandas/tests/frame/test_api.py b/pandas/tests/frame/test_api.py index 29a2d9c17202e..b544887a04c0a 100644 --- a/pandas/tests/frame/test_api.py +++ b/pandas/tests/frame/test_api.py @@ -322,11 +322,13 @@ def test_set_flags(self, allows_duplicate_labels, frame_or_series): assert obj.iloc[key] == 0 def test_constructor_expanddim_lookup(self): - # GH#33628 accessing _constructor_expanddim should not - # raise NotImplementedError + # GH#33628 accessing _constructor_expanddim should not raise NotImplementedError + # GH38782 pandas has no container higher than DatafFame (two-dim), so + # DataFrame._constructor_expand_dim, doesn't make sense, so is removed. df = DataFrame() - with pytest.raises(NotImplementedError, match="Not supported for DataFrames!"): + msg = "'DataFrame' object has no attribute '_constructor_expanddim'" + with pytest.raises(AttributeError, match=msg): df._constructor_expanddim(np.arange(27).reshape(3, 3, 3)) @skip_if_no("jinja2") From abf0873c948fe79b84fa53631eb3eb50f0e97a7b Mon Sep 17 00:00:00 2001 From: tp Date: Wed, 30 Dec 2020 00:45:18 +0000 Subject: [PATCH 5/9] fixup --- pandas/tests/frame/test_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/frame/test_api.py b/pandas/tests/frame/test_api.py index b544887a04c0a..6b8284908213a 100644 --- a/pandas/tests/frame/test_api.py +++ b/pandas/tests/frame/test_api.py @@ -321,9 +321,9 @@ def test_set_flags(self, allows_duplicate_labels, frame_or_series): result.iloc[key] = 10 assert obj.iloc[key] == 0 - def test_constructor_expanddim_lookup(self): + def test_constructor_expanddim(self): # GH#33628 accessing _constructor_expanddim should not raise NotImplementedError - # GH38782 pandas has no container higher than DatafFame (two-dim), so + # GH38782 pandas has no container higher than DataFrame (two-dim), so # DataFrame._constructor_expand_dim, doesn't make sense, so is removed. df = DataFrame() From ac865966d52ba264842c50e5771b4bea82dcfa7c Mon Sep 17 00:00:00 2001 From: tp Date: Sat, 16 Jan 2021 09:04:39 +0000 Subject: [PATCH 6/9] move to v1.2.1 --- doc/source/whatsnew/v1.2.1.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.2.1.rst b/doc/source/whatsnew/v1.2.1.rst index 8bfe233ae50cc..335ad18893702 100644 --- a/doc/source/whatsnew/v1.2.1.rst +++ b/doc/source/whatsnew/v1.2.1.rst @@ -135,6 +135,7 @@ Other - Bumped minimum fastparquet version to 0.4.0 to avoid ``AttributeError`` from numba (:issue:`38344`) - Bumped minimum pymysql version to 0.8.1 to avoid test failures (:issue:`38344`) - Fixed build failure on MacOS 11 in Python 3.9.1 (:issue:`38766`) +- ``inspect.getmembers(Series)`` no longer raises an ``AbstractMethodError`` (:issue:`38782`). - Added reference to backwards incompatible ``check_freq`` arg of :func:`testing.assert_frame_equal` and :func:`testing.assert_series_equal` in :ref:`pandas 1.1.0 whats new ` (:issue:`34050`) .. --------------------------------------------------------------------------- From a58416b17cc32776dbcb36ba1995b2b5c97be5e4 Mon Sep 17 00:00:00 2001 From: tp Date: Sat, 16 Jan 2021 09:23:12 +0000 Subject: [PATCH 7/9] move texts --- doc/source/whatsnew/v1.3.0.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index ebacc7e70edb7..ed00e51b5d324 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -219,7 +219,7 @@ See :ref:`install.dependencies` and :ref:`install.optional_dependencies` for mor Other API changes ^^^^^^^^^^^^^^^^^ - Partially initialized :class:`CategoricalDtype` (i.e. those with ``categories=None`` objects will no longer compare as equal to fully initialized dtype objects. -- Accessing ``_constructor_expanddim`` on a :class:`DataFrame` and ``_constructor_sliced`` on a :class:`Series` now raise an ``AttributeError``. Previously a ``NotImplementedError`` was raised (:issue:`38782`) +- - .. --------------------------------------------------------------------------- @@ -450,6 +450,7 @@ Other - Bug in :func:`pandas.testing.assert_series_equal`, :func:`pandas.testing.assert_frame_equal`, :func:`pandas.testing.assert_index_equal` and :func:`pandas.testing.assert_extension_array_equal` incorrectly raising when an attribute has an unrecognized NA type (:issue:`39461`) - Bug in :class:`Styler` where ``subset`` arg in methods raised an error for some valid multiindex slices (:issue:`33562`) - +- .. --------------------------------------------------------------------------- From 37ff708bac2bfeb0eb6016895e15a8708f519bf0 Mon Sep 17 00:00:00 2001 From: tp Date: Sat, 16 Jan 2021 10:56:23 +0000 Subject: [PATCH 8/9] move to v1.3 --- doc/source/whatsnew/v1.2.1.rst | 1 - doc/source/whatsnew/v1.3.0.rst | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.2.1.rst b/doc/source/whatsnew/v1.2.1.rst index 335ad18893702..8bfe233ae50cc 100644 --- a/doc/source/whatsnew/v1.2.1.rst +++ b/doc/source/whatsnew/v1.2.1.rst @@ -135,7 +135,6 @@ Other - Bumped minimum fastparquet version to 0.4.0 to avoid ``AttributeError`` from numba (:issue:`38344`) - Bumped minimum pymysql version to 0.8.1 to avoid test failures (:issue:`38344`) - Fixed build failure on MacOS 11 in Python 3.9.1 (:issue:`38766`) -- ``inspect.getmembers(Series)`` no longer raises an ``AbstractMethodError`` (:issue:`38782`). - Added reference to backwards incompatible ``check_freq`` arg of :func:`testing.assert_frame_equal` and :func:`testing.assert_series_equal` in :ref:`pandas 1.1.0 whats new ` (:issue:`34050`) .. --------------------------------------------------------------------------- diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index ed00e51b5d324..a497f2167ca5d 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -219,7 +219,7 @@ See :ref:`install.dependencies` and :ref:`install.optional_dependencies` for mor Other API changes ^^^^^^^^^^^^^^^^^ - Partially initialized :class:`CategoricalDtype` (i.e. those with ``categories=None`` objects will no longer compare as equal to fully initialized dtype objects. -- +- Accessing ``_constructor_expanddim`` on a :class:`DataFrame` and ``_constructor_sliced`` on a :class:`Series` now raise an ``AttributeError``. Previously a ``NotImplementedError`` was raised (:issue:`38782`) - .. --------------------------------------------------------------------------- From 1b1bf16f0bb38da81836d4e8fa7989554d2138a3 Mon Sep 17 00:00:00 2001 From: tp Date: Fri, 5 Feb 2021 22:29:31 +0000 Subject: [PATCH 9/9] Update docs --- doc/source/development/extending.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/development/extending.rst b/doc/source/development/extending.rst index 5476aeedfb6f9..9a8a95bec66ad 100644 --- a/doc/source/development/extending.rst +++ b/doc/source/development/extending.rst @@ -331,7 +331,7 @@ you can retain subclasses through ``pandas`` data manipulations. There are 3 possible constructor properties to be defined on a subclass: -* ``DataFrame/Series._constructor``: Used when a manipulation result has the same (sub-)class as the original. +* ``DataFrame/Series._constructor``: Used when a manipulation result has the same dimension as the original. * ``DataFrame._constructor_sliced``: Used when a ``DataFrame`` (sub-)class manipulation result should be a ``Series`` (sub-)class. * ``Series._constructor_expanddim``: Used when a ``Series`` (sub-)class manipulation result should be a ``DataFrame`` (sub-)class, e.g. ``Series.to_frame()``.