Thread: [SQL-CVS] r921 - in trunk/SQLObject: docs sqlobject sqlobject/postgres sqlobject/tests
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: <sub...@co...> - 2005-08-19 03:14:01
|
Author: ianb Date: 2005-08-19 03:13:46 +0000 (Fri, 19 Aug 2005) New Revision: 921 Removed: trunk/SQLObject/sqlobject/include/ Modified: trunk/SQLObject/docs/DeveloperGuide.txt trunk/SQLObject/sqlobject/__init__.py trunk/SQLObject/sqlobject/col.py trunk/SQLObject/sqlobject/main.py trunk/SQLObject/sqlobject/postgres/pgconnection.py trunk/SQLObject/sqlobject/tests/test_enum.py trunk/SQLObject/sqlobject/tests/test_validation.py Log: Moved to FormEncode for the validators; see DeveloperGuide for new installation process Modified: trunk/SQLObject/docs/DeveloperGuide.txt =================================================================== --- trunk/SQLObject/docs/DeveloperGuide.txt 2005-08-19 03:09:06 UTC (rev 920) +++ trunk/SQLObject/docs/DeveloperGuide.txt 2005-08-19 03:13:46 UTC (rev 921) @@ -14,6 +14,25 @@ -- Ian Bicking +Development Installation +======================== + +First install `FormEncode <http://formencode.org>`_:: + + $ svn co http://svn.colorstudy.com/FormEncode/trunk FormEncode + $ cd FormEncode + $ sudo python setup.py develop + +Then do the same for SQLObject:: + + $ svn co http://svn.colorstudy.com/trunk/SQLObject SQLObject + $ cd SQLObject + $ sudo python setup.py develop + +Voila! The packages are globally installed, but the files from the +checkout were not copied into ``site-packages``. See `setuptools +<http://peak.telecommunity.com/DevCenter/setuptools>`_ for more. + Style Guide =========== Modified: trunk/SQLObject/sqlobject/__init__.py =================================================================== --- trunk/SQLObject/sqlobject/__init__.py 2005-08-19 03:09:06 UTC (rev 920) +++ trunk/SQLObject/sqlobject/__init__.py 2005-08-19 03:13:46 UTC (rev 921) @@ -4,7 +4,6 @@ from styles import * from joins import * from index import * -from include import validators from dbconnection import connectionForURI ## Each of these imports allows the driver to install itself Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-08-19 03:09:06 UTC (rev 920) +++ trunk/SQLObject/sqlobject/col.py 2005-08-19 03:13:46 UTC (rev 921) @@ -27,7 +27,8 @@ # Sadly the name "constraints" conflicts with many of the function # arguments in this module, so we rename it: import constraints as consts -from include import validators +from formencode import compound +from formencode import validators from classregistry import findClass from converters import array_type from util.backports import count @@ -78,12 +79,12 @@ creationOrder = count() -class SQLValidator(validators.All): +class SQLValidator(compound.All): def attemptConvert(self, value, state, validate): - if validate is validators.toPython: + if validate is validators.to_python: vlist = list(self.validators[:]) vlist.reverse() - elif validate is validators.fromPython: + elif validate is validators.from_python: vlist = self.validators else: raise RuntimeError @@ -121,6 +122,8 @@ lazy=False, noCache=False, forceDBName=False, + title=None, + tags=[], origName=None, extra_vars=None): @@ -213,6 +216,8 @@ # this is in case of ForeignKey, where we rename the column # and append an ID self.origName = origName or name + self.title = title + self.tags = tags if extra_vars: for name, value in extra_vars.items(): @@ -221,11 +226,11 @@ def _set_validator(self, value): self._validator = value if self._validator: - self.toPython = self._validator.toPython - self.fromPython = self._validator.fromPython + self.to_python = self._validator.to_python + self.from_python = self._validator.from_python else: - self.toPython = None - self.fromPython = None + self.to_python = None + self.from_python = None def _get_validator(self): return self._validator @@ -477,14 +482,14 @@ class StringValidator(validators.Validator): - def toPython(self, value, state): + def to_python(self, value, state): if value is None: return None if isinstance(value, unicode): return value.encode("ascii") return value - def fromPython(self, value, state): + def from_python(self, value, state): if value is None: return None if isinstance(value, str): @@ -504,14 +509,14 @@ class UnicodeStringValidator(validators.Validator): - def toPython(self, value, state): + def to_python(self, value, state): if value is None: return None if isinstance(value, unicode): return value return unicode(value, self.db_encoding) - def fromPython(self, value, state): + def from_python(self, value, state): if value is None: return None if isinstance(value, str): @@ -533,7 +538,7 @@ class IntValidator(validators.Validator): - def toPython(self, value, state): + def to_python(self, value, state): if value is None: return None if isinstance(value, (int, long, sqlbuilder.SQLExpression)): @@ -544,14 +549,14 @@ except OverflowError: # for Python 2.2 return long(value) except: - raise validators.InvalidField("expected an int in the IntCol '%s', got %s instead" % \ + raise validators.Invalid("expected an int in the IntCol '%s', got %s instead" % \ (self.name, type(value)), value, state) - def fromPython(self, value, state): + def from_python(self, value, state): if value is None: return None if not isinstance(value, (int, long, sqlbuilder.SQLExpression)): - raise validators.InvalidField("expected an int in the IntCol '%s', got %s instead" % \ + raise validators.Invalid("expected an int in the IntCol '%s', got %s instead" % \ (self.name, type(value)), value, state) return value @@ -573,7 +578,7 @@ class BoolValidator(validators.Validator): - def toPython(self, value, state): + def to_python(self, value, state): if value is None: return None elif not value: @@ -581,7 +586,7 @@ else: return sqlbuilder.TRUE - def fromPython(self, value, state): + def from_python(self, value, state): if value is None: return None elif value: @@ -621,7 +626,7 @@ class FloatValidator(validators.Validator): - def toPython(self, value, state): + def to_python(self, value, state): if value is None: return None if isinstance(value, (int, long, float, sqlbuilder.SQLExpression)): @@ -629,14 +634,14 @@ try: return float(value) except: - raise validators.InvalidField("expected a float in the FloatCol '%s', got %s instead" % \ + raise validators.Invalid("expected a float in the FloatCol '%s', got %s instead" % \ (self.name, type(value)), value, state) - def fromPython(self, value, state): + def from_python(self, value, state): if value is None: return None if not isinstance(value, (int, long, float, sqlbuilder.SQLExpression)): - raise validators.InvalidField("expected a float in the FloatCol '%s', got %s instead" % \ + raise validators.Invalid("expected a float in the FloatCol '%s', got %s instead" % \ (self.name, type(value)), value, state) return value @@ -765,6 +770,10 @@ def autoConstraints(self): return [consts.isString, consts.InList(self.enumValues)] + def createValidators(self): + return [EnumValidator(name = self.name, enumValues = self.enumValues)] + \ + super(SOEnumCol, self).createValidators() + def _mysqlType(self): return "ENUM(%s)" % ', '.join([sqlbuilder.sqlrepr(v, 'mysql') for v in self.enumValues]) @@ -790,13 +799,25 @@ def _maxdbType(self): raise "Enum type is not supported" +class EnumValidator(validators.Validator): + + def to_python(self, value, state): + if value in self.enumValues: + return value + else: + raise validators.Invalid("expected a member of %r in the EnumCol '%s', got %r instead" % \ + (self.enumValues, self.name, value), value, state) + + def from_python(self, value, state): + return self.to_python(value, state) + class EnumCol(Col): baseClass = SOEnumCol if datetime_available: class DateTimeValidator(validators.DateValidator): - def toPython(self, value, state): + def to_python(self, value, state): if value is None: return None if isinstance(value, (datetime.date, datetime.datetime, sqlbuilder.SQLExpression)): @@ -811,24 +832,24 @@ try: stime = time.strptime(value, self.format) except: - raise validators.InvalidField("expected an date/time string of the '%s' format in the DateTimeCol '%s', got %s instead" % \ + raise validators.Invalid("expected an date/time string of the '%s' format in the DateTimeCol '%s', got %s instead" % \ (self.format, self.name, type(value)), value, state) secs = time.mktime(stime) return datetime.datetime.fromtimestamp(secs) - def fromPython(self, value, state): + def from_python(self, value, state): if value is None: return None if isinstance(value, (datetime.date, datetime.datetime, sqlbuilder.SQLExpression)): return value if hasattr(value, "strftime"): return value.strftime(self.format) - raise validators.InvalidField("expected a datetime in the DateTimeCol '%s', got %s instead" % \ + raise validators.Invalid("expected a datetime in the DateTimeCol '%s', got %s instead" % \ (self.name, type(value)), value, state) if mxdatetime_available: class MXDateTimeValidator(validators.DateValidator): - def toPython(self, value, state): + def to_python(self, value, state): if value is None: return None if isinstance(value, (DateTimeType, sqlbuilder.SQLExpression)): @@ -842,18 +863,18 @@ try: stime = time.strptime(value, self.format) except: - raise validators.InvalidField("expected an date/time string of the '%s' format in the DateTimeCol '%s', got %s instead" % \ + raise validators.Invalid("expected an date/time string of the '%s' format in the DateTimeCol '%s', got %s instead" % \ (self.format, self.name, type(value)), value, state) return DateTime.mktime(stime) - def fromPython(self, value, state): + def from_python(self, value, state): if value is None: return None if isinstance(value, (DateTimeType, sqlbuilder.SQLExpression)): return value if hasattr(value, "strftime"): return value.strftime(self.format) - raise validators.InvalidField("expected a mxDateTime in the DateTimeCol '%s', got %s instead" % \ + raise validators.Invalid("expected a mxDateTime in the DateTimeCol '%s', got %s instead" % \ (self.name, type(value)), value, state) class SODateTimeCol(SOCol): @@ -909,13 +930,13 @@ if datetime_available: class DateValidator(DateTimeValidator): - def toPython(self, value, state): - value = super(DateValidator, self).toPython(value, state) + def to_python(self, value, state): + value = super(DateValidator, self).to_python(value, state) if isinstance(value, datetime.datetime): value = datetime.date(value.year, value.month, value.day) return value - fromPython = toPython + from_python = to_python class SODateCol(SOCol): dateFormat = '%Y-%m-%d' @@ -994,7 +1015,9 @@ of wrapper type for binary conversion. """ - def toPython(self, value, state): + _cachedValue = None + + def to_python(self, value, state): if value is None: return None if isinstance(value, str): @@ -1003,20 +1026,21 @@ value = module.decode(value) return value if isinstance(value, state.soObject._connection._binaryType): - if hasattr(self, "_binaryValue") and (value == self._binaryValue): - return self._origValue + cachedValue = self._cachedValue + if cachedValue and cachedValue[1] == value: + return cachedValue[0] if isinstance(value, array_type): # MySQL return value.tostring() return str(value) # buffer => string - raise validators.InvalidField("expected a string in the BLOBCol '%s', got %s instead" % \ + raise validators.Invalid("expected a string in the BLOBCol '%s', got %s instead" % \ (self.name, type(value)), value, state) - def fromPython(self, value, state): + def from_python(self, value, state): if value is None: return None - self._origValue = value # store the original value - self._binaryValue = state.soObject._connection.createBinary(value) - return self._binaryValue + binary = state.soObject._connection.createBinary(value) + self._cachedValue = (value, binary) + return binary class SOBLOBCol(SOStringCol): def createValidators(self): @@ -1043,42 +1067,46 @@ class PickleValidator(BinaryValidator): """ - Validator for pickle types. A pickle type is simply a binary type with - hidden pickling, so that we can simply store any kind of stuff in a - particular column. + Validator for pickle types. A pickle type is simply a binary type + with hidden pickling, so that we can simply store any kind of + stuff in a particular column. - The support for this relies directly on the support for binary for your - database. + The support for this relies directly on the support for binary for + your database. """ - def toPython(self, value, state): + def to_python(self, value, state): + print str(value) if value is None: return None if isinstance(value, unicode): value = value.encode("ascii") if isinstance(value, str): + print repr(value) return pickle.loads(value) - raise validators.InvalidField("expected a pickle string in the PickleCol '%s', got %s instead" % \ + raise validators.Invalid("expected a pickle string in the PickleCol '%s', got %s instead" % \ (self.name, type(value)), value, state) - def fromPython(self, value, state): + def from_python(self, value, state): + print "IN/OUT", [value, pickle.dumps(value)] if value is None: return None return pickle.dumps(value) class SOPickleCol(SOBLOBCol): + def __init__(self, **kw): self.pickleProtocol = popKey(kw, 'pickleProtocol', 1) SOBLOBCol.__init__(self, **kw) def createValidators(self): - return [PickleValidator(name=self.name, pickleProtocol=self.pickleProtocol)] + \ + return [PickleValidator( + name=self.name, pickleProtocol=self.pickleProtocol)] + \ super(SOPickleCol, self).createValidators() class PickleCol(BLOBCol): baseClass = SOPickleCol - def popKey(kw, name, default=None): if not kw.has_key(name): return default Modified: trunk/SQLObject/sqlobject/main.py =================================================================== --- trunk/SQLObject/sqlobject/main.py 2005-08-19 03:09:06 UTC (rev 920) +++ trunk/SQLObject/sqlobject/main.py 2005-08-19 03:13:46 UTC (rev 921) @@ -40,6 +40,7 @@ import classregistry import declarative from sresults import SelectResults +from formencode import schema, compound import sys if sys.version_info[:3] < (2, 2, 0): @@ -338,9 +339,9 @@ # making the table read-only if not column.immutable: # We start by just using the _SO_setValue method - setter = eval('lambda self, val: self._SO_setValue(%s, val, self.%s, self.%s)' % (repr(name), '_SO_fromPython_%s' % name, '_SO_toPython_%s' % name)) - setattr(soClass, '_SO_fromPython_%s' % name, column.fromPython) - setattr(soClass, '_SO_toPython_%s' % name, column.toPython) + setter = eval('lambda self, val: self._SO_setValue(%s, val, self.%s, self.%s)' % (repr(name), '_SO_from_python_%s' % name, '_SO_to_python_%s' % name)) + setattr(soClass, '_SO_from_python_%s' % name, column.from_python) + setattr(soClass, '_SO_to_python_%s' % name, column.to_python) setattr(soClass, rawSetterName(name), setter) # Then do the aliasing if not hasattr(soClass, setterName(name)) or (name == 'childName'): @@ -556,7 +557,7 @@ index = indexDef.withClass(cls.soClass) cls.indexes.append(index) addIndex = classmethod(addIndex) - + sqlhub = dbconnection.ConnectionHub() class _sqlmeta_attr(object): @@ -809,6 +810,7 @@ delJoin = _sqlmeta_attr('delJoin', 2) addIndex = _sqlmeta_attr('addIndex', 2) delIndex = _sqlmeta_attr('delIndex', 2) + getSchema = _sqlmeta_attr('getSchema', 2) # @classmethod def _SO_setupSqlmeta(cls, new_attrs, is_base): @@ -1012,7 +1014,7 @@ finally: self._SO_writeLock.release() - def _SO_setValue(self, name, value, fromPython, toPython): + def _SO_setValue(self, name, value, from_python, to_python): # This is the place where we actually update the # database. @@ -1020,12 +1022,12 @@ # in the database, and we can't insert it until all # the parts are set. So we just keep them in a # dictionary until later: - if fromPython: - dbValue = fromPython(value, self._SO_validatorState) + if from_python: + dbValue = from_python(value, self._SO_validatorState) else: dbValue = value - if toPython: - value = toPython(dbValue, self._SO_validatorState) + if to_python: + value = to_python(dbValue, self._SO_validatorState) if self.sqlmeta._creating or self.sqlmeta.lazyUpdate: self.dirty = True self._SO_createValues[name] = dbValue @@ -1056,14 +1058,14 @@ # _creating is special, see _SO_setValue if self.sqlmeta._creating or self.sqlmeta.lazyUpdate: for name, value in kw.items(): - fromPython = getattr(self, '_SO_fromPython_%s' % name, None) - if fromPython: - kw[name] = dbValue = fromPython(value, self._SO_validatorState) + from_python = getattr(self, '_SO_from_python_%s' % name, None) + if from_python: + kw[name] = dbValue = from_python(value, self._SO_validatorState) else: dbValue = value - toPython = getattr(self, '_SO_toPython_%s' % name, None) - if toPython: - value = toPython(dbValue, self._SO_validatorState) + to_python = getattr(self, '_SO_to_python_%s' % name, None) + if to_python: + value = to_python(dbValue, self._SO_validatorState) setattr(self, instanceName(name), value) for name, value in extra.items(): try: @@ -1093,14 +1095,14 @@ # else into a single UPDATE, if necessary. toUpdate = {} for name, value in kw.items(): - fromPython = getattr(self, '_SO_fromPython_%s' % name, None) - if fromPython: - dbValue = fromPython(value, self._SO_validatorState) + from_python = getattr(self, '_SO_from_python_%s' % name, None) + if from_python: + dbValue = from_python(value, self._SO_validatorState) else: dbValue = value - toPython = getattr(self, '_SO_toPython_%s' % name, None) - if toPython: - value = toPython(dbValue, self._SO_validatorState) + to_python = getattr(self, '_SO_to_python_%s' % name, None) + if to_python: + value = to_python(dbValue, self._SO_validatorState) if self.sqlmeta.cacheValues: setattr(self, instanceName(name), value) toUpdate[name] = dbValue @@ -1124,8 +1126,8 @@ def _SO_selectInit(self, row): for col, colValue in zip(self.sqlmeta.columnList, row): - if col.toPython: - colValue = col.toPython(colValue, self._SO_validatorState) + if col.to_python: + colValue = col.to_python(colValue, self._SO_validatorState) setattr(self, instanceName(col.name), colValue) def _SO_getValue(self, name): @@ -1141,8 +1143,8 @@ assert results != None, "%s with id %s is not in the database" \ % (self.__class__.__name__, self.id) value = results[0] - if column.toPython: - value = column.toPython(value, self._SO_validatorState) + if column.to_python: + value = column.to_python(value, self._SO_validatorState) return value def _SO_foreignKey(self, id, joinClass): Modified: trunk/SQLObject/sqlobject/postgres/pgconnection.py =================================================================== --- trunk/SQLObject/sqlobject/postgres/pgconnection.py 2005-08-19 03:09:06 UTC (rev 920) +++ trunk/SQLObject/sqlobject/postgres/pgconnection.py 2005-08-19 03:13:46 UTC (rev 921) @@ -102,6 +102,7 @@ q = self._insertSQL(table, names, values) if self.debug: self.printDebug(conn, q, 'QueryIns') + print [q] c.execute(q) if self.debugOutput: self.printDebug(conn, id, 'QueryIns', 'result') Modified: trunk/SQLObject/sqlobject/tests/test_enum.py =================================================================== --- trunk/SQLObject/sqlobject/tests/test_enum.py 2005-08-19 03:09:06 UTC (rev 920) +++ trunk/SQLObject/sqlobject/tests/test_enum.py 2005-08-19 03:13:46 UTC (rev 921) @@ -1,5 +1,6 @@ from sqlobject import * from sqlobject.tests.dbtest import * +from formencode import Invalid ######################################## ## Enum test @@ -13,8 +14,8 @@ setupClass(Enum1) for l in ['a', 'bcd', 'a', 'e']: Enum1(l=l) - if supports('restrictedEnum'): - raises( - (Enum1._connection.module.IntegrityError, - Enum1._connection.module.ProgrammingError), - Enum1, l='b') + raises( + (Enum1._connection.module.IntegrityError, + Enum1._connection.module.ProgrammingError, + Invalid), + Enum1, l='b') Modified: trunk/SQLObject/sqlobject/tests/test_validation.py =================================================================== --- trunk/SQLObject/sqlobject/tests/test_validation.py 2005-08-19 03:09:06 UTC (rev 920) +++ trunk/SQLObject/sqlobject/tests/test_validation.py 2005-08-19 03:13:46 UTC (rev 921) @@ -1,5 +1,6 @@ from sqlobject import * from sqlobject.tests.dbtest import * +from formencode import validators ######################################## ## Validation/conversion @@ -8,7 +9,7 @@ class SOValidation(SQLObject): name = StringCol(validator=validators.PlainText(), default='x', dbName='name_col') - name2 = StringCol(validator=validators.ConfirmType(str), default='y') + name2 = StringCol(validator=validators.ConfirmType(type=str), default='y') name3 = IntCol(validator=validators.Wrapper(fromPython=int), default=100) name4 = FloatCol(default=2.718) @@ -19,23 +20,23 @@ def test_validate(self): t = SOValidation(name='hey') - raises(validators.InvalidField, setattr, t, + raises(validators.Invalid, setattr, t, 'name', '!!!') t.name = 'you' def test_confirmType(self): t = SOValidation(name2='hey') - raises(validators.InvalidField, setattr, t, + raises(validators.Invalid, setattr, t, 'name2', 1) - raises(validators.InvalidField, setattr, t, + raises(validators.Invalid, setattr, t, 'name3', '1') - raises(validators.InvalidField, setattr, t, + raises(validators.Invalid, setattr, t, 'name4', '1') t.name2 = 'you' def test_wrapType(self): t = SOValidation(name3=1) - raises(validators.InvalidField, setattr, t, + raises(validators.Invalid, setattr, t, 'name3', 'x') t.name3 = 1L assert t.name3 == 1 |