Skip to content

Commit 2517b92

Browse files
authored
ENH/TST: Add TestBaseDtype tests for ArrowExtensionArray (#47358)
1 parent 89578fe commit 2517b92

File tree

2 files changed

+89
-18
lines changed

2 files changed

+89
-18
lines changed

pandas/core/arrays/arrow/dtype.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def name(self) -> str: # type: ignore[override]
4444
"""
4545
A string identifying the data type.
4646
"""
47-
return str(self.pyarrow_dtype)
47+
return f"{str(self.pyarrow_dtype)}[{self.storage}]"
4848

4949
@cache_readonly
5050
def numpy_dtype(self) -> np.dtype:
@@ -92,20 +92,21 @@ def construct_from_string(cls, string: str):
9292
f"'construct_from_string' expects a string, got {type(string)}"
9393
)
9494
if not string.endswith("[pyarrow]"):
95-
raise TypeError(f"string {string} must end with '[pyarrow]'")
95+
raise TypeError(f"'{string}' must end with '[pyarrow]'")
9696
base_type = string.split("[pyarrow]")[0]
97-
pa_dtype = getattr(pa, base_type, None)
98-
if pa_dtype is None:
97+
try:
98+
pa_dtype = pa.type_for_alias(base_type)
99+
except ValueError as err:
99100
has_parameters = re.search(r"\[.*\]", base_type)
100101
if has_parameters:
101102
raise NotImplementedError(
102103
"Passing pyarrow type specific parameters "
103104
f"({has_parameters.group()}) in the string is not supported. "
104105
"Please construct an ArrowDtype object with a pyarrow_dtype "
105106
"instance with specific parameters."
106-
)
107-
raise TypeError(f"'{base_type}' is not a valid pyarrow data type.")
108-
return cls(pa_dtype())
107+
) from err
108+
raise TypeError(f"'{base_type}' is not a valid pyarrow data type.") from err
109+
return cls(pa_dtype)
109110

110111
@property
111112
def _is_numeric(self) -> bool:

pandas/tests/extension/test_arrow.py

+81-11
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from pandas.core.arrays.arrow.dtype import ArrowDtype # isort:skip
3535

3636

37-
@pytest.fixture(params=tm.ALL_PYARROW_DTYPES)
37+
@pytest.fixture(params=tm.ALL_PYARROW_DTYPES, ids=str)
3838
def dtype(request):
3939
return ArrowDtype(pyarrow_dtype=request.param)
4040

@@ -104,14 +104,23 @@ class TestBaseCasting(base.BaseCastingTests):
104104

105105

106106
class TestConstructors(base.BaseConstructorsTests):
107-
@pytest.mark.xfail(
108-
reason=(
109-
"str(dtype) constructs "
110-
"e.g. in64[pyarrow] like int64 (numpy) "
111-
"due to StorageExtensionDtype.__str__"
112-
)
113-
)
114-
def test_from_dtype(self, data):
107+
def test_from_dtype(self, data, request):
108+
pa_dtype = data.dtype.pyarrow_dtype
109+
if pa.types.is_timestamp(pa_dtype) and pa_dtype.tz:
110+
if pa_version_under2p0:
111+
request.node.add_marker(
112+
pytest.mark.xfail(
113+
reason=f"timestamp data with tz={pa_dtype.tz} "
114+
"converted to integer when pyarrow < 2.0",
115+
)
116+
)
117+
else:
118+
request.node.add_marker(
119+
pytest.mark.xfail(
120+
raises=NotImplementedError,
121+
reason=f"pyarrow.type_for_alias cannot infer {pa_dtype}",
122+
)
123+
)
115124
super().test_from_dtype(data)
116125

117126

@@ -197,10 +206,71 @@ def test_loc_iloc_frame_single_dtype(self, request, using_array_manager, data):
197206
super().test_loc_iloc_frame_single_dtype(data)
198207

199208

209+
class TestBaseDtype(base.BaseDtypeTests):
210+
def test_construct_from_string_own_name(self, dtype, request):
211+
pa_dtype = dtype.pyarrow_dtype
212+
if pa.types.is_timestamp(pa_dtype) and pa_dtype.tz is not None:
213+
request.node.add_marker(
214+
pytest.mark.xfail(
215+
raises=NotImplementedError,
216+
reason=f"pyarrow.type_for_alias cannot infer {pa_dtype}",
217+
)
218+
)
219+
super().test_construct_from_string_own_name(dtype)
220+
221+
def test_is_dtype_from_name(self, dtype, request):
222+
pa_dtype = dtype.pyarrow_dtype
223+
if pa.types.is_timestamp(pa_dtype) and pa_dtype.tz is not None:
224+
request.node.add_marker(
225+
pytest.mark.xfail(
226+
raises=NotImplementedError,
227+
reason=f"pyarrow.type_for_alias cannot infer {pa_dtype}",
228+
)
229+
)
230+
super().test_is_dtype_from_name(dtype)
231+
232+
def test_construct_from_string(self, dtype, request):
233+
pa_dtype = dtype.pyarrow_dtype
234+
if pa.types.is_timestamp(pa_dtype) and pa_dtype.tz is not None:
235+
request.node.add_marker(
236+
pytest.mark.xfail(
237+
raises=NotImplementedError,
238+
reason=f"pyarrow.type_for_alias cannot infer {pa_dtype}",
239+
)
240+
)
241+
super().test_construct_from_string(dtype)
242+
243+
def test_construct_from_string_another_type_raises(self, dtype):
244+
msg = r"'another_type' must end with '\[pyarrow\]'"
245+
with pytest.raises(TypeError, match=msg):
246+
type(dtype).construct_from_string("another_type")
247+
248+
def test_get_common_dtype(self, dtype, request):
249+
pa_dtype = dtype.pyarrow_dtype
250+
if (
251+
pa.types.is_date(pa_dtype)
252+
or pa.types.is_time(pa_dtype)
253+
or (
254+
pa.types.is_timestamp(pa_dtype)
255+
and (pa_dtype.unit != "ns" or pa_dtype.tz is not None)
256+
)
257+
or (pa.types.is_duration(pa_dtype) and pa_dtype.unit != "ns")
258+
):
259+
request.node.add_marker(
260+
pytest.mark.xfail(
261+
reason=(
262+
f"{pa_dtype} does not have associated numpy "
263+
f"dtype findable by find_common_type"
264+
)
265+
)
266+
)
267+
super().test_get_common_dtype(dtype)
268+
269+
200270
class TestBaseIndex(base.BaseIndexTests):
201271
pass
202272

203273

204-
def test_arrowdtype_construct_from_string_type_with_parameters():
274+
def test_arrowdtype_construct_from_string_type_with_unsupported_parameters():
205275
with pytest.raises(NotImplementedError, match="Passing pyarrow type"):
206-
ArrowDtype.construct_from_string("timestamp[s][pyarrow]")
276+
ArrowDtype.construct_from_string("timestamp[s, tz=UTC][pyarrow]")

0 commit comments

Comments
 (0)