[SQL-CVS] r521 - in trunk/SQLObject: sqlobject tests
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: <sub...@co...> - 2005-01-09 11:27:52
|
Author: phd Date: 2005-01-09 11:27:46 +0000 (Sun, 09 Jan 2005) New Revision: 521 Modified: trunk/SQLObject/sqlobject/col.py trunk/SQLObject/tests/test_sqlobject.py Log: Added date/time validators, converters and tests. Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-01-07 11:20:49 UTC (rev 520) +++ trunk/SQLObject/sqlobject/col.py 2005-01-09 11:27:46 UTC (rev 521) @@ -2,8 +2,8 @@ Col """ +import re, time import sqlbuilder -import re # Sadly the name "constraints" conflicts with many of the function # arguments in this module, so we rename it: import constraints as consts @@ -12,7 +12,44 @@ NoDefault = sqlbuilder.NoDefault True, False = 1==1, 0==1 +try: + import datetime +except ImportError: # Python 2.2 + datetime_available = False +else: + datetime_available = True +try: + from mx import DateTime +except ImportError: + try: + import DateTime # old version of mxDateTime + except ImportError: + mxdatetime_available = False + else: + mxdatetime_available = True +else: + mxdatetime_available = True + +if datetime_available: + DATETIME_IMPLEMENTATION = "datetime" + +if mxdatetime_available: + MXDATETIME_IMPLEMENTATION = "mxDateTime" + DateTimeType = type(DateTime.now()) + +if datetime_available: + default_datetime_implementation = DATETIME_IMPLEMENTATION +elif mxdatetime_available: + default_datetime_implementation = MXDATETIME_IMPLEMENTATION +else: + default_datetime_implementation = None + +__all__ = ["datetime_available", "mxdatetime_available", + "DATETIME_IMPLEMENTATION", "MXDATETIME_IMPLEMENTATION", + "default_datetime_implementation" +] + ######################################## ## Columns ######################################## @@ -620,11 +657,84 @@ class EnumCol(Col): baseClass = SOEnumCol + +class DateTimeValidator(validators.DateValidator): + def fromPython(self, value, state): + if value is None: + return None + if isinstance(value, (datetime.date, datetime.datetime)): + return value + if hasattr(value, "strftime"): + return value.strftime(self.format) + raise validators.InvalidField("expected a datetime in the DateTimeCol '%s', got %s instead" % \ + (self.name, type(value)), value, state) + + def toPython(self, value, state): + if value is None: + return None + if isinstance(value, (datetime.date, datetime.datetime)): + return value + if mxdatetime_available: # convert mxDateTime instance to datetime + if isinstance(value, DateTimeType): + if hasattr(value, "hour"): + return datetime.datetime(value.year, value.month, value.day, + value.hour, value.minute, value.second) + else: + return datetime.date(value.year, value.month, value.day) + try: + stime = time.strptime(value, self.format) + except: + raise validators.InvalidField("expected an ISO date/time string in the DateTimeCol '%s', got %s instead" % \ + (self.name, type(value)), value, state) + secs = time.mktime(stime) + return datetime.datetime.fromtimestamp(secs) + +class MXDateTimeValidator(validators.DateValidator): + def fromPython(self, value, state): + if value is None: + return None + if isinstance(value, DateTimeType): + return value + if hasattr(value, "strftime"): + return value.strftime(self.format) + raise validators.InvalidField("expected a mxDateTime in the DateTimeCol '%s', got %s instead" % \ + (self.name, type(value)), value, state) + + def toPython(self, value, state): + if value is None: + return None + if isinstance(value, DateTimeType): + return value + if datetime_available: # convert datetime instance to mxDateTime + if isinstance(value, (datetime.date, datetime.datetime)): + if hasattr(value, "hour"): + return DateTime.DateTime(value.year, value.month, value.day, + value.hour, value.minute, value.second) + else: + return DateTime.Date(value.year, value.month, value.day) + try: + stime = time.strptime(value, self.format) + except: + raise validators.InvalidField("expected an ISO date/time string in the DateTimeCol '%s', got %s instead" % \ + (self.name, type(value)), value, state) + return DateTime.DateTime.mktime(stime) + class SODateTimeCol(SOCol): + if default_datetime_implementation == DATETIME_IMPLEMENTATION: + validatorClass = DateTimeValidator # can be overriden in descendants + elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: + validatorClass = MXDateTimeValidator # can be overriden in descendants + datetimeFormat = '%Y-%m-%d %H:%M:%S' - # 3-03 @@: provide constraints; right now we let the database - # do any parsing and checking. And DATE and TIME? + def __init__(self, **kw): + SOCol.__init__(self, **kw) + if default_datetime_implementation: + self.validator = validators.All.join(self.createValidator(), self.validator) + def createValidator(self): + """Create a validator for the column. Can be overriden in descendants.""" + return self.validatorClass(name=self.name, format=self.datetimeFormat) + def _mysqlType(self): return 'DATETIME' @@ -647,10 +757,21 @@ baseClass = SODateTimeCol class SODateCol(SOCol): + if default_datetime_implementation == DATETIME_IMPLEMENTATION: + validatorClass = DateTimeValidator # can be overriden in descendants + elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: + validatorClass = MXDateTimeValidator # can be overriden in descendants + dateFormat = '%Y-%m-%d' - # 3-03 @@: provide constraints; right now we let the database - # do any parsing and checking. And DATE and TIME? + def __init__(self, **kw): + SOCol.__init__(self, **kw) + if default_datetime_implementation: + self.validator = validators.All.join(self.createValidator(), self.validator) + def createValidator(self): + """Create a validator for the column. Can be overriden in descendants.""" + return self.validatorClass(name=self.name, format=self.dateFormat) + def _mysqlType(self): return 'DATE' @@ -672,6 +793,7 @@ class DateCol(Col): baseClass = SODateCol + class SODecimalCol(SOCol): def __init__(self, **kw): @@ -712,6 +834,7 @@ all = [] for key, value in globals().items(): - if isinstance(value, type) and issubclass(value, Col): + if isinstance(value, type) and issubclass(value, (Col, SOCol)): all.append(key) -__all__ = all +__all__.extend(all) +del all Modified: trunk/SQLObject/tests/test_sqlobject.py =================================================================== --- trunk/SQLObject/tests/test_sqlobject.py 2005-01-07 11:20:49 UTC (rev 520) +++ trunk/SQLObject/tests/test_sqlobject.py 2005-01-09 11:27:46 UTC (rev 521) @@ -19,7 +19,11 @@ from sqlobject import * from sqlobject.include import validators from sqlobject import classregistry -from mx import DateTime +if default_datetime_implementation == DATETIME_IMPLEMENTATION: + from datetime import datetime + now = datetime.now +elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: + from mx.DateTime import now global curr_db curr_db = None from sqlobject import cache @@ -704,12 +708,12 @@ john = AutoTest(firstName='john', lastName='doe', age=10, - created=DateTime.now(), + created=now(), wannahavefun=False) jane = AutoTest(firstName='jane', lastName='doe', happy='N', - created=DateTime.now(), + created=now(), wannahavefun=True) self.failIf(john.wannahavefun) self.failUnless(jane.wannahavefun) @@ -1285,6 +1289,27 @@ self.assertEqual(self.data[count].encode('latin1'), col2) ######################################## +## Date/time columns +######################################## + +class DateTime1(SQLObject): + col1 = DateCol() + col2 = DateTimeCol() + +class DateTimeTest(SQLObjectTest): + + classes = [DateTime1] + + def testNow(self): + _now = now() + dt1 = DateTime1(col1=_now, col2=_now) + + today_str = _now.strftime(SODateCol.dateFormat) + now_str = _now.strftime(SODateTimeCol.datetimeFormat) + self.assertEqual(str(dt1.col1), today_str) + self.assertEqual(str(dt1.col2), now_str) + +######################################## ## Run from command-line: ######################################## |