From 759d6201e972b78229302b7a7fded6acb44d8f6a Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Fri, 20 Dec 2019 15:18:12 -0800 Subject: [PATCH 1/9] DEPR: deprecate pandas.np module for python 3.7+ --- pandas/__init__.py | 14 +++++++++++++- pandas/core/api.py | 2 -- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/pandas/__init__.py b/pandas/__init__.py index d68fc2f48624b..957a1a34b3784 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -105,7 +105,6 @@ to_datetime, to_timedelta, # misc - np, Grouper, factorize, unique, @@ -209,6 +208,19 @@ class Panel: pass return Panel + + elif name == "np": + + warnings.warn( + "The pandas.np module is deprecated and will be removed from pandas in a future version. " + "Import numpy directly instead", + FutureWarning, + stacklevel=2, + ) + import numpy as np + + return np + elif name in {"SparseSeries", "SparseDataFrame"}: warnings.warn( "The {} class is removed from pandas. Accessing it from " diff --git a/pandas/core/api.py b/pandas/core/api.py index 5261801600111..b0b65f9d0be34 100644 --- a/pandas/core/api.py +++ b/pandas/core/api.py @@ -1,7 +1,5 @@ # flake8: noqa -import numpy as np - from pandas._libs import NaT, Period, Timedelta, Timestamp from pandas._libs.missing import NA From 75ced19877a13aa88b8d7f92389781602809e187 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Fri, 20 Dec 2019 15:24:46 -0800 Subject: [PATCH 2/9] Added whatsnew entry --- doc/source/whatsnew/v1.0.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index 539649df05046..620fc62f3fa6a 100755 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -205,6 +205,7 @@ Other enhancements (:meth:`~DataFrame.to_parquet` / :func:`read_parquet`) using the `'pyarrow'` engine now preserve those data types with pyarrow >= 1.0.0 (:issue:`20612`). - The ``partition_cols`` argument in :meth:`DataFrame.to_parquet` now accepts a string (:issue:`27117`) +- The pandas.np submodule is now deprecated. Import numpy directly instead(:issue:`30296`) Build Changes ^^^^^^^^^^^^^ From ed1c53e70968bfb288c381fae22b213bc0d6dd22 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Fri, 20 Dec 2019 18:51:58 -0800 Subject: [PATCH 3/9] Fix bad tests --- pandas/tests/api/test_api.py | 2 +- pandas/tests/indexes/period/test_indexing.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index 900ba878e4c0a..b64ded66cc420 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -101,7 +101,7 @@ class TestPDApi(Base): deprecated_classes_in_future: List[str] = [] # external modules exposed in pandas namespace - modules = ["np", "datetime"] + modules = ["datetime"] # top-level functions funcs = [ diff --git a/pandas/tests/indexes/period/test_indexing.py b/pandas/tests/indexes/period/test_indexing.py index c8f0d3b3fe553..e17f0af24760c 100644 --- a/pandas/tests/indexes/period/test_indexing.py +++ b/pandas/tests/indexes/period/test_indexing.py @@ -679,7 +679,7 @@ def test_indexing(self): def test_period_index_indexer(self): # GH4125 idx = pd.period_range("2002-01", "2003-12", freq="M") - df = pd.DataFrame(pd.np.random.randn(24, 10), index=idx) + df = pd.DataFrame(np.random.randn(24, 10), index=idx) tm.assert_frame_equal(df, df.loc[idx]) tm.assert_frame_equal(df, df.loc[list(idx)]) tm.assert_frame_equal(df, df.loc[list(idx)]) From 185e22a0896bc5520874047d8fb21c7cedd354ce Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Sat, 21 Dec 2019 11:08:19 -0800 Subject: [PATCH 4/9] Hacky py 3.6 solution and tests added --- pandas/__init__.py | 19 ++++++++++++++++++- pandas/tests/api/test_api.py | 13 +++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/pandas/__init__.py b/pandas/__init__.py index b3ecbb924da79..63d8828bdd74c 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -188,7 +188,6 @@ __git_version__ = v.get("full-revisionid") del get_versions, v - # GH 27101 # TODO: remove Panel compat in 1.0 if pandas.compat.PY37: @@ -248,6 +247,24 @@ class SparseDataFrame: class SparseSeries: pass + class numpy: + def __init__(self): + import numpy as np + import warnings + + self.np = np + self.warnings = warnings + + def __getattr__(self, item): + self.warnings.warn( + "The pandas.np module is deprecated and will be removed from pandas in a future version. " + "Import numpy directly instead", + FutureWarning, + stacklevel=2, + ) + return getattr(self.np, item) + + np = numpy() # module level doc-string __doc__ = """ diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index b64ded66cc420..203bd99cbdd8d 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -93,6 +93,7 @@ class TestPDApi(Base): ] if not compat.PY37: classes.extend(["Panel", "SparseSeries", "SparseDataFrame"]) + deprecated_modules.extend("np") # these are already deprecated; awaiting removal deprecated_classes: List[str] = [] @@ -220,6 +221,18 @@ def test_api(self): self.ignored, ) + def test_depr(self): + deprecated = ( + self.deprecated_modules + + self.deprecated_classes + + self.deprecated_classes_in_future + + self.deprecated_funcs + + self.deprecated_funcs_in_future + ) + for depr in deprecated: + with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + getattr(pd, depr) + class TestApi(Base): From 1da5ba8a0c47baf7fc7c860740b8ed473ca7bd1d Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Sat, 21 Dec 2019 16:19:05 -0800 Subject: [PATCH 5/9] Rewrite tests and numpy wrapper --- pandas/__init__.py | 12 +++++++----- pandas/tests/api/test_api.py | 8 ++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/pandas/__init__.py b/pandas/__init__.py index 63d8828bdd74c..de66121137099 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -247,7 +247,7 @@ class SparseDataFrame: class SparseSeries: pass - class numpy: + class __numpy: def __init__(self): import numpy as np import warnings @@ -255,16 +255,18 @@ def __init__(self): self.np = np self.warnings = warnings - def __getattr__(self, item): - self.warnings.warn( + def __getattribute__(self, item): + np = object.__getattribute__(self, "np") + warnings = object.__getattribute__(self, "warnings") + warnings.warn( "The pandas.np module is deprecated and will be removed from pandas in a future version. " "Import numpy directly instead", FutureWarning, stacklevel=2, ) - return getattr(self.np, item) + return object.__getattribute__(np, item) - np = numpy() + np = __numpy() # module level doc-string __doc__ = """ diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index 203bd99cbdd8d..24cdc811aaba7 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -93,7 +93,7 @@ class TestPDApi(Base): ] if not compat.PY37: classes.extend(["Panel", "SparseSeries", "SparseDataFrame"]) - deprecated_modules.extend("np") + deprecated_modules.append("np") # these are already deprecated; awaiting removal deprecated_classes: List[str] = [] @@ -231,7 +231,11 @@ def test_depr(self): ) for depr in deprecated: with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): - getattr(pd, depr) + if compat.PY37: + getattr(pd, depr) + else: + deprecated = getattr(pd, depr) + getattr(deprecated, dir(deprecated)[-1]) class TestApi(Base): From 3b7c97f9e630f9a6ffefd6f4c17e2f44c41b28c4 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Sat, 21 Dec 2019 16:46:59 -0800 Subject: [PATCH 6/9] Formatting --- doc/source/whatsnew/v1.0.0.rst | 2 +- pandas/__init__.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index ab3f3cecc3687..d08d3700a6dbc 100755 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -205,7 +205,7 @@ Other enhancements (:meth:`~DataFrame.to_parquet` / :func:`read_parquet`) using the `'pyarrow'` engine now preserve those data types with pyarrow >= 1.0.0 (:issue:`20612`). - The ``partition_cols`` argument in :meth:`DataFrame.to_parquet` now accepts a string (:issue:`27117`) -- The pandas.np submodule is now deprecated. Import numpy directly instead(:issue:`30296`) +- The pandas.np submodule is now deprecated. Import numpy directly instead (:issue:`30296`) - :func:`to_parquet` now appropriately handles the ``schema`` argument for user defined schemas in the pyarrow engine. (:issue: `30270`) - DataFrame constructor preserve `ExtensionArray` dtype with `ExtensionArray` (:issue:`11363`) diff --git a/pandas/__init__.py b/pandas/__init__.py index de66121137099..24029e9a8b570 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -213,7 +213,8 @@ class Panel: elif name == "np": warnings.warn( - "The pandas.np module is deprecated and will be removed from pandas in a future version. " + "The pandas.np module is deprecated " + "and will be removed from pandas in a future version. " "Import numpy directly instead", FutureWarning, stacklevel=2, @@ -259,7 +260,8 @@ def __getattribute__(self, item): np = object.__getattribute__(self, "np") warnings = object.__getattribute__(self, "warnings") warnings.warn( - "The pandas.np module is deprecated and will be removed from pandas in a future version. " + "The pandas.np module is deprecated " + "and will be removed from pandas in a future version. " "Import numpy directly instead", FutureWarning, stacklevel=2, From cdc5297ad9ace11a4e67df9da12f01df5f21f854 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Mon, 23 Dec 2019 10:15:17 -0800 Subject: [PATCH 7/9] Assorted cleanups --- pandas/__init__.py | 11 ++++++----- pandas/tests/api/test_api.py | 18 +++++++++++------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/pandas/__init__.py b/pandas/__init__.py index 24029e9a8b570..0d4f7bedb77e6 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -256,17 +256,18 @@ def __init__(self): self.np = np self.warnings = warnings - def __getattribute__(self, item): - np = object.__getattribute__(self, "np") - warnings = object.__getattribute__(self, "warnings") - warnings.warn( + def __getattr__(self, item): + self.warnings.warn( "The pandas.np module is deprecated " "and will be removed from pandas in a future version. " "Import numpy directly instead", FutureWarning, stacklevel=2, ) - return object.__getattribute__(np, item) + try: + return getattr(self.np, item) + except AttributeError: + raise AttributeError(f"module numpy has no attribute {item}") np = __numpy() diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index 24cdc811aaba7..c75e4e5738a96 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -20,7 +20,6 @@ def check(self, namespace, expected, ignored=None): class TestPDApi(Base): - # these are optionally imported based on testing # & need to be ignored ignored = ["tests", "locale", "conftest"] @@ -230,29 +229,34 @@ def test_depr(self): + self.deprecated_funcs_in_future ) for depr in deprecated: - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + with tm.assert_produces_warning(FutureWarning): if compat.PY37: getattr(pd, depr) else: deprecated = getattr(pd, depr) - getattr(deprecated, dir(deprecated)[-1]) + deprecated.__getattr__(dir(deprecated)[-1]) -class TestApi(Base): +def test_np(): + import numpy as np + import warnings + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FutureWarning) + assert np.array_equal(pd.np.arange(0, 10), np.arange(0, 10)) + +class TestApi(Base): allowed = ["types", "extensions", "indexers"] def test_api(self): - self.check(api, self.allowed) class TestTesting(Base): - funcs = ["assert_frame_equal", "assert_series_equal", "assert_index_equal"] def test_testing(self): - from pandas import testing self.check(testing, self.funcs) From 581ad01e0c585dcd9a2bf904d687132651938a02 Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Mon, 23 Dec 2019 11:12:29 -0800 Subject: [PATCH 8/9] Fix style issue --- pandas/tests/api/test_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index c75e4e5738a96..d586dbbb72831 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -243,7 +243,7 @@ def test_np(): with warnings.catch_warnings(): warnings.simplefilter("ignore", FutureWarning) - assert np.array_equal(pd.np.arange(0, 10), np.arange(0, 10)) + assert (pd.np.arange(0, 10) == np.arange(0, 10)).all() class TestApi(Base): From 094677960e2d2cf7a0d13336c896359744cffa3f Mon Sep 17 00:00:00 2001 From: Thomas Li Date: Wed, 25 Dec 2019 17:31:44 -0800 Subject: [PATCH 9/9] Fix doc formatting --- doc/source/whatsnew/v1.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index d08d3700a6dbc..180e74ac79388 100755 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -205,7 +205,7 @@ Other enhancements (:meth:`~DataFrame.to_parquet` / :func:`read_parquet`) using the `'pyarrow'` engine now preserve those data types with pyarrow >= 1.0.0 (:issue:`20612`). - The ``partition_cols`` argument in :meth:`DataFrame.to_parquet` now accepts a string (:issue:`27117`) -- The pandas.np submodule is now deprecated. Import numpy directly instead (:issue:`30296`) +- The ``pandas.np`` submodule is now deprecated. Import numpy directly instead (:issue:`30296`) - :func:`to_parquet` now appropriately handles the ``schema`` argument for user defined schemas in the pyarrow engine. (:issue: `30270`) - DataFrame constructor preserve `ExtensionArray` dtype with `ExtensionArray` (:issue:`11363`)