Skip to content
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

Type check sentinel values #3472

Merged
merged 5 commits into from
Oct 31, 2019
Merged
Show file tree
Hide file tree
Changes from 4 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
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
37 changes: 17 additions & 20 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,11 +887,11 @@ def _replace( # type: ignore
self._coord_names = coord_names
if dims is not None:
self._dims = dims
if attrs is not self.__default:
if not isinstance(attrs, Default):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like there's some Chesterton's fence here: is there some reason we had self. here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. self.__default is misleading - it was a class attribute to begin with (you could rewrite it as Dataset.__default).

self._attrs = attrs
if indexes is not self.__default:
if not isinstance(indexes, Default):
self._indexes = indexes
if encoding is not self.__default:
if not isinstance(encoding, Default):
self._encoding = encoding
obj = self
else:
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
7 changes: 7 additions & 0 deletions xarray/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -701,3 +701,10 @@ def get_temp_dimname(dims: Container[Hashable], new_dim: Hashable) -> Hashable:
while new_dim in dims:
new_dim = "_" + str(new_dim)
return new_dim


class Default:
pass


_default = Default()