Skip to content

TYP: make na_value consistently a property #47676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions pandas/core/arrays/string_.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,11 @@ class StringDtype(StorageExtensionDtype):

name = "string"

#: StringDtype.na_value uses pandas.NA
na_value = libmissing.NA
#: StringDtype().na_value uses pandas.NA
@property
def na_value(self) -> libmissing.NAType:
return libmissing.NA

_metadata = ("storage",)

def __init__(self, storage=None) -> None:
Expand Down Expand Up @@ -335,13 +338,11 @@ def _from_sequence(cls, scalars, *, dtype: Dtype | None = None, copy=False):
na_values = scalars._mask
result = scalars._data
result = lib.ensure_string_array(result, copy=copy, convert_na_value=False)
result[na_values] = StringDtype.na_value
result[na_values] = libmissing.NA

else:
# convert non-na-likes to str, and nan-likes to StringDtype.na_value
result = lib.ensure_string_array(
scalars, na_value=StringDtype.na_value, copy=copy
)
# convert non-na-likes to str, and nan-likes to StringDtype().na_value
result = lib.ensure_string_array(scalars, na_value=libmissing.NA, copy=copy)

# Manually creating new array avoids the validation step in the __init__, so is
# faster. Refactor need for validation?
Expand Down Expand Up @@ -396,7 +397,7 @@ def __setitem__(self, key, value):
# validate new items
if scalar_value:
if isna(value):
value = StringDtype.na_value
value = libmissing.NA
elif not isinstance(value, str):
raise ValueError(
f"Cannot set non-string value '{value}' into a StringArray."
Expand Down Expand Up @@ -497,7 +498,7 @@ def _cmp_method(self, other, op):

if op.__name__ in ops.ARITHMETIC_BINOPS:
result = np.empty_like(self._ndarray, dtype="object")
result[mask] = StringDtype.na_value
result[mask] = libmissing.NA
result[valid] = op(self._ndarray[valid], other)
return StringArray(result)
else:
Expand All @@ -512,7 +513,7 @@ def _cmp_method(self, other, op):
# String methods interface
# error: Incompatible types in assignment (expression has type "NAType",
# base class "PandasArray" defined the type as "float")
_str_na_value = StringDtype.na_value # type: ignore[assignment]
_str_na_value = libmissing.NA # type: ignore[assignment]

def _str_map(
self, f, na_value=None, dtype: Dtype | None = None, convert: bool = True
Expand Down
5 changes: 3 additions & 2 deletions pandas/core/arrays/string_arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,9 @@ def astype(self, dtype, copy: bool = True):
# ------------------------------------------------------------------------
# String methods interface

# error: Cannot determine type of 'na_value'
_str_na_value = StringDtype.na_value # type: ignore[has-type]
# error: Incompatible types in assignment (expression has type "NAType",
# base class "ObjectStringArrayMixin" defined the type as "float")
_str_na_value = libmissing.NA # type: ignore[assignment]

def _str_map(
self, f, na_value=None, dtype: Dtype | None = None, convert: bool = True
Expand Down
9 changes: 7 additions & 2 deletions pandas/core/dtypes/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,11 +676,14 @@ class DatetimeTZDtype(PandasExtensionDtype):
kind: str_type = "M"
num = 101
base = np.dtype("M8[ns]") # TODO: depend on reso?
na_value = NaT
_metadata = ("unit", "tz")
_match = re.compile(r"(datetime64|M8)\[(?P<unit>.+), (?P<tz>.+)\]")
_cache_dtypes: dict[str_type, PandasExtensionDtype] = {}

@property
def na_value(self) -> NaTType:
return NaT

@cache_readonly
def str(self):
return f"|M8[{self._unit}]"
Expand Down Expand Up @@ -1450,7 +1453,9 @@ class BaseMaskedDtype(ExtensionDtype):
base = None
type: type

na_value = libmissing.NA
@property
def na_value(self) -> libmissing.NAType:
return libmissing.NA

@cache_readonly
def numpy_dtype(self) -> np.dtype:
Expand Down
5 changes: 4 additions & 1 deletion pandas/core/indexes/numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,10 @@ class Float64Index(NumericIndex):
__doc__ = _num_index_shared_docs["class_descr"] % _index_descr_args

_typ = "float64index"
_engine_type = libindex.Float64Engine
_default_dtype = np.dtype(np.float64)
_dtype_validation_metadata = (is_float_dtype, "float")
_is_backward_compat_public_numeric_index: bool = False

@property
def _engine_type(self) -> type[libindex.Float64Engine]:
return libindex.Float64Engine