[SQL-CVS] r536 - in trunk/SQLObject: sqlobject sqlobject/mysql sqlobject/postgres tests
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: <sub...@co...> - 2005-01-12 17:36:25
|
Author: phd Date: 2005-01-12 17:36:14 +0000 (Wed, 12 Jan 2005) New Revision: 536 Modified: trunk/SQLObject/sqlobject/col.py trunk/SQLObject/sqlobject/converters.py trunk/SQLObject/sqlobject/dbconnection.py trunk/SQLObject/sqlobject/mysql/mysqlconnection.py trunk/SQLObject/sqlobject/postgres/pgconnection.py trunk/SQLObject/tests/test_sqlobject.py Log: Added BLOB column type (for PostgreSQL and MySQL), BinaryValidator and a test for them. Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-01-12 12:25:36 UTC (rev 535) +++ trunk/SQLObject/sqlobject/col.py 2005-01-12 17:36:14 UTC (rev 536) @@ -845,6 +845,46 @@ class CurrencyCol(DecimalCol): baseClass = SOCurrencyCol + +class BinaryValidator(validators.Validator): + """ + Validator for binary types. + + We're assuming that the per-database modules provide some form + of wrapper type for binary conversion. + """ + + def fromPython(self, value, state): + return state.soObject._connection.createBinary(value) + +class SOBLOBCol(SOStringCol): + validatorClass = BinaryValidator # can be overriden in descendants + + def __init__(self, **kw): + SOStringCol.__init__(self, **kw) + self.validator = validators.All.join(self.createValidator(), self.validator) + + def createValidator(self): + return self.validatorClass() + + def _mysqlType(self): + length = self.length + varchar = self.varchar + if length >= 2**24: + return varchar and "LONGTEXT" or "LONGBLOB" + if length >= 2**16: + return varchar and "MEDIUMTEXT" or "MEDIUMBLOB" + if length >= 2**8: + return varchar and "TEXT" or "BLOB" + return varchar and "TINYTEXT" or "TINYBLOB" + + def _postgresType(self): + return 'BYTEA' + +class BLOBCol(StringCol): + baseClass = SOBLOBCol + + def popKey(kw, name, default=None): if not kw.has_key(name): return default Modified: trunk/SQLObject/sqlobject/converters.py =================================================================== --- trunk/SQLObject/sqlobject/converters.py 2005-01-12 12:25:36 UTC (rev 535) +++ trunk/SQLObject/sqlobject/converters.py 2005-01-12 17:36:14 UTC (rev 536) @@ -188,4 +188,3 @@ else: return reprFunc(db) - Modified: trunk/SQLObject/sqlobject/dbconnection.py =================================================================== --- trunk/SQLObject/sqlobject/dbconnection.py 2005-01-12 12:25:36 UTC (rev 535) +++ trunk/SQLObject/sqlobject/dbconnection.py 2005-01-12 17:36:14 UTC (rev 536) @@ -375,6 +375,13 @@ # that. self.query("DELETE FROM %s" % tableName) + def createBinary(self, value): + """ + Create a binary object wrapper for the given database. + """ + # Default is Binary() function from the connection driver. + return self.module.Binary(value) + # The _SO_* series of methods are sorts of "friend" methods # with SQLObject. They grab values from the SQLObject instances # or classes freely, but keep the SQLObject class from accessing Modified: trunk/SQLObject/sqlobject/mysql/mysqlconnection.py =================================================================== --- trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2005-01-12 12:25:36 UTC (rev 535) +++ trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2005-01-12 17:36:14 UTC (rev 536) @@ -120,6 +120,21 @@ return col.DateTimeCol, {} elif t.startswith('bool'): return col.BoolCol, {} + elif t.startswith('tinyblob'): + return col.BLOBCol, {"length": 2**8-1} + elif t.startswith('tinytext'): + return col.BLOBCol, {"length": 2**8-1, "varchar": True} + elif t.startswith('blob'): + return col.BLOBCol, {"length": 2**16-1} + elif t.startswith('text'): + return col.BLOBCol, {"length": 2**16-1, "varchar": True} + elif t.startswith('mediumblob'): + return col.BLOBCol, {"length": 2**24-1} + elif t.startswith('mediumtext'): + return col.BLOBCol, {"length": 2**24-1, "varchar": True} + elif t.startswith('longblob'): + return col.BLOBCol, {"length": 2**32} + elif t.startswith('longtext'): + return col.BLOBCol, {"length": 2**32, "varchar": True} else: return col.Col, {} - Modified: trunk/SQLObject/sqlobject/postgres/pgconnection.py =================================================================== --- trunk/SQLObject/sqlobject/postgres/pgconnection.py 2005-01-12 12:25:36 UTC (rev 535) +++ trunk/SQLObject/sqlobject/postgres/pgconnection.py 2005-01-12 17:36:14 UTC (rev 536) @@ -2,6 +2,7 @@ import re from sqlobject import col from sqlobject import sqlbuilder +from sqlobject.converters import registerConverter psycopg = None pgdb = None @@ -24,6 +25,10 @@ import psycopg self.module = psycopg + # Register a converter for psycopg Binary type. + registerConverter(type(psycopg.Binary('')), + PsycoBinaryConverter) + if dsn is None: dsn = [] if db: @@ -49,7 +54,9 @@ connectionFromURI = classmethod(connectionFromURI) def _setAutoCommit(self, conn, auto): - conn.autocommit(auto) + # psycopg2 does not have an autocommit method. + if hasattr(conn, 'autocommit'): + conn.autocommit(auto) def makeConnection(self): try: @@ -57,7 +64,9 @@ except self.module.OperationalError, e: raise self.module.OperationalError("%s; used connection string %r" % (e, self.dsn)) if self.autoCommit: - conn.autocommit(1) + # psycopg2 does not have an autocommit method. + if hasattr(conn, 'autocommit'): + conn.autocommit(1) return conn def _queryInsertID(self, conn, soInstance, id, names, values): @@ -199,6 +208,8 @@ return col.DateTimeCol, {} elif t.startswith('bool'): return col.BoolCol, {} + elif t.startswith('bytea'): + return col.BLOBCol, {} else: return col.Col, {} @@ -210,3 +221,9 @@ self._server_version = server_version.split()[1] return self._server_version server_version = property(server_version) + + +# Converter for psycopg Binary type. +def PsycoBinaryConverter(value, db): + assert db == 'postgres' + return str(value) Modified: trunk/SQLObject/tests/test_sqlobject.py =================================================================== --- trunk/SQLObject/tests/test_sqlobject.py 2005-01-12 12:25:36 UTC (rev 535) +++ trunk/SQLObject/tests/test_sqlobject.py 2005-01-12 17:36:14 UTC (rev 536) @@ -1339,6 +1339,28 @@ self.assertEqual(str(dt2.col2), now_str) ######################################## +## BLOB columns +######################################## + +class Profile(SQLObject): + image = BLOBCol(default='emptydata', length=65535) + +class BLOBColTest(SQLObjectTest): + classes = [Profile] + + def testBLOBCol(self): + data = ''.join([chr(x) for x in range(256)]) + + prof = Profile() + prof.image = data + iid = prof.id + + connection().cache.clear() + + prof2 = Profile.get(iid) + assert prof2.image == data + +######################################## ## Run from command-line: ######################################## |