[pypy-commit] pypy default: clean up datetime argument handling, improve tests

bdkearns noreply at buildbot.pypy.org
Sat Feb 9 01:54:15 CET 2013


Author: Brian Kearns <bdkearns at gmail.com>
Branch: 
Changeset: r60995:72e79a8305c7
Date: 2013-02-08 19:52 -0500
http://bitbucket.org/pypy/pypy/changeset/72e79a8305c7/

Log:	clean up datetime argument handling, improve tests

diff --git a/lib_pypy/datetime.py b/lib_pypy/datetime.py
--- a/lib_pypy/datetime.py
+++ b/lib_pypy/datetime.py
@@ -18,6 +18,7 @@
 
 import time as _time
 import math as _math
+import decimal as _decimal
 
 MINYEAR = 1
 MAXYEAR = 9999
@@ -270,10 +271,15 @@
         return offset
     raise ValueError("%s()=%d, must be in -1439..1439" % (name, offset))
 
+def _check_int_field(value):
+    if not isinstance(value, (int, long, _decimal.Decimal)):
+        raise TypeError('integer argument expected')
+    return int(value)
+
 def _check_date_fields(year, month, day):
-    for value in [year, day]:
-        if not isinstance(value, (int, long)):
-            raise TypeError('int expected')
+    year = _check_int_field(year)
+    month = _check_int_field(month)
+    day = _check_int_field(day)
     if not MINYEAR <= year <= MAXYEAR:
         raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
     if not 1 <= month <= 12:
@@ -281,11 +287,13 @@
     dim = _days_in_month(year, month)
     if not 1 <= day <= dim:
         raise ValueError('day must be in 1..%d' % dim, day)
+    return year, month, day
 
 def _check_time_fields(hour, minute, second, microsecond):
-    for value in [hour, minute, second, microsecond]:
-        if not isinstance(value, (int, long)):
-            raise TypeError('int expected')
+    hour = _check_int_field(hour)
+    minute = _check_int_field(minute)
+    second = _check_int_field(second)
+    microsecond = _check_int_field(microsecond)
     if not 0 <= hour <= 23:
         raise ValueError('hour must be in 0..23', hour)
     if not 0 <= minute <= 59:
@@ -294,6 +302,7 @@
         raise ValueError('second must be in 0..59', second)
     if not 0 <= microsecond <= 999999:
         raise ValueError('microsecond must be in 0..999999', microsecond)
+    return hour, minute, second, microsecond
 
 def _check_tzinfo_arg(tz):
     if tz is not None and not isinstance(tz, tzinfo):
@@ -768,7 +777,7 @@
             self = object.__new__(cls)
             self.__setstate(year)
             return self
-        _check_date_fields(year, month, day)
+        year, month, day = _check_date_fields(year, month, day)
         self = object.__new__(cls)
         self._year = year
         self._month = month
@@ -889,7 +898,7 @@
             month = self._month
         if day is None:
             day = self._day
-        _check_date_fields(year, month, day)
+        year, month, day = _check_date_fields(year, month, day)
         return date(year, month, day)
 
     # Comparisons of date objects with other.
@@ -1150,13 +1159,14 @@
         second, microsecond (default to zero)
         tzinfo (default to None)
         """
-        self = object.__new__(cls)
         if isinstance(hour, str):
             # Pickle support
+            self = object.__new__(cls)
             self.__setstate(hour, minute or None)
             return self
+        hour, minute, second, microsecond = _check_time_fields(hour, minute, second, microsecond)
         _check_tzinfo_arg(tzinfo)
-        _check_time_fields(hour, minute, second, microsecond)
+        self = object.__new__(cls)
         self._hour = hour
         self._minute = minute
         self._second = second
@@ -1387,7 +1397,7 @@
             microsecond = self.microsecond
         if tzinfo is True:
             tzinfo = self.tzinfo
-        _check_time_fields(hour, minute, second, microsecond)
+        hour, minute, second, microsecond = _check_time_fields(hour, minute, second, microsecond)
         _check_tzinfo_arg(tzinfo)
         return time(hour, minute, second, microsecond, tzinfo)
 
@@ -1449,10 +1459,10 @@
             self = date.__new__(cls, year[:4])
             self.__setstate(year, month)
             return self
+        year, month, day = _check_date_fields(year, month, day)
+        hour, minute, second, microsecond = _check_time_fields(hour, minute, second, microsecond)
         _check_tzinfo_arg(tzinfo)
-        _check_time_fields(hour, minute, second, microsecond)
-        self = date.__new__(cls, year, month, day)
-        # XXX This duplicates __year, __month, __day for convenience :-(
+        self = object.__new__(cls)
         self._year = year
         self._month = month
         self._day = day
@@ -1617,8 +1627,8 @@
             microsecond = self.microsecond
         if tzinfo is True:
             tzinfo = self.tzinfo
-        _check_date_fields(year, month, day)
-        _check_time_fields(hour, minute, second, microsecond)
+        year, month, day = _check_date_fields(year, month, day)
+        hour, minute, second, microsecond = _check_time_fields(hour, minute, second, microsecond)
         _check_tzinfo_arg(tzinfo)
         return datetime(year, month, day, hour, minute, second,
                           microsecond, tzinfo)
diff --git a/pypy/module/test_lib_pypy/test_datetime.py b/pypy/module/test_lib_pypy/test_datetime.py
--- a/pypy/module/test_lib_pypy/test_datetime.py
+++ b/pypy/module/test_lib_pypy/test_datetime.py
@@ -30,14 +30,40 @@
     dt = datetime.datetime.utcfromtimestamp(0)
     assert isinstance(dt.microsecond, int)
 
+def test_default_args():
+    with py.test.raises(TypeError):
+        datetime.datetime()
+    with py.test.raises(TypeError):
+        datetime.datetime(10)
+    with py.test.raises(TypeError):
+        datetime.datetime(10, 10)
+    datetime.datetime(10, 10, 10)
 
-def test_integer_args():
+def test_check_arg_types():
+    import decimal
+    i10 = 10
+    l10 = 10L
+    d10 = decimal.Decimal(10)
+    d11 = decimal.Decimal(10.9)
+    assert datetime.datetime(i10, i10, i10, i10, i10, i10, i10) == \
+           datetime.datetime(l10, l10, l10, l10, l10, l10, l10) == \
+           datetime.datetime(d10, d10, d10, d10, d10, d10, d10) == \
+           datetime.datetime(d11, d11, d11, d11, d11, d11, d11)
+
+    with py.test.raises(TypeError):
+        datetime.datetime(10., 10, 10)
+    with py.test.raises(TypeError):
+        datetime.datetime(10, 10., 10)
     with py.test.raises(TypeError):
         datetime.datetime(10, 10, 10.)
     with py.test.raises(TypeError):
+        datetime.datetime(10, 10, 10, 10.)
+    with py.test.raises(TypeError):
         datetime.datetime(10, 10, 10, 10, 10.)
     with py.test.raises(TypeError):
         datetime.datetime(10, 10, 10, 10, 10, 10.)
+    with py.test.raises(TypeError):
+        datetime.datetime(10, 10, 10, 10, 10, 10, 10.)
 
 def test_utcnow_microsecond():
     dt = datetime.datetime.utcnow()


More information about the pypy-commit mailing list