Author: Brian Kearns <[email protected]>
Branch: py3k
Changeset: r69839:7de8ab2d6960
Date: 2014-03-10 14:29 -0400
http://bitbucket.org/pypy/pypy/changeset/7de8ab2d6960/
Log: optimizations for datetime, only calculate hash once
diff --git a/lib-python/3/datetime.py b/lib-python/3/datetime.py
--- a/lib-python/3/datetime.py
+++ b/lib-python/3/datetime.py
@@ -333,7 +333,7 @@
Representation: (days, seconds, microseconds). Why? Because I
felt like it.
"""
- __slots__ = '_days', '_seconds', '_microseconds'
+ __slots__ = '_days', '_seconds', '_microseconds', '_hashcode'
def __new__(cls, days=0, seconds=0, microseconds=0,
milliseconds=0, minutes=0, hours=0, weeks=0):
@@ -426,14 +426,14 @@
assert isinstance(s, int) and 0 <= s < 24*3600
assert isinstance(us, int) and 0 <= us < 1000000
+ if abs(d) > 999999999:
+ raise OverflowError("timedelta # of days is too large: %d" % d)
+
self = object.__new__(cls)
-
self._days = d
self._seconds = s
self._microseconds = us
- if abs(d) > 999999999:
- raise OverflowError("timedelta # of days is too large: %d" % d)
-
+ self._hashcode = -1
return self
def __repr__(self):
@@ -617,7 +617,9 @@
return _cmp(self._getstate(), other._getstate())
def __hash__(self):
- return hash(self._getstate())
+ if self._hashcode == -1:
+ self._hashcode = hash(self._getstate())
+ return self._hashcode
def __bool__(self):
return (self._days != 0 or
@@ -665,7 +667,7 @@
Properties (readonly):
year, month, day
"""
- __slots__ = '_year', '_month', '_day'
+ __slots__ = '_year', '_month', '_day', '_hashcode'
def __new__(cls, year, month=None, day=None):
"""Constructor.
@@ -679,12 +681,14 @@
# Pickle support
self = object.__new__(cls)
self.__setstate(year)
+ self._hashcode = -1
return self
year, month, day = _check_date_fields(year, month, day)
self = object.__new__(cls)
self._year = year
self._month = month
self._day = day
+ self._hashcode = -1
return self
# Additional constructors
@@ -847,7 +851,9 @@
def __hash__(self):
"Hash."
- return hash(self._getstate())
+ if self._hashcode == -1:
+ self._hashcode = hash(self._getstate())
+ return self._hashcode
# Computations
@@ -1022,7 +1028,7 @@
Properties (readonly):
hour, minute, second, microsecond, tzinfo
"""
- __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo'
+ __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo',
'_hashcode'
def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
"""Constructor.
@@ -1037,6 +1043,7 @@
# Pickle support
self = object.__new__(cls)
self.__setstate(hour, minute or None)
+ self._hashcode = -1
return self
hour, minute, second, microsecond = _check_time_fields(
hour, minute, second, microsecond)
@@ -1047,6 +1054,7 @@
self._second = second
self._microsecond = microsecond
self._tzinfo = tzinfo
+ self._hashcode = -1
return self
# Read-only field accessors
@@ -1142,16 +1150,20 @@
def __hash__(self):
"""Hash."""
- tzoff = self.utcoffset()
- if not tzoff: # zero or None
- return hash(self._getstate()[0])
- h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff,
- timedelta(hours=1))
- assert not m % timedelta(minutes=1), "whole minute"
- m //= timedelta(minutes=1)
- if 0 <= h < 24:
- return hash(time(h, m, self.second, self.microsecond))
- return hash((h, m, self.second, self.microsecond))
+ if self._hashcode == -1:
+ tzoff = self.utcoffset()
+ if not tzoff: # zero or None
+ self._hashcode = hash(self._getstate()[0])
+ else:
+ h, m = divmod(timedelta(hours=self.hour, minutes=self.minute)
- tzoff,
+ timedelta(hours=1))
+ assert not m % timedelta(minutes=1), "whole minute"
+ m //= timedelta(minutes=1)
+ if 0 <= h < 24:
+ self._hashcode = hash(time(h, m, self.second,
self.microsecond))
+ else:
+ self._hashcode = hash((h, m, self.second,
self.microsecond))
+ return self._hashcode
# Conversion to string
@@ -1292,12 +1304,11 @@
return (basestate, self._tzinfo)
def __setstate(self, string, tzinfo):
+ if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
+ raise TypeError("bad tzinfo state arg")
self._hour, self._minute, self._second, us1, us2, us3 = string
self._microsecond = (((us1 << 8) | us2) << 8) | us3
- if tzinfo is None or isinstance(tzinfo, _tzinfo_class):
- self._tzinfo = tzinfo
- else:
- raise TypeError("bad tzinfo state arg")
+ self._tzinfo = tzinfo
def __reduce__(self):
return (time, self._getstate())
@@ -1320,8 +1331,9 @@
microsecond=0, tzinfo=None):
if isinstance(year, bytes) and len(year) == 10 and 1 <= year[2] <= 12:
# Pickle support
- self = date.__new__(cls, year[:4])
+ self = object.__new__(cls)
self.__setstate(year, month)
+ self._hashcode = -1
return self
year, month, day = _check_date_fields(year, month, day)
hour, minute, second, microsecond = _check_time_fields(
@@ -1336,6 +1348,7 @@
self._second = second
self._microsecond = microsecond
self._tzinfo = tzinfo
+ self._hashcode = -1
return self
# Read-only field accessors
@@ -1736,12 +1749,15 @@
return base + otoff - myoff
def __hash__(self):
- tzoff = self.utcoffset()
- if tzoff is None:
- return hash(self._getstate()[0])
- days = _ymd2ord(self.year, self.month, self.day)
- seconds = self.hour * 3600 + self.minute * 60 + self.second
- return hash(timedelta(days, seconds, self.microsecond) - tzoff)
+ if self._hashcode == -1:
+ tzoff = self.utcoffset()
+ if tzoff is None:
+ self._hashcode = hash(self._getstate()[0])
+ else:
+ days = _ymd2ord(self.year, self.month, self.day)
+ seconds = self.hour * 3600 + self.minute * 60 + self.second
+ self._hashcode = hash(timedelta(days, seconds,
self.microsecond) - tzoff)
+ return self._hashcode
# Pickle support.
@@ -1758,14 +1774,13 @@
return (basestate, self._tzinfo)
def __setstate(self, string, tzinfo):
+ if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
+ raise TypeError("bad tzinfo state arg")
(yhi, ylo, self._month, self._day, self._hour,
self._minute, self._second, us1, us2, us3) = string
self._year = yhi * 256 + ylo
self._microsecond = (((us1 << 8) | us2) << 8) | us3
- if tzinfo is None or isinstance(tzinfo, _tzinfo_class):
- self._tzinfo = tzinfo
- else:
- raise TypeError("bad tzinfo state arg")
+ self._tzinfo = tzinfo
def __reduce__(self):
return (self.__class__, self._getstate())
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit