# Make `Delorean` hashable again ## Problem `Delorean` instances cannot be put in a `set` or used as `dict` keys: ```python >>> from datetime import datetime >>> from delorean import Delorean >>> d = Delorean(datetime(2015, 1, 1), timezone="UTC") >>> hash(d) Traceback (most recent call last): ... TypeError: unhashable type: 'Delorean' >>> {d} TypeError: unhashable type: 'Delorean' ``` This is surprising for a date/time value object: the standard library's `datetime.datetime` is hashable, and `Delorean` supports equality and ordering, so grouping instances in sets or keying dictionaries by them is a natural thing to want. ## Root cause `delorean/dates.py` defines `__eq__` (and the rich-comparison operators) on `Delorean`, but does not define `__hash__`. In Python 3, defining `__eq__` without `__hash__` sets `__hash__` to `None`, which makes the class unhashable: ```python >>> Delorean.__hash__ is None True ``` Under Python 2 (the version delorean originally targeted) defining `__eq__` left the inherited `__hash__` in place, so this is effectively a regression introduced by the move to Python 3. ## Fix Add a `__hash__` consistent with the existing `__eq__`. `__eq__` compares `self.epoch == other.epoch`, so hashing on `self.epoch` guarantees the hash invariant (equal objects hash equal), including two instances describing the same instant in different timezones: ```python def __hash__(self): return hash(self.epoch) ``` ## Test Added two tests to `tests/delorean_tests.py`: - `test_hashable`: `hash()` works and an instance can be stored in a set and used as a dict key. - `test_hash_consistent_with_equality`: two equal instances (same instant, different timezone) hash equal and collapse to one element in a set. ## Gate - `python -m pytest tests/` -> 232 passed, 44 subtests passed. Counterfactual (fix reverted, tests kept): both new tests fail with `TypeError: unhashable type: 'Delorean'`.