sqlobject-cvs Mailing List for SQLObject (Page 172)
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
(9) |
Apr
(74) |
May
(29) |
Jun
(16) |
Jul
(28) |
Aug
(10) |
Sep
(57) |
Oct
(9) |
Nov
(29) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(7) |
Feb
(14) |
Mar
(6) |
Apr
(3) |
May
(12) |
Jun
(34) |
Jul
(9) |
Aug
(29) |
Sep
(22) |
Oct
(2) |
Nov
(15) |
Dec
(52) |
2005 |
Jan
(47) |
Feb
(78) |
Mar
(14) |
Apr
(35) |
May
(33) |
Jun
(16) |
Jul
(26) |
Aug
(63) |
Sep
(40) |
Oct
(96) |
Nov
(96) |
Dec
(123) |
2006 |
Jan
(159) |
Feb
(144) |
Mar
(64) |
Apr
(31) |
May
(88) |
Jun
(48) |
Jul
(16) |
Aug
(64) |
Sep
(87) |
Oct
(92) |
Nov
(56) |
Dec
(76) |
2007 |
Jan
(94) |
Feb
(103) |
Mar
(126) |
Apr
(123) |
May
(85) |
Jun
(11) |
Jul
(130) |
Aug
(47) |
Sep
(65) |
Oct
(70) |
Nov
(12) |
Dec
(11) |
2008 |
Jan
(30) |
Feb
(55) |
Mar
(88) |
Apr
(20) |
May
(50) |
Jun
|
Jul
(38) |
Aug
(1) |
Sep
(9) |
Oct
(5) |
Nov
(6) |
Dec
(39) |
2009 |
Jan
(8) |
Feb
(16) |
Mar
(3) |
Apr
(33) |
May
(44) |
Jun
(1) |
Jul
(10) |
Aug
(33) |
Sep
(74) |
Oct
(22) |
Nov
|
Dec
(15) |
2010 |
Jan
(28) |
Feb
(22) |
Mar
(46) |
Apr
(29) |
May
(1) |
Jun
(1) |
Jul
(27) |
Aug
(8) |
Sep
(5) |
Oct
(33) |
Nov
(24) |
Dec
(41) |
2011 |
Jan
(4) |
Feb
(12) |
Mar
(35) |
Apr
(29) |
May
(19) |
Jun
(16) |
Jul
(32) |
Aug
(25) |
Sep
(5) |
Oct
(11) |
Nov
(21) |
Dec
(12) |
2012 |
Jan
(3) |
Feb
(4) |
Mar
(20) |
Apr
(4) |
May
(25) |
Jun
(13) |
Jul
|
Aug
|
Sep
(2) |
Oct
(25) |
Nov
(9) |
Dec
(1) |
2013 |
Jan
(6) |
Feb
(8) |
Mar
|
Apr
(10) |
May
(31) |
Jun
(7) |
Jul
(18) |
Aug
(33) |
Sep
(4) |
Oct
(16) |
Nov
|
Dec
(27) |
2014 |
Jan
(2) |
Feb
|
Mar
|
Apr
(11) |
May
(39) |
Jun
(8) |
Jul
(11) |
Aug
(4) |
Sep
|
Oct
(27) |
Nov
|
Dec
(71) |
2015 |
Jan
(17) |
Feb
(47) |
Mar
(33) |
Apr
|
May
|
Jun
(9) |
Jul
(7) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(8) |
2016 |
Jan
(4) |
Feb
(4) |
Mar
|
Apr
|
May
(12) |
Jun
(7) |
Jul
(9) |
Aug
(31) |
Sep
(8) |
Oct
(3) |
Nov
(15) |
Dec
(1) |
2017 |
Jan
(13) |
Feb
(7) |
Mar
(14) |
Apr
(8) |
May
(10) |
Jun
(4) |
Jul
(2) |
Aug
(1) |
Sep
|
Oct
(8) |
Nov
(4) |
Dec
(5) |
2018 |
Jan
(2) |
Feb
(8) |
Mar
|
Apr
(4) |
May
|
Jun
(6) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
2019 |
Jan
(1) |
Feb
(16) |
Mar
(1) |
Apr
(3) |
May
(5) |
Jun
(1) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
(3) |
2020 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
(1) |
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
(2) |
Nov
|
Dec
(2) |
2021 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
2022 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(6) |
Oct
(1) |
Nov
(1) |
Dec
(4) |
2023 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(3) |
Sep
(2) |
Oct
(2) |
Nov
(4) |
Dec
|
2024 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(9) |
2025 |
Jan
|
Feb
(4) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <sub...@co...> - 2005-01-13 17:29:08
|
Author: ianb Date: 2005-01-13 17:29:02 +0000 (Thu, 13 Jan 2005) New Revision: 540 Modified: trunk/SQLObject/docs/SQLObject.txt Log: Noted that MySQL does support transactions a little more clearly Modified: trunk/SQLObject/docs/SQLObject.txt =================================================================== --- trunk/SQLObject/docs/SQLObject.txt 2005-01-13 10:50:11 UTC (rev 539) +++ trunk/SQLObject/docs/SQLObject.txt 2005-01-13 17:29:02 UTC (rev 540) @@ -1082,9 +1082,10 @@ `MySQLConnection` takes the keyword arguments `host`, `db`, `user`, and `passwd`, just like `MySQLdb.connect` does. -MySQLConnection supports all the features, though MySQL does not -support transactions_ (except using a special proprietary backend that -I haven't used). +MySQLConnection supports all the features, though MySQL only supports +transactions_ when using the InnoDB backend, and SQLObject currently +does not have support for explicitly defining the backend when using +``createTable``. Postgres -------- |
From: Ian B. <ia...@co...> - 2005-01-13 16:40:23
|
sub...@co... wrote: > Author: phd > Date: 2005-01-13 10:43:56 +0000 (Thu, 13 Jan 2005) > New Revision: 538 > > Modified: > trunk/SQLObject/sqlobject/converters.py > Log: > Fixed a bug in sqlStringReplace - MySQL and PostgreSQL use backslash to escape quotes. Did you actually encounter this as a bug? They should both accept '' as well as \'; they are still different than other databases, because you have to quote \'s themselves, but you don't have to use that form. -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: <sub...@co...> - 2005-01-13 10:50:17
|
Author: phd Date: 2005-01-13 10:50:11 +0000 (Thu, 13 Jan 2005) New Revision: 539 Modified: home/phd/SQLObject/inheritance/sqlobject/converters.py Log: Fixed a bug in sqlStringReplace - MySQL and PostgreSQL use backslash to escape quotes. Modified: home/phd/SQLObject/inheritance/sqlobject/converters.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/converters.py 2005-01-13 10:43:56 UTC (rev 538) +++ home/phd/SQLObject/inheritance/sqlobject/converters.py 2005-01-13 10:50:11 UTC (rev 539) @@ -47,7 +47,7 @@ sqlStringReplace = [ ('\\', '\\\\'), - ("'", "''"), + ("'", "\\'"), ('\000', '\\0'), ('\b', '\\b'), ('\n', '\\n'), |
From: <sub...@co...> - 2005-01-13 10:44:06
|
Author: phd Date: 2005-01-13 10:43:56 +0000 (Thu, 13 Jan 2005) New Revision: 538 Modified: trunk/SQLObject/sqlobject/converters.py Log: Fixed a bug in sqlStringReplace - MySQL and PostgreSQL use backslash to escape quotes. Modified: trunk/SQLObject/sqlobject/converters.py =================================================================== --- trunk/SQLObject/sqlobject/converters.py 2005-01-12 17:39:30 UTC (rev 537) +++ trunk/SQLObject/sqlobject/converters.py 2005-01-13 10:43:56 UTC (rev 538) @@ -47,7 +47,7 @@ sqlStringReplace = [ ('\\', '\\\\'), - ("'", "''"), + ("'", "\\'"), ('\000', '\\0'), ('\b', '\\b'), ('\n', '\\n'), |
From: <sub...@co...> - 2005-01-12 17:39:42
|
Author: phd Date: 2005-01-12 17:39:30 +0000 (Wed, 12 Jan 2005) New Revision: 537 Modified: home/phd/SQLObject/inheritance/sqlobject/col.py home/phd/SQLObject/inheritance/sqlobject/converters.py home/phd/SQLObject/inheritance/sqlobject/dbconnection.py home/phd/SQLObject/inheritance/sqlobject/mysql/mysqlconnection.py home/phd/SQLObject/inheritance/sqlobject/postgres/pgconnection.py home/phd/SQLObject/inheritance/tests/test_sqlobject.py Log: Merged patches from revision 536: added BLOB column type (for PostgreSQL and MySQL), BinaryValidator and a test for them. Modified: home/phd/SQLObject/inheritance/sqlobject/col.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-12 17:36:14 UTC (rev 536) +++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-12 17:39:30 UTC (rev 537) @@ -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: home/phd/SQLObject/inheritance/sqlobject/converters.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/converters.py 2005-01-12 17:36:14 UTC (rev 536) +++ home/phd/SQLObject/inheritance/sqlobject/converters.py 2005-01-12 17:39:30 UTC (rev 537) @@ -188,4 +188,3 @@ else: return reprFunc(db) - Modified: home/phd/SQLObject/inheritance/sqlobject/dbconnection.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/dbconnection.py 2005-01-12 17:36:14 UTC (rev 536) +++ home/phd/SQLObject/inheritance/sqlobject/dbconnection.py 2005-01-12 17:39:30 UTC (rev 537) @@ -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: home/phd/SQLObject/inheritance/sqlobject/mysql/mysqlconnection.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/mysql/mysqlconnection.py 2005-01-12 17:36:14 UTC (rev 536) +++ home/phd/SQLObject/inheritance/sqlobject/mysql/mysqlconnection.py 2005-01-12 17:39:30 UTC (rev 537) @@ -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: home/phd/SQLObject/inheritance/sqlobject/postgres/pgconnection.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/postgres/pgconnection.py 2005-01-12 17:36:14 UTC (rev 536) +++ home/phd/SQLObject/inheritance/sqlobject/postgres/pgconnection.py 2005-01-12 17:39:30 UTC (rev 537) @@ -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: home/phd/SQLObject/inheritance/tests/test_sqlobject.py =================================================================== --- home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-12 17:36:14 UTC (rev 536) +++ home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-12 17:39:30 UTC (rev 537) @@ -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: ######################################## |
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: ######################################## |
From: <sub...@co...> - 2005-01-12 12:25:41
|
Author: phd Date: 2005-01-12 12:25:36 +0000 (Wed, 12 Jan 2005) New Revision: 535 Modified: home/phd/SQLObject/inheritance/sqlobject/col.py Log: mxDateTime stores second as float - datetime wants an int. Modified: home/phd/SQLObject/inheritance/sqlobject/col.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-12 12:25:05 UTC (rev 534) +++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-12 12:25:36 UTC (rev 535) @@ -698,7 +698,7 @@ # convert mxDateTime instance to datetime if ("%H" in self.format) or ("%T" in self.format): return datetime.datetime(value.year, value.month, value.day, - value.hour, value.minute, value.second) + value.hour, value.minute, int(value.second)) else: return datetime.date(value.year, value.month, value.day) try: |
From: <sub...@co...> - 2005-01-12 12:25:10
|
Author: phd Date: 2005-01-12 12:25:05 +0000 (Wed, 12 Jan 2005) New Revision: 534 Modified: trunk/SQLObject/sqlobject/col.py Log: mxDateTime stores second as float - datetime wants an int. Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-01-12 12:14:08 UTC (rev 533) +++ trunk/SQLObject/sqlobject/col.py 2005-01-12 12:25:05 UTC (rev 534) @@ -698,7 +698,7 @@ # convert mxDateTime instance to datetime if ("%H" in self.format) or ("%T" in self.format): return datetime.datetime(value.year, value.month, value.day, - value.hour, value.minute, value.second) + value.hour, value.minute, int(value.second)) else: return datetime.date(value.year, value.month, value.day) try: |
From: <sub...@co...> - 2005-01-12 12:14:14
|
Author: phd Date: 2005-01-12 12:14:08 +0000 (Wed, 12 Jan 2005) New Revision: 533 Modified: home/phd/SQLObject/inheritance/sqlobject/cache.py home/phd/SQLObject/inheritance/sqlobject/col.py Log: Merged patches from revisions 528:532 Modified: home/phd/SQLObject/inheritance/sqlobject/cache.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/cache.py 2005-01-11 21:20:59 UTC (rev 532) +++ home/phd/SQLObject/inheritance/sqlobject/cache.py 2005-01-12 12:14:08 UTC (rev 533) @@ -1,3 +1,11 @@ +""" +This implements the instance caching in SQLObject. Caching is +relatively aggressive. All objects are retained so long as they are +in memory, by keeping weak references to objects. We also keep other +objects in a cache that doesn't allow them to be garbage collected +(unless caching is turned off). +""" + import threading from weakref import ref from time import time as now @@ -46,6 +54,9 @@ self.lock = threading.Lock() def tryGet(self, id): + """ + This returns None, or the object in cache. + """ value = self.expiredCache.get(id) if value: # it's actually a weakref: @@ -55,7 +66,29 @@ return self.cache.get(id) def get(self, id): + """ + This method can cause deadlocks! tryGet is safer + This returns the object found in cache, or None. If None, + then the cache will remain locked! This is so that the + calling function can create the object in a threadsafe manner + before releasing the lock. You should use this like (note + that ``cache`` is actually a CacheSet object in this + example):: + + obj = cache.get(some_id, my_class) + if obj is None: + try: + obj = create_object(some_id) + cache.put(some_id, my_class, obj) + finally: + cache.finishPut(cls) + + This method checks both the main cache (which retains + references) and the 'expired' cache, which retains only weak + references. + """ + if self.doCache: if self.cullCount > self.cullFrequency: # Two threads could hit the cull in a row, but @@ -109,21 +142,40 @@ return val def put(self, id, obj): + """ + Puts an object into the cache. Should only be called after + .get(), so that duplicate objects don't end up in the cache. + """ if self.doCache: self.cache[id] = obj else: self.expiredCache[id] = ref(obj) def finishPut(self): + """ + Releases the lock that is retained when .get() is called and + returns None. + """ self.lock.release() def created(self, id, obj): + """ + Inserts and object into the cache. Should be used when no one + else knows about the object yet, so there cannot be any object + already in the cache. After a database INSERT is an example + of this situation. + """ if self.doCache: self.cache[id] = obj else: self.expiredCache[id] = ref(obj) def cull(self): + """ + Runs through the cache and expires objects. E.g., if + ``cullFraction`` is 3, then every third object is moved to + the 'expired' (aka weakref) cache. + """ self.lock.acquire() try: keys = self.cache.keys() @@ -139,11 +191,19 @@ self.lock.release() def clear(self): + """ + Removes everything from the cache. Warning! This can cause + duplicate objects in memory. + """ if self.doCache: self.cache.clear() self.expiredCache.clear() def expire(self, id): + """ + Expires a single object. Typically called after a delete. + Doesn't even keep a weakref. (@@: bad name?) + """ if not self.doCache: return self.lock.acquire() @@ -156,6 +216,10 @@ self.lock.release() def expireAll(self): + """ + Expires all objects, moving them all into the expired/weakref + cache. + """ if not self.doCache: return self.lock.acquire() @@ -167,6 +231,9 @@ self.lock.release() def allIDs(self): + """ + Returns the IDs of all objects in the cache. + """ if self.doCache: all = self.cache.keys() else: @@ -178,6 +245,14 @@ class CacheSet(object): + """ + A CacheSet is used to collect and maintain a series of caches. In + SQLObject, there is one CacheSet per connection, and one Cache + in the CacheSet for each class, since IDs are not unique across + classes. It contains methods similar to Cache, but that take + a ``cls`` argument. + """ + def __init__(self, *args, **kw): self.caches = {} self.args = args Modified: home/phd/SQLObject/inheritance/sqlobject/col.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-11 21:20:59 UTC (rev 532) +++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-12 12:14:08 UTC (rev 533) @@ -1,5 +1,21 @@ """ -Col +Col -- SQLObject columns + +Note that each column object is named BlahBlahCol, and these are used +in class definitions. But there's also a corresponding SOBlahBlahCol +object, which is used in SQLObject *classes*. + +An explanation: when a SQLObject subclass is created, the metaclass +looks through your class definition for any subclasses of Col. It +collects them together, and indexes them to do all the database stuff +you like, like the magic attributes and whatnot. It then asks the Col +object to create an SOCol object (usually a subclass, actually). The +SOCol object contains all the interesting logic, as well as a record +of the attribute name you used and the class it is bound to (set by +the metaclass). + +So, in summary: Col objects are what you define, but SOCol objects +are what gets used. """ import re, time |
From: <sub...@co...> - 2005-01-11 17:22:47
|
Author: ianb Date: 2005-01-11 17:22:39 +0000 (Tue, 11 Jan 2005) New Revision: 530 Modified: trunk/SQLObject/sqlobject/cache.py Log: Added docstrings to methods and module Modified: trunk/SQLObject/sqlobject/cache.py =================================================================== --- trunk/SQLObject/sqlobject/cache.py 2005-01-11 17:22:12 UTC (rev 529) +++ trunk/SQLObject/sqlobject/cache.py 2005-01-11 17:22:39 UTC (rev 530) @@ -1,3 +1,11 @@ +""" +This implements the instance caching in SQLObject. Caching is +relatively aggressive. All objects are retained so long as they are +in memory, by keeping weak references to objects. We also keep other +objects in a cache that doesn't allow them to be garbage collected +(unless caching is turned off). +""" + import threading from weakref import ref from time import time as now @@ -46,6 +54,9 @@ self.lock = threading.Lock() def tryGet(self, id): + """ + This returns None, or the object in cache. + """ value = self.expiredCache.get(id) if value: # it's actually a weakref: @@ -55,7 +66,29 @@ return self.cache.get(id) def get(self, id): + """ + This method can cause deadlocks! tryGet is safer + This returns the object found in cache, or None. If None, + then the cache will remain locked! This is so that the + calling function can create the object in a threadsafe manner + before releasing the lock. You should use this like (note + that ``cache`` is actually a CacheSet object in this + example):: + + obj = cache.get(some_id, my_class) + if obj is None: + try: + obj = create_object(some_id) + cache.put(some_id, my_class, obj) + finally: + cache.finishPut(cls) + + This method checks both the main cache (which retains + references) and the 'expired' cache, which retains only weak + references. + """ + if self.doCache: if self.cullCount > self.cullFrequency: # Two threads could hit the cull in a row, but @@ -109,21 +142,40 @@ return val def put(self, id, obj): + """ + Puts an object into the cache. Should only be called after + .get(), so that duplicate objects don't end up in the cache. + """ if self.doCache: self.cache[id] = obj else: self.expiredCache[id] = ref(obj) def finishPut(self): + """ + Releases the lock that is retained when .get() is called and + returns None. + """ self.lock.release() def created(self, id, obj): + """ + Inserts and object into the cache. Should be used when no one + else knows about the object yet, so there cannot be any object + already in the cache. After a database INSERT is an example + of this situation. + """ if self.doCache: self.cache[id] = obj else: self.expiredCache[id] = ref(obj) def cull(self): + """ + Runs through the cache and expires objects. E.g., if + ``cullFraction`` is 3, then every third object is moved to + the 'expired' (aka weakref) cache. + """ self.lock.acquire() try: keys = self.cache.keys() @@ -139,11 +191,19 @@ self.lock.release() def clear(self): + """ + Removes everything from the cache. Warning! This can cause + duplicate objects in memory. + """ if self.doCache: self.cache.clear() self.expiredCache.clear() def expire(self, id): + """ + Expires a single object. Typically called after a delete. + Doesn't even keep a weakref. (@@: bad name?) + """ if not self.doCache: return self.lock.acquire() @@ -156,6 +216,10 @@ self.lock.release() def expireAll(self): + """ + Expires all objects, moving them all into the expired/weakref + cache. + """ if not self.doCache: return self.lock.acquire() @@ -167,6 +231,9 @@ self.lock.release() def allIDs(self): + """ + Returns the IDs of all objects in the cache. + """ if self.doCache: all = self.cache.keys() else: @@ -178,6 +245,14 @@ class CacheSet(object): + """ + A CacheSet is used to collect and maintain a series of caches. In + SQLObject, there is one CacheSet per connection, and one Cache + in the CacheSet for each class, since IDs are not unique across + classes. It contains methods similar to Cache, but that take + a ``cls`` argument. + """ + def __init__(self, *args, **kw): self.caches = {} self.args = args |
From: <sub...@co...> - 2005-01-11 17:22:17
|
Author: ianb Date: 2005-01-11 17:22:12 +0000 (Tue, 11 Jan 2005) New Revision: 529 Modified: trunk/SQLObject/sqlobject/col.py Log: Added docstring to top Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-01-10 11:55:16 UTC (rev 528) +++ trunk/SQLObject/sqlobject/col.py 2005-01-11 17:22:12 UTC (rev 529) @@ -1,5 +1,21 @@ """ -Col +Col -- SQLObject columns + +Note that each column object is named BlahBlahCol, and these are used +in class definitions. But there's also a corresponding SOBlahBlahCol +object, which is used in SQLObject *classes*. + +An explanation: when a SQLObject subclass is created, the metaclass +looks through your class definition for any subclasses of Col. It +collects them together, and indexes them to do all the database stuff +you like, like the magic attributes and whatnot. It then asks the Col +object to create an SOCol object (usually a subclass, actually). The +SOCol object contains all the interesting logic, as well as a record +of the attribute name you used and the class it is bound to (set by +the metaclass). + +So, in summary: Col objects are what you define, but SOCol objects +are what gets used. """ import re, time |
From: <sub...@co...> - 2005-01-10 11:55:25
|
Author: phd Date: 2005-01-10 11:55:16 +0000 (Mon, 10 Jan 2005) New Revision: 528 Modified: home/phd/SQLObject/inheritance/tests/test_sqlobject.py Log: Minor improvements in the date/time tests. Modified: home/phd/SQLObject/inheritance/tests/test_sqlobject.py =================================================================== --- home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-10 11:54:39 UTC (rev 527) +++ home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-10 11:55:16 UTC (rev 528) @@ -1308,12 +1308,9 @@ def testDateTime(self): _now = now() dt1 = DateTime1(col1=_now, col2=_now) + self.failUnless(isinstance(dt1.col1, date)) + self.failUnless(isinstance(dt1.col2, datetime)) - date_type = date - datetime_type = datetime - self.assertEqual(type(dt1.col1), date_type) - self.assertEqual(type(dt1.col2), datetime_type) - today_str = _now.strftime("%Y-%m-%d") now_str = _now.strftime("%Y-%m-%d %T") self.assertEqual(str(dt1.col1), today_str) @@ -1333,12 +1330,9 @@ def testMxDateTime(self): _now = now() dt2 = DateTime2(col1=_now, col2=_now) + self.failUnless(isinstance(dt2.col1, col.DateTimeType)) + self.failUnless(isinstance(dt2.col2, col.DateTimeType)) - date_type = col.DateTimeType - datetime_type = col.DateTimeType - self.assertEqual(type(dt2.col1), date_type) - self.assertEqual(type(dt2.col2), datetime_type) - today_str = _now.strftime("%Y-%m-%d 00:00:00.00") now_str = _now.strftime("%Y-%m-%d %T.00") self.assertEqual(str(dt2.col1), today_str) |
From: <sub...@co...> - 2005-01-10 11:54:45
|
Author: phd Date: 2005-01-10 11:54:39 +0000 (Mon, 10 Jan 2005) New Revision: 527 Modified: trunk/SQLObject/tests/test_sqlobject.py Log: Minor improvements in the date/time tests. Modified: trunk/SQLObject/tests/test_sqlobject.py =================================================================== --- trunk/SQLObject/tests/test_sqlobject.py 2005-01-09 16:55:21 UTC (rev 526) +++ trunk/SQLObject/tests/test_sqlobject.py 2005-01-10 11:54:39 UTC (rev 527) @@ -1308,12 +1308,9 @@ def testDateTime(self): _now = now() dt1 = DateTime1(col1=_now, col2=_now) + self.failUnless(isinstance(dt1.col1, date)) + self.failUnless(isinstance(dt1.col2, datetime)) - date_type = date - datetime_type = datetime - self.assertEqual(type(dt1.col1), date_type) - self.assertEqual(type(dt1.col2), datetime_type) - today_str = _now.strftime("%Y-%m-%d") now_str = _now.strftime("%Y-%m-%d %T") self.assertEqual(str(dt1.col1), today_str) @@ -1333,12 +1330,9 @@ def testMxDateTime(self): _now = now() dt2 = DateTime2(col1=_now, col2=_now) + self.failUnless(isinstance(dt2.col1, col.DateTimeType)) + self.failUnless(isinstance(dt2.col2, col.DateTimeType)) - date_type = col.DateTimeType - datetime_type = col.DateTimeType - self.assertEqual(type(dt2.col1), date_type) - self.assertEqual(type(dt2.col2), datetime_type) - today_str = _now.strftime("%Y-%m-%d 00:00:00.00") now_str = _now.strftime("%Y-%m-%d %T.00") self.assertEqual(str(dt2.col1), today_str) |
From: <sub...@co...> - 2005-01-09 16:55:26
|
Author: phd Date: 2005-01-09 16:55:21 +0000 (Sun, 09 Jan 2005) New Revision: 526 Modified: home/phd/SQLObject/inheritance/sqlobject/col.py home/phd/SQLObject/inheritance/tests/test_sqlobject.py Log: Merged patch from revision 525: a lot of minor improvements and bug fixes in date/time validators and tests. Added tests for MXDateTimeValidator. Modified: home/phd/SQLObject/inheritance/sqlobject/col.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-09 16:54:03 UTC (rev 525) +++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-09 16:55:21 UTC (rev 526) @@ -46,9 +46,12 @@ default_datetime_implementation = None __all__ = ["datetime_available", "mxdatetime_available", - "DATETIME_IMPLEMENTATION", "MXDATETIME_IMPLEMENTATION", "default_datetime_implementation" ] +if datetime_available: + __all__.append("DATETIME_IMPLEMENTATION") +if mxdatetime_available: + __all__.append("MXDATETIME_IMPLEMENTATION") ######################################## ## Columns @@ -658,82 +661,85 @@ 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) +if datetime_available: + 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): + def toPython(self, value, state): + if value is None: + return None + if isinstance(value, (datetime.date, datetime.datetime)): + return value + if mxdatetime_available and isinstance(value, DateTimeType): + # convert mxDateTime instance to datetime if ("%H" in self.format) or ("%T" in self.format): 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" % \ + 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" % \ + (self.format, self.name, type(value)), value, state) + secs = time.mktime(stime) + return datetime.datetime.fromtimestamp(secs) + +if mxdatetime_available: + 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) - 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"): + 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.datetime): return DateTime.DateTime(value.year, value.month, value.day, value.hour, value.minute, value.second) - else: + elif isinstance(value, datetime.date): 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) + 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" % \ + (self.format, self.name, type(value)), value, state) + return 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' def __init__(self, **kw): + datetimeFormat = popKey(kw, 'datetimeFormat') + if datetimeFormat: self.datetimeFormat = datetimeFormat 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) + if default_datetime_implementation == DATETIME_IMPLEMENTATION: + validatorClass = DateTimeValidator + elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: + validatorClass = MXDateTimeValidator + return validatorClass(name=self.name, format=self.datetimeFormat) def _mysqlType(self): return 'DATETIME' @@ -757,20 +763,22 @@ 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' def __init__(self, **kw): + dateFormat = popKey(kw, 'dateFormat') + if dateFormat: self.dateFormat = dateFormat 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) + if default_datetime_implementation == DATETIME_IMPLEMENTATION: + validatorClass = DateTimeValidator + elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: + validatorClass = MXDateTimeValidator + return validatorClass(name=self.name, format=self.dateFormat) def _mysqlType(self): return 'DATE' Modified: home/phd/SQLObject/inheritance/tests/test_sqlobject.py =================================================================== --- home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-09 16:54:03 UTC (rev 525) +++ home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-09 16:55:21 UTC (rev 526) @@ -17,6 +17,7 @@ from SQLObjectTest import * from sqlobject import * +from sqlobject import col from sqlobject.include import validators from sqlobject import classregistry if default_datetime_implementation == DATETIME_IMPLEMENTATION: @@ -1292,23 +1293,57 @@ ## Date/time columns ######################################## -class DateTime1(SQLObject): - col1 = DateCol() - col2 = DateTimeCol() +if datetime_available: + col.default_datetime_implementation = DATETIME_IMPLEMENTATION + from datetime import date, datetime -class DateTimeTest(SQLObjectTest): + class DateTime1(SQLObject): + col1 = DateCol() + col2 = DateTimeCol() - classes = [DateTime1] + class DateTimeTest1(SQLObjectTest): - def testNow(self): - _now = now() - dt1 = DateTime1(col1=_now, col2=_now) + classes = [DateTime1] - 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) + def testDateTime(self): + _now = now() + dt1 = DateTime1(col1=_now, col2=_now) + date_type = date + datetime_type = datetime + self.assertEqual(type(dt1.col1), date_type) + self.assertEqual(type(dt1.col2), datetime_type) + + today_str = _now.strftime("%Y-%m-%d") + now_str = _now.strftime("%Y-%m-%d %T") + self.assertEqual(str(dt1.col1), today_str) + self.assertEqual(str(dt1.col2), now_str) + +if mxdatetime_available: + col.default_datetime_implementation = MXDATETIME_IMPLEMENTATION + + class DateTime2(SQLObject): + col1 = DateCol() + col2 = DateTimeCol() + + class DateTimeTest2(SQLObjectTest): + + classes = [DateTime2] + + def testMxDateTime(self): + _now = now() + dt2 = DateTime2(col1=_now, col2=_now) + + date_type = col.DateTimeType + datetime_type = col.DateTimeType + self.assertEqual(type(dt2.col1), date_type) + self.assertEqual(type(dt2.col2), datetime_type) + + today_str = _now.strftime("%Y-%m-%d 00:00:00.00") + now_str = _now.strftime("%Y-%m-%d %T.00") + self.assertEqual(str(dt2.col1), today_str) + self.assertEqual(str(dt2.col2), now_str) + ######################################## ## Run from command-line: ######################################## |
From: <sub...@co...> - 2005-01-09 16:54:13
|
Author: phd Date: 2005-01-09 16:54:03 +0000 (Sun, 09 Jan 2005) New Revision: 525 Modified: trunk/SQLObject/sqlobject/col.py trunk/SQLObject/tests/test_sqlobject.py Log: A lot of minor improvements and bug fixes in date/time validators and tests. Added tests for MXDateTimeValidator. Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-01-09 11:38:33 UTC (rev 524) +++ trunk/SQLObject/sqlobject/col.py 2005-01-09 16:54:03 UTC (rev 525) @@ -46,9 +46,12 @@ default_datetime_implementation = None __all__ = ["datetime_available", "mxdatetime_available", - "DATETIME_IMPLEMENTATION", "MXDATETIME_IMPLEMENTATION", "default_datetime_implementation" ] +if datetime_available: + __all__.append("DATETIME_IMPLEMENTATION") +if mxdatetime_available: + __all__.append("MXDATETIME_IMPLEMENTATION") ######################################## ## Columns @@ -658,82 +661,85 @@ 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) +if datetime_available: + 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): + def toPython(self, value, state): + if value is None: + return None + if isinstance(value, (datetime.date, datetime.datetime)): + return value + if mxdatetime_available and isinstance(value, DateTimeType): + # convert mxDateTime instance to datetime if ("%H" in self.format) or ("%T" in self.format): 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" % \ + 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" % \ + (self.format, self.name, type(value)), value, state) + secs = time.mktime(stime) + return datetime.datetime.fromtimestamp(secs) + +if mxdatetime_available: + 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) - 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"): + 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.datetime): return DateTime.DateTime(value.year, value.month, value.day, value.hour, value.minute, value.second) - else: + elif isinstance(value, datetime.date): 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) + 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" % \ + (self.format, self.name, type(value)), value, state) + return 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' def __init__(self, **kw): + datetimeFormat = popKey(kw, 'datetimeFormat') + if datetimeFormat: self.datetimeFormat = datetimeFormat 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) + if default_datetime_implementation == DATETIME_IMPLEMENTATION: + validatorClass = DateTimeValidator + elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: + validatorClass = MXDateTimeValidator + return validatorClass(name=self.name, format=self.datetimeFormat) def _mysqlType(self): return 'DATETIME' @@ -757,20 +763,22 @@ 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' def __init__(self, **kw): + dateFormat = popKey(kw, 'dateFormat') + if dateFormat: self.dateFormat = dateFormat 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) + if default_datetime_implementation == DATETIME_IMPLEMENTATION: + validatorClass = DateTimeValidator + elif default_datetime_implementation == MXDATETIME_IMPLEMENTATION: + validatorClass = MXDateTimeValidator + return validatorClass(name=self.name, format=self.dateFormat) def _mysqlType(self): return 'DATE' Modified: trunk/SQLObject/tests/test_sqlobject.py =================================================================== --- trunk/SQLObject/tests/test_sqlobject.py 2005-01-09 11:38:33 UTC (rev 524) +++ trunk/SQLObject/tests/test_sqlobject.py 2005-01-09 16:54:03 UTC (rev 525) @@ -17,6 +17,7 @@ from SQLObjectTest import * from sqlobject import * +from sqlobject import col from sqlobject.include import validators from sqlobject import classregistry if default_datetime_implementation == DATETIME_IMPLEMENTATION: @@ -1292,23 +1293,57 @@ ## Date/time columns ######################################## -class DateTime1(SQLObject): - col1 = DateCol() - col2 = DateTimeCol() +if datetime_available: + col.default_datetime_implementation = DATETIME_IMPLEMENTATION + from datetime import date, datetime -class DateTimeTest(SQLObjectTest): + class DateTime1(SQLObject): + col1 = DateCol() + col2 = DateTimeCol() - classes = [DateTime1] + class DateTimeTest1(SQLObjectTest): - def testNow(self): - _now = now() - dt1 = DateTime1(col1=_now, col2=_now) + classes = [DateTime1] - 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) + def testDateTime(self): + _now = now() + dt1 = DateTime1(col1=_now, col2=_now) + date_type = date + datetime_type = datetime + self.assertEqual(type(dt1.col1), date_type) + self.assertEqual(type(dt1.col2), datetime_type) + + today_str = _now.strftime("%Y-%m-%d") + now_str = _now.strftime("%Y-%m-%d %T") + self.assertEqual(str(dt1.col1), today_str) + self.assertEqual(str(dt1.col2), now_str) + +if mxdatetime_available: + col.default_datetime_implementation = MXDATETIME_IMPLEMENTATION + + class DateTime2(SQLObject): + col1 = DateCol() + col2 = DateTimeCol() + + class DateTimeTest2(SQLObjectTest): + + classes = [DateTime2] + + def testMxDateTime(self): + _now = now() + dt2 = DateTime2(col1=_now, col2=_now) + + date_type = col.DateTimeType + datetime_type = col.DateTimeType + self.assertEqual(type(dt2.col1), date_type) + self.assertEqual(type(dt2.col2), datetime_type) + + today_str = _now.strftime("%Y-%m-%d 00:00:00.00") + now_str = _now.strftime("%Y-%m-%d %T.00") + self.assertEqual(str(dt2.col1), today_str) + self.assertEqual(str(dt2.col2), now_str) + ######################################## ## Run from command-line: ######################################## |
From: <sub...@co...> - 2005-01-09 11:38:36
|
Author: phd Date: 2005-01-09 11:38:33 +0000 (Sun, 09 Jan 2005) New Revision: 524 Modified: home/phd/SQLObject/inheritance/sqlobject/col.py Log: Merged patch from revision 523: DateTime always has 'hour' - test for date by or in format. Modified: home/phd/SQLObject/inheritance/sqlobject/col.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-09 11:37:24 UTC (rev 523) +++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-09 11:38:33 UTC (rev 524) @@ -676,7 +676,7 @@ return value if mxdatetime_available: # convert mxDateTime instance to datetime if isinstance(value, DateTimeType): - if hasattr(value, "hour"): + if ("%H" in self.format) or ("%T" in self.format): return datetime.datetime(value.year, value.month, value.day, value.hour, value.minute, value.second) else: |
From: <sub...@co...> - 2005-01-09 11:37:28
|
Author: phd Date: 2005-01-09 11:37:24 +0000 (Sun, 09 Jan 2005) New Revision: 523 Modified: trunk/SQLObject/sqlobject/col.py Log: DateTime always has 'hour' - test for date by or in format. Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-01-09 11:28:46 UTC (rev 522) +++ trunk/SQLObject/sqlobject/col.py 2005-01-09 11:37:24 UTC (rev 523) @@ -676,7 +676,7 @@ return value if mxdatetime_available: # convert mxDateTime instance to datetime if isinstance(value, DateTimeType): - if hasattr(value, "hour"): + if ("%H" in self.format) or ("%T" in self.format): return datetime.datetime(value.year, value.month, value.day, value.hour, value.minute, value.second) else: |
From: <sub...@co...> - 2005-01-09 11:28:53
|
Author: phd Date: 2005-01-09 11:28:46 +0000 (Sun, 09 Jan 2005) New Revision: 522 Modified: home/phd/SQLObject/inheritance/sqlobject/col.py home/phd/SQLObject/inheritance/tests/test_sqlobject.py Log: Merged patch from revision 521: added date/time validators, converters and tests. Modified: home/phd/SQLObject/inheritance/sqlobject/col.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-09 11:27:46 UTC (rev 521) +++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-09 11:28:46 UTC (rev 522) @@ -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: home/phd/SQLObject/inheritance/tests/test_sqlobject.py =================================================================== --- home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-09 11:27:46 UTC (rev 521) +++ home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-09 11:28:46 UTC (rev 522) @@ -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: ######################################## |
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: ######################################## |
From: <sub...@co...> - 2005-01-07 11:20:53
|
Author: phd Date: 2005-01-07 11:20:49 +0000 (Fri, 07 Jan 2005) New Revision: 520 Modified: home/phd/SQLObject/inheritance/sqlobject/col.py Log: Merged patch from rev 519: changed IntValidator.toPython - it now calls int() to convert non-integer value. Modified: home/phd/SQLObject/inheritance/sqlobject/col.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-07 11:16:34 UTC (rev 519) +++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-07 11:20:49 UTC (rev 520) @@ -386,10 +386,16 @@ def toPython(self, value, state): if value is None: return None - if not isinstance(value, (int, long, sqlbuilder.SQLExpression)): + if isinstance(value, (int, long, sqlbuilder.SQLExpression)): + return value + try: + try: + return int(value) + except OverflowError: # for Python 2.2 + return long(value) + except: raise validators.InvalidField("expected an int in the IntCol '%s', got %s instead" % \ (self.name, type(value)), value, state) - return value class SOIntCol(SOCol): validatorClass = IntValidator # can be overriden in descendants |
From: <sub...@co...> - 2005-01-07 11:16:40
|
Author: phd Date: 2005-01-07 11:16:34 +0000 (Fri, 07 Jan 2005) New Revision: 519 Modified: trunk/SQLObject/sqlobject/col.py Log: Changed IntValidator.toPython - it now calls int() to convert non-integer value. Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-01-06 00:52:22 UTC (rev 518) +++ trunk/SQLObject/sqlobject/col.py 2005-01-07 11:16:34 UTC (rev 519) @@ -386,10 +386,16 @@ def toPython(self, value, state): if value is None: return None - if not isinstance(value, (int, long, sqlbuilder.SQLExpression)): + if isinstance(value, (int, long, sqlbuilder.SQLExpression)): + return value + try: + try: + return int(value) + except OverflowError: # for Python 2.2 + return long(value) + except: raise validators.InvalidField("expected an int in the IntCol '%s', got %s instead" % \ (self.name, type(value)), value, state) - return value class SOIntCol(SOCol): validatorClass = IntValidator # can be overriden in descendants |
From: <sub...@co...> - 2005-01-05 14:45:21
|
Author: phd Date: 2005-01-05 14:45:15 +0000 (Wed, 05 Jan 2005) New Revision: 517 Modified: home/phd/SQLObject/inheritance/sqlobject/col.py home/phd/SQLObject/inheritance/sqlobject/include/validators.py home/phd/SQLObject/inheritance/tests/test_sqlobject.py Log: Merged patches from revisions 509:516 Modified: home/phd/SQLObject/inheritance/sqlobject/col.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-05 14:40:38 UTC (rev 516) +++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-01-05 14:45:15 UTC (rev 517) @@ -346,31 +346,67 @@ def fromPython(self, value, state): if value is None: return None + if isinstance(value, str): + return value return value.encode(self.db_encoding) def toPython(self, value, state): if value is None: return None + if isinstance(value, unicode): + return value return unicode(value, self.db_encoding) class SOUnicodeCol(SOStringCol): + validatorClass = UnicodeStringValidator # can be overriden in descendants def __init__(self, **kw): self.dbEncoding = popKey(kw, 'dbEncoding', 'UTF-8') SOStringCol.__init__(self, **kw) - self.validator = validators.All.join( - UnicodeStringValidator(self.dbEncoding), self.validator) + 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(self.dbEncoding) + class UnicodeCol(Col): baseClass = SOUnicodeCol + +class IntValidator(validators.Validator): + + def fromPython(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" % \ + (self.name, type(value)), value, state) + return value + + def toPython(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" % \ + (self.name, type(value)), value, state) + return value + class SOIntCol(SOCol): + validatorClass = IntValidator # can be overriden in descendants # 3-03 @@: support precision, maybe max and min directly + def __init__(self, **kw): + SOCol.__init__(self, **kw) + self.validator = validators.All.join(self.createValidator(), self.validator) + def autoConstraints(self): return [consts.isInt] + def createValidator(self): + """Create a validator for the column. Can be overriden in descendants.""" + return self.validatorClass(name=self.name) + def _sqlType(self): return 'INT' @@ -392,14 +428,19 @@ return sqlbuilder.TRUE class SOBoolCol(SOCol): + validatorClass = BoolValidator # can be overriden in descendants def __init__(self, **kw): SOCol.__init__(self, **kw) - self.validator = validators.All.join(BoolValidator(), self.validator) + self.validator = validators.All.join(self.createValidator(), self.validator) def autoConstraints(self): return [consts.isBool] + def createValidator(self): + """Create a validator for the column. Can be overriden in descendants.""" + return self.validatorClass() + def _postgresType(self): return 'BOOL' Modified: home/phd/SQLObject/inheritance/sqlobject/include/validators.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/include/validators.py 2005-01-05 14:40:38 UTC (rev 516) +++ home/phd/SQLObject/inheritance/sqlobject/include/validators.py 2005-01-05 14:45:15 UTC (rev 517) @@ -224,13 +224,11 @@ self.validators = validators FancyValidator.__init__(self, ifInvalid=ifInvalid, **kw) - def _toPython(self, value, state=None): - return self.attemptConvert(self, value, state, - toPython) + def toPython(self, value, state=None): + return self.attemptConvert(value, state, toPython) - def _fromPython(self, value, state): - return self.attemptConvert(self, value, state, - fromPython) + def fromPython(self, value, state): + return self.attemptConvert(value, state, fromPython) def matchesProtocol(self, validator, state): target = validator.protocols Modified: home/phd/SQLObject/inheritance/tests/test_sqlobject.py =================================================================== --- home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-05 14:40:38 UTC (rev 516) +++ home/phd/SQLObject/inheritance/tests/test_sqlobject.py 2005-01-05 14:45:15 UTC (rev 517) @@ -908,8 +908,6 @@ 'name3', 'x') t.name3 = 1L self.assertEqual(t.name3, 1) - t.name3 = '1' - self.assertEqual(t.name3, 1) t.name3 = 0 self.assertEqual(t.name3, 0) |
From: <sub...@co...> - 2005-01-05 14:40:44
|
Author: phd Date: 2005-01-05 14:40:38 +0000 (Wed, 05 Jan 2005) New Revision: 516 Modified: trunk/SQLObject/tests/test_sqlobject.py Log: Removed a test - IntCol now doesn't accept a string. Modified: trunk/SQLObject/tests/test_sqlobject.py =================================================================== --- trunk/SQLObject/tests/test_sqlobject.py 2005-01-05 14:39:54 UTC (rev 515) +++ trunk/SQLObject/tests/test_sqlobject.py 2005-01-05 14:40:38 UTC (rev 516) @@ -908,8 +908,6 @@ 'name3', 'x') t.name3 = 1L self.assertEqual(t.name3, 1) - t.name3 = '1' - self.assertEqual(t.name3, 1) t.name3 = 0 self.assertEqual(t.name3, 0) |
From: <sub...@co...> - 2005-01-05 14:40:02
|
Author: phd Date: 2005-01-05 14:39:54 +0000 (Wed, 05 Jan 2005) New Revision: 515 Modified: trunk/SQLObject/sqlobject/col.py Log: Raise InvalidField instead of TypeError. Modified: trunk/SQLObject/sqlobject/col.py =================================================================== --- trunk/SQLObject/sqlobject/col.py 2005-01-05 14:38:39 UTC (rev 514) +++ trunk/SQLObject/sqlobject/col.py 2005-01-05 14:39:54 UTC (rev 515) @@ -379,16 +379,16 @@ if value is None: return None if not isinstance(value, (int, long, sqlbuilder.SQLExpression)): - raise TypeError, "expected an int in the IntCol '%s', got %s instead" % \ - (self.name, type(value)) + raise validators.InvalidField("expected an int in the IntCol '%s', got %s instead" % \ + (self.name, type(value)), value, state) return value def toPython(self, value, state): if value is None: return None if not isinstance(value, (int, long, sqlbuilder.SQLExpression)): - raise TypeError, "expected an int in the IntCol '%s', got %s instead" % \ - (self.name, type(value)) + raise validators.InvalidField("expected an int in the IntCol '%s', got %s instead" % \ + (self.name, type(value)), value, state) return value class SOIntCol(SOCol): |
From: <sub...@co...> - 2005-01-05 14:38:45
|
Author: phd Date: 2005-01-05 14:38:39 +0000 (Wed, 05 Jan 2005) New Revision: 514 Modified: trunk/SQLObject/sqlobject/include/validators.py Log: Fixed a number of bugs in calls to fromPython/toPython/attemptConvert. Modified: trunk/SQLObject/sqlobject/include/validators.py =================================================================== --- trunk/SQLObject/sqlobject/include/validators.py 2005-01-05 13:15:21 UTC (rev 513) +++ trunk/SQLObject/sqlobject/include/validators.py 2005-01-05 14:38:39 UTC (rev 514) @@ -224,13 +224,11 @@ self.validators = validators FancyValidator.__init__(self, ifInvalid=ifInvalid, **kw) - def _toPython(self, value, state=None): - return self.attemptConvert(self, value, state, - toPython) + def toPython(self, value, state=None): + return self.attemptConvert(value, state, toPython) - def _fromPython(self, value, state): - return self.attemptConvert(self, value, state, - fromPython) + def fromPython(self, value, state): + return self.attemptConvert(value, state, fromPython) def matchesProtocol(self, validator, state): target = validator.protocols |