Skip to content

Commit 8fbe1f8

Browse files
max-sixtycrusaderky
authored andcommitted
Type check sentinel values (pydata#3472)
* type check sentinel values, using Enum pattern * Code review * Code review * Code review * Code review
1 parent 96e57d0 commit 8fbe1f8

File tree

3 files changed

+36
-34
lines changed

3 files changed

+36
-34
lines changed

xarray/core/dataarray.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
from .formatting import format_item
5454
from .indexes import Indexes, default_indexes
5555
from .options import OPTIONS
56-
from .utils import ReprObject, _check_inplace, either_dict_or_kwargs
56+
from .utils import Default, ReprObject, _default, _check_inplace, either_dict_or_kwargs
5757
from .variable import (
5858
IndexVariable,
5959
Variable,
@@ -270,8 +270,6 @@ class DataArray(AbstractArray, DataWithCoords):
270270
_coarsen_cls = rolling.DataArrayCoarsen
271271
_resample_cls = resample.DataArrayResample
272272

273-
__default = ReprObject("<default>")
274-
275273
dt = property(DatetimeAccessor)
276274

277275
def __init__(
@@ -387,18 +385,18 @@ def _replace(
387385
self,
388386
variable: Variable = None,
389387
coords=None,
390-
name: Optional[Hashable] = __default,
388+
name: Union[Hashable, None, Default] = _default,
391389
) -> "DataArray":
392390
if variable is None:
393391
variable = self.variable
394392
if coords is None:
395393
coords = self._coords
396-
if name is self.__default:
394+
if name is _default:
397395
name = self.name
398396
return type(self)(variable, coords, name=name, fastpath=True)
399397

400398
def _replace_maybe_drop_dims(
401-
self, variable: Variable, name: Optional[Hashable] = __default
399+
self, variable: Variable, name: Union[Hashable, None, Default] = _default
402400
) -> "DataArray":
403401
if variable.dims == self.dims and variable.shape == self.shape:
404402
coords = self._coords.copy()
@@ -438,7 +436,7 @@ def _to_temp_dataset(self) -> Dataset:
438436
return self._to_dataset_whole(name=_THIS_ARRAY, shallow_copy=False)
439437

440438
def _from_temp_dataset(
441-
self, dataset: Dataset, name: Hashable = __default
439+
self, dataset: Dataset, name: Hashable = _default
442440
) -> "DataArray":
443441
variable = dataset._variables.pop(_THIS_ARRAY)
444442
coords = dataset._variables
@@ -2450,13 +2448,11 @@ def identical(self, other: "DataArray") -> bool:
24502448
except (TypeError, AttributeError):
24512449
return False
24522450

2453-
__default_name = object()
2454-
24552451
def _result_name(self, other: Any = None) -> Optional[Hashable]:
24562452
# use the same naming heuristics as pandas:
24572453
# https://github.com/ContinuumIO/blaze/issues/458#issuecomment-51936356
2458-
other_name = getattr(other, "name", self.__default_name)
2459-
if other_name is self.__default_name or other_name == self.name:
2454+
other_name = getattr(other, "name", _default)
2455+
if other_name is _default or other_name == self.name:
24602456
return self.name
24612457
else:
24622458
return None

xarray/core/dataset.py

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@
7070
from .options import OPTIONS, _get_keep_attrs
7171
from .pycompat import dask_array_type
7272
from .utils import (
73+
Default,
7374
Frozen,
7475
SortedKeysDict,
76+
_default,
7577
_check_inplace,
7678
decode_numpy_dict_values,
7779
either_dict_or_kwargs,
@@ -856,23 +858,18 @@ def _construct_direct(
856858
obj._accessors = None
857859
return obj
858860

859-
__default = object()
860-
861861
@classmethod
862862
def _from_vars_and_coord_names(cls, variables, coord_names, attrs=None):
863863
return cls._construct_direct(variables, coord_names, attrs=attrs)
864864

865-
# TODO(shoyer): renable type checking on this signature when pytype has a
866-
# good way to handle defaulting arguments to a sentinel value:
867-
# https://github.com/python/mypy/issues/1803
868-
def _replace( # type: ignore
865+
def _replace(
869866
self,
870867
variables: Dict[Hashable, Variable] = None,
871868
coord_names: Set[Hashable] = None,
872869
dims: Dict[Any, int] = None,
873-
attrs: Optional[Dict[Hashable, Any]] = __default,
874-
indexes: Optional[Dict[Any, pd.Index]] = __default,
875-
encoding: Optional[dict] = __default,
870+
attrs: Union[Dict[Hashable, Any], None, Default] = _default,
871+
indexes: Union[Dict[Any, pd.Index], None, Default] = _default,
872+
encoding: Union[dict, None, Default] = _default,
876873
inplace: bool = False,
877874
) -> "Dataset":
878875
"""Fastpath constructor for internal use.
@@ -890,12 +887,12 @@ def _replace( # type: ignore
890887
self._coord_names = coord_names
891888
if dims is not None:
892889
self._dims = dims
893-
if attrs is not self.__default:
894-
self._attrs = attrs
895-
if indexes is not self.__default:
896-
self._indexes = indexes
897-
if encoding is not self.__default:
898-
self._encoding = encoding
890+
if attrs is not _default:
891+
self._attrs = attrs # type: ignore # FIXME need mypy 0.750
892+
if indexes is not _default:
893+
self._indexes = indexes # type: ignore # FIXME need mypy 0.750
894+
if encoding is not _default:
895+
self._encoding = encoding # type: ignore # FIXME need mypy 0.750
899896
obj = self
900897
else:
901898
if variables is None:
@@ -904,23 +901,23 @@ def _replace( # type: ignore
904901
coord_names = self._coord_names.copy()
905902
if dims is None:
906903
dims = self._dims.copy()
907-
if attrs is self.__default:
904+
if attrs is _default:
908905
attrs = copy.copy(self._attrs)
909-
if indexes is self.__default:
906+
if indexes is _default:
910907
indexes = copy.copy(self._indexes)
911-
if encoding is self.__default:
908+
if encoding is _default:
912909
encoding = copy.copy(self._encoding)
913910
obj = self._construct_direct(
914911
variables, coord_names, dims, attrs, indexes, encoding
915912
)
916913
return obj
917914

918-
def _replace_with_new_dims( # type: ignore
915+
def _replace_with_new_dims(
919916
self,
920917
variables: Dict[Hashable, Variable],
921918
coord_names: set = None,
922-
attrs: Optional[Dict[Hashable, Any]] = __default,
923-
indexes: Dict[Hashable, pd.Index] = __default,
919+
attrs: Union[Dict[Hashable, Any], None, Default] = _default,
920+
indexes: Union[Dict[Hashable, pd.Index], None, Default] = _default,
924921
inplace: bool = False,
925922
) -> "Dataset":
926923
"""Replace variables with recalculated dimensions."""
@@ -929,12 +926,12 @@ def _replace_with_new_dims( # type: ignore
929926
variables, coord_names, dims, attrs, indexes, inplace=inplace
930927
)
931928

932-
def _replace_vars_and_dims( # type: ignore
929+
def _replace_vars_and_dims(
933930
self,
934931
variables: Dict[Hashable, Variable],
935932
coord_names: set = None,
936933
dims: Dict[Hashable, int] = None,
937-
attrs: Dict[Hashable, Any] = __default,
934+
attrs: Union[Dict[Hashable, Any], None, Default] = _default,
938935
inplace: bool = False,
939936
) -> "Dataset":
940937
"""Deprecated version of _replace_with_new_dims().

xarray/core/utils.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os.path
77
import re
88
import warnings
9+
from enum import Enum
910
from typing import (
1011
AbstractSet,
1112
Any,
@@ -701,3 +702,11 @@ def get_temp_dimname(dims: Container[Hashable], new_dim: Hashable) -> Hashable:
701702
while new_dim in dims:
702703
new_dim = "_" + str(new_dim)
703704
return new_dim
705+
706+
707+
# Singleton type, as per https://github.com/python/typing/pull/240
708+
class Default(Enum):
709+
token = 0
710+
711+
712+
_default = Default.token

0 commit comments

Comments
 (0)