Skip to content

Commit f7f8904

Browse files
jbrockmendelluckyvs1
authored andcommitted
REF: make pd._testing a directory (pandas-dev#38689)
1 parent 8c66898 commit f7f8904

File tree

8 files changed

+3228
-3170
lines changed

8 files changed

+3228
-3170
lines changed

pandas/_testing.py

-3,158
This file was deleted.

pandas/_testing/__init__.py

+1,583
Large diffs are not rendered by default.

pandas/_testing/asserters.py

+1,382
Large diffs are not rendered by default.

pandas/_testing/contexts.py

+249
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
import bz2
2+
from contextlib import contextmanager
3+
import gzip
4+
import os
5+
from shutil import rmtree
6+
import tempfile
7+
import zipfile
8+
9+
from pandas.compat import get_lzma_file, import_lzma
10+
11+
lzma = import_lzma()
12+
13+
14+
@contextmanager
15+
def decompress_file(path, compression):
16+
"""
17+
Open a compressed file and return a file object.
18+
19+
Parameters
20+
----------
21+
path : str
22+
The path where the file is read from.
23+
24+
compression : {'gzip', 'bz2', 'zip', 'xz', None}
25+
Name of the decompression to use
26+
27+
Returns
28+
-------
29+
file object
30+
"""
31+
if compression is None:
32+
f = open(path, "rb")
33+
elif compression == "gzip":
34+
# pandas\_testing.py:243: error: Incompatible types in assignment
35+
# (expression has type "IO[Any]", variable has type "BinaryIO")
36+
f = gzip.open(path, "rb") # type: ignore[assignment]
37+
elif compression == "bz2":
38+
# pandas\_testing.py:245: error: Incompatible types in assignment
39+
# (expression has type "BZ2File", variable has type "BinaryIO")
40+
f = bz2.BZ2File(path, "rb") # type: ignore[assignment]
41+
elif compression == "xz":
42+
f = get_lzma_file(lzma)(path, "rb")
43+
elif compression == "zip":
44+
zip_file = zipfile.ZipFile(path)
45+
zip_names = zip_file.namelist()
46+
if len(zip_names) == 1:
47+
# pandas\_testing.py:252: error: Incompatible types in assignment
48+
# (expression has type "IO[bytes]", variable has type "BinaryIO")
49+
f = zip_file.open(zip_names.pop()) # type: ignore[assignment]
50+
else:
51+
raise ValueError(f"ZIP file {path} error. Only one file per ZIP.")
52+
else:
53+
raise ValueError(f"Unrecognized compression type: {compression}")
54+
55+
try:
56+
yield f
57+
finally:
58+
f.close()
59+
if compression == "zip":
60+
zip_file.close()
61+
62+
63+
@contextmanager
64+
def set_timezone(tz: str):
65+
"""
66+
Context manager for temporarily setting a timezone.
67+
68+
Parameters
69+
----------
70+
tz : str
71+
A string representing a valid timezone.
72+
73+
Examples
74+
--------
75+
>>> from datetime import datetime
76+
>>> from dateutil.tz import tzlocal
77+
>>> tzlocal().tzname(datetime.now())
78+
'IST'
79+
80+
>>> with set_timezone('US/Eastern'):
81+
... tzlocal().tzname(datetime.now())
82+
...
83+
'EDT'
84+
"""
85+
import os
86+
import time
87+
88+
def setTZ(tz):
89+
if tz is None:
90+
try:
91+
del os.environ["TZ"]
92+
except KeyError:
93+
pass
94+
else:
95+
os.environ["TZ"] = tz
96+
time.tzset()
97+
98+
orig_tz = os.environ.get("TZ")
99+
setTZ(tz)
100+
try:
101+
yield
102+
finally:
103+
setTZ(orig_tz)
104+
105+
106+
@contextmanager
107+
def ensure_clean(filename=None, return_filelike=False, **kwargs):
108+
"""
109+
Gets a temporary path and agrees to remove on close.
110+
111+
Parameters
112+
----------
113+
filename : str (optional)
114+
if None, creates a temporary file which is then removed when out of
115+
scope. if passed, creates temporary file with filename as ending.
116+
return_filelike : bool (default False)
117+
if True, returns a file-like which is *always* cleaned. Necessary for
118+
savefig and other functions which want to append extensions.
119+
**kwargs
120+
Additional keywords passed in for creating a temporary file.
121+
:meth:`tempFile.TemporaryFile` is used when `return_filelike` is ``True``.
122+
:meth:`tempfile.mkstemp` is used when `return_filelike` is ``False``.
123+
Note that the `filename` parameter will be passed in as the `suffix`
124+
argument to either function.
125+
126+
See Also
127+
--------
128+
tempfile.TemporaryFile
129+
tempfile.mkstemp
130+
"""
131+
filename = filename or ""
132+
fd = None
133+
134+
kwargs["suffix"] = filename
135+
136+
if return_filelike:
137+
f = tempfile.TemporaryFile(**kwargs)
138+
139+
try:
140+
yield f
141+
finally:
142+
f.close()
143+
else:
144+
# Don't generate tempfile if using a path with directory specified.
145+
if len(os.path.dirname(filename)):
146+
raise ValueError("Can't pass a qualified name to ensure_clean()")
147+
148+
try:
149+
fd, filename = tempfile.mkstemp(**kwargs)
150+
except UnicodeEncodeError:
151+
import pytest
152+
153+
pytest.skip("no unicode file names on this system")
154+
155+
try:
156+
yield filename
157+
finally:
158+
try:
159+
os.close(fd)
160+
except OSError:
161+
print(f"Couldn't close file descriptor: {fd} (file: {filename})")
162+
try:
163+
if os.path.exists(filename):
164+
os.remove(filename)
165+
except OSError as e:
166+
print(f"Exception on removing file: {e}")
167+
168+
169+
@contextmanager
170+
def ensure_clean_dir():
171+
"""
172+
Get a temporary directory path and agrees to remove on close.
173+
174+
Yields
175+
------
176+
Temporary directory path
177+
"""
178+
directory_name = tempfile.mkdtemp(suffix="")
179+
try:
180+
yield directory_name
181+
finally:
182+
try:
183+
rmtree(directory_name)
184+
except OSError:
185+
pass
186+
187+
188+
@contextmanager
189+
def ensure_safe_environment_variables():
190+
"""
191+
Get a context manager to safely set environment variables
192+
193+
All changes will be undone on close, hence environment variables set
194+
within this contextmanager will neither persist nor change global state.
195+
"""
196+
saved_environ = dict(os.environ)
197+
try:
198+
yield
199+
finally:
200+
os.environ.clear()
201+
os.environ.update(saved_environ)
202+
203+
204+
@contextmanager
205+
def with_csv_dialect(name, **kwargs):
206+
"""
207+
Context manager to temporarily register a CSV dialect for parsing CSV.
208+
209+
Parameters
210+
----------
211+
name : str
212+
The name of the dialect.
213+
kwargs : mapping
214+
The parameters for the dialect.
215+
216+
Raises
217+
------
218+
ValueError : the name of the dialect conflicts with a builtin one.
219+
220+
See Also
221+
--------
222+
csv : Python's CSV library.
223+
"""
224+
import csv
225+
226+
_BUILTIN_DIALECTS = {"excel", "excel-tab", "unix"}
227+
228+
if name in _BUILTIN_DIALECTS:
229+
raise ValueError("Cannot override builtin dialect.")
230+
231+
csv.register_dialect(name, **kwargs)
232+
yield
233+
csv.unregister_dialect(name)
234+
235+
236+
@contextmanager
237+
def use_numexpr(use, min_elements=None):
238+
from pandas.core.computation import expressions as expr
239+
240+
if min_elements is None:
241+
min_elements = expr._MIN_ELEMENTS
242+
243+
olduse = expr.USE_NUMEXPR
244+
oldmin = expr._MIN_ELEMENTS
245+
expr.set_use_numexpr(use)
246+
expr._MIN_ELEMENTS = min_elements
247+
yield
248+
expr._MIN_ELEMENTS = oldmin
249+
expr.set_use_numexpr(olduse)

pandas/tests/internals/test_internals.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -377,11 +377,11 @@ def test_set_change_dtype(self, mgr):
377377
idx = mgr2.items.get_loc("baz")
378378
assert mgr2.iget(idx).dtype == np.object_
379379

380-
mgr2.insert(len(mgr2.items), "quux", tm.randn(N).astype(int))
380+
mgr2.insert(len(mgr2.items), "quux", np.random.randn(N).astype(int))
381381
idx = mgr2.items.get_loc("quux")
382382
assert mgr2.iget(idx).dtype == np.int_
383383

384-
mgr2.iset(mgr2.items.get_loc("quux"), tm.randn(N))
384+
mgr2.iset(mgr2.items.get_loc("quux"), np.random.randn(N))
385385
assert mgr2.iget(idx).dtype == np.float_
386386

387387
def test_copy(self, mgr):
@@ -615,11 +615,11 @@ def test_interleave_dtype(self, mgr_string, dtype):
615615
assert mgr.as_array().dtype == "object"
616616

617617
def test_consolidate_ordering_issues(self, mgr):
618-
mgr.iset(mgr.items.get_loc("f"), tm.randn(N))
619-
mgr.iset(mgr.items.get_loc("d"), tm.randn(N))
620-
mgr.iset(mgr.items.get_loc("b"), tm.randn(N))
621-
mgr.iset(mgr.items.get_loc("g"), tm.randn(N))
622-
mgr.iset(mgr.items.get_loc("h"), tm.randn(N))
618+
mgr.iset(mgr.items.get_loc("f"), np.random.randn(N))
619+
mgr.iset(mgr.items.get_loc("d"), np.random.randn(N))
620+
mgr.iset(mgr.items.get_loc("b"), np.random.randn(N))
621+
mgr.iset(mgr.items.get_loc("g"), np.random.randn(N))
622+
mgr.iset(mgr.items.get_loc("h"), np.random.randn(N))
623623

624624
# we have datetime/tz blocks in mgr
625625
cons = mgr.consolidate()

pandas/tests/series/apply/test_series_apply.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import numpy as np
55
import pytest
66

7+
from pandas.core.dtypes.common import is_number
8+
79
import pandas as pd
810
from pandas import DataFrame, Index, MultiIndex, Series, isna, timedelta_range
911
import pandas._testing as tm
@@ -400,7 +402,7 @@ def test_agg_cython_table(self, series, func, expected):
400402
# test reducing functions in
401403
# pandas.core.base.SelectionMixin._cython_table
402404
result = series.agg(func)
403-
if tm.is_number(expected):
405+
if is_number(expected):
404406
assert np.isclose(result, expected, equal_nan=True)
405407
else:
406408
assert result == expected

pandas/tests/series/methods/test_combine_first.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def test_combine_first(self):
4646

4747
# mixed types
4848
index = tm.makeStringIndex(20)
49-
floats = Series(tm.randn(20), index=index)
49+
floats = Series(np.random.randn(20), index=index)
5050
strings = Series(tm.makeStringIndex(10), index=index[::2])
5151

5252
combined = strings.combine_first(floats)

pandas/tests/series/test_repr.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ def test_repr(self, datetime_series, string_series, object_series):
7171
str(string_series.astype(int))
7272
str(object_series)
7373

74-
str(Series(tm.randn(1000), index=np.arange(1000)))
75-
str(Series(tm.randn(1000), index=np.arange(1000, 0, step=-1)))
74+
str(Series(np.random.randn(1000), index=np.arange(1000)))
75+
str(Series(np.random.randn(1000), index=np.arange(1000, 0, step=-1)))
7676

7777
# empty
7878
str(Series(dtype=object))
@@ -104,7 +104,7 @@ def test_repr(self, datetime_series, string_series, object_series):
104104
repr(string_series)
105105

106106
biggie = Series(
107-
tm.randn(1000), index=np.arange(1000), name=("foo", "bar", "baz")
107+
np.random.randn(1000), index=np.arange(1000), name=("foo", "bar", "baz")
108108
)
109109
repr(biggie)
110110

0 commit comments

Comments
 (0)