|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
3 | 3 | from datetime import datetime
|
| 4 | +import re |
4 | 5 |
|
5 | 6 | import numpy as np
|
6 | 7 | import pytest
|
|
27 | 28 | from pandas.api.types import pandas_dtype
|
28 | 29 | from pandas.arrays import SparseArray
|
29 | 30 |
|
30 |
| -ALL_EA_DTYPES = _registry.dtypes |
| 31 | + |
| 32 | +@pytest.fixture(name="ea_dtype", params=_registry.dtypes, scope="module") |
| 33 | +def fixture_ea_dtype(request) -> type[ExtensionDtype]: |
| 34 | + """ |
| 35 | + All registered ExtensionDtype subclasses. |
| 36 | + """ |
| 37 | + return request.param |
| 38 | + |
| 39 | + |
| 40 | +@pytest.fixture( |
| 41 | + name="is_dtype_func", |
| 42 | + params=(f for f in dir(com) if re.fullmatch(r"^is_\w+_dtype$", f)), |
| 43 | + scope="module", |
| 44 | +) |
| 45 | +def fixture_is_dtype_func(request): |
| 46 | + """ |
| 47 | + All functions of the form 'is_*_dtype' in pandas.core.dtypes.common, e.g. |
| 48 | + 'is_interval_dtype'. |
| 49 | + """ |
| 50 | + fname = request.param |
| 51 | + return getattr(com, fname) |
31 | 52 |
|
32 | 53 |
|
33 | 54 | # EA & Actual Dtypes
|
@@ -55,11 +76,11 @@ def test_invalid_dtype_error(self, box):
|
55 | 76 | with pytest.raises(TypeError, match=msg):
|
56 | 77 | com.pandas_dtype(box)
|
57 | 78 |
|
58 |
| - @pytest.mark.parametrize("cls", ALL_EA_DTYPES) |
59 |
| - def test_raises_for_dtype_class(self, cls: type[ExtensionDtype]): |
| 79 | + def test_raises_for_dtype_class_obj(self, ea_dtype: type[ExtensionDtype]): |
| 80 | + """GH 47108""" |
60 | 81 | msg = "Must pass dtype instance, not dtype class"
|
61 | 82 | with pytest.raises(TypeError, match=msg):
|
62 |
| - com.pandas_dtype(cls) |
| 83 | + com.pandas_dtype(ea_dtype) |
63 | 84 |
|
64 | 85 | @pytest.mark.parametrize(
|
65 | 86 | "dtype",
|
@@ -124,6 +145,25 @@ def test_period_dtype(self, dtype):
|
124 | 145 | assert com.pandas_dtype(dtype) == dtype
|
125 | 146 |
|
126 | 147 |
|
| 148 | +def test_raises_for_dtype_class_obj(is_dtype_func, ea_dtype: type[ExtensionDtype]): |
| 149 | + """GH 47108""" |
| 150 | + msg = "Must pass dtype instance, not dtype class" |
| 151 | + with pytest.raises(TypeError, match=msg): |
| 152 | + is_dtype_func(ea_dtype) |
| 153 | + |
| 154 | + |
| 155 | +def test_returns_false_for_none(is_dtype_func, request): |
| 156 | + """GH 15941; no exception should be raised""" |
| 157 | + if is_dtype_func is com.is_string_or_object_np_dtype: |
| 158 | + xfail = pytest.mark.xfail( |
| 159 | + reason="fastpath requires np.dtype obj", |
| 160 | + raises=AttributeError, |
| 161 | + ) |
| 162 | + request.node.add_marker(xfail) |
| 163 | + |
| 164 | + assert is_dtype_func(None) is False |
| 165 | + |
| 166 | + |
127 | 167 | dtypes = {
|
128 | 168 | "datetime_tz": com.pandas_dtype("datetime64[ns, US/Eastern]"),
|
129 | 169 | "datetime": com.pandas_dtype("datetime64[ns]"),
|
@@ -172,26 +212,6 @@ def test_dtype_equal_strict(dtype1, dtype2):
|
172 | 212 | assert not com.is_dtype_equal(dtype1, dtype2)
|
173 | 213 |
|
174 | 214 |
|
175 |
| -def get_is_dtype_funcs(): |
176 |
| - """ |
177 |
| - Get all functions in pandas.core.dtypes.common that |
178 |
| - begin with 'is_' and end with 'dtype' |
179 |
| -
|
180 |
| - """ |
181 |
| - fnames = [f for f in dir(com) if (f.startswith("is_") and f.endswith("dtype"))] |
182 |
| - fnames.remove("is_string_or_object_np_dtype") # fastpath requires np.dtype obj |
183 |
| - return [getattr(com, fname) for fname in fnames] |
184 |
| - |
185 |
| - |
186 |
| -@pytest.mark.parametrize("func", get_is_dtype_funcs(), ids=lambda x: x.__name__) |
187 |
| -def test_get_dtype_error_catch(func): |
188 |
| - # see gh-15941 |
189 |
| - # |
190 |
| - # No exception should be raised. |
191 |
| - |
192 |
| - assert not func(None) |
193 |
| - |
194 |
| - |
195 | 215 | def test_is_object():
|
196 | 216 | assert com.is_object_dtype(object)
|
197 | 217 | assert com.is_object_dtype(np.array([], dtype=object))
|
|
0 commit comments