import numpy as np
|
import pytest
|
|
import pandas as pd
|
from pandas.api.types import (
|
infer_dtype,
|
is_object_dtype,
|
is_string_dtype,
|
)
|
from pandas.tests.extension.base.base import BaseExtensionTests
|
|
|
class BaseDtypeTests(BaseExtensionTests):
|
"""Base class for ExtensionDtype classes"""
|
|
def test_name(self, dtype):
|
assert isinstance(dtype.name, str)
|
|
def test_kind(self, dtype):
|
valid = set("biufcmMOSUV")
|
assert dtype.kind in valid
|
|
def test_is_dtype_from_name(self, dtype):
|
result = type(dtype).is_dtype(dtype.name)
|
assert result is True
|
|
def test_is_dtype_unboxes_dtype(self, data, dtype):
|
assert dtype.is_dtype(data) is True
|
|
def test_is_dtype_from_self(self, dtype):
|
result = type(dtype).is_dtype(dtype)
|
assert result is True
|
|
def test_is_dtype_other_input(self, dtype):
|
assert dtype.is_dtype([1, 2, 3]) is False
|
|
def test_is_not_string_type(self, dtype):
|
assert not is_string_dtype(dtype)
|
|
def test_is_not_object_type(self, dtype):
|
assert not is_object_dtype(dtype)
|
|
def test_eq_with_str(self, dtype):
|
assert dtype == dtype.name
|
assert dtype != dtype.name + "-suffix"
|
|
def test_eq_with_numpy_object(self, dtype):
|
assert dtype != np.dtype("object")
|
|
def test_eq_with_self(self, dtype):
|
assert dtype == dtype
|
assert dtype != object()
|
|
def test_array_type(self, data, dtype):
|
assert dtype.construct_array_type() is type(data)
|
|
def test_check_dtype(self, data):
|
dtype = data.dtype
|
|
# check equivalency for using .dtypes
|
df = pd.DataFrame(
|
{"A": pd.Series(data, dtype=dtype), "B": data, "C": "foo", "D": 1}
|
)
|
result = df.dtypes == str(dtype)
|
|
try:
|
new_numpy_behavior = np.dtype("int64") != "Int64"
|
except TypeError:
|
# numpy<=1.20.3 this comparison could raise or in some cases
|
# come back True
|
new_numpy_behavior = True
|
assert new_numpy_behavior
|
|
expected = pd.Series([True, True, False, False], index=list("ABCD"))
|
|
self.assert_series_equal(result, expected)
|
|
expected = pd.Series([True, True, False, False], index=list("ABCD"))
|
result = df.dtypes.apply(str) == str(dtype)
|
self.assert_series_equal(result, expected)
|
|
def test_hashable(self, dtype):
|
hash(dtype) # no error
|
|
def test_str(self, dtype):
|
assert str(dtype) == dtype.name
|
|
def test_eq(self, dtype):
|
assert dtype == dtype.name
|
assert dtype != "anonther_type"
|
|
def test_construct_from_string_own_name(self, dtype):
|
result = dtype.construct_from_string(dtype.name)
|
assert type(result) is type(dtype)
|
|
# check OK as classmethod
|
result = type(dtype).construct_from_string(dtype.name)
|
assert type(result) is type(dtype)
|
|
def test_construct_from_string_another_type_raises(self, dtype):
|
msg = f"Cannot construct a '{type(dtype).__name__}' from 'another_type'"
|
with pytest.raises(TypeError, match=msg):
|
type(dtype).construct_from_string("another_type")
|
|
def test_construct_from_string_wrong_type_raises(self, dtype):
|
with pytest.raises(
|
TypeError,
|
match="'construct_from_string' expects a string, got <class 'int'>",
|
):
|
type(dtype).construct_from_string(0)
|
|
def test_get_common_dtype(self, dtype):
|
# in practice we will not typically call this with a 1-length list
|
# (we shortcut to just use that dtype as the common dtype), but
|
# still testing as good practice to have this working (and it is the
|
# only case we can test in general)
|
assert dtype._get_common_dtype([dtype]) == dtype
|
|
@pytest.mark.parametrize("skipna", [True, False])
|
def test_infer_dtype(self, data, data_missing, skipna):
|
# only testing that this works without raising an error
|
res = infer_dtype(data, skipna=skipna)
|
assert isinstance(res, str)
|
res = infer_dtype(data_missing, skipna=skipna)
|
assert isinstance(res, str)
|