More puzzling behavior while subclassing datetime

I

insyte

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 ...
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? Or am I doing
something screwy?

Thanks!

-Ben
 
W

wittempj

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):
datetime.datetime() takes these arguments: year, month, day[, hour[,
minute[, second[, microsecond[, tzinfo]]]]]), see
http://docs.python.org/lib/datetime-datetime.html
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]
time.timetuple() does not exist, see
http://docs.python.org/lib/module-time.html, time is represented as a
tuple. checkout time.mktime() on how to convert to a tuple to a time
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 ...

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? Or am I doing
something screwy?

Thanks!

-Ben

A very cutback part of your code gets the basics working:
from datetime import datetime
class Invalidtime(Exception):
pass

class GeneralizedTime(datetime):
def __new__(cls, *args, **kwargs):
if isinstance(args, tuple):
return datetime.__new__(cls, *args)
else:
raise Invalidtime(args)

t = GeneralizedTime.today()
print t.year
print t.month
print t.day
print t.hour
print t.minute
print t.second
print t.microsecond
print t.tzinfo
 
P

Peter Otten

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 ...
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:
.... print "time = ", time, "args = ", args
....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
 
I

insyte

Yes. Consider:
... print "time = ", time, "args = ", args
...
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.

D'oh. That *should* have been obvious.

I am now no longer allowed to program after midnight.

Thanks!

-Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top