sub-classing the types in the builtin module datetime

attn.steven.kuo at gmail.com attn.steven.kuo at gmail.com
Thu Aug 16 21:58:49 CEST 2007


On Aug 15, 5:54 pm, "Colin J. Williams" <c... at sympatico.ca> wrote:
> I posted this about 5 hours ago, but it seems to have gone astray.


(snipped)

>  >
>  >> I wish to sub-class (if that's the right word) datetime and to use a
>  >> different signature for the constructor.
>  >>
>  >> The second part has gone smoothly, but it is difficult to access the
>  >> type's methods from the sub-class instance.
>  >>
>  >> I'm beginning to wonder whether it might might be simpler to write my
>  >> own Date class.
>  >>
>  >> Does anyone have any comments please?
>  >>
>  >> Colin W.

(snipped)


> Yes, I should have posted an example, but I thought that others might
> have experienced the problem.
>
> It is illustrated at the bottom of this script:
>
> # subClassing.py
>
> import datetime
> import new
> import sys
> import types
>
> class Date(datetime.datetime):
>    ''' Date(s) -> a date object.__class__
>          where s is an 8 digit string'''
>
>    def __new__(cls, YYmmdd):
>      ''' YYmmdd is a string, in the form yyyymmdd i.e. 8 digits.
>      or            a 3-tuple of integers in the form (y, m, d)
>      or            a 6-tuple of integers in the form (y, m, d, h, m,
> s) '''


(snipped)

>
> a= datetime.datetime(2007, 7, 31)
> d= Date('20070731')
> tm= datetime.time(1, 2)
> try:
>    print a.today()
> #  print d.today()        # grief
>    print a.now()
> #  print d.now()          # grief
>    print a.combine(a, tm)  # OK, but  why not a.combine(tm)?
> #  e= d.combine(d, tm)    # grief
>    print a.utcnow()
> #  print d.utcnow()       # grief
>    print a.ctime()
>    print d.ctime()
> except:
>    print 'Grief'
>    print sys.exc_info()
>
> Colin W.





This problem arises when you change the function signature of __new__.
I'm a little unclear as to why but it seems for the classmethods
(thosed marked with the METH_CLASS flag in the C source code), you
need to arrange to bypass the normal method resolution (I used a
metaclass
to do this):



import datetime

class Date(datetime.datetime):
    pass

class FixClassMethods(type):
    def __init__(cls, classname, bases, classdict):
        # add strptime if using Python 2.5
        flagged_as_meth_class = ('today', 'now', 'fromtimestamp',
        'fromordinal', 'now', 'utcnow', 'utcfromtimestamp', 'combine')
        for meth in flagged_as_meth_class:
            setattr(cls, meth, getattr(datetime.datetime, meth))

class DateChangesNewSignature(datetime.datetime):
    @staticmethod
    def str2ymd(strval):
        yyyy, mm, dd = (int(substr) for substr in (strval[:4],
            strval[4:6], strval[6:]))
        return yyyy, mm, dd

    def __new__(cls, strval):
        yyyy, mm, dd = DateChangesNewSignature.str2ymd(strval)
        return super(DateChangesNewSignature,cls).__new__(cls, yyyy,
mm,
                dd)
    def __init__(self, strval):
        yyyy, mm, dd = DateChangesNewSignature.str2ymd(strval)
        super(DateChangesNewSignature, self).__init__(yyyy, mm,
                dd)

class DLast(DateChangesNewSignature):
    __metaclass__ = FixClassMethods

f = Date(2007,07,07)
print f
print f.today()

f2 = DateChangesNewSignature("20070707")
print f2
try:
    print f2.today()
except TypeError, e:
    print str(e)
    print "Uh?"


f3 = DLast("20070707")
print f3
print f3.today()


I get:

2007-07-07 00:00:00
2007-08-16 12:57:41.480679
2007-07-07 00:00:00
__new__() takes exactly 2 arguments (9 given)
Uh?
2007-07-07 00:00:00
2007-08-16 12:57:41.483104


--
Hope this helps,
Steven




More information about the Python-list mailing list