Skip to content

Commit 2f50ea0

Browse files
add tests for is_<dtype>_dtype functions
1 parent f1abd83 commit 2f50ea0

File tree

1 file changed

+57
-24
lines changed

1 file changed

+57
-24
lines changed

pandas/tests/dtypes/test_common.py

+57-24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
from datetime import datetime
4+
import re
45

56
import numpy as np
67
import pytest
@@ -27,7 +28,27 @@
2728
from pandas.api.types import pandas_dtype
2829
from pandas.arrays import SparseArray
2930

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)
3152

3253

3354
# EA & Actual Dtypes
@@ -55,11 +76,13 @@ def test_invalid_dtype_error(self, box):
5576
with pytest.raises(TypeError, match=msg):
5677
com.pandas_dtype(box)
5778

58-
@pytest.mark.parametrize("cls", ALL_EA_DTYPES)
59-
def test_raises_for_dtype_class(self, cls: type[ExtensionDtype]):
79+
def test_raises_if_passed_dtype_class(self, ea_dtype: type[ExtensionDtype]):
80+
"""
81+
GH 47108
82+
"""
6083
msg = "Must pass dtype instance, not dtype class"
6184
with pytest.raises(TypeError, match=msg):
62-
com.pandas_dtype(cls)
85+
com.pandas_dtype(ea_dtype)
6386

6487
@pytest.mark.parametrize(
6588
"dtype",
@@ -124,6 +147,36 @@ def test_period_dtype(self, dtype):
124147
assert com.pandas_dtype(dtype) == dtype
125148

126149

150+
def test_is_dtype_func_raises_if_passed_dtype_class(
151+
is_dtype_func,
152+
ea_dtype: type[ExtensionDtype],
153+
):
154+
"""
155+
GH 47108
156+
157+
These should raise, like com.pandas_dtype, if passed an ExtensionDtype subclass.
158+
"""
159+
msg = "Must pass dtype instance, not dtype class"
160+
with pytest.raises(TypeError, match=msg):
161+
is_dtype_func(ea_dtype)
162+
163+
164+
def test_is_dtype_func_returns_false_if_passed_none(is_dtype_func, request):
165+
"""
166+
GH 15941
167+
168+
is_*_dtype functions all return False if passed None (and don't raise).
169+
"""
170+
if is_dtype_func is com.is_string_or_object_np_dtype:
171+
xfail = pytest.mark.xfail(
172+
reason="fastpath requires np.dtype obj",
173+
raises=AttributeError,
174+
)
175+
request.node.add_marker(xfail)
176+
177+
assert is_dtype_func(None) is False
178+
179+
127180
dtypes = {
128181
"datetime_tz": com.pandas_dtype("datetime64[ns, US/Eastern]"),
129182
"datetime": com.pandas_dtype("datetime64[ns]"),
@@ -172,26 +225,6 @@ def test_dtype_equal_strict(dtype1, dtype2):
172225
assert not com.is_dtype_equal(dtype1, dtype2)
173226

174227

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-
195228
def test_is_object():
196229
assert com.is_object_dtype(object)
197230
assert com.is_object_dtype(np.array([], dtype=object))

0 commit comments

Comments
 (0)