More puzzling behavior while subclassing datetime

Peter Otten __peter__ at web.de
Thu Nov 16 09:34:11 CET 2006


insyte at gmail.com wrote:

> With assistance from Gabriel and Frederik (and a few old threads in
> c.l.p.) I've been making headway on my specialized datetime class.  Now
> I'm puzzled by behavior I didn't expect while attempting to use some of
> the alternate datetime constructors.  Specifically, it appears if I
> call GeneralizedTime.now() it calls the __new__ method of my class but
> treats keyword arguments as if they were positional.
> 
> My class:
> 
> class GeneralizedTime(datetime):
>     def __new__(cls, time=None, *args, **kwargs):
>         print time, args, kwargs
>         if isinstance(time, str):
>             timeValues, tzOffset = cls.stringToTimeTuple(time)
>             return datetime.__new__(cls, tzinfo=GenericTZ(tzOffset),
> **timeValues)
>         elif isinstance(time, datetime):
>             timeValues = time.timetuple()[:6]
>             tzOffset = time.utcoffset()
>             return datetime.__new__(cls, tzinfo=GenericTZ(tzOffset),
> *timeValues)
>         elif time is None:
>             print "Still gotta figure out now to do this one..."
>         else:
>             raise Invalidtime(time)
>     @staticmethod
>     def stringToTimeTuple(timeString):
>          ... regex that parses timeString ...
> 
>>>> GeneralizedTime.today()
> 2006 (11, 16, 0, 35, 18, 747275, None) {}
> Traceback (most recent call last):
>    File "<stdin>", line 1, in ?
>    File "gentime.py", line 106, in __new__
>      raise InvalidTime(time)
> gentime.InvalidTime: 2006
> 
> So it appears the time tuple is being passed to
> GeneralizedTime.__new__, but the first value is being assigned to the
> "time" argument.
> 
> Is this a side effect of how datetime is implemented?  

Yes. Consider:

>>> def today(time=None, *args):
...     print "time = ", time, "args = ", args
...
>>> today(2006, 11, 16)
time =  2006 args =  (11, 16)

To fix the issue you'll probably have to remove the time=None parameter from
GeneralizedTime.__new__() and instead extract it from args or kwargs.

Peter




More information about the Python-list mailing list