From 608f1779d552faf181b88a39b64b69cd10f40920 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 13 Jan 2020 11:02:38 -0600 Subject: [PATCH 1/5] Compat for util.testing import Closes #30869 --- pandas/tests/api/test_api.py | 15 +++++++++++++++ pandas/util/__init__.py | 25 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index 8b897524cb053..3f786c9cd9ecc 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -1,6 +1,8 @@ import sys from typing import List +import pytest + import pandas as pd from pandas import api, compat import pandas._testing as tm @@ -311,3 +313,16 @@ def test_util_testing_deprecated_direct(self): assert "pandas.util.testing is deprecated" in str(m[0].message) assert "pandas.testing instead" in str(m[0].message) + + def test_util_in_top_level(self): + # in a subprocess to avoid import caching issues + import subprocess + + out = subprocess.check_output( + ["python", "-c", "import pandas; pandas.util.testing"], + stderr=subprocess.STDOUT, + ).decode() + assert "pandas.util.testing is deprecated" in out + + with pytest.raises(AttributeError, match="foo"): + pd.util.foo diff --git a/pandas/util/__init__.py b/pandas/util/__init__.py index d906c0371d207..fc993eb164f3b 100644 --- a/pandas/util/__init__.py +++ b/pandas/util/__init__.py @@ -1,3 +1,28 @@ from pandas.util._decorators import Appender, Substitution, cache_readonly # noqa +from pandas import compat from pandas.core.util.hashing import hash_array, hash_pandas_object # noqa + +# compatibility for import pandas; pandas.util.testing + +if compat.PY37: + + def __getattr__(name): + if name == "testing": + import pandas.util.testing # noqa: F401 + else: + raise AttributeError(f"module 'pandas.util' has no attribute '{name}'") + + +else: + + class _testing: + def __getattr__(self, item): + import pandas.util.testing + + return getattr(pandas.util.testing, item) + + testing = _testing() + + +del compat From 92e7163b4de71f80ab0bd965a800eda8063cbdcc Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 13 Jan 2020 11:04:26 -0600 Subject: [PATCH 2/5] toplevel --- pandas/tests/api/test_api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index 3f786c9cd9ecc..d9fd157e39f86 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -1,3 +1,4 @@ +import subprocess import sys from typing import List @@ -316,8 +317,6 @@ def test_util_testing_deprecated_direct(self): def test_util_in_top_level(self): # in a subprocess to avoid import caching issues - import subprocess - out = subprocess.check_output( ["python", "-c", "import pandas; pandas.util.testing"], stderr=subprocess.STDOUT, From e420bbe0eb048d131b6bdce897a1d50274c4c435 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 13 Jan 2020 12:29:57 -0600 Subject: [PATCH 3/5] toplevel --- 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 d9fd157e39f86..59e2f2ca12192 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -318,7 +318,7 @@ def test_util_testing_deprecated_direct(self): def test_util_in_top_level(self): # in a subprocess to avoid import caching issues out = subprocess.check_output( - ["python", "-c", "import pandas; pandas.util.testing"], + [sys.executable, "-c", "import pandas; pandas.util.testing"], stderr=subprocess.STDOUT, ).decode() assert "pandas.util.testing is deprecated" in out From c18316f19cfa9917fdef582e6dcb7db200094893 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 13 Jan 2020 12:34:50 -0600 Subject: [PATCH 4/5] compat --- pandas/tests/api/test_api.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index 59e2f2ca12192..406d5f055797d 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -318,7 +318,11 @@ def test_util_testing_deprecated_direct(self): def test_util_in_top_level(self): # in a subprocess to avoid import caching issues out = subprocess.check_output( - [sys.executable, "-c", "import pandas; pandas.util.testing"], + [ + sys.executable, + "-c", + "import pandas; pandas.util.testing.assert_series_equal", + ], stderr=subprocess.STDOUT, ).decode() assert "pandas.util.testing is deprecated" in out From fa34e2e066787bcf77ce0d348e0bacba985e60bc Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 13 Jan 2020 12:44:22 -0600 Subject: [PATCH 5/5] compat --- pandas/util/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/util/__init__.py b/pandas/util/__init__.py index fc993eb164f3b..b5271dbc0443e 100644 --- a/pandas/util/__init__.py +++ b/pandas/util/__init__.py @@ -9,7 +9,9 @@ def __getattr__(name): if name == "testing": - import pandas.util.testing # noqa: F401 + import pandas.util.testing + + return pandas.util.testing else: raise AttributeError(f"module 'pandas.util' has no attribute '{name}'")