Skip to content

Commit

Permalink
Type check sentinel values (#3472)
Browse files Browse the repository at this point in the history
* type check sentinel values, using Enum pattern

* Code review

* Code review

* Code review

* Code review
  • Loading branch information
max-sixty authored and crusaderky committed Oct 31, 2019
1 parent 96e57d0 commit 8fbe1f8
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 34 deletions.
18 changes: 7 additions & 11 deletions xarray/core/dataarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
from .formatting import format_item
from .indexes import Indexes, default_indexes
from .options import OPTIONS
from .utils import ReprObject, _check_inplace, either_dict_or_kwargs
from .utils import Default, ReprObject, _default, _check_inplace, either_dict_or_kwargs
from .variable import (
IndexVariable,
Variable,
Expand Down Expand Up @@ -270,8 +270,6 @@ class DataArray(AbstractArray, DataWithCoords):
_coarsen_cls = rolling.DataArrayCoarsen
_resample_cls = resample.DataArrayResample

__default = ReprObject("<default>")

dt = property(DatetimeAccessor)

def __init__(
Expand Down Expand Up @@ -387,18 +385,18 @@ def _replace(
self,
variable: Variable = None,
coords=None,
name: Optional[Hashable] = __default,
name: Union[Hashable, None, Default] = _default,
) -> "DataArray":
if variable is None:
variable = self.variable
if coords is None:
coords = self._coords
if name is self.__default:
if name is _default:
name = self.name
return type(self)(variable, coords, name=name, fastpath=True)

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

def _from_temp_dataset(
self, dataset: Dataset, name: Hashable = __default
self, dataset: Dataset, name: Hashable = _default
) -> "DataArray":
variable = dataset._variables.pop(_THIS_ARRAY)
coords = dataset._variables
Expand Down Expand Up @@ -2450,13 +2448,11 @@ def identical(self, other: "DataArray") -> bool:
except (TypeError, AttributeError):
return False

__default_name = object()

def _result_name(self, other: Any = None) -> Optional[Hashable]:
# use the same naming heuristics as pandas:
# https://github.com/ContinuumIO/blaze/issues/458#issuecomment-51936356
other_name = getattr(other, "name", self.__default_name)
if other_name is self.__default_name or other_name == self.name:
other_name = getattr(other, "name", _default)
if other_name is _default or other_name == self.name:
return self.name
else:
return None
Expand Down
43 changes: 20 additions & 23 deletions xarray/core/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@
from .options import OPTIONS, _get_keep_attrs
from .pycompat import dask_array_type
from .utils import (
Default,
Frozen,
SortedKeysDict,
_default,
_check_inplace,
decode_numpy_dict_values,
either_dict_or_kwargs,
Expand Down Expand Up @@ -856,23 +858,18 @@ def _construct_direct(
obj._accessors = None
return obj

__default = object()

@classmethod
def _from_vars_and_coord_names(cls, variables, coord_names, attrs=None):
return cls._construct_direct(variables, coord_names, attrs=attrs)

# TODO(shoyer): renable type checking on this signature when pytype has a
# good way to handle defaulting arguments to a sentinel value:
# https://github.com/python/mypy/issues/1803
def _replace( # type: ignore
def _replace(
self,
variables: Dict[Hashable, Variable] = None,
coord_names: Set[Hashable] = None,
dims: Dict[Any, int] = None,
attrs: Optional[Dict[Hashable, Any]] = __default,
indexes: Optional[Dict[Any, pd.Index]] = __default,
encoding: Optional[dict] = __default,
attrs: Union[Dict[Hashable, Any], None, Default] = _default,
indexes: Union[Dict[Any, pd.Index], None, Default] = _default,
encoding: Union[dict, None, Default] = _default,
inplace: bool = False,
) -> "Dataset":
"""Fastpath constructor for internal use.
Expand All @@ -890,12 +887,12 @@ def _replace( # type: ignore
self._coord_names = coord_names
if dims is not None:
self._dims = dims
if attrs is not self.__default:
self._attrs = attrs
if indexes is not self.__default:
self._indexes = indexes
if encoding is not self.__default:
self._encoding = encoding
if attrs is not _default:
self._attrs = attrs # type: ignore # FIXME need mypy 0.750
if indexes is not _default:
self._indexes = indexes # type: ignore # FIXME need mypy 0.750
if encoding is not _default:
self._encoding = encoding # type: ignore # FIXME need mypy 0.750
obj = self
else:
if variables is None:
Expand All @@ -904,23 +901,23 @@ def _replace( # type: ignore
coord_names = self._coord_names.copy()
if dims is None:
dims = self._dims.copy()
if attrs is self.__default:
if attrs is _default:
attrs = copy.copy(self._attrs)
if indexes is self.__default:
if indexes is _default:
indexes = copy.copy(self._indexes)
if encoding is self.__default:
if encoding is _default:
encoding = copy.copy(self._encoding)
obj = self._construct_direct(
variables, coord_names, dims, attrs, indexes, encoding
)
return obj

def _replace_with_new_dims( # type: ignore
def _replace_with_new_dims(
self,
variables: Dict[Hashable, Variable],
coord_names: set = None,
attrs: Optional[Dict[Hashable, Any]] = __default,
indexes: Dict[Hashable, pd.Index] = __default,
attrs: Union[Dict[Hashable, Any], None, Default] = _default,
indexes: Union[Dict[Hashable, pd.Index], None, Default] = _default,
inplace: bool = False,
) -> "Dataset":
"""Replace variables with recalculated dimensions."""
Expand All @@ -929,12 +926,12 @@ def _replace_with_new_dims( # type: ignore
variables, coord_names, dims, attrs, indexes, inplace=inplace
)

def _replace_vars_and_dims( # type: ignore
def _replace_vars_and_dims(
self,
variables: Dict[Hashable, Variable],
coord_names: set = None,
dims: Dict[Hashable, int] = None,
attrs: Dict[Hashable, Any] = __default,
attrs: Union[Dict[Hashable, Any], None, Default] = _default,
inplace: bool = False,
) -> "Dataset":
"""Deprecated version of _replace_with_new_dims().
Expand Down
9 changes: 9 additions & 0 deletions xarray/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import os.path
import re
import warnings
from enum import Enum
from typing import (
AbstractSet,
Any,
Expand Down Expand Up @@ -701,3 +702,11 @@ def get_temp_dimname(dims: Container[Hashable], new_dim: Hashable) -> Hashable:
while new_dim in dims:
new_dim = "_" + str(new_dim)
return new_dim


# Singleton type, as per https://github.com/python/typing/pull/240
class Default(Enum):
token = 0


_default = Default.token

0 comments on commit 8fbe1f8

Please sign in to comment.