diff -r 5c09070b339b Lib/plistlib.py --- a/Lib/plistlib.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/plistlib.py Fri Mar 20 21:59:49 2009 -0500 @@ -16,7 +16,7 @@ and writePlistToBytes(). Values can be strings, integers, floats, booleans, tuples, lists, -dictionaries, Data or datetime.datetime objects. String values (including +dictionaries, Data or datetime.DateTime objects. String values (including dictionary keys) may be unicode strings -- they will be written out as UTF-8. @@ -38,7 +38,7 @@ ), someData = Data(b""), someMoreData = Data(b"" * 10), - aDate = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())), + aDate = datetime.DateTime.fromtimestamp(time.mktime(time.gmtime())), ) # unicode keys are possible, but a little awkward to use: pl[u'\xc5benraa'] = "That was a unicode key." @@ -158,7 +158,7 @@ if val is None: break lst.append(int(val)) - return datetime.datetime(*lst) + return datetime.DateTime(*lst) def _dateToString(d): return '%04d-%02d-%02dT%02d:%02d:%02dZ' % ( @@ -215,7 +215,7 @@ self.writeDict(value) elif isinstance(value, Data): self.writeData(value) - elif isinstance(value, datetime.datetime): + elif isinstance(value, datetime.DateTime): self.simpleElement("date", _dateToString(value)) elif isinstance(value, (tuple, list)): self.writeArray(value) diff -r 5c09070b339b Lib/test/test_datetime.py --- a/Lib/test/test_datetime.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/test/test_datetime.py Fri Mar 20 21:59:49 2009 -0500 @@ -12,6 +12,11 @@ from test import support from datetime import MINYEAR, MAXYEAR +from datetime import TimeDelta +from datetime import TZInfo +from datetime import Time +from datetime import Date, DateTime + from datetime import timedelta from datetime import tzinfo from datetime import time @@ -36,9 +41,9 @@ self.assertEqual(datetime.MAXYEAR, 9999) ############################################################################# -# tzinfo tests +# TZInfo tests -def fixedoffset_factory(tzi_class=tzinfo, td_class=timedelta): +def fixedoffset_factory(tzi_class=TZInfo, td_class=TimeDelta): class FixedOffset(tzi_class): def __init__(self, offset, name, dstoffset=42, td = td_class): if isinstance(offset, int): @@ -64,9 +69,9 @@ return FixedOffset, PicklableFixedOffset class TestTZInfo(unittest.TestCase): - dt_class = datetime - td_class = timedelta - tzi_class = tzinfo + dt_class = DateTime + td_class = TimeDelta + tzi_class = TZInfo FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, td_class) @@ -103,7 +108,7 @@ self.assertEqual(fo.dst(dt), self.td_class(minutes=42)) def test_pickling_base(self): - # There's no point to pickling tzinfo objects on their own (they + # There's no point to pickling TZInfo objects on their own (they # carry no data), but they need to be picklable anyway else # concrete subclasses can't be pickled. orig = self.tzi_class.__new__(self.tzi_class) @@ -132,8 +137,8 @@ self.assertEqual(derived.tzname(None), 'cookie') ############################################################################# -# Base clase for testing a particular aspect of timedelta, time, date and -# datetime comparisons. +# Base clase for testing a particular aspect of TimeDelta, Time, Date and +# DateTime comparisons. class HarmlessMixedComparison: # Test that __eq__ and __ne__ don't complain for mixed-type comparisons. @@ -169,11 +174,11 @@ self.assertRaises(TypeError, lambda: () >= me) ############################################################################# -# timedelta tests +# TimeDelta tests class TestTimeDelta(HarmlessMixedComparison, unittest.TestCase): - theclass = timedelta + theclass = TimeDelta def test_constructor(self): eq = self.assertEqual @@ -258,7 +263,7 @@ self.assertRaises(TypeError, lambda: a // x) self.assertRaises(TypeError, lambda: x // a) - # Division of int by timedelta doesn't make sense. + # Division of int by TimeDelta doesn't make sense. # Division by zero doesn't make sense. for zero in 0, 0: self.assertRaises(TypeError, lambda: zero // a) @@ -477,14 +482,14 @@ self.assertEqual(t4.as_hours(), -1) ############################################################################# -# date tests +# Date tests class TestDateOnly(unittest.TestCase): - # Tests here won't pass if also run on datetime objects, so don't - # subclass this to test datetimes too. + # Tests here won't pass if also run on DateTime objects, so don't + # subclass this to test DateTimes too. - theclass = date - td_class = timedelta + theclass = Date + td_class = TimeDelta def test_delta_non_days_ignored(self): dt = self.theclass(2000, 1, 2) @@ -515,15 +520,15 @@ dt2 = dt - delta self.assertEqual(dt2, dt - days) -class SubclassDate(date): +class SubclassDate(Date): sub_var = 1 class TestDate(HarmlessMixedComparison, unittest.TestCase): - # Tests here should pass for both dates and datetimes, except for a + # Tests here should pass for both Dates and DateTimes, except for a # few tests that TestDateTime overrides. - theclass = date - td_class = timedelta + theclass = Date + td_class = TimeDelta def test_basic_attributes(self): dt = self.theclass(2002, 3, 1) @@ -534,7 +539,7 @@ def test_roundtrip(self): for dt in (self.theclass(1, 2, 3), self.theclass.today()): - # Verify dt -> string -> date identity. + # Verify dt -> string -> Date identity. s = repr(dt) self.failUnless(s.startswith('datetime.')) s = s[9:] @@ -557,7 +562,7 @@ fromord = self.theclass.fromordinal(n) self.assertEqual(d, fromord) if hasattr(fromord, "hour"): - # if we're checking something fancier than a date, verify + # if we're checking something fancier than a Date, verify # the extra fields have been zeroed out self.assertEqual(fromord.hour, 0) self.assertEqual(fromord.minute, 0) @@ -594,7 +599,7 @@ def test_extreme_ordinals(self): a = self.theclass.min - a = self.theclass(a.year, a.month, a.day) # get rid of time parts + a = self.theclass(a.year, a.month, a.day) # get rid of Time parts aord = a.toordinal() b = a.fromordinal(aord) self.assertEqual(a, b) @@ -606,7 +611,7 @@ self.assertEqual(b, self.theclass.fromordinal(aord + 1)) a = self.theclass.max - a = self.theclass(a.year, a.month, a.day) # get rid of time parts + a = self.theclass(a.year, a.month, a.day) # get rid of Time parts aord = a.toordinal() b = a.fromordinal(aord) self.assertEqual(a, b) @@ -700,16 +705,16 @@ self.assertRaises(TypeError, lambda: i+a) self.assertRaises(TypeError, lambda: i-a) - # delta - date is senseless. + # delta - Date is senseless. self.assertRaises(TypeError, lambda: day - a) - # mixing date and (delta or date) via * or // is senseless + # mixing Date and (delta or Date) via * or // is senseless self.assertRaises(TypeError, lambda: day * a) self.assertRaises(TypeError, lambda: a * day) self.assertRaises(TypeError, lambda: day // a) self.assertRaises(TypeError, lambda: a // day) self.assertRaises(TypeError, lambda: a * a) self.assertRaises(TypeError, lambda: a // a) - # date + date is senseless + # Date + Date is senseless self.assertRaises(TypeError, lambda: a + a) def test_overflow(self): @@ -1045,7 +1050,7 @@ self.assertEqual(their < our, False) def test_bool(self): - # All dates are considered true. + # All Dates are considered true. self.failUnless(self.theclass.min) self.failUnless(self.theclass.max) @@ -1120,9 +1125,9 @@ # checks in the constructor. This can create insane objects. # The constructor doesn't want to burn the time to validate all # fields, but does check the month field. This stops, e.g., - # datetime.datetime('1995-03-25') from yielding an insane object. + # datetime.DateTime('1995-03-25') from yielding an insane object. base = b'1995-03-25' - if not issubclass(self.theclass, datetime): # XXX + if not issubclass(self.theclass, DateTime): # XXX base = base[:4] for month_byte in b'9', b'\0', b'\r', b'\xff': self.assertRaises(TypeError, self.theclass, @@ -1134,18 +1139,18 @@ self.theclass(base[:2] + bytes([ord_byte]) + base[3:]) ############################################################################# -# datetime tests +# DateTime tests -class SubclassDateTime(datetime): +class SubclassDateTime(DateTime): sub_var = 1 class TestDateTime(TestDate): - theclass = datetime - date_class = date - td_class = timedelta - tzi_class = tzinfo - time_class = time + theclass = DateTime + date_class = Date + td_class = TimeDelta + tzi_class = TZInfo + time_class = Time FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, td_class) @@ -1174,7 +1179,7 @@ def test_roundtrip(self): for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7), self.theclass.now()): - # Verify dt -> string -> datetime identity. + # Verify dt -> string -> DateTime identity. s = repr(dt) self.failUnless(s.startswith('datetime.')) s = s[9:] @@ -1263,7 +1268,7 @@ self.assert_(dt1 < dt2) def test_strftime_with_bad_tzname_replace(self): - # verify ok if tzinfo.tzname().replace() returns a non-string + # verify ok if TZInfo.tzname().replace() returns a non-string class MyTzInfo(self.FixedOffset): def tzname(self, dt): class MyStr(str): @@ -1397,16 +1402,16 @@ self.assertRaises(TypeError, lambda: i+a) self.assertRaises(TypeError, lambda: i-a) - # delta - datetime is senseless. + # delta - DateTime is senseless. self.assertRaises(TypeError, lambda: day - a) - # mixing datetime and (delta or datetime) via * or // is senseless + # mixing DateTime and (delta or DateTime) via * or // is senseless self.assertRaises(TypeError, lambda: day * a) self.assertRaises(TypeError, lambda: a * day) self.assertRaises(TypeError, lambda: day // a) self.assertRaises(TypeError, lambda: a // day) self.assertRaises(TypeError, lambda: a * a) self.assertRaises(TypeError, lambda: a // a) - # datetime + datetime is senseless + # DateTime + DateTime is senseless self.assertRaises(TypeError, lambda: a + a) def test_pickling(self): @@ -1684,13 +1689,13 @@ self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month + dt1.second - 7) -class SubclassTime(time): +class SubclassTime(Time): sub_var = 1 class TestTime(HarmlessMixedComparison, unittest.TestCase): - theclass = time - td_class = timedelta + theclass = Time + td_class = TimeDelta def test_basic_attributes(self): t = self.theclass(12, 0) @@ -1711,7 +1716,7 @@ def test_roundtrip(self): t = self.theclass(1, 2, 3, 4) - # Verify t -> string -> time identity. + # Verify t -> string -> Time identity. s = repr(t) self.failUnless(s.startswith('datetime.')) s = s[9:] @@ -1990,18 +1995,18 @@ # A mixin for classes with a tzinfo= argument. Subclasses must define # theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever) -# must be legit (which is true for time and datetime). +# must be legit (which is true for Time and DateTime). class TZInfoBase: - dt_class = datetime - td_class = timedelta - tzi_class = tzinfo - time_class = time + dt_class = DateTime + td_class = TimeDelta + tzi_class = TZInfo + time_class = Time def test_argument_passing(self): cls = self.theclass td_class = self.td_class - # A datetime passes itself on, a time passes None. + # A DateTime passes itself on, a Time passes None. class introspective(self.tzi_class): def tzname(self, dt): return dt and "real" or "none" def utcoffset(self, dt): @@ -2116,7 +2121,7 @@ td_class = self.td_class # Ensure that utcoffset() gets ignored if the comparands have - # the same tzinfo member. + # the same TZInfo member. class OperandDependentOffset(self.tzi_class): def utcoffset(self, t): if t.minute < 10: @@ -2138,9 +2143,9 @@ self.assertEqual(got, expected) # However, if they're different members, uctoffset is not ignored. - # Note that a time can't actually have an operand-depedent offset, + # Note that a Time can't actually have an operand-depedent offset, # though (and time.utcoffset() passes None to tzinfo.utcoffset()), - # so skip this test for time. + # so skip this test for Time. if cls is not self.time_class: d0 = base.replace(minute=3, tzinfo=OperandDependentOffset()) d1 = base.replace(minute=9, tzinfo=OperandDependentOffset()) @@ -2160,11 +2165,11 @@ self.assertEqual(got, expected) -# Testing time objects with a non-None tzinfo. +# Testing Time objects with a non-None TZInfo. class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase): - theclass = time - td_class = timedelta - tzi_class = tzinfo + theclass = Time + td_class = TimeDelta + tzi_class = TZInfo FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, td_class) @@ -2258,7 +2263,7 @@ self.assertRaises(TypeError, t.strftime, "%Z") def test_hash_edge_cases(self): - # Offsets that overflow a basic time. + # Offsets that overflow a basic Time. t1 = self.theclass(0, 1, 2, 3, tzinfo=self.FixedOffset(1439, "")) t2 = self.theclass(0, 0, 2, 3, tzinfo=self.FixedOffset(1438, "")) self.assertEqual(hash(t1), hash(t2)) @@ -2270,7 +2275,7 @@ def test_pickling(self): global PicklableFixedOffset PicklableFixedOffset = self.PicklableFixedOffset - # Try one without a tzinfo. + # Try one without a TZInfo. args = 20, 59, 16, 64**2 orig = self.theclass(*args) for pickler, unpickler, proto in pickle_choices: @@ -2278,7 +2283,7 @@ derived = unpickler.loads(green) self.assertEqual(orig, derived) - # Try one with a tzinfo. + # Try one with a TZInfo. tinfo = self.PicklableFixedOffset(-300, 'cookie') orig = self.theclass(5, 6, 7, tzinfo=tinfo) for pickler, unpickler, proto in pickle_choices: @@ -2291,7 +2296,7 @@ self.assertEqual(derived.tzname(), 'cookie') def test_more_bool(self): - # Test cases with non-None tzinfo. + # Test cases with non-None TZInfo. cls = self.theclass t = cls(0, tzinfo=self.FixedOffset(-300, "")) @@ -2368,7 +2373,7 @@ t2 = t2.replace(tzinfo=self.FixedOffset(0, "")) self.assertRaises(TypeError, lambda: t1 == t2) - # In time w/ identical tzinfo objects, utcoffset is ignored. + # In Time w/ identical TZInfo objects, utcoffset is ignored. td_class = self.td_class class Varies(self.tzi_class): def __init__(self): @@ -2415,14 +2420,14 @@ self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.second - 7) -# Testing datetime objects with a non-None tzinfo. +# Testing DateTime objects with a non-None TZInfo. class TestDateTimeTZ(TestDateTime, TZInfoBase, unittest.TestCase): - theclass = datetime - date_class = date - td_class = timedelta - tzi_class = tzinfo - time_class = time + theclass = DateTime + date_class = Date + td_class = TimeDelta + tzi_class = TZInfo + time_class = Time FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, td_class) @@ -2439,7 +2444,7 @@ def test_even_more_compare(self): # The test_compare() and test_more_compare() inherited from TestDate - # and TestDateTime covered non-tzinfo cases. + # and TestDateTime covered non-TZInfo cases. # Smallest possible after UTC adjustment. t1 = self.theclass(1, 1, 1, tzinfo=self.FixedOffset(1439, "")) @@ -2484,7 +2489,7 @@ self.assertRaises(TypeError, lambda: t1 == t2) self.assertEqual(t2, t2) - # It's also naive if it has tzinfo but tzinfo.utcoffset() is None. + # It's also naive if it has TZInfo but TZInfo.utcoffset() is None. class Naive(self.tzi_class): def utcoffset(self, dt): return None t2 = self.theclass(5, 6, 7, tzinfo=Naive()) @@ -2508,7 +2513,7 @@ def test_pickling(self): global PicklableFixedOffset PicklableFixedOffset = self.PicklableFixedOffset - # Try one without a tzinfo. + # Try one without a TZInfo. args = 6, 7, 23, 20, 59, 1, 64**2 orig = self.theclass(*args) for pickler, unpickler, proto in pickle_choices: @@ -2516,7 +2521,7 @@ derived = unpickler.loads(green) self.assertEqual(orig, derived) - # Try one with a tzinfo. + # Try one with a TZInfo. tinfo = self.PicklableFixedOffset(-300, 'cookie') orig = self.theclass(*args, **{'tzinfo': tinfo}) derived = self.theclass(1, 1, 1, tzinfo=self.FixedOffset(0, "", 0)) @@ -2531,7 +2536,7 @@ def test_extreme_hashes(self): # If an attempt is made to hash these via subtracting the offset - # then hashing a datetime object, OverflowError results. The + # then hashing a DateTime object, OverflowError results. The # Python implementation used to blow up here. t = self.theclass(1, 1, 1, tzinfo=self.FixedOffset(1439, "")) hash(t) @@ -2603,7 +2608,7 @@ self.assertRaises(TypeError, lambda: now - nowaware) self.assertRaises(TypeError, lambda: nowaware - now) - # And adding datetime's doesn't make sense, aware or not. + # And adding DateTime's doesn't make sense, aware or not. self.assertRaises(TypeError, lambda: now + nowaware) self.assertRaises(TypeError, lambda: nowaware + now) self.assertRaises(TypeError, lambda: nowaware + nowaware) @@ -2654,7 +2659,7 @@ def test_tzinfo_now(self): meth = self.theclass.now - # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up). + # Ensure it doesn't require TZInfo (i.e., that this doesn't blow up). base = meth() # Try with and without naming the keyword. off42 = self.FixedOffset(42, "42") @@ -2670,7 +2675,7 @@ # Too many args. self.assertRaises(TypeError, meth, off42, off42) - # We don't know which time zone we're in, and don't have a tzinfo + # We don't know which time zone we're in, and don't have a TZInfo # class to represent it, so seeing whether a tz argument actually # does a conversion is tricky. weirdtz = self.FixedOffset(self.td_class(hours=15, minutes=58), @@ -2693,7 +2698,7 @@ import time meth = self.theclass.fromtimestamp ts = time.time() - # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up). + # Ensure it doesn't require TZInfo (i.e., that this doesn't blow up). base = meth(ts) # Try with and without naming the keyword. off42 = self.FixedOffset(42, "42") @@ -2727,7 +2732,7 @@ def test_tzinfo_utcnow(self): meth = self.theclass.utcnow - # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up). + # Ensure it doesn't require TZInfo (i.e., that this doesn't blow up). base = meth() # Try with and without naming the keyword; for whatever reason, # utcnow() doesn't accept a tzinfo argument. @@ -2739,7 +2744,7 @@ import time meth = self.theclass.utcfromtimestamp ts = time.time() - # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up). + # Ensure it doesn't require TZInfo (i.e., that this doesn't blow up). base = meth(ts) # Try with and without naming the keyword; for whatever reason, # utcfromtimestamp() doesn't accept a tzinfo argument. @@ -2748,7 +2753,7 @@ self.assertRaises(TypeError, meth, ts, tzinfo=off42) def test_tzinfo_timetuple(self): - # TestDateTime tested most of this. datetime adds a twist to the + # TestDateTime tested most of this. DateTime adds a twist to the # DST flag. td_class = self.td_class class DST(self.tzi_class): @@ -2807,7 +2812,7 @@ return self.uofs # Ensure tm_isdst is 0 regardless of what dst() says: DST is never - # in effect for a UTC time. + # in effect for a UTC Time. for dstvalue in -33, 33, 0, None: d = cls(1, 2, 3, 10, 20, 30, 40, tzinfo=UOFS(-53, dstvalue)) t = d.utctimetuple() @@ -2824,7 +2829,7 @@ self.assertEqual(0, t.tm_isdst) # At the edges, UTC adjustment can normalize into years out-of-range - # for a datetime object. Ensure that a correct timetuple is + # for a DateTime object. Ensure that a correct timetuple is # created anyway. tiny = cls(MINYEAR, 1, 1, 0, 0, 37, tzinfo=UOFS(1439)) # That goes back 1 minute less than a full day. @@ -2895,7 +2900,7 @@ self.assertEqual(expected, got) i += 1 - # Ensure we can get rid of a tzinfo. + # Ensure we can get rid of a TZInfo. self.assertEqual(base.tzname(), "+100") base2 = base.replace(tzinfo=None) self.failUnless(base2.tzinfo is None) @@ -2918,23 +2923,23 @@ dt = self.theclass.now(tz=f44m) self.failUnless(dt.tzinfo is f44m) - # Replacing with degenerate tzinfo raises an exception. + # Replacing with degenerate TZInfo raises an exception. self.assertRaises(ValueError, dt.astimezone, fnone) # Ditto with None tz. self.assertRaises(TypeError, dt.astimezone, None) - # Replacing with same tzinfo makes no change. + # Replacing with same TZInfo makes no change. x = dt.astimezone(dt.tzinfo) self.failUnless(x.tzinfo is f44m) self.assertEqual(x.date(), dt.date()) self.assertEqual(x.time(), dt.time()) - # Replacing with different tzinfo does adjust. + # Replacing with different TZInfo does adjust. got = dt.astimezone(fm5h) self.failUnless(got.tzinfo is fm5h) self.assertEqual(got.utcoffset(), self.td_class(hours=-5)) expected = dt - dt.utcoffset() # in effect, convert to UTC expected += fm5h.utcoffset(dt) # and from there to local time - expected = expected.replace(tzinfo=fm5h) # and attach new tzinfo + expected = expected.replace(tzinfo=fm5h) # and attach new TZInfo self.assertEqual(got.date(), expected.date()) self.assertEqual(got.time(), expected.time()) self.assertEqual(got.timetz(), expected.timetz()) @@ -2998,7 +3003,7 @@ self.assertRaises(TypeError, lambda: t1 == t2) td_class = self.td_class - # In datetime w/ identical tzinfo objects, utcoffset is ignored. + # In DateTime w/ identical TZInfo objects, utcoffset is ignored. class Varies(self.tzi_class): def __init__(self): self.offset = td_class(minutes=22) @@ -3044,10 +3049,10 @@ self.assertEqual(dt2.newmeth(-7), dt1.hour + dt1.year - 7) class TestTimezoneConversions(unittest.TestCase): - theclass = datetime - theotherclass = date - td_class = timedelta - tzi_class = tzinfo + theclass = DateTime + theotherclass = Date + td_class = TimeDelta + tzi_class = TZInfo FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, td_class) ZERO = td_class(0) @@ -3064,7 +3069,7 @@ def __repr__(self): return self.reprname - # Pain to set up DST-aware tzinfo classes. + # Pain to set up DST-aware TZInfo classes. def first_sunday_on_or_after(self, dt): days_to_go = 6 - dt.weekday() @@ -3231,7 +3236,7 @@ self.convert_between_tz_and_utc(self.Pacific, self.Eastern) # OTOH, these fail! Don't enable them. The difficulty is that # the edge case tests assume that every hour is representable in - # the "utc" class. This is always true for a fixed-offset tzinfo + # the "utc" class. This is always true for a fixed-offset TZInfo # class (lke utc_real and utc_fake), but not for Eastern or Central. # For these adjacent DST-aware time zones, the range of time offsets # tested ends up creating hours in the one that aren't representable @@ -3312,8 +3317,8 @@ def test_fromutc(self): self.assertRaises(TypeError, self.Eastern.fromutc) # not enough args now = self.theclass.utcnow().replace(tzinfo=self.utc_real) - self.assertRaises(ValueError, self.Eastern.fromutc, now) # wrong tzinfo - now = now.replace(tzinfo=self.Eastern) # insert correct tzinfo + self.assertRaises(ValueError, self.Eastern.fromutc, now) # wrong TZInfo + now = now.replace(tzinfo=self.Eastern) # insert correct TZInfo enow = self.Eastern.fromutc(now) # doesn't blow up self.assertEqual(enow.tzinfo, self.Eastern) # has right tzinfo member # too many args @@ -3376,13 +3381,13 @@ # oddballs class Oddballs(unittest.TestCase): - date_class = date - dt_class = datetime - time_class = time + date_class = Date + dt_class = DateTime + time_class = Time def test_bug_1028306(self): - # Trying to compare a date to a datetime should act like a mixed- - # type comparison, despite that datetime is a subclass of date. + # Trying to compare a Date to a DateTime should act like a mixed- + # type comparison, despite that DateTime is a subclass of Date. as_date = self.date_class.today() as_datetime = self.dt_class.combine(as_date, self.time_class()) self.assert_(as_date != as_datetime) @@ -3398,24 +3403,162 @@ self.assertRaises(TypeError, lambda: as_date >= as_datetime) self.assertRaises(TypeError, lambda: as_datetime >= as_date) - # Neverthelss, comparison should work with the base-class (date) + # Neverthelss, comparison should work with the base-class (Date) # projection if use of a date method is forced. self.assertEqual(as_date.__eq__(as_datetime), True) different_day = (as_date.day + 1) % 20 + 1 as_different = as_datetime.replace(day= different_day) self.assertEqual(as_date.__eq__(as_different), False) - # And date should compare with other subclasses of date. If a + # And Date should compare with other subclasses of Date. If a # subclass wants to stop this, it's up to the subclass to do so. date_sc = SubclassDate(as_date.year, as_date.month, as_date.day) self.assertEqual(as_date, date_sc) self.assertEqual(date_sc, as_date) - # Ditto for datetimes. - datetime_sc = SubclassDateTime(as_datetime.year, as_datetime.month, + # Ditto for DateTimes. + datetime_sc = SubclassDatetime(as_datetime.year, as_datetime.month, as_date.day, 0, 0, 0) self.assertEqual(as_datetime, datetime_sc) self.assertEqual(datetime_sc, as_datetime) + + +# tests for deprecated classes mostly inherit +class TestTZInfo_DEPRECATE(TestTZInfo): + dt_class = datetime + td_class = timedelta + tzi_class = tzinfo + FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, + td_class) + +class TestTimeDelta_DEPRECATE(TestTimeDelta): + theclass = timedelta + +class TestDateOnly_DEPRECATE(TestDateOnly): + theclass = date + td_class = timedelta + +class SubclassDate(date): + sub_var = 1 + +class TestDate_DEPRECATE(TestDate): + theclass = date + td_class = timedelta + +class SubclassDatetime(datetime): + sub_var = 1 + +class TestDateTime_DEPRECATE(TestDateTime): + theclass = datetime + date_class = date + td_class = timedelta + tzi_class = tzinfo + time_class = time + FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, + td_class) + +class SubclassTime(time): + sub_var = 1 + +class TestTime_DEPRECATE(TestTime): + theclass = time + td_class = timedelta + +class TZInfoBase_DEPRECATE(TZInfoBase): + dt_class = datetime + td_class = timedelta + tzi_class = tzinfo + time_class = time + +class TestTimeTZ_DEPRECATE(TZInfoBase_DEPRECATE, TestTimeTZ): + theclass = time + td_class = timedelta + tzi_class = tzinfo + FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, + td_class) + +class TestDateTimeTZ_DEPRECATE(TZInfoBase_DEPRECATE, TestDateTimeTZ): + theclass = datetime + date_class = date + td_class = timedelta + tzi_class = tzinfo + time_class = time + FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, + td_class) + +class TestTimezoneConversions_DEPRECATE(TestTimezoneConversions): + theclass = datetime + theotherclass = date + td_class = timedelta + tzi_class = tzinfo + FixedOffset, PicklableFixedOffset = fixedoffset_factory(tzi_class, + td_class) + + ZERO = td_class(0) + HOUR = td_class(hours=1) + DAY = td_class(days=1) + + # In the US, DST starts at 2am (standard time) on the first Sunday in + # April. + TestTimezoneConversions.USTimeZone.DSTSTART = theclass(1, 4, 1, 2) + # and ends at 2am (DST time; 1am standard time) on the last Sunday of + # Oct, which is the first Sunday on or after Oct 25. Because we view + # 1:MM as being standard time on that day, there is no spelling in + # local time of the last hour of DST (that's 1:MM DST, but 1:MM is + # taken as standard time). + TestTimezoneConversions.USTimeZone.DSTEND = theclass(1, 10, 25, 1) + TestTimezoneConversions.USTimeZone.HOUR = HOUR + TestTimezoneConversions.USTimeZone.ZERO = ZERO + + TestTimezoneConversions.USTimeZone.td_class = td_class + Eastern = TestTimezoneConversions.USTimeZone(-5, "Eastern", "EST", "EDT") + Central = TestTimezoneConversions.USTimeZone(-6, "Central", "CST", "CDT") + Mountain = TestTimezoneConversions.USTimeZone(-7, "Mountain", "MST", "MDT") + Pacific = TestTimezoneConversions.USTimeZone(-8, "Pacific", "PST", "PDT") + utc_real = FixedOffset(0, "UTC", 0) + # For better test coverage, we want another flavor of UTC that's west of + # the Eastern and Pacific timezones. + utc_fake = FixedOffset(-12*60, "UTCfake", 0) + + # The DST switch times for 2002, in std time. + dston = theclass(2002, 4, 7, 2) + dstoff = theclass(2002, 10, 27, 1) + +class Oddballs_DEPRECATE(Oddballs): + date_class = date + dt_class = datetime + time_class = time + +class TestDeprecation_DEPRECATE(unittest.TestCase): + def test_pending(self): + from warnings import simplefilter, catch_warnings + count = 0 + with catch_warnings(record=True) as w: + simplefilter("always") + + d = date(2008,3,12) + self.assert_(len(w) > count); count = len(w) + dt = datetime(2008,3,12,12,30) + self.assert_(len(w) > count); count = len(w) + t = time(6,45,30) + self.assert_(len(w) > count); count = len(w) + td = timedelta(3) + self.assert_(len(w) > count); count = len(w) + td + td + self.assert_(len(w) > count); count = len(w) + d + td + self.assert_(len(w) > count); count = len(w) + td + d + self.assert_(len(w) > count); count = len(w) + dt + td + self.assert_(len(w) > count); count = len(w) + td + dt + self.assert_(len(w) > count); count = len(w) + datetime.combine(d, t) + self.assert_(len(w) > count); count = len(w) + + for warning in w: + self.assert_(warning.category is PendingDeprecationWarning) def test_main(): diff -r 5c09070b339b Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/test/test_inspect.py Fri Mar 20 21:59:49 2009 -0500 @@ -90,9 +90,9 @@ else: self.failIf(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals)) if hasattr(types, 'MemberDescriptorType'): - self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days') + self.istest(inspect.ismemberdescriptor, 'datetime.TimeDelta.days') else: - self.failIf(inspect.ismemberdescriptor(datetime.timedelta.days)) + self.failIf(inspect.ismemberdescriptor(datetime.TimeDelta.days)) def test_isroutine(self): self.assert_(inspect.isroutine(mod.spam)) diff -r 5c09070b339b Lib/test/test_plistlib.py --- a/Lib/test/test_plistlib.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/test/test_plistlib.py Fri Mar 20 21:59:49 2009 -0500 @@ -111,7 +111,7 @@ someData = plistlib.Data(b""), someMoreData = plistlib.Data(b"\0\1\2\3" * 10), nestedData = [plistlib.Data(b"\0\1\2\3" * 10)], - aDate = datetime.datetime(2004, 10, 26, 10, 33, 33), + aDate = datetime.DateTime(2004, 10, 26, 10, 33, 33), ) pl['\xc5benraa'] = "That was a unicode key." return pl diff -r 5c09070b339b Lib/test/test_strptime.py --- a/Lib/test/test_strptime.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/test/test_strptime.py Fri Mar 20 21:59:49 2009 -0500 @@ -6,7 +6,7 @@ import re import sys from test import support -from datetime import date as datetime_date +from datetime import Date as datetime_date import _strptime @@ -275,7 +275,7 @@ def test_fraction(self): import datetime - now = datetime.datetime.now() + now = datetime.DateTime.now() tup, frac = _strptime._strptime(str(now), format="%Y-%m-%d %H:%M:%S.%f") self.assertEqual(frac, now.microsecond) diff -r 5c09070b339b Lib/test/test_sys.py --- a/Lib/test/test_sys.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/test/test_sys.py Fri Mar 20 21:59:49 2009 -0500 @@ -522,7 +522,7 @@ # XXX # member_descriptor (descriptor object) import datetime - check(datetime.timedelta.days, size(h + '2PP')) + check(datetime.TimeDelta.days, size(h + '2PP')) # getset_descriptor (descriptor object) import collections check(collections.defaultdict.default_factory, size(h + '2PP')) diff -r 5c09070b339b Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/test/test_unicode.py Fri Mar 20 21:59:49 2009 -0500 @@ -482,7 +482,7 @@ self.assertEqual("My name is {0} :-{{}}".format('Fred'), "My name is Fred :-{}") - d = datetime.date(2007, 8, 18) + d = datetime.Date(2007, 8, 18) self.assertEqual("The year is {0.year}".format(d), "The year is 2007") @@ -529,7 +529,7 @@ def __format__(self, format_spec): return 1.0 - class I(datetime.date): + class I(datetime.Date): def __format__(self, format_spec): return self.strftime(format_spec) diff -r 5c09070b339b Lib/test/test_xmlrpc.py --- a/Lib/test/test_xmlrpc.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/test/test_xmlrpc.py Fri Mar 20 21:59:49 2009 -0500 @@ -24,7 +24,7 @@ 'datetime2': xmlrpclib.DateTime( (2005, 2, 10, 11, 41, 23, 0, 1, -1)), 'datetime3': xmlrpclib.DateTime( - datetime.datetime(2005, 2, 10, 11, 41, 23)), + datetime.DateTime(2005, 2, 10, 11, 41, 23)), }] class XMLRPCTestCase(unittest.TestCase): @@ -35,11 +35,11 @@ self.assertEquals(alist, load[0][0]) def test_dump_bare_datetime(self): - # This checks that an unwrapped datetime.date object can be handled + # This checks that an unwrapped datetime.Date object can be handled # by the marshalling code. This can't be done via test_dump_load() # since with use_datetime set to 1 the unmarshaller would create - # datetime objects for the 'datetime[123]' keys as well - dt = datetime.datetime(2005, 2, 10, 11, 41, 23) + # DateTime objects for the 'DateTime[123]' keys as well + dt = datetime.DateTime(2005, 2, 10, 11, 41, 23) s = xmlrpclib.dumps((dt,)) (newdt,), m = xmlrpclib.loads(s, use_datetime=1) self.assertEquals(newdt, dt) @@ -50,7 +50,7 @@ def test_datetime_before_1900(self): # same as before but with a date before 1900 - dt = datetime.datetime(1, 2, 10, 11, 41, 23) + dt = datetime.DateTime(1, 2, 10, 11, 41, 23) s = xmlrpclib.dumps((dt,)) (newdt,), m = xmlrpclib.loads(s, use_datetime=1) self.assertEquals(newdt, dt) @@ -60,11 +60,11 @@ self.assertEquals(newdt, xmlrpclib.DateTime('00010210T11:41:23')) def test_cmp_datetime_DateTime(self): - now = datetime.datetime.now() + now = datetime.DateTime.now() dt = xmlrpclib.DateTime(now.timetuple()) self.assert_(dt == now) self.assert_(now == dt) - then = now + datetime.timedelta(seconds=4) + then = now + datetime.TimeDelta(seconds=4) self.assert_(then >= dt) self.assert_(dt < then) @@ -193,12 +193,12 @@ self.assertEqual(str(t), time.strftime("%Y%m%dT%H:%M:%S", d)) def test_datetime_datetime(self): - d = datetime.datetime(2007,1,2,3,4,5) + d = datetime.DateTime(2007,1,2,3,4,5) t = xmlrpclib.DateTime(d) self.assertEqual(str(t), '20070102T03:04:05') def test_repr(self): - d = datetime.datetime(2007,1,2,3,4,5) + d = datetime.DateTime(2007,1,2,3,4,5) t = xmlrpclib.DateTime(d) val ="" % id(t) self.assertEqual(repr(t), val) @@ -207,7 +207,7 @@ d = ' 20070908T07:11:13 ' t1 = xmlrpclib.DateTime() t1.decode(d) - tref = xmlrpclib.DateTime(datetime.datetime(2007,9,8,7,11,13)) + tref = xmlrpclib.DateTime(datetime.DateTime(2007,9,8,7,11,13)) self.assertEqual(t1, tref) t2 = xmlrpclib._datetime(d) diff -r 5c09070b339b Lib/xmlrpc/client.py --- a/Lib/xmlrpc/client.py Fri Mar 20 21:55:15 2009 -0500 +++ b/Lib/xmlrpc/client.py Fri Mar 20 21:59:49 2009 -0500 @@ -277,7 +277,7 @@ def _strftime(value): if datetime: - if isinstance(value, datetime.datetime): + if isinstance(value, datetime.DateTime): return "%04d%02d%02dT%02d:%02d:%02d" % ( value.year, value.month, value.day, value.hour, value.minute, value.second) @@ -305,7 +305,7 @@ if isinstance(other, DateTime): s = self.value o = other.value - elif datetime and isinstance(other, datetime.datetime): + elif datetime and isinstance(other, datetime.DateTime): s = self.value o = other.strftime("%Y%m%dT%H:%M:%S") elif isinstance(other, (str, unicode)): @@ -376,7 +376,7 @@ def _datetime_type(data): t = time.strptime(data, "%Y%m%dT%H:%M:%S") - return datetime.datetime(*tuple(t)[:6]) + return datetime.DateTime(*tuple(t)[:6]) ## # Wrapper for binary data. This can be used to transport any kind @@ -677,7 +677,7 @@ write("") write(_strftime(value)) write("\n") - dispatch[datetime.datetime] = dump_datetime + dispatch[datetime.DateTime] = dump_datetime def dump_instance(self, value, write): # check for special wrappers diff -r 5c09070b339b Modules/datetimemodule.c --- a/Modules/datetimemodule.c Fri Mar 20 21:55:15 2009 -0500 +++ b/Modules/datetimemodule.c Fri Mar 20 21:59:49 2009 -0500 @@ -2131,7 +2131,7 @@ static PyTypeObject PyDateTime_DeltaType = { PyVarObject_HEAD_INIT(NULL, 0) - "datetime.timedelta", /* tp_name */ + "datetime.TimeDelta", /* tp_name */ sizeof(PyDateTime_Delta), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ @@ -2685,7 +2685,7 @@ }; static char date_doc[] = -PyDoc_STR("date(year, month, day) --> date object"); +PyDoc_STR("Date(year, month, day) --> Date object"); static PyNumberMethods date_as_number = { date_add, /* nb_add */ @@ -2702,7 +2702,7 @@ static PyTypeObject PyDateTime_DateType = { PyVarObject_HEAD_INIT(NULL, 0) - "datetime.date", /* tp_name */ + "datetime.Date", /* tp_name */ sizeof(PyDateTime_Date), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ @@ -2933,17 +2933,17 @@ static PyMethodDef tzinfo_methods[] = { {"tzname", (PyCFunction)tzinfo_tzname, METH_O, - PyDoc_STR("datetime -> string name of time zone.")}, + PyDoc_STR("Datetime -> string name of time zone.")}, {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O, - PyDoc_STR("datetime -> minutes east of UTC (negative for " + PyDoc_STR("Datetime -> minutes east of UTC (negative for " "west of UTC).")}, {"dst", (PyCFunction)tzinfo_dst, METH_O, - PyDoc_STR("datetime -> DST offset in minutes east of UTC.")}, + PyDoc_STR("Datetime -> DST offset in minutes east of UTC.")}, {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O, - PyDoc_STR("datetime in UTC -> datetime in local time.")}, + PyDoc_STR("Datetime in UTC -> datetime in local time.")}, {"__reduce__", (PyCFunction)tzinfo_reduce, METH_NOARGS, PyDoc_STR("-> (cls, state)")}, @@ -2956,7 +2956,7 @@ static PyTypeObject PyDateTime_TZInfoType = { PyVarObject_HEAD_INIT(NULL, 0) - "datetime.tzinfo", /* tp_name */ + "datetime.TZInfo", /* tp_name */ sizeof(PyDateTime_TZInfo), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ @@ -3451,7 +3451,7 @@ }; static char time_doc[] = -PyDoc_STR("time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) --> a time object\n\ +PyDoc_STR("Time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) --> a Time object\n\ \n\ All arguments are optional. tzinfo may be None, or an instance of\n\ a tzinfo subclass. The remaining arguments may be ints or longs.\n"); @@ -3471,7 +3471,7 @@ static PyTypeObject PyDateTime_TimeType = { PyVarObject_HEAD_INIT(NULL, 0) - "datetime.time", /* tp_name */ + "datetime.Time", /* tp_name */ sizeof(PyDateTime_Time), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)time_dealloc, /* tp_dealloc */ @@ -4507,11 +4507,11 @@ {"now", (PyCFunction)datetime_now, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - PyDoc_STR("[tz] -> new datetime with tz's local day and time.")}, + PyDoc_STR("[tz] -> new DateTime with tz's local day and time.")}, {"utcnow", (PyCFunction)datetime_utcnow, METH_NOARGS | METH_CLASS, - PyDoc_STR("Return a new datetime representing UTC day and time.")}, + PyDoc_STR("Return a new DateTime representing UTC day and time.")}, {"fromtimestamp", (PyCFunction)datetime_fromtimestamp, METH_VARARGS | METH_KEYWORDS | METH_CLASS, @@ -4519,28 +4519,28 @@ {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp, METH_VARARGS | METH_CLASS, - PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp " + PyDoc_STR("timestamp -> UTC DateTime from a POSIX timestamp " "(like time.time()).")}, {"strptime", (PyCFunction)datetime_strptime, METH_VARARGS | METH_CLASS, - PyDoc_STR("string, format -> new datetime parsed from a string " + PyDoc_STR("string, format -> new DateTime parsed from a string " "(like time.strptime()).")}, {"combine", (PyCFunction)datetime_combine, METH_VARARGS | METH_KEYWORDS | METH_CLASS, - PyDoc_STR("date, time -> datetime with same date and time fields")}, + PyDoc_STR("Date, Time -> DateTime with same date and time fields")}, /* Instance methods: */ {"date", (PyCFunction)datetime_getdate, METH_NOARGS, - PyDoc_STR("Return date object with same year, month and day.")}, + PyDoc_STR("Return Date object with same year, month and day.")}, {"time", (PyCFunction)datetime_gettime, METH_NOARGS, - PyDoc_STR("Return time object with same time but with tzinfo=None.")}, + PyDoc_STR("Return Time object with same time but with tzinfo=None.")}, {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS, - PyDoc_STR("Return time object with same time and tzinfo.")}, + PyDoc_STR("Return Time object with same time and tzinfo.")}, {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS, PyDoc_STR("Return ctime() style string.")}, @@ -4567,7 +4567,7 @@ PyDoc_STR("Return self.tzinfo.dst(self).")}, {"replace", (PyCFunction)datetime_replace, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("Return datetime with new specified fields.")}, + PyDoc_STR("Return DateTime with new specified fields.")}, {"astimezone", (PyCFunction)datetime_astimezone, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("tz -> convert to local time in new timezone tz\n")}, @@ -4579,7 +4579,7 @@ }; static char datetime_doc[] = -PyDoc_STR("datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\ +PyDoc_STR("DateTime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\ \n\ The year, month and day arguments are required. tzinfo may be None, or an\n\ instance of a tzinfo subclass. The remaining arguments may be ints or longs.\n"); @@ -4599,7 +4599,7 @@ static PyTypeObject PyDateTime_DateTimeType = { PyVarObject_HEAD_INIT(NULL, 0) - "datetime.datetime", /* tp_name */ + "datetime.DateTime", /* tp_name */ sizeof(PyDateTime_DateTime), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)datetime_dealloc, /* tp_dealloc */ @@ -4640,6 +4640,176 @@ }; /* --------------------------------------------------------------------------- + * Pending deprecations for PEP 8 compliance. + */ + +/* forward declarations */ +static PyTypeObject PyDateTime_DateType_DEPRECATE; +static PyTypeObject PyDateTime_DateTimeType_DEPRECATE; +static PyTypeObject PyDateTime_DeltaType_DEPRECATE; +static PyTypeObject PyDateTime_TimeType_DEPRECATE; +static PyTypeObject PyDateTime_TZInfoType_DEPRECATE; + +/* function-definition helper macro - first variation for _new functions */ +#define FUNC_DEPRECATE(func, old, new) \ +static PyObject *\ +func ## _DEPRECATE(PyTypeObject *type, PyObject *args, PyObject *kw) {\ + PyObject *retval = func(type, args, kw);\ + PyErr_WarnEx(PyExc_PendingDeprecationWarning,\ + "Please use " #new " instead of " #old, 1);\ + return retval;\ +} + +/* define deprecated functions in terms of permanent functions */ +FUNC_DEPRECATE(date_new, date, Date) +FUNC_DEPRECATE(datetime_new, datetime, DateTime) +FUNC_DEPRECATE(time_new, time, Time) +FUNC_DEPRECATE(delta_new, timedelta, TimeDelta) +FUNC_DEPRECATE(PyType_GenericNew, tzinfo, TZInfo) + +/* function-definition helper macro - second variation for binary functions */ +#undef FUNC_DEPRECATE +#define FUNC_DEPRECATE(func, old, new, obj, alt) \ +static PyObject *\ +func ## _DEPRECATE(PyObject *left, PyObject *right) {\ + PyObject *retval = func(left, right);\ + if (retval) {\ + if (alt && !PyDate_Check(retval))\ + retval->ob_type = alt;\ + else\ + retval->ob_type = obj;\ + }\ + PyErr_WarnEx(PyExc_PendingDeprecationWarning,\ + "Please use " #new " instead of " #old, 1);\ + return retval;\ +} + +FUNC_DEPRECATE(date_add, date, Date, &PyDateTime_DateType_DEPRECATE, 0) +FUNC_DEPRECATE(date_subtract, date, Date, &PyDateTime_DateType_DEPRECATE, + &PyDateTime_DeltaType_DEPRECATE) + +FUNC_DEPRECATE(datetime_add, datetime, DateTime, + &PyDateTime_DateTimeType_DEPRECATE, 0) +FUNC_DEPRECATE(datetime_subtract, datetime, DateTime, + &PyDateTime_DateTimeType_DEPRECATE, + &PyDateTime_DeltaType_DEPRECATE) + +FUNC_DEPRECATE(delta_add, timedelta, TimeDelta, + &PyDateTime_DeltaType_DEPRECATE, 0) +FUNC_DEPRECATE(delta_subtract, timedelta, TimeDelta, + &PyDateTime_DeltaType_DEPRECATE, 0) +FUNC_DEPRECATE(delta_multiply, timedelta, TimeDelta, + &PyDateTime_DeltaType_DEPRECATE, 0) +FUNC_DEPRECATE(delta_divide, timedelta, TimeDelta, + &PyDateTime_DeltaType_DEPRECATE, 0) + +/* function-definition helper macro - third variation for unary functions */ +#undef FUNC_DEPRECATE +#define FUNC_DEPRECATE(func, old, new, obj) \ +static PyObject *\ +func ## _DEPRECATE(PyObject *self) {\ + PyObject *retval = func((PyDateTime_Delta *)self);\ + if (retval)\ + retval->ob_type = obj;\ + PyErr_WarnEx(PyExc_PendingDeprecationWarning,\ + "Please use " #new " instead of " #old, 1);\ + return retval;\ +} + +FUNC_DEPRECATE(delta_negative, timedelta, TimeDelta, + &PyDateTime_DeltaType_DEPRECATE) +FUNC_DEPRECATE(delta_positive, timedelta, TimeDelta, + &PyDateTime_DeltaType_DEPRECATE) +FUNC_DEPRECATE(delta_abs, timedelta, TimeDelta, + &PyDateTime_DeltaType_DEPRECATE) + +#undef FUNC_DEPRECATE + +static PyNumberMethods date_as_number_DEPRECATE = { + date_add_DEPRECATE, /* nb_add */ + date_subtract_DEPRECATE, /* nb_subtract */ +}; + +static PyNumberMethods datetime_as_number_DEPRECATE = { + datetime_add_DEPRECATE, /* nb_add */ + datetime_subtract_DEPRECATE, /* nb_subtract */ +}; + +static PyNumberMethods delta_as_number_DEPRECATE = { + delta_add_DEPRECATE, /* nb_add */ + delta_subtract_DEPRECATE, /* nb_subtract */ + delta_multiply_DEPRECATE, /* nb_multiply */ + 0, /* nb_remainder */ + 0, /* nb_divmod */ + 0, /* nb_power */ + (unaryfunc)delta_negative_DEPRECATE, /* nb_negative */ + (unaryfunc)delta_positive_DEPRECATE, /* nb_positive */ + (unaryfunc)delta_abs_DEPRECATE, /* nb_absolute */ + 0, /* nb_bool */ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + 0, /*nb_int*/ + 0, /*nb_reserved*/ + 0, /*nb_float*/ + 0, /*nb_inplace_add*/ + 0, /*nb_inplace_subtract*/ + 0, /*nb_inplace_multiply*/ + 0, /*nb_inplace_remainder*/ + 0, /*nb_inplace_power*/ + 0, /*nb_inplace_lshift*/ + 0, /*nb_inplace_rshift*/ + 0, /*nb_inplace_and*/ + 0, /*nb_inplace_xor*/ + 0, /*nb_inplace_or*/ + delta_divide_DEPRECATE, /* nb_floor_divide */ + 0, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ +}; + +static char date_doc_DEPRECATE[] = +PyDoc_STR("Please use the Date class instead of date\n"); +static char datetime_doc_DEPRECATE[] = +PyDoc_STR("Please use the DateTime class instead of datetime\n"); +static char time_doc_DEPRECATE[] = +PyDoc_STR("Please use the Time class instead of time\n"); +static char timedelta_doc_DEPRECATE[] = +PyDoc_STR("Please use the TimeDelta class instead of timedelta\n"); +static char tzinfo_doc_DEPRECATE[] = +PyDoc_STR("Please use the TZInfo class instead of tzinfo\n"); + +/* type-definition helper macro */ +#define TYPE_DEPRECATE(base, dep_name, new_func, number)\ +static PyTypeObject \ +base ## _DEPRECATE = {\ + PyVarObject_HEAD_INIT(NULL, 0)\ + "datetime." #dep_name, /* tp_name */\ + 0, 0, 0, 0, 0, 0, 0, 0,\ + number, /* tp_as_number */\ + 0, 0, 0, 0, 0, 0, 0, 0,\ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\ + dep_name ## _doc_DEPRECATE, /* tp_doc */\ + 0, 0, 0, 0, 0, 0, 0, 0, 0,\ + & base, /* tp_base */\ + 0, 0, 0, 0, 0, 0,\ + new_func, /* tp_new */\ + 0,\ +}; + +TYPE_DEPRECATE(PyDateTime_DateType, date, date_new_DEPRECATE, + &date_as_number_DEPRECATE) +TYPE_DEPRECATE(PyDateTime_DateTimeType, datetime, datetime_new_DEPRECATE, + &datetime_as_number_DEPRECATE) +TYPE_DEPRECATE(PyDateTime_TimeType, time, time_new_DEPRECATE, 0) +TYPE_DEPRECATE(PyDateTime_DeltaType, timedelta, delta_new_DEPRECATE, + &delta_as_number_DEPRECATE) +TYPE_DEPRECATE(PyDateTime_TZInfoType, tzinfo, PyType_GenericNew_DEPRECATE, 0) + +/* --------------------------------------------------------------------------- * Module methods and initialization. */ @@ -4700,6 +4870,18 @@ if (PyType_Ready(&PyDateTime_TZInfoType) < 0) return NULL; + /* DEPRECATED */ + if (PyType_Ready(&PyDateTime_DateType_DEPRECATE) < 0) + return NULL; + if (PyType_Ready(&PyDateTime_DateTimeType_DEPRECATE) < 0) + return NULL; + if (PyType_Ready(&PyDateTime_DeltaType_DEPRECATE) < 0) + return NULL; + if (PyType_Ready(&PyDateTime_TimeType_DEPRECATE) < 0) + return NULL; + if (PyType_Ready(&PyDateTime_TZInfoType_DEPRECATE) < 0) + return NULL; + /* timedelta values */ d = PyDateTime_DeltaType.tp_dict; @@ -4768,6 +4950,84 @@ Py_DECREF(x); x = new_delta(0, 0, 1, 0); + if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) + return NULL; + Py_DECREF(x); + + /* DEPRECATED */ + /* timedelta values */ + d = PyDateTime_DeltaType.tp_dict; + + x = new_delta_ex(0, 0, 1, 0, &PyDateTime_DeltaType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) + return NULL; + Py_DECREF(x); + + x = new_delta_ex(-MAX_DELTA_DAYS, 0, 0, 0, + &PyDateTime_DeltaType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) + return NULL; + Py_DECREF(x); + + x = new_delta_ex(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0, + &PyDateTime_DeltaType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) + return NULL; + Py_DECREF(x); + + /* date values */ + d = PyDateTime_DateType_DEPRECATE.tp_dict; + + x = new_date_ex(1, 1, 1, &PyDateTime_DateType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) + return NULL; + Py_DECREF(x); + + x = new_date_ex(MAXYEAR, 12, 31, &PyDateTime_DateType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) + return NULL; + Py_DECREF(x); + + x = new_delta_ex(1, 0, 0, 0, &PyDateTime_DeltaType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) + return NULL; + Py_DECREF(x); + + /* time values */ + d = PyDateTime_TimeType_DEPRECATE.tp_dict; + + x = new_time_ex(0, 0, 0, 0, Py_None, &PyDateTime_TimeType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) + return NULL; + Py_DECREF(x); + + x = new_time_ex(23, 59, 59, 999999, Py_None, + &PyDateTime_TimeType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) + return NULL; + Py_DECREF(x); + + x = new_delta_ex(0, 0, 1, 0, &PyDateTime_DeltaType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) + return NULL; + Py_DECREF(x); + + /* datetime values */ + d = PyDateTime_DateTimeType_DEPRECATE.tp_dict; + + x = new_datetime_ex(1, 1, 1, 0, 0, 0, 0, Py_None, + &PyDateTime_DateTimeType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) + return NULL; + Py_DECREF(x); + + x = new_datetime_ex(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None, + &PyDateTime_DateTimeType_DEPRECATE); + if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) + return NULL; + Py_DECREF(x); + + x = new_delta_ex(0, 0, 1, 0, &PyDateTime_DeltaType_DEPRECATE); if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) return NULL; Py_DECREF(x); @@ -4777,20 +5037,42 @@ PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR); Py_INCREF(&PyDateTime_DateType); - PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType); + PyModule_AddObject(m, "Date", (PyObject *) &PyDateTime_DateType); Py_INCREF(&PyDateTime_DateTimeType); + PyModule_AddObject(m, "DateTime", + (PyObject *)&PyDateTime_DateTimeType); + + Py_INCREF(&PyDateTime_TimeType); + PyModule_AddObject(m, "Time", (PyObject *) &PyDateTime_TimeType); + + Py_INCREF(&PyDateTime_DeltaType); + PyModule_AddObject(m, "TimeDelta", + (PyObject *) &PyDateTime_DeltaType); + + Py_INCREF(&PyDateTime_TZInfoType); + PyModule_AddObject(m, "TZInfo", (PyObject *) &PyDateTime_TZInfoType); + + /* DEPRECATED */ + Py_INCREF(&PyDateTime_DateType_DEPRECATE); + PyModule_AddObject(m, "date", + (PyObject *) &PyDateTime_DateType_DEPRECATE); + + Py_INCREF(&PyDateTime_DateTimeType_DEPRECATE); PyModule_AddObject(m, "datetime", - (PyObject *)&PyDateTime_DateTimeType); - - Py_INCREF(&PyDateTime_TimeType); - PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType); - - Py_INCREF(&PyDateTime_DeltaType); - PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType); - - Py_INCREF(&PyDateTime_TZInfoType); - PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType); + (PyObject *)&PyDateTime_DateTimeType_DEPRECATE); + + Py_INCREF(&PyDateTime_TimeType_DEPRECATE); + PyModule_AddObject(m, "time", + (PyObject *) &PyDateTime_TimeType_DEPRECATE); + + Py_INCREF(&PyDateTime_DeltaType_DEPRECATE); + PyModule_AddObject(m, "timedelta", + (PyObject *) &PyDateTime_DeltaType_DEPRECATE); + + Py_INCREF(&PyDateTime_TZInfoType_DEPRECATE); + PyModule_AddObject(m, "tzinfo", + (PyObject *) &PyDateTime_TZInfoType_DEPRECATE); x = PyCObject_FromVoidPtrAndDesc(&CAPI, (void*) DATETIME_API_MAGIC, NULL);