Carl Banks wrote:
On Dec 10, 5:26 pm, Ethan Furman <[EMAIL PROTECTED]> wrote:

Greetings List!

I'm writing a wrapper to the datetime.date module to support having no
date.  Its intended use is to hold a date value from a dbf file, which
can be empty.

The class is functional at this point, but there is one thing I would
like to change -- datetime.date.max and datetime.date.min are class
attributes of datetime.date, and hold datetime.date values.  At this
point I have to have two lines outside the actual class definition to do
the same thing, e.g.:

<trimmed down class code>
  class NullDate(object):
      "adds null capable DateTime.Date constructs"
      __slots__ = ['_date']
      def __new__(cls, date='', month=0, day=0):
          nulldate = object.__new__(cls)
          nulldate._date = ""
               .
               .
               .
         return nulldate
<snip>
  NullDate.max = NullDate(dt.date.max)
  NullDate.min = NullDate(dt.date.min)
</trimmed down class code>

How can I move those last two lines into the class definition so that:
  1) they are class attributes (not instance), and
  2) they are NullDate type objects?



It can't be done by any straightforward method I know of.  I advise
you not to worry about it, and just define them afterwards, perhaps
with an apologetic comment saying you would have put them inside the
class definition if you could have.


If the out-of-scope issue bothers you that much, you could use some
metaclass hackery to run a method that defines the class attributes
after the class is created, at the unrecommendable cost of confusing
most readers.  Here is a very simple example:

def make_class_and_run_postcreate(name,bases,clsdict):
    cls = type.__new__(type,name,bases,clsdict)
    cls.__postcreate__()
    return cls

class A(object):
    __metaclass__ = make_class_and_run_postcreate
    @classmethod
    def __postcreate__(cls):
        cls.internal_circular_class_ref = cls()

Well, since "Practicality beats purity" ;) , I'll stick with having the two assignment statements just outside the class. Not to mention my metaclass skills are nonexistent at this point.

BTW, if you don't mind some criticism of your code, the code you
posted seems to be much too complex for the job you're describing.

Critiques always welcome.

First of all, do you even need to wrap the datetime.date class?  With
Python's duck typing ability, you could have a separate NullDate class
to go alongside the datetime.date, and use a regular datetime.date
object when the date is present, and NullDate when it's absent.  If
necessary you can subclass datetime.date to add any new methods it
would have to have.  Use a factory function to return either NullDate
or a datetime.date depending on whether the dbf cell is empty.

class ValidDate(datetime.date):
    def is_valid(self):
        return True

class NullDate(object):
    # implement any necessary methods of datetime.date interface here
    def is_valid(self):
        return False

def create_date_from_dbf_cell(dbf_cell):
    if dbf_cell.empty():
        return NullDate()
    return ValidDate(dbf_cell.value)


If you do this, you don't have to muck around with __getattr__ or
__new__ or snooping to datetime.date's class dict anything like that.


Carl Banks

Good question. My goal with NullDate is to have a date object that I can treat the same regardless of whether or not it actually holds a date. NullDates with no value should sort before any NullDates with a value, should be comparable to dates as well as NullDates, and should support all the same methods. In other words, I don't want to have to worry about whether my date object has an actual date under most circumstances (printing, using as dictionary keys, comparing, etc.).

Does my design make more sense given these expanded requirements, or could it still be done simpler? For that matter, do my requirements make sense?

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to