sqlobject-cvs Mailing List for SQLObject (Page 167)
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
(1) |
Sep
|
Oct
|
Nov
(2) |
Dec
(2) |
|
From: <sub...@co...> - 2005-04-07 22:29:18
|
Author: ianb
Date: 2005-04-07 22:29:12 +0000 (Thu, 07 Apr 2005)
New Revision: 719
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
We shouldn't overwrite the connection hub if we don't have a viable alternative connection
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-04-07 07:22:55 UTC (rev 718)
+++ trunk/SQLObject/sqlobject/main.py 2005-04-07 22:29:12 UTC (rev 719)
@@ -450,7 +450,7 @@
if hasattr(mod, '__connection__'):
connection = mod.__connection__
- if connection or not hasattr(cls, '_connection'):
+ if connection and not hasattr(cls, '_connection'):
cls.setConnection(connection)
# We have to check if there are columns in the inherited
|
|
From: <sub...@co...> - 2005-04-06 05:29:45
|
Author: ianb
Date: 2005-04-06 05:29:37 +0000 (Wed, 06 Apr 2005)
New Revision: 717
Modified:
trunk/SQLObject/sqlobject/manager/command.py
Log:
Added an execute command, for running arbitrary SQL
Modified: trunk/SQLObject/sqlobject/manager/command.py
===================================================================
--- trunk/SQLObject/sqlobject/manager/command.py 2005-04-05 16:40:42 UTC (rev 716)
+++ trunk/SQLObject/sqlobject/manager/command.py 2005-04-06 05:29:37 UTC (rev 717)
@@ -52,7 +52,7 @@
register = the_runner.register
def standard_parser(connection=True, simulate=True,
- interactive=False):
+ interactive=False, find_modules=True):
parser = optparse.OptionParser()
parser.add_option('-v', '--verbose',
help='Be verbose (multiple times for more verbosity)',
@@ -74,24 +74,25 @@
help="The WSGIKit config file that contains the database URI (in the database key)",
metavar="FILE",
dest="config_file")
- parser.add_option('-m', '--module',
- help="Module in which to find SQLObject classes",
- action='append',
- metavar='MODULE',
- dest='modules',
- default=[])
- parser.add_option('-p', '--package',
- help="Package to search for SQLObject classes",
- action="append",
- metavar="PACKAGE",
- dest="packages",
- default=[])
- parser.add_option('--class',
- help="Select only named classes (wildcards allowed)",
- action="append",
- metavar="NAME",
- dest="class_matchers",
- default=[])
+ if find_modules:
+ parser.add_option('-m', '--module',
+ help="Module in which to find SQLObject classes",
+ action='append',
+ metavar='MODULE',
+ dest='modules',
+ default=[])
+ parser.add_option('-p', '--package',
+ help="Package to search for SQLObject classes",
+ action="append",
+ metavar="PACKAGE",
+ dest="packages",
+ default=[])
+ parser.add_option('--class',
+ help="Select only named classes (wildcards allowed)",
+ action="append",
+ metavar="NAME",
+ dest="class_matchers",
+ default=[])
if interactive:
parser.add_option('-i', '--interactive',
help="Ask before doing anything (use twice to be more careful)",
@@ -444,6 +445,58 @@
if command.aliases:
print '%s (Aliases: %s)' % (
' '*max_len, ', '.join(command.aliases))
+
+class CommandExecute(Command):
+
+ name = 'execute'
+ summary = 'Execute SQL statements'
+
+ parser = standard_parser(find_modules=False)
+ parser.add_option('--stdin',
+ help="Read SQL from stdin (normally takes SQL from the command line)",
+ dest="use_stdin",
+ action="store_true")
+
+ max_args = None
+
+ def command(self):
+ args = self.args
+ if self.options.use_stdin:
+ if self.options.verbose:
+ print "Reading additional SQL from stdin (Ctrl-D or Ctrl-Z to finish)..."
+ args.append(sys.stdin.read())
+ self.conn = self.connection().getConnection()
+ self.cursor = self.conn.cursor()
+ for sql in args:
+ self.execute_sql(sql)
+
+ def execute_sql(self, sql):
+ if self.options.verbose:
+ print sql
+ try:
+ self.cursor.execute(sql)
+ except Exception, e:
+ if not self.options.verbose:
+ print sql
+ print "****Error:"
+ print ' ', e
+ return
+ desc = self.cursor.description
+ rows = self.cursor.fetchall()
+ if self.options.verbose:
+ if not self.cursor.rowcount:
+ print "No rows accessed"
+ else:
+ print "%i rows accessed" % self.cursor.rowcount
+ if desc:
+ for name, type_code, display_size, internal_size, precision, scale, null_ok in desc:
+ sys.stdout.write("%s\t" % name)
+ sys.stdout.write("\n")
+ for row in rows:
+ for col in row:
+ sys.stdout.write("%r\t" % col)
+ sys.stdout.write("\n")
+ print
def update_sys_path(paths, verbose):
if isinstance(paths, (str, unicode)):
|
|
From: <sub...@co...> - 2005-04-05 16:40:48
|
Author: phd
Date: 2005-04-05 16:40:42 +0000 (Tue, 05 Apr 2005)
New Revision: 716
Modified:
trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
Log:
Fixed a bug reported as bug 1169875.
Modified: trunk/SQLObject/sqlobject/firebird/firebirdconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2005-04-05 14:57:46 UTC (rev 715)
+++ trunk/SQLObject/sqlobject/firebird/firebirdconnection.py 2005-04-05 16:40:42 UTC (rev 716)
@@ -42,6 +42,9 @@
password = 'masterkey'
if not auth:
auth='sysdba'
+ if os.name == 'nt' and path[0] == '/':
+ # strip the leading slash off of db name/alias
+ path = path[1:]
path = path.replace('/', os.sep)
return cls(host, db=path, user=auth, passwd=password, **args)
connectionFromURI = classmethod(connectionFromURI)
|
|
From: <sub...@co...> - 2005-04-05 14:57:49
|
Author: phd
Date: 2005-04-05 14:57:46 +0000 (Tue, 05 Apr 2005)
New Revision: 715
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
Applied bugfix from the bug 1174944.
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-04-05 14:50:14 UTC (rev 714)
+++ trunk/SQLObject/sqlobject/main.py 2005-04-05 14:57:46 UTC (rev 715)
@@ -522,7 +522,7 @@
def get(cls, id, connection=None, selectResults=None):
- assert id is not None, 'None is not a possible id for %s' % cls.__name
+ assert id is not None, 'None is not a possible id for %s' % cls.__name__
id = cls._idType(id)
|
|
From: <sub...@co...> - 2005-04-05 14:50:24
|
Author: phd Date: 2005-04-05 14:50:14 +0000 (Tue, 05 Apr 2005) New Revision: 714 Modified: trunk/SQLObject/docs/FAQ.txt Log: Added the suggsetion from bug 1173573: _idType = str. Modified: trunk/SQLObject/docs/FAQ.txt =================================================================== --- trunk/SQLObject/docs/FAQ.txt 2005-04-05 13:05:51 UTC (rev 713) +++ trunk/SQLObject/docs/FAQ.txt 2005-04-05 14:50:14 UTC (rev 714) @@ -180,7 +180,9 @@ This will be resolved in a future version when ID column types can be declared like other columns. +Additionally you can set _idType = str in you SQLObject class. + Binary Values ------------- |
|
From: <sub...@co...> - 2005-04-05 13:05:57
|
Author: phd
Date: 2005-04-05 13:05:51 +0000 (Tue, 05 Apr 2005)
New Revision: 713
Modified:
trunk/SQLObject/sqlobject/col.py
trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
Log:
BINARY columns in MySQL are too binary - they ignore locale order
and are sorted in their binary order. Because of that I have changed
the entire concept of case_sensitive attribute: it is renamed to char_binary,
the default is None, and it is still only meaninful for MySQL.
Modified: trunk/SQLObject/sqlobject/col.py
===================================================================
--- trunk/SQLObject/sqlobject/col.py 2005-04-04 20:50:38 UTC (rev 712)
+++ trunk/SQLObject/sqlobject/col.py 2005-04-05 13:05:51 UTC (rev 713)
@@ -352,7 +352,7 @@
def __init__(self, **kw):
self.length = popKey(kw, 'length')
self.varchar = popKey(kw, 'varchar', 'auto')
- self.case_sensitive = popKey(kw, 'case_sensitive', True)
+ self.char_binary = popKey(kw, 'char_binary', None) # A hack for MySQL
if not self.length:
assert self.varchar == 'auto' or not self.varchar, \
"Without a length strings are treated as TEXT, not varchar"
@@ -379,12 +379,12 @@
return 'CHAR(%i)' % self.length
def _check_case_sensitive(self, db):
- if not self.case_sensitive:
- raise ValueError, "%s does not support case-insensitive columns" % db
+ if self.char_binary:
+ raise ValueError, "%s does not support binary character columns" % db
def _mysqlType(self):
type = self._sqlType()
- if self.case_sensitive:
+ if self.char_binary:
type += " BINARY"
return type
Modified: trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2005-04-04 20:50:38 UTC (rev 712)
+++ trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2005-04-05 13:05:51 UTC (rev 713)
@@ -141,18 +141,18 @@
return col.IntCol, {}
elif t.startswith('varchar'):
if t.endswith('binary'):
- return col.StringCol, {'length': int(t[8:-8])}
+ return col.StringCol, {'length': int(t[8:-8]),
+ 'char_binary': True}
else:
- return col.StringCol, {'length': int(t[8:-1]),
- 'case_sensitive': False}
+ return col.StringCol, {'length': int(t[8:-1])}
elif t.startswith('char'):
if t.endswith('binary'):
return col.StringCol, {'length': int(t[5:-8]),
- 'varchar': False}
+ 'varchar': False,
+ 'char_binary': True}
else:
return col.StringCol, {'length': int(t[5:-1]),
- 'varchar': False,
- 'case_sensitive': False}
+ 'varchar': False}
elif t.startswith('datetime'):
return col.DateTimeCol, {}
elif t.startswith('bool'):
|
|
From: <sub...@co...> - 2005-04-04 20:50:43
|
Author: phd
Date: 2005-04-04 20:50:38 +0000 (Mon, 04 Apr 2005)
New Revision: 712
Modified:
trunk/SQLObject/sqlobject/col.py
trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
Log:
StringCol now has a new attribute: case_sensitive. Default value for is True.
Currently it is meaningful to set it to False only for MySQL:
it strips CHAR/VARCHAR columns off of the BINARY attribute.
Modified: trunk/SQLObject/sqlobject/col.py
===================================================================
--- trunk/SQLObject/sqlobject/col.py 2005-04-04 19:08:30 UTC (rev 711)
+++ trunk/SQLObject/sqlobject/col.py 2005-04-04 20:50:38 UTC (rev 712)
@@ -352,6 +352,7 @@
def __init__(self, **kw):
self.length = popKey(kw, 'length')
self.varchar = popKey(kw, 'varchar', 'auto')
+ self.case_sensitive = popKey(kw, 'case_sensitive', True)
if not self.length:
assert self.varchar == 'auto' or not self.varchar, \
"Without a length strings are treated as TEXT, not varchar"
@@ -377,19 +378,40 @@
else:
return 'CHAR(%i)' % self.length
+ def _check_case_sensitive(self, db):
+ if not self.case_sensitive:
+ raise ValueError, "%s does not support case-insensitive columns" % db
+
+ def _mysqlType(self):
+ type = self._sqlType()
+ if self.case_sensitive:
+ type += " BINARY"
+ return type
+
+ def _postgresType(self):
+ self._check_case_sensitive("PostgreSQL")
+ return super(SOStringCol, self)._postgresType()
+
+ def _sqliteType(self):
+ self._check_case_sensitive("SQLite")
+ return super(SOStringCol, self)._sqliteType()
+
def _sybaseType(self):
+ self._check_case_sensitive("SYBASE")
type = self._sqlType()
if not self.notNone and not self.alternateID:
type += ' NULL'
return type
def _firebirdType(self):
+ self._check_case_sensitive("FireBird")
if not self.length:
return 'BLOB SUB_TYPE TEXT'
else:
return self._sqlType()
def _maxdbType(self):
+ self._check_case_sensitive("SAP DB/MaxDB")
if not self.length:
return 'LONG ASCII'
else:
Modified: trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2005-04-04 19:08:30 UTC (rev 711)
+++ trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2005-04-04 20:50:38 UTC (rev 712)
@@ -140,10 +140,19 @@
if t.startswith('int'):
return col.IntCol, {}
elif t.startswith('varchar'):
- return col.StringCol, {'length': int(t[8:-1])}
+ if t.endswith('binary'):
+ return col.StringCol, {'length': int(t[8:-8])}
+ else:
+ return col.StringCol, {'length': int(t[8:-1]),
+ 'case_sensitive': False}
elif t.startswith('char'):
- return col.StringCol, {'length': int(t[5:-1]),
- 'varchar': False}
+ if t.endswith('binary'):
+ return col.StringCol, {'length': int(t[5:-8]),
+ 'varchar': False}
+ else:
+ return col.StringCol, {'length': int(t[5:-1]),
+ 'varchar': False,
+ 'case_sensitive': False}
elif t.startswith('datetime'):
return col.DateTimeCol, {}
elif t.startswith('bool'):
|
|
From: <sub...@co...> - 2005-04-04 19:08:35
|
Author: phd
Date: 2005-04-04 19:08:30 +0000 (Mon, 04 Apr 2005)
New Revision: 711
Modified:
trunk/SQLObject/sqlobject/cache.py
Log:
Fixed a misspelling.
Modified: trunk/SQLObject/sqlobject/cache.py
===================================================================
--- trunk/SQLObject/sqlobject/cache.py 2005-04-04 16:58:07 UTC (rev 710)
+++ trunk/SQLObject/sqlobject/cache.py 2005-04-04 19:08:30 UTC (rev 711)
@@ -186,7 +186,7 @@
# This offset tries to balance out which objects we
# expire, so no object will just hang out in the cache
# forever.
- self.cullOffset = (self.culldOffset + 1) % self.cullFraction
+ self.cullOffset = (self.cullOffset + 1) % self.cullFraction
finally:
self.lock.release()
|
|
From: <sub...@co...> - 2005-04-04 05:56:32
|
Author: ianb
Date: 2005-04-04 05:56:29 +0000 (Mon, 04 Apr 2005)
New Revision: 708
Modified:
trunk/SQLObject/sqlobject/col.py
Log:
Reverting commits I didn't mean to make
Modified: trunk/SQLObject/sqlobject/col.py
===================================================================
--- trunk/SQLObject/sqlobject/col.py 2005-04-04 05:54:10 UTC (rev 707)
+++ trunk/SQLObject/sqlobject/col.py 2005-04-04 05:56:29 UTC (rev 708)
@@ -980,218 +980,3 @@
all.append(key)
__all__.extend(all)
del all
-
-
-
-# import boundattributes
-# import declarative
-
-# class BoundCol(object):
-
-# __metaclass__ = declarative.DeclarativeMeta
-
-# sqlTypeRegistry = {}
-
-# def __classinit__(cls, new_attrs):
-# cls.sqlTypeRegistry = cls.sqlTypeRegistry.copy()
-
-# def registerSQLType(cls, dbname, type_func):
-# if not isinstance(dbname, (list, tuple)):
-# dbname = [dbname]
-# for name in dbname:
-# cls.sqlTypeRegistry[name] = type_func
-# registerSQLType = classmethod(registerSQLType)
-
-# def __init__(self, added_class, attr_name,
-# dbName=None,
-# default=NoDefault,
-# alternateID=False,
-# alternateMethodName=None,
-# constraints=None,
-# notNull=NoDefault,
-# notNon=NoDefault,
-# sqlType=None,
-# validator=None,
-# immutable=False,
-# cascade=None,
-# lazy=False,
-# noCache=False,
-# forceDBName=False):
-# if not forceDBName:
-# assert sqlbuilder.sqlIdentifier(name), (
-# "Name must be SQL-safe (letters, numbers, underscores): "
-# "%s (or use forceDBName=True)" % repr(name))
-# assert attr_name != 'id', (
-# "The column name 'id' is reserved for SQLObject use (and is "
-# "implicitly created).")
-# assert name, "You must provide a name for all columns"
-# self.immutable = immutable
-# assert cascade in (None, True, False), (
-# "The cascade attribute must be one of None, True, or False "
-# "(you gave: %r" % cascade)
-# self.cascade = cascade
-
-# if not isinstance(constraints, (list, tuple)):
-# constraints = [constraints]
-# self.constraints = self.autoConstraints() + constraints
-
-# self.notNone = False
-# if notNull is not NoDefault:
-# self.notNone = notNull
-# assert (notNone is NoDefault or
-# (not notNone) == (not notNull)), (
-# "The notNull and notNone arguments are aliases, and must "
-# "not conflict. You gave notNull=%r, notNone=%r"
-# % (notNull, notNone))
-# elif notNone is not NoDefault:
-# self.notNone = notNone
-# if self.notNone:
-# self.constraints = [consts.notNull] + self.constraints
-
-# self.name = attr_name
-# self.soClass = added_class
-# self._default = default
-# self.customSQLType = sqlType
-
-# # if they don't give us a specific database name for
-# # the column, we separate the mixedCase into mixed_case
-# # and assume that.
-# if dbName is None:
-# self.dbName = added_class.sqlmeta.style.pythonAttrToDBColumn(self.name)
-# else:
-# self.dbName = dbName
-
-# # alternateID means that this is a unique column that
-# # can be used to identify rows
-# self.alternateID = alternateID
-# if self.alternateID and alternateMethodName is None:
-# self.alternateMethodName = 'by' + self.name[0].capitalize() + self.name[1:]
-# else:
-# self.alternateMethodName = alternateMethodName
-
-# if unique is NoDefault:
-# self.unique = alternateID
-# else:
-# self.unique = unique
-# self.validator = validator
-# self.noCache = noCache
-# self.lazy = lazy
-
-# self.soClass.addColumn(self.name, self)
-
-# def _set_validator(self, value):
-# self._validator = value
-# if self._validator:
-# self.toPython = self._validator.toPython
-# self.fromPython = self._validator.fromPython
-# else:
-# self.toPython = None
-# self.fromPython = None
-
-# def _get_validator(self):
-# return self._validator
-
-# validator = property(_get_validator, _set_validator)
-
-# def autoConstraints(self):
-# return []
-
-# def _get_default(self):
-# # A default can be a callback or a plain value,
-# # here we resolve the callback
-# if self._default is NoDefault:
-# return NoDefault
-# elif hasattr(self._default, '__sqlrepr__'):
-# return self._default
-# elif callable(self._default):
-# return self._default()
-# else:
-# return self._default
-# default = property(_get_default, None, None)
-
-# def __repr__(self):
-# r = '<%s %s' % (self.__class__.__name__, self.name)
-# if self.default is not NoDefault:
-# r += ' default=%s' % repr(self.default)
-# if self.foreignKey:
-# r += ' connected to %s' % self.foreignKey
-# if self.alternateID:
-# r += ' alternate ID'
-# if self.notNone:
-# r += ' not null'
-# return r + '>'
-
-# def createSQL(self, dbname):
-# if self.customSQLType is not None:
-# return self.customSQLType
-# try:
-# func = self.sqlTypeRegistry[dbname]
-# except KeyError:
-# assert 0, (
-# "The database %s does not support the column type %s "
-# "(no SQL type generator found; only %s found)"
-# % (dbname, self.__class__.__name__,
-# ', '.join(self.sqlTypeRegistry.keys())))
-# else:
-# return func(self, dbname)
-
-# def __get__(self, obj, type=None):
-# if obj is None:
-# # class attribute, return the descriptor itself
-# return self
-# if obj.sqlmeta.obsolete:
-# raise SQLObjectNotFound, (
-# "This object has been deleted from the database: %r"
-# % obj)
-# if obj.sqlmeta.cacheColumns:
-# columns = obj.sqlmeta._columnCache
-# if columns is None:
-# obj.sqlmeta.loadValues()
-# try:
-# return columns[name]
-# except KeyError:
-# return obj.sqlmeta.loadColumn(self)
-# else:
-# return obj.sqlmeta.loadColumn(self)
-
-# def __set__(self, obj, value):
-# if self.immutable:
-# raise AttributeError("The column %s.%s is immutable" %
-# (obj.__class__.__name__,
-# self.name))
-# obj.sqlmeta.setColumn(self, value)
-
-# def __delete__(self, obj):
-# raise AttributeError("I can't be deleted from %r" % obj)
-
-# class Col(boundattributes.BoundFactory):
-# factory_class = BoundCol
-
-# def addToClass(self, cls, addToThisClass, name):
-# me = self or cls
-# me.__addtoclass__(addToThisClass, name)
-# addToClass = declarative.classinstancemethod(addToClass)
-
-# class BoundStringCol(BoundCol):
-
-# def __init__(self, *args, **kw):
-# self.length = popKey(kw, 'length')
-# self.varchar = popKey(kw, 'varchar', 'auto')
-# if not self.length:
-# assert self.varchar == 'auto' or not self.varchar, (
-# "Without a length strings are treated as TEXT, not "
-# "VARCHAR")
-# self.varchar = False
-# elif self.varchar == 'auto':
-# self.varchar = True
-# BoundCol.__init__(self, *args, **kw)
-
-# def autoConstraints(self):
-# constraints = [consts.isString]
-# if self.length is not None:
-# constraints += [consts.MaxLength(self.length)]
-# return constraints
-
-
-# class StringCol(Col):
-# factory_class = BoundStringCol
|
|
From: <sub...@co...> - 2005-04-04 05:54:22
|
Author: ianb
Date: 2005-04-04 05:54:10 +0000 (Mon, 04 Apr 2005)
New Revision: 707
Modified:
trunk/SQLObject/sqlobject/boundattributes.py
trunk/SQLObject/sqlobject/col.py
trunk/SQLObject/sqlobject/main.py
trunk/SQLObject/sqlobject/mysql/__init__.py
Log:
Added a default connection, sqlhub; made _connection.style setting in __classinit__ catch the AttributeError that hubs can throw
Modified: trunk/SQLObject/sqlobject/boundattributes.py
===================================================================
--- trunk/SQLObject/sqlobject/boundattributes.py 2005-04-04 02:21:00 UTC (rev 706)
+++ trunk/SQLObject/sqlobject/boundattributes.py 2005-04-04 05:54:10 UTC (rev 707)
@@ -100,8 +100,8 @@
factory_class = None
- def make_object(cls, *args, **kw):
- return cls.factory_class(*args, **kw)
+ def make_object(cls, added_class, attr_name, *args, **kw):
+ return cls.factory_class(added_class, attr_name, *args, **kw)
def bind_attributes(cls, new_attrs):
for name, value in new_attrs.items():
Modified: trunk/SQLObject/sqlobject/col.py
===================================================================
--- trunk/SQLObject/sqlobject/col.py 2005-04-04 02:21:00 UTC (rev 706)
+++ trunk/SQLObject/sqlobject/col.py 2005-04-04 05:54:10 UTC (rev 707)
@@ -980,3 +980,218 @@
all.append(key)
__all__.extend(all)
del all
+
+
+
+# import boundattributes
+# import declarative
+
+# class BoundCol(object):
+
+# __metaclass__ = declarative.DeclarativeMeta
+
+# sqlTypeRegistry = {}
+
+# def __classinit__(cls, new_attrs):
+# cls.sqlTypeRegistry = cls.sqlTypeRegistry.copy()
+
+# def registerSQLType(cls, dbname, type_func):
+# if not isinstance(dbname, (list, tuple)):
+# dbname = [dbname]
+# for name in dbname:
+# cls.sqlTypeRegistry[name] = type_func
+# registerSQLType = classmethod(registerSQLType)
+
+# def __init__(self, added_class, attr_name,
+# dbName=None,
+# default=NoDefault,
+# alternateID=False,
+# alternateMethodName=None,
+# constraints=None,
+# notNull=NoDefault,
+# notNon=NoDefault,
+# sqlType=None,
+# validator=None,
+# immutable=False,
+# cascade=None,
+# lazy=False,
+# noCache=False,
+# forceDBName=False):
+# if not forceDBName:
+# assert sqlbuilder.sqlIdentifier(name), (
+# "Name must be SQL-safe (letters, numbers, underscores): "
+# "%s (or use forceDBName=True)" % repr(name))
+# assert attr_name != 'id', (
+# "The column name 'id' is reserved for SQLObject use (and is "
+# "implicitly created).")
+# assert name, "You must provide a name for all columns"
+# self.immutable = immutable
+# assert cascade in (None, True, False), (
+# "The cascade attribute must be one of None, True, or False "
+# "(you gave: %r" % cascade)
+# self.cascade = cascade
+
+# if not isinstance(constraints, (list, tuple)):
+# constraints = [constraints]
+# self.constraints = self.autoConstraints() + constraints
+
+# self.notNone = False
+# if notNull is not NoDefault:
+# self.notNone = notNull
+# assert (notNone is NoDefault or
+# (not notNone) == (not notNull)), (
+# "The notNull and notNone arguments are aliases, and must "
+# "not conflict. You gave notNull=%r, notNone=%r"
+# % (notNull, notNone))
+# elif notNone is not NoDefault:
+# self.notNone = notNone
+# if self.notNone:
+# self.constraints = [consts.notNull] + self.constraints
+
+# self.name = attr_name
+# self.soClass = added_class
+# self._default = default
+# self.customSQLType = sqlType
+
+# # if they don't give us a specific database name for
+# # the column, we separate the mixedCase into mixed_case
+# # and assume that.
+# if dbName is None:
+# self.dbName = added_class.sqlmeta.style.pythonAttrToDBColumn(self.name)
+# else:
+# self.dbName = dbName
+
+# # alternateID means that this is a unique column that
+# # can be used to identify rows
+# self.alternateID = alternateID
+# if self.alternateID and alternateMethodName is None:
+# self.alternateMethodName = 'by' + self.name[0].capitalize() + self.name[1:]
+# else:
+# self.alternateMethodName = alternateMethodName
+
+# if unique is NoDefault:
+# self.unique = alternateID
+# else:
+# self.unique = unique
+# self.validator = validator
+# self.noCache = noCache
+# self.lazy = lazy
+
+# self.soClass.addColumn(self.name, self)
+
+# def _set_validator(self, value):
+# self._validator = value
+# if self._validator:
+# self.toPython = self._validator.toPython
+# self.fromPython = self._validator.fromPython
+# else:
+# self.toPython = None
+# self.fromPython = None
+
+# def _get_validator(self):
+# return self._validator
+
+# validator = property(_get_validator, _set_validator)
+
+# def autoConstraints(self):
+# return []
+
+# def _get_default(self):
+# # A default can be a callback or a plain value,
+# # here we resolve the callback
+# if self._default is NoDefault:
+# return NoDefault
+# elif hasattr(self._default, '__sqlrepr__'):
+# return self._default
+# elif callable(self._default):
+# return self._default()
+# else:
+# return self._default
+# default = property(_get_default, None, None)
+
+# def __repr__(self):
+# r = '<%s %s' % (self.__class__.__name__, self.name)
+# if self.default is not NoDefault:
+# r += ' default=%s' % repr(self.default)
+# if self.foreignKey:
+# r += ' connected to %s' % self.foreignKey
+# if self.alternateID:
+# r += ' alternate ID'
+# if self.notNone:
+# r += ' not null'
+# return r + '>'
+
+# def createSQL(self, dbname):
+# if self.customSQLType is not None:
+# return self.customSQLType
+# try:
+# func = self.sqlTypeRegistry[dbname]
+# except KeyError:
+# assert 0, (
+# "The database %s does not support the column type %s "
+# "(no SQL type generator found; only %s found)"
+# % (dbname, self.__class__.__name__,
+# ', '.join(self.sqlTypeRegistry.keys())))
+# else:
+# return func(self, dbname)
+
+# def __get__(self, obj, type=None):
+# if obj is None:
+# # class attribute, return the descriptor itself
+# return self
+# if obj.sqlmeta.obsolete:
+# raise SQLObjectNotFound, (
+# "This object has been deleted from the database: %r"
+# % obj)
+# if obj.sqlmeta.cacheColumns:
+# columns = obj.sqlmeta._columnCache
+# if columns is None:
+# obj.sqlmeta.loadValues()
+# try:
+# return columns[name]
+# except KeyError:
+# return obj.sqlmeta.loadColumn(self)
+# else:
+# return obj.sqlmeta.loadColumn(self)
+
+# def __set__(self, obj, value):
+# if self.immutable:
+# raise AttributeError("The column %s.%s is immutable" %
+# (obj.__class__.__name__,
+# self.name))
+# obj.sqlmeta.setColumn(self, value)
+
+# def __delete__(self, obj):
+# raise AttributeError("I can't be deleted from %r" % obj)
+
+# class Col(boundattributes.BoundFactory):
+# factory_class = BoundCol
+
+# def addToClass(self, cls, addToThisClass, name):
+# me = self or cls
+# me.__addtoclass__(addToThisClass, name)
+# addToClass = declarative.classinstancemethod(addToClass)
+
+# class BoundStringCol(BoundCol):
+
+# def __init__(self, *args, **kw):
+# self.length = popKey(kw, 'length')
+# self.varchar = popKey(kw, 'varchar', 'auto')
+# if not self.length:
+# assert self.varchar == 'auto' or not self.varchar, (
+# "Without a length strings are treated as TEXT, not "
+# "VARCHAR")
+# self.varchar = False
+# elif self.varchar == 'auto':
+# self.varchar = True
+# BoundCol.__init__(self, *args, **kw)
+
+# def autoConstraints(self):
+# constraints = [consts.isString]
+# if self.length is not None:
+# constraints += [consts.MaxLength(self.length)]
+# return constraints
+
+
+# class StringCol(Col):
+# factory_class = BoundStringCol
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-04-04 02:21:00 UTC (rev 706)
+++ trunk/SQLObject/sqlobject/main.py 2005-04-04 05:54:10 UTC (rev 707)
@@ -187,10 +187,12 @@
def setClass(cls, soClass):
cls.soClass = soClass
if not cls.style:
- if cls.soClass._connection and cls.soClass._connection.style:
- cls.style = cls.soClass._connection.style
- else:
- cls.style = styles.defaultStyle
+ cls.style = styles.defaultStyle
+ try:
+ if cls.soClass._connection and cls.soClass._connection.style:
+ cls.style = cls.soClass._connection.style
+ except AttributeError:
+ pass
if cls.table is None:
cls.table = cls.style.pythonClassToDBTable(cls.soClass.__name__)
if cls.idName is None:
@@ -221,6 +223,8 @@
setClass = classmethod(setClass)
+sqlhub = dbconnection.ConnectionHub()
+
class _sqlmeta_attr(object):
def __init__(self, name, deprecation_level):
@@ -267,7 +271,7 @@
# will be true. It's false by default:
_SO_perConnection = False
- _connection = None
+ _connection = sqlhub
_columns = []
@@ -1397,4 +1401,4 @@
__all__ = ['NoDefault', 'SQLObject', 'sqlmeta',
'getID', 'getObject',
- 'SQLObjectNotFound']
+ 'SQLObjectNotFound', 'sqlhub']
Modified: trunk/SQLObject/sqlobject/mysql/__init__.py
===================================================================
--- trunk/SQLObject/sqlobject/mysql/__init__.py 2005-04-04 02:21:00 UTC (rev 706)
+++ trunk/SQLObject/sqlobject/mysql/__init__.py 2005-04-04 05:54:10 UTC (rev 707)
@@ -1,4 +1,5 @@
from sqlobject.dbconnection import registerConnection
+#import mysqltypes
def builder():
import mysqlconnection
|
|
From: <sub...@co...> - 2005-04-04 02:21:05
|
Author: ianb
Date: 2005-04-04 02:21:00 +0000 (Mon, 04 Apr 2005)
New Revision: 706
Modified:
trunk/SQLObject/sqlobject/manager/command.py
Log:
Added support for WSGIKit configuration files, including 'database' key and 'sys_path' key
Modified: trunk/SQLObject/sqlobject/manager/command.py
===================================================================
--- trunk/SQLObject/sqlobject/manager/command.py 2005-04-04 02:20:15 UTC (rev 705)
+++ trunk/SQLObject/sqlobject/manager/command.py 2005-04-04 02:21:00 UTC (rev 706)
@@ -3,6 +3,10 @@
import fnmatch
import os
import sys
+try:
+ from wsgikit import pyconfig
+except ImportError:
+ pyconfig = None
import sqlobject
from sqlobject.util import moduleloader
@@ -65,6 +69,11 @@
help="The database connection URI",
metavar='URI',
dest='connection_uri')
+ if pyconfig:
+ parser.add_option('-f', '--config-file',
+ help="The WSGIKit config file that contains the database URI (in the database key)",
+ metavar="FILE",
+ dest="config_file")
parser.add_option('-m', '--module',
help="Module in which to find SQLObject classes",
action='append',
@@ -138,6 +147,9 @@
if not getattr(self.options, var_name, None):
self.runner.invalid(
'You must provide the option %s' % option_name)
+ conf = self.config()
+ if conf and conf.get('sys_path'):
+ update_sys_path(conf['sys_path'], self.options.verbose)
self.command()
def classes(self, require_connection=True):
@@ -193,11 +205,27 @@
return all
def connection(self):
- if getattr(self.options, 'connection_uri', None):
+ config = self.config()
+ if config is not None:
+ assert config.get('database'), (
+ "No database variable found in config file %s"
+ % self.options.config_file)
+ return sqlobject.connectionForURI(config['database'])
+ elif getattr(self.options, 'connection_uri', None):
return sqlobject.connectionForURI(self.options.connection_uri)
else:
return None
+ def config(self):
+ if getattr(self.options, 'config_file', None):
+ assert pyconfig, (
+ "The --config-file option should not be available without wsgikit.pyconfig installed")
+ config = pyconfig.Config()
+ config.load(self.options.config_file)
+ return config
+ else:
+ return None
+
def classes_from_package(self, package_name):
raise NotImplementedError
@@ -417,6 +445,15 @@
print '%s (Aliases: %s)' % (
' '*max_len, ', '.join(command.aliases))
+def update_sys_path(paths, verbose):
+ if isinstance(paths, (str, unicode)):
+ paths = [paths]
+ for path in paths:
+ path = os.path.abspath(path)
+ if path not in sys.path:
+ if verbose:
+ print 'Adding %s to path' % path
+ sys.path.append(path)
if __name__ == '__main__':
the_runner.run(sys.argv)
|
|
From: <sub...@co...> - 2005-04-04 02:20:20
|
Author: ianb
Date: 2005-04-04 02:20:15 +0000 (Mon, 04 Apr 2005)
New Revision: 705
Modified:
trunk/SQLObject/scripts/sqlobject-admin
Log:
Fixed sys.path fixup
Modified: trunk/SQLObject/scripts/sqlobject-admin
===================================================================
--- trunk/SQLObject/scripts/sqlobject-admin 2005-04-02 00:14:25 UTC (rev 704)
+++ trunk/SQLObject/scripts/sqlobject-admin 2005-04-04 02:20:15 UTC (rev 705)
@@ -11,8 +11,8 @@
updir = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(here))),
'sqlobject')
- if sys.path.exists(updir):
- sys.path.insert(0, updir)
+ if os.path.exists(updir):
+ sys.path.insert(0, os.path.dirname(updir))
else:
print 'I cannot find the sqlobject module'
print 'If SQLObject is installed, you may need to set $PYTHONPATH'
|
|
From: <sub...@co...> - 2005-04-02 00:14:33
|
Author: ianb
Date: 2005-04-02 00:14:25 +0000 (Sat, 02 Apr 2005)
New Revision: 704
Modified:
trunk/SQLObject/sqlobject/manager/command.py
Log:
Added status command
Modified: trunk/SQLObject/sqlobject/manager/command.py
===================================================================
--- trunk/SQLObject/sqlobject/manager/command.py 2005-04-01 23:54:02 UTC (rev 703)
+++ trunk/SQLObject/sqlobject/manager/command.py 2005-04-02 00:14:25 UTC (rev 704)
@@ -116,11 +116,12 @@
self.runner = runner
def run(self):
- self.parser.usage = "%%prog [options]\n%s" % (
- self.description or self.summary)
+ self.parser.usage = "%%prog [options]\n%s" % self.summary
self.parser.prog = '%s %s' % (
os.path.basename(self.invoked_as),
self.command_name)
+ if self.description:
+ self.parser.description = description
self.options, self.args = self.parser.parse_args(self.raw_args)
if (getattr(self.options, 'simulate', False)
and not self.options.verbose):
@@ -192,7 +193,7 @@
return all
def connection(self):
- if self.options.connection_uri:
+ if getattr(self.options, 'connection_uri', None):
return sqlobject.connectionForURI(self.options.connection_uri)
else:
return None
@@ -324,6 +325,70 @@
print '%i tables dropped (%i didn\'t exist)' % (
dropped, not_existing)
+class CommandStatus(Command):
+
+ name = 'status'
+ summary = 'Show status of classes vs. database'
+
+ parser = standard_parser(simulate=False)
+
+ def print_class(self, soClass):
+ if self.printed:
+ return
+ self.printed = True
+ print 'Checking %s...' % soClass.__name__
+
+ def command(self):
+ good = 0
+ bad = 0
+ missing_tables = 0
+ columnsFromSchema_warning = False
+ for soClass in self.classes():
+ conn = soClass._connection
+ self.printed = False
+ if self.options.verbose:
+ self.print_class(soClass)
+ if not conn.tableExists(soClass.sqlmeta.table):
+ self.print_class(soClass)
+ print ' Does not exist in database'
+ missing_tables += 1
+ continue
+ try:
+ columns = conn.columnsFromSchema(soClass.sqlmeta.table,
+ soClass)
+ except AttributeError:
+ if not columnsFromSchema_warning:
+ print 'Database does not support reading columns'
+ columnsFromSchema_warning = True
+ good += 1
+ continue
+ existing = {}
+ for col in columns:
+ col = col.withClass(soClass)
+ existing[col.dbName] = col
+ missing = {}
+ for col in soClass.sqlmeta._columns:
+ if existing.has_key(col.dbName):
+ del existing[col.dbName]
+ else:
+ missing[col.dbName] = col
+ if existing:
+ self.print_class(soClass)
+ for col in existing.values():
+ print ' Database has extra column: %s' % col.dbName
+ if missing:
+ self.print_class(soClass)
+ for col in missing.values():
+ print ' Database missing column: %s' % col.dbName
+ if existing or missing:
+ bad += 1
+ else:
+ good += 1
+ if self.options.verbose:
+ print '%i in sync; %i out of sync; %i not in database' % (
+ good, bad, missing_tables)
+
+
class CommandHelp(Command):
name = 'help'
|
|
From: <sub...@co...> - 2005-04-01 23:54:05
|
Author: ianb
Date: 2005-04-01 23:54:02 +0000 (Fri, 01 Apr 2005)
New Revision: 703
Modified:
trunk/SQLObject/sqlobject/manager/command.py
Log:
Improve error and help messages slightly
Modified: trunk/SQLObject/sqlobject/manager/command.py
===================================================================
--- trunk/SQLObject/sqlobject/manager/command.py 2005-04-01 23:36:18 UTC (rev 702)
+++ trunk/SQLObject/sqlobject/manager/command.py 2005-04-01 23:54:02 UTC (rev 703)
@@ -25,7 +25,8 @@
break
else:
# no command found
- self.invalid('No COMMAND given')
+ self.invalid('No COMMAND given (try "%s help")'
+ % os.path.basename(invoked_as))
real_command = self.command_aliases.get(command, command)
if real_command not in self.commands.keys():
self.invalid('COMMAND %s unknown' % command)
@@ -100,6 +101,7 @@
max_args_error = 'You must provide no more than %(max_args)s arguments'
aliases = ()
required_args = []
+ description = None
def __classinit__(cls, new_args):
if cls.__bases__ == (object,):
@@ -114,6 +116,11 @@
self.runner = runner
def run(self):
+ self.parser.usage = "%%prog [options]\n%s" % (
+ self.description or self.summary)
+ self.parser.prog = '%s %s' % (
+ os.path.basename(self.invoked_as),
+ self.command_name)
self.options, self.args = self.parser.parse_args(self.raw_args)
if (getattr(self.options, 'simulate', False)
and not self.options.verbose):
@@ -331,8 +338,9 @@
the_runner.run([self.invoked_as, self.args[0], '-h'])
else:
print 'Available commands:'
- print ' (use "%s help COMMAND" or "%s COMMAND -h" for more)' % (
+ print ' (use "%s help COMMAND" or "%s COMMAND -h" ' % (
self.prog_name, self.prog_name)
+ print ' for more information)'
items = the_runner.commands.items()
items.sort()
max_len = max([len(cn) for cn, c in items])
|
|
From: <sub...@co...> - 2005-04-01 23:36:41
|
Author: ianb
Date: 2005-04-01 23:36:18 +0000 (Fri, 01 Apr 2005)
New Revision: 702
Added:
trunk/SQLObject/scripts/
trunk/SQLObject/scripts/sqlobject-admin
trunk/SQLObject/sqlobject/manager/
trunk/SQLObject/sqlobject/manager/__init__.py
trunk/SQLObject/sqlobject/manager/command.py
trunk/SQLObject/sqlobject/util/moduleloader.py
Modified:
trunk/SQLObject/setup.py
Log:
First go at a command-line client
Added: trunk/SQLObject/scripts/sqlobject-admin
===================================================================
--- trunk/SQLObject/scripts/sqlobject-admin 2005-04-01 22:41:16 UTC (rev 701)
+++ trunk/SQLObject/scripts/sqlobject-admin 2005-04-01 23:36:18 UTC (rev 702)
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+import sys
+import os
+try:
+ import sqlobject
+except ImportError:
+ try:
+ here = __file__
+ except NameError:
+ here = sys.argv[0]
+ updir = os.path.join(
+ os.path.dirname(os.path.dirname(os.path.abspath(here))),
+ 'sqlobject')
+ if sys.path.exists(updir):
+ sys.path.insert(0, updir)
+ else:
+ print 'I cannot find the sqlobject module'
+ print 'If SQLObject is installed, you may need to set $PYTHONPATH'
+ sys.exit(3)
+
+from sqlobject.manager import command
+command.the_runner.run(sys.argv)
+
Property changes on: trunk/SQLObject/scripts/sqlobject-admin
___________________________________________________________________
Name: svn:executable
+ *
Modified: trunk/SQLObject/setup.py
===================================================================
--- trunk/SQLObject/setup.py 2005-04-01 22:41:16 UTC (rev 701)
+++ trunk/SQLObject/setup.py 2005-04-01 23:36:18 UTC (rev 702)
@@ -3,7 +3,7 @@
warnings.filterwarnings("ignore", "Unknown distribution option")
subpackages = ['firebird', 'include', 'inheritance', 'mysql', 'postgres',
- 'sqlite', 'sybase', 'maxdb']
+ 'sqlite', 'sybase', 'maxdb', 'util', 'manager']
import sys
# patch distutils if it can't cope with the "classifiers" keyword
@@ -34,6 +34,7 @@
url="http://sqlobject.org",
license="LGPL",
packages=["sqlobject"] + ['sqlobject.%s' % package for package in subpackages],
+ scripts=["scripts/sqlobject-admin"],
download_url="http://prdownloads.sourceforge.net/sqlobject/SQLObject-0.6.1.tar.gz?download")
# Send announce to:
Added: trunk/SQLObject/sqlobject/manager/__init__.py
===================================================================
--- trunk/SQLObject/sqlobject/manager/__init__.py 2005-04-01 22:41:16 UTC (rev 701)
+++ trunk/SQLObject/sqlobject/manager/__init__.py 2005-04-01 23:36:18 UTC (rev 702)
@@ -0,0 +1 @@
+#
Added: trunk/SQLObject/sqlobject/manager/command.py
===================================================================
--- trunk/SQLObject/sqlobject/manager/command.py 2005-04-01 22:41:16 UTC (rev 701)
+++ trunk/SQLObject/sqlobject/manager/command.py 2005-04-01 23:36:18 UTC (rev 702)
@@ -0,0 +1,349 @@
+#!/usr/bin/env python
+import optparse
+import fnmatch
+import os
+import sys
+
+import sqlobject
+from sqlobject.util import moduleloader
+from sqlobject.declarative import DeclarativeMeta
+
+class CommandRunner(object):
+
+ def __init__(self):
+ self.commands = {}
+ self.command_aliases = {}
+
+ def run(self, argv):
+ invoked_as = argv[0]
+ args = argv[1:]
+ for i in range(len(args)):
+ if not args[i].startswith('-'):
+ # this must be a command
+ command = args[i].lower()
+ del args[i]
+ break
+ else:
+ # no command found
+ self.invalid('No COMMAND given')
+ real_command = self.command_aliases.get(command, command)
+ if real_command not in self.commands.keys():
+ self.invalid('COMMAND %s unknown' % command)
+ runner = self.commands[real_command](
+ invoked_as, command, args, self)
+ runner.run()
+
+ def register(self, command):
+ name = command.name
+ self.commands[name] = command
+ for alias in command.aliases:
+ self.command_aliases[alias] = name
+
+ def invalid(self, msg, code=2):
+ print msg
+ sys.exit(code)
+
+the_runner = CommandRunner()
+register = the_runner.register
+
+def standard_parser(connection=True, simulate=True,
+ interactive=False):
+ parser = optparse.OptionParser()
+ parser.add_option('-v', '--verbose',
+ help='Be verbose (multiple times for more verbosity)',
+ action='count',
+ dest='verbose',
+ default=0)
+ if simulate:
+ parser.add_option('-n', '--simulate',
+ help="Don't actually do anything (implies -v)",
+ action='store_true',
+ dest='simulate')
+ if connection:
+ parser.add_option('-c', '--connection',
+ help="The database connection URI",
+ metavar='URI',
+ dest='connection_uri')
+ parser.add_option('-m', '--module',
+ help="Module in which to find SQLObject classes",
+ action='append',
+ metavar='MODULE',
+ dest='modules',
+ default=[])
+ parser.add_option('-p', '--package',
+ help="Package to search for SQLObject classes",
+ action="append",
+ metavar="PACKAGE",
+ dest="packages",
+ default=[])
+ parser.add_option('--class',
+ help="Select only named classes (wildcards allowed)",
+ action="append",
+ metavar="NAME",
+ dest="class_matchers",
+ default=[])
+ if interactive:
+ parser.add_option('-i', '--interactive',
+ help="Ask before doing anything (use twice to be more careful)",
+ action="count",
+ dest="interactive",
+ default=0)
+ return parser
+
+class Command(object):
+
+ __metaclass__ = DeclarativeMeta
+
+ min_args = 0
+ min_args_error = 'You must provide at least %(min_args)s arguments'
+ max_args = 0
+ max_args_error = 'You must provide no more than %(max_args)s arguments'
+ aliases = ()
+ required_args = []
+
+ def __classinit__(cls, new_args):
+ if cls.__bases__ == (object,):
+ # This abstract base class
+ return
+ register(cls)
+
+ def __init__(self, invoked_as, command_name, args, runner):
+ self.invoked_as = invoked_as
+ self.command_name = command_name
+ self.raw_args = args
+ self.runner = runner
+
+ def run(self):
+ self.options, self.args = self.parser.parse_args(self.raw_args)
+ if (getattr(self.options, 'simulate', False)
+ and not self.options.verbose):
+ self.options.verbose = 1
+ if self.min_args is not None and len(self.args) < self.min_args:
+ self.runner.invalid(
+ self.min_args_error % {'min_args': self.min_args,
+ 'actual_args': len(self.args)})
+ if self.max_args is not None and len(self.args) > self.max_args:
+ self.runner.invalid(
+ self.max_args_error % {'max_args': self.max_args,
+ 'actual_args': len(self.args)})
+ for var_name, option_name in self.required_args:
+ if not getattr(self.options, var_name, None):
+ self.runner.invalid(
+ 'You must provide the option %s' % option_name)
+ self.command()
+
+ def classes(self, require_connection=True):
+ all = []
+ for module_name in self.options.modules:
+ all.extend(self.classes_from_module(
+ moduleloader.load_module(module_name)))
+ for package_name in self.options.packages:
+ all.extend(self.classes_from_package(package_name))
+ if self.options.class_matchers:
+ filtered = []
+ for soClass in all:
+ name = soClass.__name__
+ for matcher in self.options.class_matchers:
+ if fnmatch.fnmatch(name, matcher):
+ filtered.append(soClass)
+ break
+ all = filtered
+ conn = self.connection()
+ if conn:
+ for soClass in all:
+ soClass._connection = conn
+ else:
+ missing = []
+ for soClass in all:
+ try:
+ if not soClass._connection:
+ missing.append(soClass)
+ except AttributeError:
+ missing.append(soClass)
+ if missing and require_connection:
+ self.runner.invalid(
+ 'These classes do not have connections set:\n * %s\n'
+ 'You must indicate --connection=URI'
+ % '\n * '.join([soClass.__name__
+ for soClass in missing]))
+ return all
+
+ def classes_from_module(self, module):
+ all = []
+ if hasattr(module, 'soClasses'):
+ for name_or_class in module.soClasses:
+ if isinstance(name_or_class, str):
+ name_or_class = getattr(module, name_or_class)
+ all.append(name_or_class)
+ else:
+ for name in dir(module):
+ value = getattr(module, name)
+ if (isinstance(value, type)
+ and issubclass(value, sqlobject.SQLObject)
+ and value.__module__ == module.__name__):
+ all.append(value)
+ return all
+
+ def connection(self):
+ if self.options.connection_uri:
+ return sqlobject.connectionForURI(self.options.connection_uri)
+ else:
+ return None
+
+ def classes_from_package(self, package_name):
+ raise NotImplementedError
+
+ def command(self):
+ raise NotImplementedError
+
+ def _get_prog_name(self):
+ return os.path.basename(self.invoked_as)
+ prog_name = property(_get_prog_name)
+
+ def ask(self, prompt, safe=False, default=True):
+ if self.options.interactive >= 2:
+ default = safe
+ if default:
+ prompt += ' [Y/n]? '
+ else:
+ prompt += ' [y/N]? '
+ while 1:
+ response = raw_input(prompt).strip()
+ if not response.strip():
+ return default
+ if response and response[0].lower() in ('y', 'n'):
+ return response[0].lower() == 'y'
+ print 'Y or N please'
+
+class CommandSQL(Command):
+
+ name = 'sql'
+ summary = 'Show SQL CREATE statements'
+
+ parser = standard_parser(simulate=False)
+
+ def command(self):
+ classes = self.classes()
+ for cls in classes:
+ if self.options.verbose >= 1:
+ print '-- %s from %s' % (
+ cls.__name__, cls.__module__)
+ print cls.createTableSQL().strip() + ';\n'
+
+class CommandList(Command):
+
+ name = 'list'
+ summary = 'Show all SQLObject classes found'
+
+ parser = standard_parser(simulate=False, connection=False)
+
+ def command(self):
+ if self.options.verbose >= 1:
+ print 'Classes found:'
+ classes = self.classes(require_connection=False)
+ for soClass in classes:
+ print '%s.%s' % (soClass.__module__, soClass.__name__)
+ if self.options.verbose >= 1:
+ print ' Table: %s' % soClass.sqlmeta.table
+
+class CommandCreate(Command):
+
+ name = 'create'
+ summary = 'Create tables'
+
+ parser = standard_parser(interactive=True)
+
+ def command(self):
+ v = self.options.verbose
+ created = 0
+ existing = 0
+ for soClass in self.classes():
+ exists = soClass._connection.tableExists(soClass.sqlmeta.table)
+ if v >= 1:
+ if exists:
+ existing += 1
+ print '%s already exists.' % soClass.__name__
+ else:
+ print 'Creating %s' % soClass.__name__
+ if v >= 2:
+ print soClass.createTableSQL()
+ if (not self.options.simulate
+ and not exists):
+ if self.options.interactive:
+ if self.ask('Create %s' % soClass.__name__):
+ created += 1
+ soClass.createTable()
+ else:
+ print 'Cancelled'
+ else:
+ created += 1
+ soClass.createTable()
+ if v >= 1:
+ print '%i tables created (%i already exist)' % (
+ created, existing)
+
+
+class CommandDrop(Command):
+
+ name = 'drop'
+ summary = 'Drop tables'
+
+ parser = standard_parser(interactive=True)
+
+ def command(self):
+ v = self.options.verbose
+ dropped = 0
+ not_existing = 0
+ for soClass in self.classes():
+ exists = soClass._connection.tableExists(soClass.sqlmeta.table)
+ if v >= 1:
+ if exists:
+ print 'Dropping %s' % soClass.__name__
+ else:
+ not_existing += 1
+ print '%s does not exist.' % soClass.__name__
+ if (not self.options.simulate
+ and exists):
+ if self.options.interactive:
+ if self.ask('Drop %s' % soClass.__name__):
+ dropped += 1
+ soClass.dropTable()
+ else:
+ print 'Cancelled'
+ else:
+ dropped += 1
+ soClass.dropTable()
+ if v >= 1:
+ print '%i tables dropped (%i didn\'t exist)' % (
+ dropped, not_existing)
+
+class CommandHelp(Command):
+
+ name = 'help'
+ summary = 'Show help'
+
+ parser = optparse.OptionParser()
+
+ max_args = 1
+
+ def command(self):
+ if self.args:
+ the_runner.run([self.invoked_as, self.args[0], '-h'])
+ else:
+ print 'Available commands:'
+ print ' (use "%s help COMMAND" or "%s COMMAND -h" for more)' % (
+ self.prog_name, self.prog_name)
+ items = the_runner.commands.items()
+ items.sort()
+ max_len = max([len(cn) for cn, c in items])
+ for command_name, command in items:
+ print '%s:%s %s' % (command_name,
+ ' '*(max_len-len(command_name)),
+ command.summary)
+ if command.aliases:
+ print '%s (Aliases: %s)' % (
+ ' '*max_len, ', '.join(command.aliases))
+
+
+if __name__ == '__main__':
+ the_runner.run(sys.argv)
Property changes on: trunk/SQLObject/sqlobject/manager/command.py
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/SQLObject/sqlobject/util/moduleloader.py
===================================================================
--- trunk/SQLObject/sqlobject/util/moduleloader.py 2005-04-01 22:41:16 UTC (rev 701)
+++ trunk/SQLObject/sqlobject/util/moduleloader.py 2005-04-01 23:36:18 UTC (rev 702)
@@ -0,0 +1,42 @@
+import sys
+import imp
+
+def load_module(module_name):
+ mod = __import__(module_name)
+ components = module_name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+def load_module_from_name(filename, module_name):
+ if sys.modules.has_key(module_name):
+ return sys.modules[module_name]
+ init_filename = os.path.join(os.path.dirname(filename), '__init__.py')
+ if not os.path.exists(init_filename):
+ try:
+ f = open(init_filename, 'w')
+ except (OSError, IOError), e:
+ raise IOError(
+ 'Cannot write __init__.py file into directory %s (%s)\n'
+ % (os.path.dirname(filename), e))
+ f.write('#\n')
+ f.close()
+ fp = None
+ if sys.modules.has_key(module_name):
+ return sys.modules[module_name]
+ if '.' in module_name:
+ parent_name = '.'.join(module_name.split('.')[:-1])
+ base_name = module_name.split('.')[-1]
+ parent = load_module_from_name(os.path.dirname(filename),
+ parent_name)
+ else:
+ base_name = module_name
+ fp = None
+ try:
+ fp, pathname, stuff = imp.find_module(
+ base_name, [os.path.dirname(filename)])
+ module = imp.load_module(module_name, fp, pathname, stuff)
+ finally:
+ if fp is not None:
+ fp.close()
+ return module
|
|
From: <sub...@co...> - 2005-04-01 22:41:19
|
Author: ianb
Date: 2005-04-01 22:41:16 +0000 (Fri, 01 Apr 2005)
New Revision: 701
Removed:
trunk/SQLObject/sqlobject/threadinglocal.py
Log:
and deleting...
Deleted: trunk/SQLObject/sqlobject/threadinglocal.py
===================================================================
--- trunk/SQLObject/sqlobject/threadinglocal.py 2005-04-01 22:40:51 UTC (rev 700)
+++ trunk/SQLObject/sqlobject/threadinglocal.py 2005-04-01 22:41:16 UTC (rev 701)
@@ -1,35 +0,0 @@
-try:
- import threading
-except ImportError:
- # No threads, so "thread local" means process-global
- class local(object):
- pass
-else:
- try:
- local = threading.local
- except AttributeError:
- # Added in 2.4, but now we'll have to define it ourselves
- import thread
- class local(object):
-
- def __init__(self):
- self.__dict__['__objs'] = {}
-
- def __getattr__(self, attr, g=thread.get_ident):
- try:
- return self.__dict__['__objs'][g()][attr]
- except KeyError:
- raise AttributeError(
- "No variable %s defined for the thread %s"
- % (attr, g()))
-
- def __setattr__(self, attr, value, g=thread.get_ident):
- self.__dict__['__objs'].setdefault(g(), {})[attr] = value
-
- def __delattr__(self, attr, g=thread.get_ident):
- try:
- del self.__dict__['__objs'][g()][attr]
- except KeyError:
- raise AttributeError(
- "No variable %s defined for thread %s"
- % (attr, g()))
|
|
From: <sub...@co...> - 2005-04-01 22:40:58
|
Author: ianb Date: 2005-04-01 22:40:51 +0000 (Fri, 01 Apr 2005) New Revision: 700 Added: trunk/SQLObject/sqlobject/util/__init__.py trunk/SQLObject/sqlobject/util/threadinglocal.py Modified: trunk/SQLObject/sqlobject/dbconnection.py Log: Moved threadinglocal into the util package Modified: trunk/SQLObject/sqlobject/dbconnection.py =================================================================== --- trunk/SQLObject/sqlobject/dbconnection.py 2005-04-01 17:45:03 UTC (rev 699) +++ trunk/SQLObject/sqlobject/dbconnection.py 2005-04-01 22:40:51 UTC (rev 700) @@ -3,7 +3,7 @@ True, False = 1==1, 0==1 import threading -from threadinglocal import local as threading_local +from util.threadinglocal import local as threading_local import re import warnings import atexit Added: trunk/SQLObject/sqlobject/util/__init__.py =================================================================== --- trunk/SQLObject/sqlobject/util/__init__.py 2005-04-01 17:45:03 UTC (rev 699) +++ trunk/SQLObject/sqlobject/util/__init__.py 2005-04-01 22:40:51 UTC (rev 700) @@ -0,0 +1 @@ +# Copied: trunk/SQLObject/sqlobject/util/threadinglocal.py (from rev 699, trunk/SQLObject/sqlobject/threadinglocal.py) |
|
From: <sub...@co...> - 2005-04-01 17:45:07
|
Author: ianb
Date: 2005-04-01 17:45:03 +0000 (Fri, 01 Apr 2005)
New Revision: 699
Added:
trunk/SQLObject/sqlobject/threadinglocal.py
Modified:
trunk/SQLObject/sqlobject/dbconnection.py
trunk/SQLObject/sqlobject/tests/dbtest.py
Log:
Added ConnectionHub, an alternate way to set up connections on a
process or thread basis. I'm not sure how to test it yet, except by
providing a different implementation of setupClass which uses it
(now commented out)
Modified: trunk/SQLObject/sqlobject/dbconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/dbconnection.py 2005-04-01 17:37:04 UTC (rev 698)
+++ trunk/SQLObject/sqlobject/dbconnection.py 2005-04-01 17:45:03 UTC (rev 699)
@@ -3,6 +3,7 @@
True, False = 1==1, 0==1
import threading
+from threadinglocal import local as threading_local
import re
import warnings
import atexit
@@ -255,7 +256,8 @@
elif self.autoCommit:
if self.debug:
self.printDebug(conn, 'auto', 'COMMIT')
- conn.commit()
+ if not getattr(conn, 'autocommit', False):
+ conn.commit()
else:
if self.debug:
self.printDebug(conn, 'auto', 'ROLLBACK')
@@ -727,6 +729,60 @@
return
self.rollback()
+class ConnectionHub(object):
+
+ """
+ This object serves as a hub for connections, so that you can pass
+ in a ConnectionHub to a SQLObject subclass as though it was a
+ connection, but actually bind a real database connection later.
+ You can also bind connections on a per-thread basis.
+
+ You must hang onto the original ConnectionHub instance, as you
+ cannot retrieve it again from the class or instance.
+
+ To use the hub, do something like::
+
+ hub = ConnectionHub()
+ class MyClass(SQLObject):
+ _connection = hub
+
+ hub.threadConnection = connectionFromURI('...')
+
+ """
+
+ def __init__(self):
+ self.threadingLocal = threading_local()
+
+ def __get__(self, obj, type=None):
+ return self.getConnection()
+
+ def __set__(self, obj, value):
+ obj.__dict__['_connection'] = value
+
+ def getConnection(self):
+ try:
+ return self.threadingLocal.connection
+ except AttributeError:
+ try:
+ return self.processConnection
+ except AttributeError:
+ raise AttributeError(
+ "No connection has been defined for this thread "
+ "or process")
+
+ def _set_threadConnection(self, value):
+ self.threadingLocal.connection = value
+
+ def _get_threadConnection(self):
+ return self.threadingLocal.connection
+
+ def _del_threadConnection(self):
+ del self.threadingLocal.connection
+
+ threadConnection = property(_get_threadConnection,
+ _set_threadConnection,
+ _del_threadConnection)
+
class ConnectionURIOpener(object):
def __init__(self):
Modified: trunk/SQLObject/sqlobject/tests/dbtest.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/dbtest.py 2005-04-01 17:37:04 UTC (rev 698)
+++ trunk/SQLObject/sqlobject/tests/dbtest.py 2005-04-01 17:45:03 UTC (rev 699)
@@ -63,10 +63,19 @@
B, then do setupClass([B, A]) and B won't be destroyed or cleared
until after A is destroyed or cleared.
"""
+ global hub
if not isinstance(soClasses, (list, tuple)):
soClasses = [soClasses]
connection = getConnection()
for soClass in soClasses:
+ ## This would be an alternate way to register connections...
+ #try:
+ # hub
+ #except NameError:
+ # hub = sqlobject.dbconnection.ConnectionHub()
+ #soClass._connection = hub
+ #hub.threadConnection = connection
+ #hub.processConnection = connection
soClass._connection = connection
installOrClear(soClasses)
return soClasses
Added: trunk/SQLObject/sqlobject/threadinglocal.py
===================================================================
--- trunk/SQLObject/sqlobject/threadinglocal.py 2005-04-01 17:37:04 UTC (rev 698)
+++ trunk/SQLObject/sqlobject/threadinglocal.py 2005-04-01 17:45:03 UTC (rev 699)
@@ -0,0 +1,35 @@
+try:
+ import threading
+except ImportError:
+ # No threads, so "thread local" means process-global
+ class local(object):
+ pass
+else:
+ try:
+ local = threading.local
+ except AttributeError:
+ # Added in 2.4, but now we'll have to define it ourselves
+ import thread
+ class local(object):
+
+ def __init__(self):
+ self.__dict__['__objs'] = {}
+
+ def __getattr__(self, attr, g=thread.get_ident):
+ try:
+ return self.__dict__['__objs'][g()][attr]
+ except KeyError:
+ raise AttributeError(
+ "No variable %s defined for the thread %s"
+ % (attr, g()))
+
+ def __setattr__(self, attr, value, g=thread.get_ident):
+ self.__dict__['__objs'].setdefault(g(), {})[attr] = value
+
+ def __delattr__(self, attr, g=thread.get_ident):
+ try:
+ del self.__dict__['__objs'][g()][attr]
+ except KeyError:
+ raise AttributeError(
+ "No variable %s defined for thread %s"
+ % (attr, g()))
|
|
From: <sub...@co...> - 2005-04-01 17:37:26
|
Author: ianb
Date: 2005-04-01 17:37:04 +0000 (Fri, 01 Apr 2005)
New Revision: 698
Modified:
trunk/SQLObject/sqlobject/tests/test_conngetter.py
Log:
Updated for changed private attribute name
Modified: trunk/SQLObject/sqlobject/tests/test_conngetter.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_conngetter.py 2005-04-01 17:36:23 UTC (rev 697)
+++ trunk/SQLObject/sqlobject/tests/test_conngetter.py 2005-04-01 17:37:04 UTC (rev 698)
@@ -22,7 +22,7 @@
TestSimple.dropTable(connection=conn, ifExists=True)
TestSimple.createTable(connection=conn, ifNotExists=True)
TestJoined.createTable(connection=conn, ifNotExists=True)
- assert conn.TestSimple.__sqlobject_class__ is TestSimple
+ assert conn.TestSimple._soClass is TestSimple
obj = conn.TestSimple(name='test')
assert (TestSimple.get(obj.id, connection=conn) is obj)
assert obj._connection is conn
|
|
From: <sub...@co...> - 2005-04-01 17:36:44
|
Author: ianb
Date: 2005-04-01 17:36:23 +0000 (Fri, 01 Apr 2005)
New Revision: 697
Modified:
trunk/SQLObject/sqlobject/col.py
Log:
Two bugs: the class wasn't being tracked by the columns (!), and when creating foreign key constraints we weren't looking up the other class respecting its registry
Modified: trunk/SQLObject/sqlobject/col.py
===================================================================
--- trunk/SQLObject/sqlobject/col.py 2005-04-01 17:34:57 UTC (rev 696)
+++ trunk/SQLObject/sqlobject/col.py 2005-04-01 17:36:23 UTC (rev 697)
@@ -140,7 +140,7 @@
self.constraints = [consts.notNull] + self.constraints
self.name = name
- self.soClass = None
+ self.soClass = soClass
self._default = default
self.customSQLType = sqlType
@@ -622,7 +622,8 @@
def postgresCreateSQL(self):
sql = SOKeyCol.postgresCreateSQL(self)
- other = findClass(self.foreignKey)
+ print [self, self.soClass]
+ other = findClass(self.foreignKey, self.soClass.sqlmeta.registry)
tName = other.sqlmeta.table
idName = other.sqlmeta.idName
if self.cascade is not None:
|
|
From: <sub...@co...> - 2005-04-01 17:35:27
|
Author: ianb
Date: 2005-04-01 17:34:57 +0000 (Fri, 01 Apr 2005)
New Revision: 696
Modified:
trunk/SQLObject/sqlobject/classregistry.py
Log:
Give better error message when a class is not found
Modified: trunk/SQLObject/sqlobject/classregistry.py
===================================================================
--- trunk/SQLObject/sqlobject/classregistry.py 2005-03-30 15:28:00 UTC (rev 695)
+++ trunk/SQLObject/sqlobject/classregistry.py 2005-04-01 17:34:57 UTC (rev 696)
@@ -98,7 +98,15 @@
callback(cls, *args, **kw)
def getClass(self, className):
- return self.classes[className]
+ try:
+ return self.classes[className]
+ except KeyError:
+ all = self.classes.keys()
+ all.sort()
+ raise KeyError(
+ "No class %s found in the registry %s (these classes "
+ "exist: %s)"
+ % (className, self.name or '[default]', ', '.join(all)))
def allClasses(self):
return self.classes.values()
|
|
From: <sub...@co...> - 2005-03-30 15:28:05
|
Author: phd
Date: 2005-03-30 15:28:00 +0000 (Wed, 30 Mar 2005)
New Revision: 695
Modified:
trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
Log:
Added "unix_socket", "named_pipe", "init_command", "read_default_file", "read_default_group",
"connect_time", "compress", "named_pipe", "use_unicode", "client_flag", "local_infile" parameters.
Modified: trunk/SQLObject/sqlobject/mysql/mysqlconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2005-03-30 15:23:45 UTC (rev 694)
+++ trunk/SQLObject/sqlobject/mysql/mysqlconnection.py 2005-03-30 15:28:00 UTC (rev 695)
@@ -18,6 +18,15 @@
self.db = db
self.user = user
self.password = passwd
+ self.kw = {}
+ for key in ("unix_socket", "named_pipe", "init_command",
+ "read_default_file", "read_default_group"):
+ if key in kw:
+ self.kw[key] = col.popKey(kw, key)
+ for key in ("connect_time", "compress", "named_pipe", "use_unicode",
+ "client_flag", "local_infile"):
+ if key in kw:
+ self.kw[key] = int(col.popKey(kw, key))
DBAPI.__init__(self, **kw)
def connectionFromURI(cls, uri):
@@ -29,7 +38,7 @@
def makeConnection(self):
try:
conn = self.module.connect(host=self.host, port=self.port,
- db=self.db, user=self.user, passwd=self.password)
+ db=self.db, user=self.user, passwd=self.password, **self.kw)
except self.module.OperationalError, e:
raise self.module.OperationalError(
"%s; used connection string: host=%s, port=%s, db=%s, user=%s, pwd=%s" % (
|
|
From: <sub...@co...> - 2005-03-30 15:23:55
|
Author: phd
Date: 2005-03-30 15:23:45 +0000 (Wed, 30 Mar 2005)
New Revision: 694
Modified:
trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py
Log:
Applied patch 1172964, and added "mode" and "encoding" parameters.
Modified: trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py 2005-03-30 11:54:36 UTC (rev 693)
+++ trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py 2005-03-30 15:23:45 UTC (rev 694)
@@ -1,4 +1,5 @@
from sqlobject.dbconnection import DBAPI
+from sqlobject.col import popKey
sqlite = None
class SQLiteConnection(DBAPI):
@@ -16,9 +17,17 @@
if not autoCommit and not kw.has_key('pool'):
# Pooling doesn't work with transactions...
kw['pool'] = 0
- # use only one connection for sqlite - supports multiple
+ # connection options
+ opts = {'autocommit': autoCommit}
+ if 'encoding' in kw:
+ opts['encoding'] = popKey(kw, 'encoding')
+ if 'mode' in kw:
+ opts['mode'] = int(popKey(kw, 'mode'), 0)
+ if 'timeout' in kw:
+ opts['timeout'] = float(popKey(kw, 'timeout'))
+ # use only one connection for sqlite - supports multiple)
# cursors per connection
- self._conn = sqlite.connect(self.filename, autocommit=autoCommit)
+ self._conn = sqlite.connect(self.filename, **opts)
DBAPI.__init__(self, **kw)
def connectionFromURI(cls, uri):
|
|
From: <sub...@co...> - 2005-03-30 11:54:41
|
Author: phd
Date: 2005-03-30 11:54:36 +0000 (Wed, 30 Mar 2005)
New Revision: 693
Modified:
trunk/SQLObject/examples/people.py
trunk/SQLObject/examples/setup.py
trunk/SQLObject/sqlobject/sresults.py
Log:
Applied patch 1040531: implemented SELECT COUNT(DISTINCT id).
Modified: trunk/SQLObject/examples/people.py
===================================================================
--- trunk/SQLObject/examples/people.py 2005-03-29 16:48:12 UTC (rev 692)
+++ trunk/SQLObject/examples/people.py 2005-03-30 11:54:36 UTC (rev 693)
@@ -125,6 +125,18 @@
>>> print [p.id for p in peeps3]
"""
+test4 = """
+>>> bob = Person(firstName="Bob", lastName="Smith", username="bs")
+>>> phone1 = PhoneNumber(person=bob, phoneNumber='123-555-3210', phoneType='home')
+>>> phone2 = PhoneNumber(person=bob, phoneNumber='333-555-8888', phoneType='work')
+>>> alice = Person(firstName="Alice", lastName="Nowak", username="alicen")
+>>> print "Number of people:", Person.select().count()
+3
+>>> print "Number of phones:", PhoneNumber.select().count()
+3
+>>> print "Number of people with phones:", Person.select(Person.q.id == PhoneNumber.q.personID, distinct=True).count()
+2
+"""
############################################################
## Run tests:
@@ -137,6 +149,8 @@
print line
exec line[4:]
+reset()
runTest(test1)
runTest(test2)
runTest(test3)
+runTest(test4)
Modified: trunk/SQLObject/examples/setup.py
===================================================================
--- trunk/SQLObject/examples/setup.py 2005-03-29 16:48:12 UTC (rev 692)
+++ trunk/SQLObject/examples/setup.py 2005-03-30 11:54:36 UTC (rev 693)
@@ -5,7 +5,7 @@
main = sys.modules['__main__']
if '-v' in sys.argv:
- conn.debug = 1
+ sqlobject.connectionForURI(conn).debug = True
def reset():
classes = []
Modified: trunk/SQLObject/sqlobject/sresults.py
===================================================================
--- trunk/SQLObject/sqlobject/sresults.py 2005-03-29 16:48:12 UTC (rev 692)
+++ trunk/SQLObject/sqlobject/sresults.py 2005-03-30 11:54:36 UTC (rev 693)
@@ -140,9 +140,19 @@
def count(self):
""" Counting elements of current select results """
- assert not self.ops.get('distinct'), "It is not currently supported to count distinct objects"
-
- count = self.accumulate('COUNT(*)')
+ assert not (self.ops.get('distinct') and (self.ops.get('start')
+ or self.ops.get('end'))), \
+ "distinct-counting of sliced objects is not supported"
+ if self.ops.get('distinct'):
+ # Column must be specified, so we are using unique ID column.
+ # COUNT(DISTINCT column) is supported by MySQL and PostgreSQL,
+ # but not by SQLite. Perhaps more portable would be subquery:
+ # SELECT COUNT(*) FROM (SELECT DISTINCT id FROM table)
+ count = self.accumulate('COUNT(DISTINCT %s.%s)' % (
+ self.sourceClass.sqlmeta.table,
+ self.sourceClass.sqlmeta.idName))
+ else:
+ count = self.accumulate('COUNT(*)')
if self.ops.get('start'):
count -= self.ops['start']
if self.ops.get('end'):
|
|
From: <sub...@co...> - 2005-03-29 16:48:15
|
Author: phd
Date: 2005-03-29 16:48:12 +0000 (Tue, 29 Mar 2005)
New Revision: 692
Modified:
trunk/SQLObject/sqlobject/tests/dbtest.py
Log:
Applied fix 1171905.
Modified: trunk/SQLObject/sqlobject/tests/dbtest.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/dbtest.py 2005-03-29 16:30:20 UTC (rev 691)
+++ trunk/SQLObject/sqlobject/tests/dbtest.py 2005-03-29 16:48:12 UTC (rev 692)
@@ -2,18 +2,25 @@
The framework for making database tests.
"""
+import sys
import os
import re
import sqlobject
from py.test import raises
+if sys.platform[:3] == "win":
+ def getcwd():
+ return os.getcwd().replace(':', '|')
+else:
+ getcwd = os.getcwd
+
connectionShortcuts = {
'mysql': 'mysql://test@localhost/test',
'dbm': 'dbm:///data',
'postgres': 'postgres:///test',
'postgresql': 'postgres:///test',
'pygresql': 'pygresql://localhost/test',
- 'sqlite': 'sqlite:///%s/data/sqlite.data' % os.getcwd(),
+ 'sqlite': 'sqlite:///%s/data/sqlite.data' % getcwd(),
'sybase': 'sybase://test:test123@sybase/test?autoCommit=0',
'firebird': 'firebird://sysdba:masterkey@localhost/var/lib/firebird/data/test.gdb',
}
@@ -64,7 +71,7 @@
installOrClear(soClasses)
return soClasses
-installedDBFilename = os.path.join(os.getcwd(), 'dbs_data.tmp')
+installedDBFilename = os.path.join(getcwd(), 'dbs_data.tmp')
installedDBTracker = sqlobject.connectionForURI(
'sqlite:///' + installedDBFilename)
|