sqlobject-cvs Mailing List for SQLObject (Page 170)
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-02-10 18:32:14
|
Author: phd
Date: 2005-02-10 18:32:10 +0000 (Thu, 10 Feb 2005)
New Revision: 598
Added:
trunk/SQLObject/sqlobject/sresults.py
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
class SelectResults has been moved to sresults.py.
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-02-10 13:17:11 UTC (rev 597)
+++ trunk/SQLObject/sqlobject/main.py 2005-02-10 18:32:10 UTC (rev 598)
@@ -31,6 +31,7 @@
import index
import classregistry
import declarative
+from sresults import SelectResults
import sys
if sys.version_info[:3] < (2, 2, 0):
@@ -1256,163 +1257,6 @@
return '_SO_val_%s' % name
-class SelectResults(object):
-
- def __init__(self, sourceClass, clause, clauseTables=None,
- **ops):
- self.sourceClass = sourceClass
- if clause is None or isinstance(clause, str) and clause == 'all':
- clause = sqlbuilder.SQLTrueClause
- self.clause = clause
- tablesDict = sqlbuilder.tablesUsedDict(self.clause)
- tablesDict[sourceClass._table] = 1
- if clauseTables:
- for table in clauseTables:
- tablesDict[table] = 1
- self.clauseTables = clauseTables
- self.tables = tablesDict.keys()
- self.ops = ops
- if self.ops.get('orderBy', NoDefault) is NoDefault:
- self.ops['orderBy'] = sourceClass._defaultOrder
- orderBy = self.ops['orderBy']
- if isinstance(orderBy, list) or isinstance(orderBy, tuple):
- orderBy = map(self._mungeOrderBy, orderBy)
- else:
- orderBy = self._mungeOrderBy(orderBy)
- #print "OUT: %r; in: %r" % (sourceClass.sqlrepr(orderBy), sourceClass.sqlrepr(self.ops['orderBy']))
- self.ops['dbOrderBy'] = orderBy
- if ops.has_key('connection') and ops['connection'] is None:
- del ops['connection']
-
- def _mungeOrderBy(self, orderBy):
- if isinstance(orderBy, str) and orderBy.startswith('-'):
- orderBy = orderBy[1:]
- desc = True
- else:
- desc = False
- if isinstance(orderBy, (str, unicode)):
- if self.sourceClass._SO_columnDict.has_key(orderBy):
- val = self.sourceClass._SO_columnDict[orderBy].dbName
- if desc:
- return '-' + val
- else:
- return val
- else:
- if desc:
- return '-' + orderBy
- else:
- return orderBy
- else:
- return orderBy
-
- def clone(self, **newOps):
- ops = self.ops.copy()
- ops.update(newOps)
- return self.__class__(self.sourceClass, self.clause,
- self.clauseTables, **ops)
-
- def orderBy(self, orderBy):
- return self.clone(orderBy=orderBy)
-
- def connection(self, conn):
- return self.clone(connection=conn)
-
- def limit(self, limit):
- return self[:limit]
-
- def lazyColumns(self, value):
- return self.clone(lazyColumns=value)
-
- def reversed(self):
- return self.clone(reversed=not self.ops.get('reversed', False))
-
- def distinct(self):
- return self.clone(distinct=True)
-
- def __getitem__(self, value):
- if type(value) is type(slice(1)):
- assert not value.step, "Slices do not support steps"
- if not value.start and not value.stop:
- # No need to copy, I'm immutable
- return self
-
- # Negative indexes aren't handled (and everything we
- # don't handle ourselves we just create a list to
- # handle)
- if (value.start and value.start < 0) \
- or (value.stop and value.stop < 0):
- if value.start:
- if value.stop:
- return list(self)[value.start:value.stop]
- return list(self)[value.start:]
- return list(self)[:value.stop]
-
-
- if value.start:
- assert value.start >= 0
- start = self.ops.get('start', 0) + value.start
- if value.stop is not None:
- assert value.stop >= 0
- if value.stop < value.start:
- # an empty result:
- end = start
- else:
- end = value.stop + self.ops.get('start', 0)
- if self.ops.get('end', None) is not None \
- and value['end'] < end:
- # truncated by previous slice:
- end = self.ops['end']
- else:
- end = self.ops.get('end', None)
- else:
- start = self.ops.get('start', 0)
- end = value.stop + start
- if self.ops.get('end', None) is not None \
- and self.ops['end'] < end:
- end = self.ops['end']
- return self.clone(start=start, end=end)
- else:
- if value < 0:
- return list(iter(self))[value]
- else:
- start = self.ops.get('start', 0) + value
- return list(self.clone(start=start, end=start+1))[0]
-
- def __iter__(self):
- conn = self.ops.get('connection', self.sourceClass._connection)
- return conn.iterSelect(self)
-
- def accumulate(self, expression):
- """ Use an accumulate expression to select result
- using another SQL select through current
- connection.
- Return the accumulate result
- """
- conn = self.ops.get('connection', self.sourceClass._connection)
- return conn.accumulateSelect(self, expression)
-
- 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(*)')
- if self.ops.get('start'):
- count -= self.ops['start']
- if self.ops.get('end'):
- count = min(self.ops['end'] - self.ops.get('start', 0), count)
- return count
-
- def sum(self, attribute):
- """ Making the sum of a given select result attribute.
- `attribute` can be a column name (like 'a_column')
- or a dot-q attribute (like Table.q.aColumn)
- """
- if type(attribute) == type(''):
- expression = 'SUM(%s)' % attribute
- else:
- expression = sqlbuilder.func.SUM(attribute)
- return self.accumulate(expression)
-
class SQLObjectState(object):
def __init__(self, soObject):
Added: trunk/SQLObject/sqlobject/sresults.py
===================================================================
--- trunk/SQLObject/sqlobject/sresults.py 2005-02-10 13:17:11 UTC (rev 597)
+++ trunk/SQLObject/sqlobject/sresults.py 2005-02-10 18:32:10 UTC (rev 598)
@@ -0,0 +1,159 @@
+import sqlbuilder
+
+class SelectResults(object):
+
+ def __init__(self, sourceClass, clause, clauseTables=None,
+ **ops):
+ self.sourceClass = sourceClass
+ if clause is None or isinstance(clause, str) and clause == 'all':
+ clause = sqlbuilder.SQLTrueClause
+ self.clause = clause
+ tablesDict = sqlbuilder.tablesUsedDict(self.clause)
+ tablesDict[sourceClass._table] = 1
+ if clauseTables:
+ for table in clauseTables:
+ tablesDict[table] = 1
+ self.clauseTables = clauseTables
+ self.tables = tablesDict.keys()
+ self.ops = ops
+ if self.ops.get('orderBy', sqlbuilder.NoDefault) is sqlbuilder.NoDefault:
+ self.ops['orderBy'] = sourceClass._defaultOrder
+ orderBy = self.ops['orderBy']
+ if isinstance(orderBy, list) or isinstance(orderBy, tuple):
+ orderBy = map(self._mungeOrderBy, orderBy)
+ else:
+ orderBy = self._mungeOrderBy(orderBy)
+ self.ops['dbOrderBy'] = orderBy
+ if ops.has_key('connection') and ops['connection'] is None:
+ del ops['connection']
+
+ def _mungeOrderBy(self, orderBy):
+ if isinstance(orderBy, str) and orderBy.startswith('-'):
+ orderBy = orderBy[1:]
+ desc = True
+ else:
+ desc = False
+ if isinstance(orderBy, (str, unicode)):
+ if self.sourceClass._SO_columnDict.has_key(orderBy):
+ val = self.sourceClass._SO_columnDict[orderBy].dbName
+ if desc:
+ return '-' + val
+ else:
+ return val
+ else:
+ if desc:
+ return '-' + orderBy
+ else:
+ return orderBy
+ else:
+ return orderBy
+
+ def clone(self, **newOps):
+ ops = self.ops.copy()
+ ops.update(newOps)
+ return self.__class__(self.sourceClass, self.clause,
+ self.clauseTables, **ops)
+
+ def orderBy(self, orderBy):
+ return self.clone(orderBy=orderBy)
+
+ def connection(self, conn):
+ return self.clone(connection=conn)
+
+ def limit(self, limit):
+ return self[:limit]
+
+ def lazyColumns(self, value):
+ return self.clone(lazyColumns=value)
+
+ def reversed(self):
+ return self.clone(reversed=not self.ops.get('reversed', False))
+
+ def distinct(self):
+ return self.clone(distinct=True)
+
+ def __getitem__(self, value):
+ if type(value) is type(slice(1)):
+ assert not value.step, "Slices do not support steps"
+ if not value.start and not value.stop:
+ # No need to copy, I'm immutable
+ return self
+
+ # Negative indexes aren't handled (and everything we
+ # don't handle ourselves we just create a list to
+ # handle)
+ if (value.start and value.start < 0) \
+ or (value.stop and value.stop < 0):
+ if value.start:
+ if value.stop:
+ return list(self)[value.start:value.stop]
+ return list(self)[value.start:]
+ return list(self)[:value.stop]
+
+
+ if value.start:
+ assert value.start >= 0
+ start = self.ops.get('start', 0) + value.start
+ if value.stop is not None:
+ assert value.stop >= 0
+ if value.stop < value.start:
+ # an empty result:
+ end = start
+ else:
+ end = value.stop + self.ops.get('start', 0)
+ if self.ops.get('end', None) is not None \
+ and value['end'] < end:
+ # truncated by previous slice:
+ end = self.ops['end']
+ else:
+ end = self.ops.get('end', None)
+ else:
+ start = self.ops.get('start', 0)
+ end = value.stop + start
+ if self.ops.get('end', None) is not None \
+ and self.ops['end'] < end:
+ end = self.ops['end']
+ return self.clone(start=start, end=end)
+ else:
+ if value < 0:
+ return list(iter(self))[value]
+ else:
+ start = self.ops.get('start', 0) + value
+ return list(self.clone(start=start, end=start+1))[0]
+
+ def __iter__(self):
+ conn = self.ops.get('connection', self.sourceClass._connection)
+ return conn.iterSelect(self)
+
+ def accumulate(self, expression):
+ """ Use an accumulate expression to select result
+ using another SQL select through current
+ connection.
+ Return the accumulate result
+ """
+ conn = self.ops.get('connection', self.sourceClass._connection)
+ return conn.accumulateSelect(self, expression)
+
+ 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(*)')
+ if self.ops.get('start'):
+ count -= self.ops['start']
+ if self.ops.get('end'):
+ count = min(self.ops['end'] - self.ops.get('start', 0), count)
+ return count
+
+ def sum(self, attribute):
+ """ Making the sum of a given select result attribute.
+ `attribute` can be a column name (like 'a_column')
+ or a dot-q attribute (like Table.q.aColumn)
+ """
+ if type(attribute) == type(''):
+ expression = 'SUM(%s)' % attribute
+ else:
+ expression = sqlbuilder.func.SUM(attribute)
+ return self.accumulate(expression)
+
+__all__ = ['SelectResults']
|
|
From: <sub...@co...> - 2005-02-10 13:17:17
|
Author: phd
Date: 2005-02-10 13:17:11 +0000 (Thu, 10 Feb 2005)
New Revision: 597
Modified:
home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/test_inheritance.py
home/phd/SQLObject/inheritance/sqlobject/main.py
Log:
Fixed a bug with inhereted .q magic attribute.
Added more inheritance tests.
Modified: home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/test_inheritance.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/test_inheritance.py 2005-02-10 12:18:05 UTC (rev 596)
+++ home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/test_inheritance.py 2005-02-10 13:17:11 UTC (rev 597)
@@ -16,14 +16,17 @@
_inheritable = 0 # If I don't want this class to be inherited
position = StringCol()
-
-def test_inheritance():
+def setup():
setupClass(Person)
setupClass(Employee)
Employee(firstName='Ian', lastName='Bicking', position='Project leader')
Person(firstName='Daniel', lastName='Savard')
+
+def test_inheritance():
+ setup()
+
persons = Person.select() # all
for person in persons:
assert isinstance(person, Person)
@@ -32,3 +35,16 @@
else:
assert hasattr(person, "childName")
assert not person.childName
+
+
+def test_inheritance_select():
+ setup()
+
+ persons = Person.select(Person.q.firstName <> None)
+ assert persons.count() == 2
+
+ employees = Employee.select(Employee.q.firstName <> None)
+ assert employees.count() == 1
+
+ employees = Employee.select(Employee.q.position <> None)
+ assert employees.count() == 1
Modified: home/phd/SQLObject/inheritance/sqlobject/main.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/main.py 2005-02-10 12:18:05 UTC (rev 596)
+++ home/phd/SQLObject/inheritance/sqlobject/main.py 2005-02-10 13:17:11 UTC (rev 597)
@@ -577,15 +577,6 @@
cls.sqlmeta.idName = cls._idName
del cls._idName
- #DSM: If we are a child, get the q magic from the parent
- currentClass = cls
- while currentClass._parentClass:
- currentClass = currentClass._parentClass
- for column in currentClass._columns:
- if type(column) == col.ForeignKey: continue
- setattr(cls.q, column.name,
- getattr(currentClass.q, column.name))
-
# We have to check if there are columns in the inherited
# _columns where the attribute has been set to None in this
# class. If so, then we need to remove that column from
@@ -626,6 +617,15 @@
if not is_base:
cls.q = sqlbuilder.SQLObjectTable(cls)
+ #DSM: If we are a child, get the q magic from the parent
+ currentClass = cls
+ while currentClass._parentClass:
+ currentClass = currentClass._parentClass
+ for column in currentClass._columns:
+ if type(column) == col.ForeignKey: continue
+ setattr(cls.q, column.name,
+ getattr(currentClass.q, column.name))
+
classregistry.registry(cls._registry).addClass(cls)
_style = _sqlmeta_attr('style')
|
|
From: <sub...@co...> - 2005-02-10 12:18:11
|
Author: phd
Date: 2005-02-10 12:18:05 +0000 (Thu, 10 Feb 2005)
New Revision: 596
Added:
home/phd/SQLObject/inheritance/sqlobject/tests/test_basic_old.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_sorting_old.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_stringid_old.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_style_old.py
Modified:
home/phd/SQLObject/inheritance/sqlobject/classregistry.py
home/phd/SQLObject/inheritance/sqlobject/main.py
home/phd/SQLObject/inheritance/sqlobject/tests/dbtest.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_basic.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_sorting.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_stringid.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_style.py
Log:
Merged patches from revisions 591:595 from the trunk
Modified: home/phd/SQLObject/inheritance/sqlobject/classregistry.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/classregistry.py 2005-02-10 04:53:14 UTC (rev 595)
+++ home/phd/SQLObject/inheritance/sqlobject/classregistry.py 2005-02-10 12:18:05 UTC (rev 596)
@@ -74,9 +74,11 @@
"%r, from the module %s in %s)"
% (cls.__name__,
other, other.__module__,
- sys.modules[other.__module__].__file__,
+ getattr(sys.modules.get(other.__module__),
+ '__file__', '(unknown)'),
cls, cls.__module__,
- sys.modules[cls.__module__].__file__))
+ getattr(sys.modules.get(cls.__module__),
+ '__file__', '(unknown)')))
self.classes[cls.__name__] = cls
if self.callbacks.has_key(cls.__name__):
for callback, args, kw in self.callbacks[cls.__name__]:
Modified: home/phd/SQLObject/inheritance/sqlobject/main.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/main.py 2005-02-10 04:53:14 UTC (rev 595)
+++ home/phd/SQLObject/inheritance/sqlobject/main.py 2005-02-10 12:18:05 UTC (rev 596)
@@ -30,7 +30,6 @@
import joins
import index
import classregistry
-findClass = classregistry.findClass # for those who imported findClass from sqlobject.main
import declarative
import sys
@@ -110,8 +109,6 @@
delFunc(obj, var)
break
-#phd: findClass has been moved to classregistry to avoid circular import
-
def findDependencies(name, registry=None):
depends = []
for klass in classregistry.registry(registry).allClasses():
@@ -161,9 +158,6 @@
def setClass(cls, soClass):
cls.soClass = soClass
- setClass = classmethod(setClass)
-
- def finishClass(cls):
if not cls.style:
if cls.soClass._connection and cls.soClass._connection.style:
cls.style = cls.soClass._connection.style
@@ -173,7 +167,7 @@
cls.table = cls.style.pythonClassToDBTable(cls.soClass.__name__)
if cls.idName is None:
cls.idName = cls.style.idForTable(cls.table)
- finishClass = classmethod(finishClass)
+ setClass = classmethod(setClass)
class _sqlmeta_attr(object):
@@ -182,17 +176,24 @@
def __get__(self, obj, type=None):
return getattr((type or obj).sqlmeta, self.name)
-
+
# @@: This should become a public interface or documented or
# something. Turning it on gives earlier warning about things
# that will be deprecated (having this off we won't flood people
# with warnings right away).
-strict_warnings = False
+warnings_level = 1
+exception_level = None
+# Current levels:
+# 1) Actively deprecated in version after 0.6.1 (0.7?); removed after
+# 2) Deprecated after 1 (0.8?)
+# 3) Deprecated after 2 (0.9?)
-def deprecated(message):
- if strict_warnings:
- warnings.warn(message, DeprecationWarning, stacklevel=1)
+def deprecated(message, level=1):
+ if exception_level is not None and exception_level <= level:
+ raise NotImplementedError(message)
+ if warnings_level is not None and warnings_level <= level:
+ warnings.warn(message, DeprecationWarning, stacklevel=2)
class SelectResults(object):
IterationClass = dbconnection.Iteration
@@ -437,8 +438,6 @@
#cls.sqlmeta = cls.sqlmeta.clone()
cls.sqlmeta = type('sqlmeta', (cls.sqlmeta,), {})
cls.sqlmeta.setClass(cls)
- cls.sqlmeta.finishClass()
-
implicitColumns = []
implicitJoins = []
@@ -462,7 +461,7 @@
if (new_attrs.has_key('_table') and not is_base):
deprecated("'_table' is deprecated; please set the 'table' "
- "attribute in sqlmeta instead")
+ "attribute in sqlmeta instead", level=2)
cls.sqlmeta.table = cls._table
del cls._table
@@ -551,7 +550,7 @@
if (new_attrs.has_key('_style') and not is_base):
deprecated("'_style' is deprecated; please set the 'style' "
- "attribute in sqlmeta instead")
+ "attribute in sqlmeta instead", level=2)
cls.sqlmeta.style = cls._style
del cls._style
@@ -574,7 +573,7 @@
if (new_attrs.has_key('_idName') and not is_base):
deprecated("'_idName' is deprecated; please set the 'idName' "
- "attribute in sqlmeta instead")
+ "attribute in sqlmeta instead", level=2)
cls.sqlmeta.idName = cls._idName
del cls._idName
@@ -1504,6 +1503,6 @@
else:
return obj
-__all__ = ['NoDefault', 'SQLObject',
+__all__ = ['NoDefault', 'SQLObject', 'sqlmeta',
'getID', 'getObject',
'SQLObjectNotFound']
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/dbtest.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/dbtest.py 2005-02-10 04:53:14 UTC (rev 595)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/dbtest.py 2005-02-10 12:18:05 UTC (rev 596)
@@ -229,5 +229,27 @@
# To avoid name clashes:
_inserts = inserts
+def deprecated_module():
+ sqlobject.main.warnings_level = None
+ sqlobject.main.exception_level = None
+
+def setup_module(mod):
+ # modules with '_old' test backward compatible methods, so they
+ # don't get warnings or errors.
+ mod_name = str(mod.__name__)
+ if mod_name.endswith('/py'):
+ mod_name = mod_name[:-3]
+ if mod_name.endswith('_old'):
+ sqlobject.main.warnings_level = None
+ sqlobject.main.exception_level = None
+ else:
+ sqlobject.main.warnings_level = None
+ sqlobject.main.exception_level = 0
+
+def teardown_module(mod=None):
+ sqlobject.main.warnings_level = None
+ sqlobject.main.exception_level = 0
+
__all__ = ['getConnection', 'setupClass', 'Dummy', 'raises',
- 'd', 'inserts', 'supports']
+ 'd', 'inserts', 'supports', 'deprecated_module',
+ 'setup_module', 'teardown_module']
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_basic.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_basic.py 2005-02-10 04:53:14 UTC (rev 595)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_basic.py 2005-02-10 12:18:05 UTC (rev 596)
@@ -5,9 +5,7 @@
name = StringCol(length=50, dbName='name_col')
_cacheValues = False
- _columns = [
- StringCol('passwd', length=10),
- ]
+ passwd = StringCol(length=10)
def _set_passwd(self, passwd):
self._SO_set_passwd(passwd.encode('rot13'))
Copied: home/phd/SQLObject/inheritance/sqlobject/tests/test_basic_old.py (from rev 595, trunk/SQLObject/sqlobject/tests/test_basic_old.py)
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_sorting.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_sorting.py 2005-02-10 04:53:14 UTC (rev 595)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_sorting.py 2005-02-10 12:18:05 UTC (rev 596)
@@ -3,7 +3,8 @@
class Names(SQLObject):
- _table = 'names_table'
+ class sqlmeta(sqlmeta):
+ table = 'names_table'
firstName = StringCol(length=30)
lastName = StringCol(length=30)
Copied: home/phd/SQLObject/inheritance/sqlobject/tests/test_sorting_old.py (from rev 595, trunk/SQLObject/sqlobject/tests/test_sorting_old.py)
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_stringid.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_stringid.py 2005-02-10 04:53:14 UTC (rev 595)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_stringid.py 2005-02-10 12:18:05 UTC (rev 596)
@@ -7,7 +7,8 @@
class SOStringID(SQLObject):
- _table = 'so_string_id'
+ class sqlmeta(sqlmeta):
+ table = 'so_string_id'
_idType = str
val = StringCol(alternateID=True)
Copied: home/phd/SQLObject/inheritance/sqlobject/tests/test_stringid_old.py (from rev 595, trunk/SQLObject/sqlobject/tests/test_stringid_old.py)
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_style.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_style.py 2005-02-10 04:53:14 UTC (rev 595)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_style.py 2005-02-10 12:18:05 UTC (rev 596)
@@ -12,11 +12,13 @@
class SOStyleTest1(SQLObject):
a = StringCol()
st2 = ForeignKey('SOStyleTest2')
- _style = AnotherStyle()
+ class sqlmeta(sqlmeta):
+ style = AnotherStyle()
class SOStyleTest2(SQLObject):
b = StringCol()
- _style = AnotherStyle()
+ class sqlmeta(sqlmeta):
+ style = AnotherStyle()
def test_style():
setupClass([SOStyleTest2, SOStyleTest1])
Copied: home/phd/SQLObject/inheritance/sqlobject/tests/test_style_old.py (from rev 595, trunk/SQLObject/sqlobject/tests/test_style_old.py)
|
|
From: <sub...@co...> - 2005-02-10 04:53:21
|
Author: ianb
Date: 2005-02-10 04:53:14 +0000 (Thu, 10 Feb 2005)
New Revision: 595
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
Removed sqlmeta.finishClass method (merged with setClass)
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-02-10 04:50:41 UTC (rev 594)
+++ trunk/SQLObject/sqlobject/main.py 2005-02-10 04:53:14 UTC (rev 595)
@@ -162,9 +162,6 @@
def setClass(cls, soClass):
cls.soClass = soClass
- setClass = classmethod(setClass)
-
- def finishClass(cls):
if not cls.style:
if cls.soClass._connection and cls.soClass._connection.style:
cls.style = cls.soClass._connection.style
@@ -174,7 +171,7 @@
cls.table = cls.style.pythonClassToDBTable(cls.soClass.__name__)
if cls.idName is None:
cls.idName = cls.style.idForTable(cls.table)
- finishClass = classmethod(finishClass)
+ setClass = classmethod(setClass)
class _sqlmeta_attr(object):
@@ -276,8 +273,6 @@
#cls.sqlmeta = cls.sqlmeta.clone()
cls.sqlmeta = type('sqlmeta', (cls.sqlmeta,), {})
cls.sqlmeta.setClass(cls)
- cls.sqlmeta.finishClass()
-
implicitColumns = []
implicitJoins = []
|
|
From: <sub...@co...> - 2005-02-10 04:50:44
|
Author: ianb
Date: 2005-02-10 04:50:41 +0000 (Thu, 10 Feb 2005)
New Revision: 594
Added:
trunk/SQLObject/sqlobject/tests/test_basic_old.py
trunk/SQLObject/sqlobject/tests/test_sorting_old.py
trunk/SQLObject/sqlobject/tests/test_stringid_old.py
trunk/SQLObject/sqlobject/tests/test_style_old.py
Modified:
trunk/SQLObject/sqlobject/tests/dbtest.py
trunk/SQLObject/sqlobject/tests/test_basic.py
trunk/SQLObject/sqlobject/tests/test_sorting.py
trunk/SQLObject/sqlobject/tests/test_stringid.py
trunk/SQLObject/sqlobject/tests/test_style.py
Log:
Updated tests to use new style when applicable; added modules that
test the backward compatible style when that occurred
Modified: trunk/SQLObject/sqlobject/tests/dbtest.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/dbtest.py 2005-02-10 04:50:00 UTC (rev 593)
+++ trunk/SQLObject/sqlobject/tests/dbtest.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -229,5 +229,27 @@
# To avoid name clashes:
_inserts = inserts
+def deprecated_module():
+ sqlobject.main.warnings_level = None
+ sqlobject.main.exception_level = None
+
+def setup_module(mod):
+ # modules with '_old' test backward compatible methods, so they
+ # don't get warnings or errors.
+ mod_name = str(mod.__name__)
+ if mod_name.endswith('/py'):
+ mod_name = mod_name[:-3]
+ if mod_name.endswith('_old'):
+ sqlobject.main.warnings_level = None
+ sqlobject.main.exception_level = None
+ else:
+ sqlobject.main.warnings_level = None
+ sqlobject.main.exception_level = 0
+
+def teardown_module(mod=None):
+ sqlobject.main.warnings_level = None
+ sqlobject.main.exception_level = 0
+
__all__ = ['getConnection', 'setupClass', 'Dummy', 'raises',
- 'd', 'inserts', 'supports']
+ 'd', 'inserts', 'supports', 'deprecated_module',
+ 'setup_module', 'teardown_module']
Modified: trunk/SQLObject/sqlobject/tests/test_basic.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_basic.py 2005-02-10 04:50:00 UTC (rev 593)
+++ trunk/SQLObject/sqlobject/tests/test_basic.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -5,9 +5,7 @@
name = StringCol(length=50, dbName='name_col')
_cacheValues = False
- _columns = [
- StringCol('passwd', length=10),
- ]
+ passwd = StringCol(length=10)
def _set_passwd(self, passwd):
self._SO_set_passwd(passwd.encode('rot13'))
Copied: trunk/SQLObject/sqlobject/tests/test_basic_old.py (from rev 580, trunk/SQLObject/sqlobject/tests/test_basic.py)
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_basic.py 2005-02-09 04:50:46 UTC (rev 580)
+++ trunk/SQLObject/sqlobject/tests/test_basic_old.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -0,0 +1,50 @@
+from sqlobject import *
+from sqlobject.tests.dbtest import *
+
+deprecated_module()
+
+class OldTestSO1(SQLObject):
+
+ name = StringCol(length=50, dbName='name_col')
+ _cacheValues = False
+ _columns = [
+ StringCol('passwd', length=10),
+ ]
+
+ def _set_passwd(self, passwd):
+ self._SO_set_passwd(passwd.encode('rot13'))
+
+def setupGetters(cls):
+ setupClass(cls)
+ inserts(cls, [('bob', 'god'), ('sally', 'sordid'),
+ ('dave', 'dremel'), ('fred', 'forgo')],
+ 'name passwd')
+
+def test_case1():
+ setupGetters(OldTestSO1)
+ bob = OldTestSO1.selectBy(name='bob')[0]
+ assert bob.name == 'bob'
+ assert bob.passwd == 'god'.encode('rot13')
+
+def test_newline():
+ setupGetters(OldTestSO1)
+ bob = OldTestSO1.selectBy(name='bob')[0]
+ testString = 'hey\nyou\\can\'t you see me?\t'
+ bob.name = testString
+ bob.expire()
+ assert bob.name == testString
+
+def test_count():
+ setupGetters(OldTestSO1)
+ assert OldTestSO1.selectBy(name='bob').count() == 1
+ assert OldTestSO1.select(OldTestSO1.q.name == 'bob').count() == 1
+ assert OldTestSO1.select().count() == len(list(OldTestSO1.select()))
+
+def test_getset():
+ setupGetters(OldTestSO1)
+ bob = OldTestSO1.selectBy(name='bob')[0]
+ assert bob.name == 'bob'
+ bob.name = 'joe'
+ assert bob.name == 'joe'
+
+teardown_module()
Modified: trunk/SQLObject/sqlobject/tests/test_sorting.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_sorting.py 2005-02-10 04:50:00 UTC (rev 593)
+++ trunk/SQLObject/sqlobject/tests/test_sorting.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -3,7 +3,8 @@
class Names(SQLObject):
- _table = 'names_table'
+ class sqlmeta(sqlmeta):
+ table = 'names_table'
firstName = StringCol(length=30)
lastName = StringCol(length=30)
Added: trunk/SQLObject/sqlobject/tests/test_sorting_old.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_sorting_old.py 2005-02-10 04:50:00 UTC (rev 593)
+++ trunk/SQLObject/sqlobject/tests/test_sorting_old.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -0,0 +1,36 @@
+from sqlobject import *
+from sqlobject.tests.dbtest import *
+
+deprecated_module()
+
+class OldNames(SQLObject):
+
+ _table = 'names_table'
+
+ firstName = StringCol(length=30)
+ lastName = StringCol(length=30)
+
+ _defaultOrder = ['lastName', 'firstName']
+
+def setupNames():
+ setupClass(OldNames)
+ inserts(OldNames, [('aj', 'baker'), ('joe', 'robbins'),
+ ('tim', 'jackson'), ('joe', 'baker'),
+ ('zoe', 'robbins')],
+ schema='firstName lastName')
+
+def nameList(names):
+ result = []
+ for name in names:
+ result.append('%s %s' % (name.firstName, name.lastName))
+ return result
+
+def firstList(names):
+ return [n.firstName for n in names]
+
+def test_defaultOrder():
+ setupNames()
+ assert nameList(OldNames.select()) == \
+ ['aj baker', 'joe baker',
+ 'tim jackson', 'joe robbins',
+ 'zoe robbins']
Modified: trunk/SQLObject/sqlobject/tests/test_stringid.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_stringid.py 2005-02-10 04:50:00 UTC (rev 593)
+++ trunk/SQLObject/sqlobject/tests/test_stringid.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -7,7 +7,8 @@
class SOStringID(SQLObject):
- _table = 'so_string_id'
+ class sqlmeta(sqlmeta):
+ table = 'so_string_id'
_idType = str
val = StringCol(alternateID=True)
Added: trunk/SQLObject/sqlobject/tests/test_stringid_old.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_stringid_old.py 2005-02-10 04:50:00 UTC (rev 593)
+++ trunk/SQLObject/sqlobject/tests/test_stringid_old.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -0,0 +1,65 @@
+from sqlobject import *
+from sqlobject.tests.dbtest import *
+
+deprecated_module()
+
+########################################
+## String ID test
+########################################
+
+class OldSOStringID(SQLObject):
+
+ _table = 'so_string_id'
+ _idType = str
+ val = StringCol(alternateID=True)
+
+ mysqlCreate = """
+ CREATE TABLE IF NOT EXISTS so_string_id (
+ id VARCHAR(50) PRIMARY KEY,
+ val TEXT
+ )
+ """
+
+ postgresCreate = """
+ CREATE TABLE so_string_id (
+ id VARCHAR(50) PRIMARY KEY,
+ val TEXT
+ )
+ """
+
+ sybaseCreate = """
+ CREATE TABLE so_string_id (
+ id VARCHAR(50) UNIQUE,
+ val VARCHAR(50) NULL
+ )
+ """
+
+ firebirdCreate = """
+ CREATE TABLE so_string_id (
+ id VARCHAR(50) NOT NULL PRIMARY KEY,
+ val BLOB SUB_TYPE TEXT
+ )
+ """
+
+ sqliteCreate = postgresCreate
+
+ mysqlDrop = """
+ DROP TABLE IF EXISTS so_string_id
+ """
+
+ postgresDrop = """
+ DROP TABLE so_string_id
+ """
+
+ sqliteDrop = postgresDrop
+ firebirdDrop = postgresDrop
+
+
+def test_stringID():
+ setupClass(OldSOStringID)
+ t = OldSOStringID(id='hey', val='whatever')
+ t2 = OldSOStringID.byVal('whatever')
+ assert t == t2
+ t3 = OldSOStringID(id='you', val='nowhere')
+ t4 = OldSOStringID.get('you')
+ assert t3 == t4
Modified: trunk/SQLObject/sqlobject/tests/test_style.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_style.py 2005-02-10 04:50:00 UTC (rev 593)
+++ trunk/SQLObject/sqlobject/tests/test_style.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -12,11 +12,13 @@
class SOStyleTest1(SQLObject):
a = StringCol()
st2 = ForeignKey('SOStyleTest2')
- _style = AnotherStyle()
+ class sqlmeta(sqlmeta):
+ style = AnotherStyle()
class SOStyleTest2(SQLObject):
b = StringCol()
- _style = AnotherStyle()
+ class sqlmeta(sqlmeta):
+ style = AnotherStyle()
def test_style():
setupClass([SOStyleTest2, SOStyleTest1])
Added: trunk/SQLObject/sqlobject/tests/test_style_old.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_style_old.py 2005-02-10 04:50:00 UTC (rev 593)
+++ trunk/SQLObject/sqlobject/tests/test_style_old.py 2005-02-10 04:50:41 UTC (rev 594)
@@ -0,0 +1,31 @@
+from sqlobject import *
+from sqlobject.tests.dbtest import *
+from sqlobject import styles
+
+deprecated_module()
+
+class AnotherStyle(styles.MixedCaseUnderscoreStyle):
+ def pythonAttrToDBColumn(self, attr):
+ if attr.lower().endswith('id'):
+ return 'id'+styles.MixedCaseUnderscoreStyle.pythonAttrToDBColumn(self, attr[:-2])
+ else:
+ return styles.MixedCaseUnderscoreStyle.pythonAttrToDBColumn(self, attr)
+
+class OldSOStyleTest1(SQLObject):
+ a = StringCol()
+ st2 = ForeignKey('OldSOStyleTest2')
+ _style = AnotherStyle()
+
+class OldSOStyleTest2(SQLObject):
+ b = StringCol()
+ _style = AnotherStyle()
+
+def test_style():
+ setupClass([OldSOStyleTest2, OldSOStyleTest1])
+ st1 = OldSOStyleTest1(a='something', st2=None)
+ st2 = OldSOStyleTest2(b='whatever')
+ st1.st2 = st2
+ assert st1._SO_columnDict['st2ID'].dbName == 'idst2'
+ assert st1.st2 == st2
+
+teardown_module()
|
|
From: <sub...@co...> - 2005-02-10 04:50:05
|
Author: ianb
Date: 2005-02-10 04:50:00 +0000 (Thu, 10 Feb 2005)
New Revision: 593
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
* Give some more explicit controls about how warnings and errors for
deprecated features are given.
* Export sqlmeta
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-02-10 04:49:16 UTC (rev 592)
+++ trunk/SQLObject/sqlobject/main.py 2005-02-10 04:50:00 UTC (rev 593)
@@ -189,11 +189,18 @@
# something. Turning it on gives earlier warning about things
# that will be deprecated (having this off we won't flood people
# with warnings right away).
-strict_warnings = False
+warnings_level = 1
+exception_level = None
+# Current levels:
+# 1) Actively deprecated in version after 0.6.1 (0.7?); removed after
+# 2) Deprecated after 1 (0.8?)
+# 3) Deprecated after 2 (0.9?)
-def deprecated(message):
- if strict_warnings:
- warnings.warn(message, DeprecationWarning, stacklevel=1)
+def deprecated(message, level=1):
+ if exception_level is not None and exception_level <= level:
+ raise NotImplementedError(message)
+ if warnings_level is not None and warnings_level <= level:
+ warnings.warn(message, DeprecationWarning, stacklevel=2)
# SQLObject is the superclass for all SQLObject classes, of
# course. All the deeper magic is done in MetaSQLObject, and
@@ -294,7 +301,7 @@
if (new_attrs.has_key('_table') and not is_base):
deprecated("'_table' is deprecated; please set the 'table' "
- "attribute in sqlmeta instead")
+ "attribute in sqlmeta instead", level=2)
cls.sqlmeta.table = cls._table
del cls._table
@@ -349,7 +356,7 @@
if (new_attrs.has_key('_style') and not is_base):
deprecated("'_style' is deprecated; please set the 'style' "
- "attribute in sqlmeta instead")
+ "attribute in sqlmeta instead", level=2)
cls.sqlmeta.style = cls._style
del cls._style
@@ -372,7 +379,7 @@
if (new_attrs.has_key('_idName') and not is_base):
deprecated("'_idName' is deprecated; please set the 'idName' "
- "attribute in sqlmeta instead")
+ "attribute in sqlmeta instead", level=2)
cls.sqlmeta.idName = cls._idName
del cls._idName
@@ -1450,6 +1457,6 @@
else:
return obj
-__all__ = ['NoDefault', 'SQLObject',
+__all__ = ['NoDefault', 'SQLObject', 'sqlmeta',
'getID', 'getObject',
'SQLObjectNotFound']
|
|
From: <sub...@co...> - 2005-02-10 04:49:24
|
Author: ianb
Date: 2005-02-10 04:49:16 +0000 (Thu, 10 Feb 2005)
New Revision: 592
Modified:
trunk/SQLObject/sqlobject/classregistry.py
Log:
Be careful about sys.modules when generating an error (py.test doesn't
put modules in sys.modules)
Modified: trunk/SQLObject/sqlobject/classregistry.py
===================================================================
--- trunk/SQLObject/sqlobject/classregistry.py 2005-02-09 13:16:59 UTC (rev 591)
+++ trunk/SQLObject/sqlobject/classregistry.py 2005-02-10 04:49:16 UTC (rev 592)
@@ -74,9 +74,11 @@
"%r, from the module %s in %s)"
% (cls.__name__,
other, other.__module__,
- sys.modules[other.__module__].__file__,
+ getattr(sys.modules.get(other.__module__),
+ '__file__', '(unknown)'),
cls, cls.__module__,
- sys.modules[cls.__module__].__file__))
+ getattr(sys.modules.get(cls.__module__),
+ '__file__', '(unknown)')))
self.classes[cls.__name__] = cls
if self.callbacks.has_key(cls.__name__):
for callback, args, kw in self.callbacks[cls.__name__]:
|
|
From: <sub...@co...> - 2005-02-09 13:17:02
|
Author: phd Date: 2005-02-09 13:16:59 +0000 (Wed, 09 Feb 2005) New Revision: 591 Added: home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/ home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/__init__.py home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/test_inheritance.py Log: Added inheritance tests. Added: home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/__init__.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/__init__.py 2005-02-09 13:15:16 UTC (rev 590) +++ home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/__init__.py 2005-02-09 13:16:59 UTC (rev 591) @@ -0,0 +1 @@ +# Added: home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/test_inheritance.py =================================================================== --- home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/test_inheritance.py 2005-02-09 13:15:16 UTC (rev 590) +++ home/phd/SQLObject/inheritance/sqlobject/inheritance/tests/test_inheritance.py 2005-02-09 13:16:59 UTC (rev 591) @@ -0,0 +1,34 @@ +from sqlobject import * +from sqlobject.tests.dbtest import * +from sqlobject.inheritance import InheritableSQLObject + +######################################## +## Inheritance +######################################## + + +class Person(InheritableSQLObject): + _inheritable = 1 # I want this class to be inherited + firstName = StringCol() + lastName = StringCol() + +class Employee(Person): + _inheritable = 0 # If I don't want this class to be inherited + position = StringCol() + + +def test_inheritance(): + setupClass(Person) + setupClass(Employee) + + Employee(firstName='Ian', lastName='Bicking', position='Project leader') + Person(firstName='Daniel', lastName='Savard') + + persons = Person.select() # all + for person in persons: + assert isinstance(person, Person) + if isinstance(person, Employee): + assert not hasattr(person, "childName") + else: + assert hasattr(person, "childName") + assert not person.childName |
|
From: <sub...@co...> - 2005-02-09 13:15:25
|
Author: phd
Date: 2005-02-09 13:15:16 +0000 (Wed, 09 Feb 2005)
New Revision: 590
Added:
home/phd/SQLObject/inheritance/sqlobject/boundattributes.py
home/phd/SQLObject/inheritance/sqlobject/declarative.py
home/phd/SQLObject/inheritance/sqlobject/inheritance/iteration.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_boundattributes.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_declarative.py
Modified:
home/phd/SQLObject/inheritance/sqlobject/col.py
home/phd/SQLObject/inheritance/sqlobject/dbconnection.py
home/phd/SQLObject/inheritance/sqlobject/include/validators.py
home/phd/SQLObject/inheritance/sqlobject/inheritance/__init__.py
home/phd/SQLObject/inheritance/sqlobject/main.py
home/phd/SQLObject/inheritance/sqlobject/sqlbuilder.py
home/phd/SQLObject/inheritance/sqlobject/sqlite/sqliteconnection.py
home/phd/SQLObject/inheritance/sqlobject/styles.py
home/phd/SQLObject/inheritance/sqlobject/tests/dbtest.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_auto.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_basic.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_blob.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_distinct.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_joins.py
home/phd/SQLObject/inheritance/sqlobject/tests/test_style.py
Log:
Merged patches from revisiosn 571:589 from the trunk.
Moved InheritanceIteration from dbconnection.py to inheritance/iteration.py.
Copied: home/phd/SQLObject/inheritance/sqlobject/boundattributes.py (from rev 585, trunk/SQLObject/sqlobject/boundattributes.py)
Modified: home/phd/SQLObject/inheritance/sqlobject/col.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/col.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/col.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -888,6 +888,8 @@
"""
def fromPython(self, value, state):
+ if value is None:
+ return None
return state.soObject._connection.createBinary(value)
class SOBLOBCol(SOStringCol):
Modified: home/phd/SQLObject/inheritance/sqlobject/dbconnection.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/dbconnection.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/dbconnection.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -45,13 +45,14 @@
atexit.register(_closeConnection, weakref.ref(self))
def uri(self):
- auth = self.user or ''
+ auth = getattr(self, 'user', None) or ''
if auth:
if self.password:
auth = auth + '@' + self.password
auth = auth + ':'
else:
- assert not self.password, 'URIs cannot express passwords without usernames'
+ assert not getattr(self, 'password', None), (
+ 'URIs cannot express passwords without usernames')
uri = '%s://%s' % (self.dbName, auth)
if self.host:
uri += self.host + '/'
@@ -181,6 +182,8 @@
conn.close()
def printDebug(self, conn, s, name, type='query'):
+ if name == 'Pool' and self.debug != 'Pool':
+ return
if type == 'query':
sep = ': '
else:
@@ -541,80 +544,6 @@
def __del__(self):
self._cleanup()
-class InheritableIteration(Iteration):
- #phd: default array size for cursor.fetchmany()
- defaultArraySize = 10000
-
- def __init__(self, dbconn, rawconn, select, keepConnection=False):
- super(InheritableIteration, self).__init__(dbconn, rawconn, select, keepConnection)
- self.cursor.arraysize = self.defaultArraySize
- self._results = []
- #phd: find the index of the childName column
- childNameIdx = None
- columns = select.sourceClass._SO_columns
- for i in range(len(columns)): #phd: enumerate() is unavailable python 2.2
- if columns[i].name == "childName":
- childNameIdx = i
- break
- self._childNameIdx = childNameIdx
-
- def next(self):
- lazyColumns = self.select.ops.get('lazyColumns', 0)
- if not self._results:
- self._results = list(self.cursor.fetchmany())
- if not lazyColumns: self.fetchChildren()
- if not self._results:
- self._cleanup()
- raise StopIteration
- result = self._results[0]
- del self._results[0]
- if lazyColumns:
- obj = self.select.sourceClass.get(result[0], connection=self.dbconn)
- return obj
- else:
- id = result[0]
- if id in self._childrenResults:
- childResults = self._childrenResults[id]
- del self._childrenResults[id]
- else:
- childResults = None
- obj = self.select.sourceClass.get(id, selectResults=result[1:],
- childResults=childResults, connection=self.dbconn)
- return obj
-
- def fetchChildren(self):
- """Prefetch childrens' data
-
- Fetch childrens' data for every subclass in one big .select()
- to avoid .get() fetching it one by one.
- """
- self._childrenResults = {}
- if self._childNameIdx is None:
- return
- childIdsNames = {}
- childNameIdx = self._childNameIdx
- for result in self._results:
- childName = result[childNameIdx+1]
- if childName:
- ids = childIdsNames.get(childName)
- if ids is None:
- ids = childIdsNames[childName] = []
- ids.append(result[0])
- dbconn = self.dbconn
- rawconn = self.rawconn
- cursor = rawconn.cursor()
- registry = self.select.sourceClass._registry
- for childName, ids in childIdsNames.items():
- klass = findClass(childName, registry)
- select = klass.select(sqlbuilder.IN(sqlbuilder.SQLConstant("id"), ids))
- query = dbconn.queryForSelect(select)
- if dbconn.debug:
- dbconn.printDebug(rawconn, query, 'Select children of the class %s' % childName)
- self.dbconn._executeRetry(rawconn, cursor, query)
- for result in cursor.fetchall():
- self._childrenResults[result[0]] = result[1:]
-
-
class Transaction(object):
def __init__(self, dbConnection):
Copied: home/phd/SQLObject/inheritance/sqlobject/declarative.py (from rev 585, trunk/SQLObject/sqlobject/declarative.py)
Modified: home/phd/SQLObject/inheritance/sqlobject/include/validators.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/include/validators.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/include/validators.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -195,7 +195,7 @@
self._toPython,
self.validatePython)
- def fromPython(self, value, state):
+ def fromPython(self, value, state=None):
return self.attemptConvert(value, state,
self.validatePython,
self._fromPython,
@@ -227,7 +227,7 @@
def toPython(self, value, state=None):
return self.attemptConvert(value, state, toPython)
- def fromPython(self, value, state):
+ def fromPython(self, value, state=None):
return self.attemptConvert(value, state, fromPython)
def matchesProtocol(self, validator, state):
Modified: home/phd/SQLObject/inheritance/sqlobject/inheritance/__init__.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/inheritance/__init__.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/inheritance/__init__.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -1,11 +1,11 @@
from sqlobject import sqlbuilder
-from sqlobject import dbconnection
from sqlobject import classregistry
from sqlobject.main import SQLObject, SelectResults, True, False, makeProperties, getterName, setterName
+import iteration
class InheritableSelectResults(SelectResults):
- IterationClass = dbconnection.InheritableIteration
+ IterationClass = iteration.InheritableIteration
def __init__(self, sourceClass, clause, clauseTables=None,
**ops):
@@ -177,7 +177,7 @@
]
)
self._parent = parentClass(kw=parent_kw)
- self._parent.childName = self._className
+ self._parent.childName = self.__class__.__name__
id = self._parent.id
super(InheritableSQLObject, self)._create(id, **kw)
Added: home/phd/SQLObject/inheritance/sqlobject/inheritance/iteration.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/inheritance/iteration.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/inheritance/iteration.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -0,0 +1,76 @@
+from sqlobject import sqlbuilder
+from sqlobject.classregistry import findClass
+from sqlobject.dbconnection import Iteration
+
+class InheritableIteration(Iteration):
+ #phd: default array size for cursor.fetchmany()
+ defaultArraySize = 10000
+
+ def __init__(self, dbconn, rawconn, select, keepConnection=False):
+ super(InheritableIteration, self).__init__(dbconn, rawconn, select, keepConnection)
+ self.cursor.arraysize = self.defaultArraySize
+ self._results = []
+ #phd: find the index of the childName column
+ childNameIdx = None
+ columns = select.sourceClass._SO_columns
+ for i in range(len(columns)): #phd: enumerate() is unavailable python 2.2
+ if columns[i].name == "childName":
+ childNameIdx = i
+ break
+ self._childNameIdx = childNameIdx
+
+ def next(self):
+ lazyColumns = self.select.ops.get('lazyColumns', 0)
+ if not self._results:
+ self._results = list(self.cursor.fetchmany())
+ if not lazyColumns: self.fetchChildren()
+ if not self._results:
+ self._cleanup()
+ raise StopIteration
+ result = self._results[0]
+ del self._results[0]
+ if lazyColumns:
+ obj = self.select.sourceClass.get(result[0], connection=self.dbconn)
+ return obj
+ else:
+ id = result[0]
+ if id in self._childrenResults:
+ childResults = self._childrenResults[id]
+ del self._childrenResults[id]
+ else:
+ childResults = None
+ obj = self.select.sourceClass.get(id, selectResults=result[1:],
+ childResults=childResults, connection=self.dbconn)
+ return obj
+
+ def fetchChildren(self):
+ """Prefetch childrens' data
+
+ Fetch childrens' data for every subclass in one big .select()
+ to avoid .get() fetching it one by one.
+ """
+ self._childrenResults = {}
+ if self._childNameIdx is None:
+ return
+ childIdsNames = {}
+ childNameIdx = self._childNameIdx
+ for result in self._results:
+ childName = result[childNameIdx+1]
+ if childName:
+ ids = childIdsNames.get(childName)
+ if ids is None:
+ ids = childIdsNames[childName] = []
+ ids.append(result[0])
+ dbconn = self.dbconn
+ rawconn = self.rawconn
+ cursor = rawconn.cursor()
+ registry = self.select.sourceClass._registry
+ for childName, ids in childIdsNames.items():
+ klass = findClass(childName, registry)
+ select = klass.select(sqlbuilder.IN(sqlbuilder.SQLConstant("id"), ids))
+ query = dbconn.queryForSelect(select)
+ if dbconn.debug:
+ dbconn.printDebug(rawconn, query, 'Select children of the class %s' % childName)
+ self.dbconn._executeRetry(rawconn, cursor, query)
+ for result in cursor.fetchall():
+ self._childrenResults[result[0]] = result[1:]
Modified: home/phd/SQLObject/inheritance/sqlobject/main.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/main.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/main.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -4,14 +4,6 @@
SQLObject is a object-relational mapper. See SQLObject.html or
SQLObject.txt for more.
-Modified by
- Daniel Savard, Xsoli Inc <sqlobject xsoli.com> 7 Feb 2004
- - Added support for simple table inheritance.
-
- Oleg Broytmann, SIA "ANK" <ph...@ph...> 3 Feb 2005
- - Split inheritance support into a number of separate classes -
- InheritableSQLObject at al.
-
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
@@ -39,6 +31,7 @@
import index
import classregistry
findClass = classregistry.findClass # for those who imported findClass from sqlobject.main
+import declarative
import sys
if sys.version_info[:3] < (2, 2, 0):
@@ -51,209 +44,6 @@
True, False = 1==1, 0==1
-# This is the metaclass. It essentially takes a dictionary
-# of all the attributes (and thus methods) defined in the
-# class definition. It futzes with them, and spits out the
-# new class definition.
-class MetaSQLObject(type):
-
- def __new__(cls, className, bases, d):
-
- # We fix up the columns here -- replacing any strings with
- # simply-contructed Col objects, and searching the class
- # variables for instances of Col objects (which get put into
- # the _columns instance variable and deleted).
- columns = []
- for column in d.get('_columns', []):
- if isinstance(column, str):
- column = col.Col(column)
- columns.append(column)
- if columns:
- d['_columns'] = columns
-
- implicitColumns = []
- implicitJoins = []
- implicitIndexes = []
- for attr, value in d.items():
- if isinstance(value, col.Col):
- value.name = attr
- implicitColumns.append(value)
- del d[attr]
- continue
- if isinstance(value, joins.Join):
- value.joinMethodName = attr
- implicitJoins.append(value)
- del d[attr]
- continue
- if isinstance(value, index.DatabaseIndex):
- value.setName(attr)
- implicitIndexes.append(value)
- del d[attr]
- continue
-
- # We *don't* want to inherit _table, so we make sure it
- # is defined in this class (not a superclass)
- if not d.has_key('_table'):
- d['_table'] = None
-
-
- if d.has_key('_connection'):
- connection = d['_connection']
- del d['_connection']
- assert not d.has_key('connection')
- elif d.has_key('connection'):
- connection = d['connection']
- del d['connection']
- else:
- connection = None
-
- # We actually create the class.
- newClass = type.__new__(cls, className, bases, d)
- newClass._SO_finishedClassCreation = False
-
- #DSM: Need to keep the name of the class for easy access later
- newClass._className = className
- newClass._childClasses = {}
- #DSM: Need to know very soon if the class is a child of an
- #DSM: inheritable class. If so, we keep a link to our parent class.
- for cls in bases:
- if hasattr(cls, '_inheritable') and cls._inheritable:
- newClass._parentClass = cls
- newClass._parent = None
- cls._childClasses[className] = newClass
-
- # We append to _columns, but we don't want to change the
- # superclass's _columns list, so we make a copy if necessary
- if not d.has_key('_columns'):
- newClass._columns = newClass._columns[:]
- #DSM: If this class is a child of a parent class, we need to do some
- #DSM: attribute check and a a foreign key to the parent.
- if newClass._parentClass:
- #DSM: First, look for invalid column name:
- #DSM: reserved ones or same as a parent
- parentCols = [column.name for column in newClass._columns]
- for column in implicitColumns:
- cname = column.name
- if cname in ['childName']:
- raise AttributeError, \
- "The column name '%s' is reserved" % cname
- if cname in parentCols:
- raise AttributeError, "The column '%s' is already " \
- "defined in an inheritable parent" % cname
- #DSM: Remove columns if inherited from an inheritable class
- #DSM: as we don't want them. All we want is a foreign key
- #DSM: that will link to our parent
- newClass._columns = []
- #DSM: If this is inheritable, add some default columns
- # to be able to link to children
- if hasattr(newClass, '_inheritable') and newClass._inheritable:
- newClass._columns.append(
- col.StringCol(name='childName',default=None))
- newClass._columns.extend(implicitColumns)
- if not d.has_key('_joins'):
- newClass._joins = newClass._joins[:]
- newClass._joins.extend(implicitJoins)
- if not d.has_key('_indexes'):
- newClass._indexes = newClass._indexes[:]
- newClass._indexes.extend(implicitIndexes)
-
- ######################################################
- # Set some attributes to their defaults, if necessary.
- # First we get the connection:
- if not connection and not getattr(newClass, '_connection', None):
- mod = sys.modules[newClass.__module__]
- # See if there's a __connection__ global in
- # the module, use it if there is.
- if hasattr(mod, '__connection__'):
- connection = mod.__connection__
-
- if connection or not hasattr(newClass, '_connection'):
- newClass.setConnection(connection)
-
- # The style object tells how to map between Python
- # identifiers and Database identifiers:
- if not newClass._style:
- if newClass._connection and newClass._connection.style:
- newClass._style = newClass._connection.style
- else:
- newClass._style = styles.defaultStyle
-
- # plainSetters are columns that haven't been overridden by the
- # user, so we can contact the database directly to set them.
- # Note that these can't set these in the SQLObject class
- # itself, because they specific to this subclass of SQLObject,
- # and cannot be shared among classes.
- newClass._SO_plainSetters = {}
- newClass._SO_plainGetters = {}
- newClass._SO_plainForeignSetters = {}
- newClass._SO_plainForeignGetters = {}
- newClass._SO_plainJoinGetters = {}
- newClass._SO_plainJoinAdders = {}
- newClass._SO_plainJoinRemovers = {}
-
- # This is a dictionary of columnName: columnObject
- newClass._SO_columnDict = {}
- newClass._SO_columns = []
-
- # If _table isn't given, use style default
- if not newClass._table:
- newClass._table = newClass._style.pythonClassToDBTable(className)
-
- # If _idName isn't given, use style default
- if not d.has_key('_idName'):
- newClass._idName = newClass._style.idForTable(newClass._table)
-
- # We use the magic "q" attribute for accessing lazy
- # SQL where-clause generation. See the sql module for
- # more.
- newClass.q = sqlbuilder.SQLObjectTable(newClass)
- #DSM: If we are a child, get the q magic from the parent
- currentClass = newClass
- while currentClass._parentClass:
- currentClass = currentClass._parentClass
- for column in currentClass._columns:
- if type(column) == col.ForeignKey: continue
- setattr(newClass.q, column.name,
- getattr(currentClass.q, column.name))
-
- # We have to check if there are columns in the inherited
- # _columns where the attribute has been set to None in this
- # class. If so, then we need to remove that column from
- # _columns.
- for column in newClass._columns[:]:
- if d.has_key(column.name) and d[column.name] is None:
- newClass._columns.remove(column)
-
- for column in newClass._columns:
- newClass.addColumn(column)
- if newClass._fromDatabase:
- newClass.addColumnsFromDatabase()
-
- ########################################
- # Now we do the joins:
-
- # We keep track of the different joins by index,
- # putting them in this list.
- newClass._SO_joinList = []
- newClass._SO_joinDict = {}
-
- for join in newClass._joins:
- newClass.addJoin(join)
-
- # We don't setup the properties until we're finished with the
- # batch adding of all the columns...
- newClass._SO_finishedClassCreation = True
- makeProperties(newClass)
-
- newClass._SO_indexList = []
- for idx in newClass._indexes:
- newClass.addIndex(idx)
-
- classregistry.registry(newClass._registry).addClass(newClass)
-
- # And return the class
- return newClass
-
def makeProperties(obj):
"""
This function takes a dictionary of methods and finds
@@ -343,12 +133,67 @@
"""
pass
+class sqlmeta(object):
-try:
- basestring
-except NameError: # Python 2.2
- basestring = (types.StringType, types.UnicodeType)
+ """
+ This object is the object we use to keep track of all sorts of
+ information. Subclasses are made for each SQLObject subclass
+ (dynamically if necessary), and instances are created to go
+ alongside every SQLObject instance.
+ """
+ table = None
+ idName = None
+ style = None
+
+ __metaclass__ = declarative.DeclarativeMeta
+
+ # These attributes shouldn't be shared with superclasses:
+ _unshared_attributes = ['table']
+
+ def __classinit__(cls, new_attrs):
+ for attr in cls._unshared_attributes:
+ if not new_attrs.has_key(attr):
+ setattr(cls, attr, None)
+
+ def __init__(self, instance):
+ self.instance = instance
+
+ def setClass(cls, soClass):
+ cls.soClass = soClass
+ setClass = classmethod(setClass)
+
+ def finishClass(cls):
+ if not cls.style:
+ if cls.soClass._connection and cls.soClass._connection.style:
+ cls.style = cls.soClass._connection.style
+ else:
+ cls.style = styles.defaultStyle
+ if cls.table is None:
+ cls.table = cls.style.pythonClassToDBTable(cls.soClass.__name__)
+ if cls.idName is None:
+ cls.idName = cls.style.idForTable(cls.table)
+ finishClass = classmethod(finishClass)
+
+class _sqlmeta_attr(object):
+
+ def __init__(self, name):
+ self.name = name
+
+ def __get__(self, obj, type=None):
+ return getattr((type or obj).sqlmeta, self.name)
+
+
+# @@: This should become a public interface or documented or
+# something. Turning it on gives earlier warning about things
+# that will be deprecated (having this off we won't flood people
+# with warnings right away).
+strict_warnings = False
+
+def deprecated(message):
+ if strict_warnings:
+ warnings.warn(message, DeprecationWarning, stacklevel=1)
+
class SelectResults(object):
IterationClass = dbconnection.Iteration
@@ -360,10 +205,6 @@
self.clause = clause
tablesDict = sqlbuilder.tablesUsedDict(self.clause)
tablesDict[sourceClass._table] = 1
- orderBy = ops.get('orderBy')
- if orderBy and not isinstance(orderBy, basestring):
- tablesDict.update(sqlbuilder.tablesUsedDict(orderBy))
-
if clauseTables:
for table in clauseTables:
tablesDict[table] = 1
@@ -487,12 +328,12 @@
Return the accumulate result
"""
conn = self.ops.get('connection', self.sourceClass._connection)
- return conn.accumulateSelect(self,expression)
+ return conn.accumulateSelect(self, expression)
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(*)')
if self.ops.get('start'):
count -= self.ops['start']
@@ -511,7 +352,6 @@
expression = sqlbuilder.func.SUM(attribute)
return self.accumulate(expression)
-
# SQLObject is the superclass for all SQLObject classes, of
# course. All the deeper magic is done in MetaSQLObject, and
# only lesser magic is done here. All the actual work is done
@@ -520,7 +360,7 @@
# MetaSQLObject.
class SQLObject(object):
- __metaclass__ = MetaSQLObject
+ __metaclass__ = declarative.DeclarativeMeta
# When an object is being created, it has an instance
# variable _SO_creating, which is true. This way all the
@@ -542,14 +382,6 @@
# it's set (default 1).
_cacheValues = True
- #DSM: The _inheritable attribute controls wheter the class can by
- #DSM: inherited 'logically' with a foreignKey and back reference.
- _inheritable = False # Does this class is inheritable
- _parentClass = None # A reference to the parent class
- _parent = None # A reference to the parent instance
- _childClasses = {} # Reference to child classes
- childName = None # Children name (to be able to get a subclass)
-
# The _defaultOrder is used by SelectResults
_defaultOrder = None
@@ -578,13 +410,233 @@
# aren't using integer IDs
_idType = int
+ sqlmeta = sqlmeta
+
+ #DSM: The _inheritable attribute controls wheter the class can by
+ #DSM: inherited 'logically' with a foreignKey and back reference.
+ _inheritable = False # Does this class is inheritable
+ _parentClass = None # A reference to the parent class
+ _parent = None # A reference to the parent instance
+ _childClasses = {} # Reference to child classes
+ childName = None # Children name (to be able to get a subclass)
+
# The law of Demeter: the class should not call another classes by name
SelectResultsClass = SelectResults
+ def __classinit__(cls, new_attrs):
+
+ # This is true if we're initializing the SQLObject class,
+ # instead of a subclass:
+ is_base = cls.__bases__ == (object,)
+
+ if (not new_attrs.has_key('sqlmeta')
+ and not is_base):
+ # We have to create our own subclass, usually.
+ # type(className, bases_tuple, attr_dict) creates a new
+ # subclass:
+ #cls.sqlmeta = cls.sqlmeta.clone()
+ cls.sqlmeta = type('sqlmeta', (cls.sqlmeta,), {})
+ cls.sqlmeta.setClass(cls)
+ cls.sqlmeta.finishClass()
+
+
+ implicitColumns = []
+ implicitJoins = []
+ implicitIndexes = []
+ for attr, value in new_attrs.items():
+ if isinstance(value, col.Col):
+ value.name = attr
+ implicitColumns.append(value)
+ delattr(cls, attr)
+ continue
+ if isinstance(value, joins.Join):
+ value.joinMethodName = attr
+ implicitJoins.append(value)
+ delattr(cls, attr)
+ continue
+ if isinstance(value, index.DatabaseIndex):
+ value.setName(attr)
+ implicitIndexes.append(value)
+ delattr(cls, attr)
+ continue
+
+ if (new_attrs.has_key('_table') and not is_base):
+ deprecated("'_table' is deprecated; please set the 'table' "
+ "attribute in sqlmeta instead")
+ cls.sqlmeta.table = cls._table
+ del cls._table
+
+ if new_attrs.has_key('_connection'):
+ connection = new_attrs['_connection']
+ del cls._connection
+ assert not new_attrs.has_key('connection')
+ elif new_attrs.has_key('connection'):
+ connection = new_attrs['connection']
+ del cls.connection
+ else:
+ connection = None
+
+ cls._SO_finishedClassCreation = False
+
+ # We fix up the columns here -- replacing any strings with
+ # simply-contructed Col objects, and searching the class
+ # variables for instances of Col objects (which get put into
+ # the _columns instance variable and deleted).
+ columns = []
+ for column in new_attrs.get('_columns', []):
+ if isinstance(column, str):
+ column = col.Col(column)
+ columns.append(column)
+ if columns:
+ cls._columns = columns
+
+ # We append to _columns, but we don't want to change the
+ # superclass's _columns list, so we make a copy if necessary
+ if not new_attrs.has_key('_columns'):
+ cls._columns = cls._columns[:]
+
+ #DSM: Need to know very soon if the class is a child of an
+ #DSM: inheritable class. If so, we keep a link to our parent class.
+ cls._childClasses = {}
+ for _cls in cls.__bases__:
+ if hasattr(_cls, '_inheritable') and _cls._inheritable:
+ cls._parentClass = _cls
+ cls._parent = None
+ _cls._childClasses[cls.__name__] = cls
+
+ #DSM: If this class is a child of a parent class, we need to do some
+ #DSM: attribute check and a a foreign key to the parent.
+ if cls._parentClass:
+ #DSM: First, look for invalid column name:
+ #DSM: reserved ones or same as a parent
+ parentCols = [column.name for column in cls._columns]
+ for column in implicitColumns:
+ cname = column.name
+ if cname in ['childName']:
+ raise AttributeError, \
+ "The column name '%s' is reserved" % cname
+ if cname in parentCols:
+ raise AttributeError, "The column '%s' is already " \
+ "defined in an inheritable parent" % cname
+ #DSM: Remove columns if inherited from an inheritable class
+ #DSM: as we don't want them. All we want is a foreign key
+ #DSM: that will link to our parent
+ cls._columns = []
+ #DSM: If this is inheritable, add some default columns
+ # to be able to link to children
+ if hasattr(cls, '_inheritable') and cls._inheritable:
+ cls._columns.append(
+ col.StringCol(name='childName',default=None))
+
+ cls._columns.extend(implicitColumns)
+ if not new_attrs.has_key('_joins'):
+ cls._joins = cls._joins[:]
+ cls._joins.extend(implicitJoins)
+ if not new_attrs.has_key('_indexes'):
+ cls._indexes = cls._indexes[:]
+ cls._indexes.extend(implicitIndexes)
+
+ ######################################################
+ # Set some attributes to their defaults, if necessary.
+ # First we get the connection:
+ if not connection and not getattr(cls, '_connection', None):
+ mod = sys.modules[cls.__module__]
+ # See if there's a __connection__ global in
+ # the module, use it if there is.
+ if hasattr(mod, '__connection__'):
+ connection = mod.__connection__
+
+ if connection or not hasattr(cls, '_connection'):
+ cls.setConnection(connection)
+
+ if (new_attrs.has_key('_style') and not is_base):
+ deprecated("'_style' is deprecated; please set the 'style' "
+ "attribute in sqlmeta instead")
+ cls.sqlmeta.style = cls._style
+ del cls._style
+
+ # plainSetters are columns that haven't been overridden by the
+ # user, so we can contact the database directly to set them.
+ # Note that these can't set these in the SQLObject class
+ # itself, because they specific to this subclass of SQLObject,
+ # and cannot be shared among classes.
+ cls._SO_plainSetters = {}
+ cls._SO_plainGetters = {}
+ cls._SO_plainForeignSetters = {}
+ cls._SO_plainForeignGetters = {}
+ cls._SO_plainJoinGetters = {}
+ cls._SO_plainJoinAdders = {}
+ cls._SO_plainJoinRemovers = {}
+
+ # This is a dictionary of columnName: columnObject
+ cls._SO_columnDict = {}
+ cls._SO_columns = []
+
+ if (new_attrs.has_key('_idName') and not is_base):
+ deprecated("'_idName' is deprecated; please set the 'idName' "
+ "attribute in sqlmeta instead")
+ cls.sqlmeta.idName = cls._idName
+ del cls._idName
+
+ #DSM: If we are a child, get the q magic from the parent
+ currentClass = cls
+ while currentClass._parentClass:
+ currentClass = currentClass._parentClass
+ for column in currentClass._columns:
+ if type(column) == col.ForeignKey: continue
+ setattr(cls.q, column.name,
+ getattr(currentClass.q, column.name))
+
+ # We have to check if there are columns in the inherited
+ # _columns where the attribute has been set to None in this
+ # class. If so, then we need to remove that column from
+ # _columns.
+ for column in cls._columns[:]:
+ if (new_attrs.has_key(column.name)
+ and new_attrs[column.name] is None):
+ cls._columns.remove(column)
+
+ for column in cls._columns:
+ cls.addColumn(column)
+ if cls._fromDatabase:
+ cls.addColumnsFromDatabase()
+
+ ########################################
+ # Now we do the joins:
+
+ # We keep track of the different joins by index,
+ # putting them in this list.
+ cls._SO_joinList = []
+ cls._SO_joinDict = {}
+
+ for join in cls._joins:
+ cls.addJoin(join)
+
+ # We don't setup the properties until we're finished with the
+ # batch adding of all the columns...
+ cls._SO_finishedClassCreation = True
+ makeProperties(cls)
+
+ cls._SO_indexList = []
+ for idx in cls._indexes:
+ cls.addIndex(idx)
+
+ # We use the magic "q" attribute for accessing lazy
+ # SQL where-clause generation. See the sql module for
+ # more.
+ if not is_base:
+ cls.q = sqlbuilder.SQLObjectTable(cls)
+
+ classregistry.registry(cls._registry).addClass(cls)
+
+ _style = _sqlmeta_attr('style')
+ _table = _sqlmeta_attr('table')
+ _idName = _sqlmeta_attr('idName')
+
def get(cls, id, connection=None, selectResults=None):
assert id is not None, 'None is not a possible id for %s' % cls.__name
-
+
id = cls._idType(id)
if connection is None:
@@ -662,7 +714,7 @@
setattr(cls, '_SO_toPython_%s' % name, column.toPython)
setattr(cls, rawSetterName(name), setter)
# Then do the aliasing
- if not hasattr(cls, setterName(name)) or name == 'childName':
+ if not hasattr(cls, setterName(name)) or (name == 'childName'):
setattr(cls, setterName(name), setter)
# We keep track of setters that haven't been
# overridden, because we can combine these
@@ -775,7 +827,7 @@
conn.delColumn(cls._table, column)
if cls._SO_finishedClassCreation:
- delattr(cls, name)
+ unmakeProperties(cls)
delColumn = classmethod(delColumn)
@@ -853,7 +905,7 @@
delattr(cls, 'add' + join.addRemovePrefix)
if cls._SO_finishedClassCreation:
- delattr(cls, meth)
+ unmakeProperties(cls)
delJoin = classmethod(delJoin)
@@ -863,6 +915,10 @@
# created, unlike __init__ which would be called
# anytime the object was returned from cache.
self.id = id
+ # We shadow the sqlmeta class with an instance of sqlmeta
+ # that points to us (our sqlmeta buddy object; where the
+ # sqlmeta class is our class's buddy class)
+ self.sqlmeta = self.__class__.sqlmeta(self)
self._SO_writeLock = threading.Lock()
# If no connection was given, we'll inherit the class
@@ -1119,6 +1175,7 @@
self._create(id, **kw)
def _create(self, id, **kw):
+
self._SO_creating = True
self._SO_createValues = {}
self._SO_validatorState = SQLObjectState(self)
@@ -1393,7 +1450,6 @@
cls._connection = value
setConnection = classmethod(setConnection)
-
def capitalize(name):
return name[0].capitalize() + name[1:]
Modified: home/phd/SQLObject/inheritance/sqlobject/sqlbuilder.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/sqlbuilder.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/sqlbuilder.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -329,6 +329,9 @@
def __init__(self, soClass):
self.soClass = soClass
+ assert soClass._table, (
+ "Bad table name in class %r: %r"
+ % (soClass, soClass._table))
Table.__init__(self, soClass._table)
def __getattr__(self, attr):
Modified: home/phd/SQLObject/inheritance/sqlobject/sqlite/sqliteconnection.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/sqlite/sqliteconnection.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/sqlite/sqliteconnection.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -23,11 +23,18 @@
def connectionFromURI(cls, uri):
user, password, host, path, args = cls._parseURI(uri)
- assert host is None, "SQLite can only be used locally (with a URI like sqlite:///file or sql:/file, not %r)" % uri
- assert user is None and password is None, "You may not provide usernames or passwords for SQLite databases"
+ assert host is None, (
+ "SQLite can only be used locally (with a URI like "
+ "sqlite:///file or sqlite:/file, not %r)" % uri)
+ assert user is None and password is None, (
+ "You may not provide usernames or passwords for SQLite "
+ "databases")
return cls(filename=path, **args)
connectionFromURI = classmethod(connectionFromURI)
+ def uri(self):
+ return 'sqlite:///%s' % self.filename
+
def _setAutoCommit(self, conn, auto):
conn.autocommit = auto
Modified: home/phd/SQLObject/inheritance/sqlobject/styles.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/styles.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/styles.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -58,6 +58,9 @@
# keys, you can't really change this style.
return attr + "ID"
+ def tableReference(self, table):
+ return table + "_id"
+
class MixedCaseUnderscoreStyle(Style):
"""
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/dbtest.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/dbtest.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/dbtest.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -43,17 +43,26 @@
}
-def setupClass(soClass):
+def setupClass(soClasses):
"""
- Makes sure the class has a corresponding and correct table.
- This won't recreate the table if it already exists. It will
- check that the table is properly defined (in case you change
- your table definition).
+ Makes sure the classes have a corresponding and correct table.
+ This won't recreate the table if it already exists. It will check
+ that the table is properly defined (in case you change your table
+ definition).
+
+ You can provide a single class or a list of classes; if a list
+ then classes will be created in the order you provide, and
+ destroyed in the opposite order. So if class A depends on class
+ B, then do setupClass([B, A]) and B won't be destroyed or cleared
+ until after A is destroyed or cleared.
"""
+ if not isinstance(soClasses, (list, tuple)):
+ soClasses = [soClasses]
connection = getConnection()
- soClass._connection = connection
- installOrClear(soClass)
- return soClass
+ for soClass in soClasses:
+ soClass._connection = connection
+ installOrClear(soClasses)
+ return soClasses
installedDBFilename = os.path.join(os.getcwd(), 'dbs_data.tmp')
@@ -82,27 +91,33 @@
createSQL = sqlobject.StringCol(notNull=True)
connectionURI = sqlobject.StringCol(notNull=True)
- def installOrClear(cls, soClass):
+ def installOrClear(cls, soClasses):
cls.setup()
- table = soClass._table
- if not soClass._connection.tableExists(table):
- cls.install(soClass)
- items = list(cls.selectBy(
- tableName=table,
- connectionURI=soClass._connection.uri()))
- if items:
- instance = items[0]
- sql = instance.createSQL
- else:
- sql = None
- newSQL = soClass.createTableSQL()
- if sql != newSQL:
- if sql is not None:
- instance.destroySelf()
- cls.drop(soClass)
- cls.install(soClass)
- else:
- cls.clear(soClass)
+ reversed = list(soClasses)[:]
+ reversed.reverse()
+ for soClass in reversed:
+ table = soClass._table
+ if not soClass._connection.tableExists(table):
+ continue
+ items = list(cls.selectBy(
+ tableName=table,
+ connectionURI=soClass._connection.uri()))
+ if items:
+ instance = items[0]
+ sql = instance.createSQL
+ else:
+ sql = None
+ newSQL = soClass.createTableSQL()
+ if sql != newSQL:
+ if sql is not None:
+ instance.destroySelf()
+ cls.drop(soClass)
+ else:
+ cls.clear(soClass)
+ for soClass in soClasses:
+ table = soClass._table
+ if not soClass._connection.tableExists(table):
+ cls.install(soClass)
installOrClear = classmethod(installOrClear)
def install(cls, soClass):
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_auto.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_auto.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_auto.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -73,6 +73,7 @@
age INT DEFAULT NULL,
created DATETIME NOT NULL,
happy char(1) DEFAULT 'Y' NOT NULL,
+ long_field TEXT,
wannahavefun TINYINT DEFAULT 0 NOT NULL
)
"""
@@ -85,6 +86,7 @@
age INT DEFAULT 0,
created VARCHAR(40) NOT NULL,
happy char(1) DEFAULT 'Y' NOT NULL,
+ long_field TEXT,
wannahavefun BOOL DEFAULT FALSE NOT NULL
)
"""
@@ -96,7 +98,8 @@
last_name VARCHAR(200) NOT NULL,
age INT DEFAULT 0,
created VARCHAR(40) NOT NULL,
- happy char(1) DEFAULT 'Y' NOT NULL
+ happy char(1) DEFAULT 'Y' NOT NULL,
+ long_field TEXT
)
"""
@@ -125,12 +128,16 @@
lastName='doe',
age=10,
created=now(),
- wannahavefun=False)
+ wannahavefun=False,
+ long_field='x'*1000)
jane = AutoTest(firstName='jane',
lastName='doe',
happy='N',
created=now(),
- wannahavefun=True)
+ wannahavefun=True,
+ long_field='x'*1000)
assert not john.wannahavefun
assert jane.wannahavefun
+ assert john.long_field == 'x'*1000
+ assert jane.long_field == 'x'*1000
del classregistry.registry(AutoTest._registry).classes['AutoTest']
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_basic.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_basic.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_basic.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -77,8 +77,7 @@
me = StringCol(length=10)
def test_foreignKey():
- setupClass(TestSO3)
- setupClass(TestSO4)
+ setupClass([TestSO4, TestSO3])
tc3 = TestSO3(name='a')
assert tc3.other is None
assert tc3.other2 is None
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_blob.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_blob.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_blob.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -19,4 +19,7 @@
ImageData._connection.cache.clear()
prof2 = ImageData.get(iid)
+ # @@: This seems to fail in SQLite, which trims off the
+ # first and last character (\x00 and \xff). We should write
+ # a test for the upstream driver, as the error might be there.
assert prof2.image == data
Copied: home/phd/SQLObject/inheritance/sqlobject/tests/test_boundattributes.py (from rev 585, trunk/SQLObject/sqlobject/tests/test_boundattributes.py)
Copied: home/phd/SQLObject/inheritance/sqlobject/tests/test_declarative.py (from rev 585, trunk/SQLObject/sqlobject/tests/test_declarative.py)
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_distinct.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_distinct.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_distinct.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -18,8 +18,7 @@
return result
def test_distinct():
- setupClass(Distinct1)
- setupClass(Distinct2)
+ setupClass([Distinct1, Distinct2])
obs = [Distinct1(n=i) for i in range(3)]
Distinct2(other=obs[0])
Distinct2(other=obs[0])
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_joins.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_joins.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_joins.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -76,8 +76,7 @@
class TestJoin2:
def setup_method(self, meth):
- setupClass(PersonJoiner2)
- setupClass(AddressJoiner2)
+ setupClass([PersonJoiner2, AddressJoiner2])
p1 = PersonJoiner2(name='bob')
p2 = PersonJoiner2(name='sally')
for z in ['11111', '22222', '33333']:
Modified: home/phd/SQLObject/inheritance/sqlobject/tests/test_style.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/tests/test_style.py 2005-02-09 08:37:37 UTC (rev 589)
+++ home/phd/SQLObject/inheritance/sqlobject/tests/test_style.py 2005-02-09 13:15:16 UTC (rev 590)
@@ -19,8 +19,7 @@
_style = AnotherStyle()
def test_style():
- setupClass(SOStyleTest2)
- setupClass(SOStyleTest1)
+ setupClass([SOStyleTest2, SOStyleTest1])
st1 = SOStyleTest1(a='something', st2=None)
st2 = SOStyleTest2(b='whatever')
st1.st2 = st2
|
|
From: <sub...@co...> - 2005-02-09 08:37:40
|
Author: ianb
Date: 2005-02-09 08:37:37 +0000 (Wed, 09 Feb 2005)
New Revision: 589
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
Started putting information into the sqlmeta class:
* the table name
* the ID name
* the style
Maintaining backward compatibility.
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-02-09 08:35:21 UTC (rev 588)
+++ trunk/SQLObject/sqlobject/main.py 2005-02-09 08:37:37 UTC (rev 589)
@@ -143,9 +143,58 @@
alongside every SQLObject instance.
"""
+ table = None
+ idName = None
+ style = None
+
+ __metaclass__ = declarative.DeclarativeMeta
+
+ # These attributes shouldn't be shared with superclasses:
+ _unshared_attributes = ['table']
+
+ def __classinit__(cls, new_attrs):
+ for attr in cls._unshared_attributes:
+ if not new_attrs.has_key(attr):
+ setattr(cls, attr, None)
+
def __init__(self, instance):
self.instance = instance
+ def setClass(cls, soClass):
+ cls.soClass = soClass
+ setClass = classmethod(setClass)
+
+ def finishClass(cls):
+ if not cls.style:
+ if cls.soClass._connection and cls.soClass._connection.style:
+ cls.style = cls.soClass._connection.style
+ else:
+ cls.style = styles.defaultStyle
+ if cls.table is None:
+ cls.table = cls.style.pythonClassToDBTable(cls.soClass.__name__)
+ if cls.idName is None:
+ cls.idName = cls.style.idForTable(cls.table)
+ finishClass = classmethod(finishClass)
+
+class _sqlmeta_attr(object):
+
+ def __init__(self, name):
+ self.name = name
+
+ def __get__(self, obj, type=None):
+ return getattr((type or obj).sqlmeta, self.name)
+
+
+# @@: This should become a public interface or documented or
+# something. Turning it on gives earlier warning about things
+# that will be deprecated (having this off we won't flood people
+# with warnings right away).
+strict_warnings = False
+
+def deprecated(message):
+ if strict_warnings:
+ warnings.warn(message, DeprecationWarning, stacklevel=1)
+
# SQLObject is the superclass for all SQLObject classes, of
# course. All the deeper magic is done in MetaSQLObject, and
# only lesser magic is done here. All the actual work is done
@@ -208,13 +257,20 @@
def __classinit__(cls, new_attrs):
+ # This is true if we're initializing the SQLObject class,
+ # instead of a subclass:
+ is_base = cls.__bases__ == (object,)
+
if (not new_attrs.has_key('sqlmeta')
- and not cls.__bases__ == (object,)):
+ and not is_base):
# We have to create our own subclass, usually.
# type(className, bases_tuple, attr_dict) creates a new
# subclass:
+ #cls.sqlmeta = cls.sqlmeta.clone()
cls.sqlmeta = type('sqlmeta', (cls.sqlmeta,), {})
- cls.sqlmeta.soClass = cls
+ cls.sqlmeta.setClass(cls)
+ cls.sqlmeta.finishClass()
+
implicitColumns = []
implicitJoins = []
@@ -236,10 +292,11 @@
delattr(cls, attr)
continue
- # We *don't* want to inherit _table, so we make sure it
- # is defined in this class (not a superclass)
- if not new_attrs.has_key('_table'):
- cls._table = None
+ if (new_attrs.has_key('_table') and not is_base):
+ deprecated("'_table' is deprecated; please set the 'table' "
+ "attribute in sqlmeta instead")
+ cls.sqlmeta.table = cls._table
+ del cls._table
if new_attrs.has_key('_connection'):
connection = new_attrs['_connection']
@@ -290,13 +347,11 @@
if connection or not hasattr(cls, '_connection'):
cls.setConnection(connection)
- # The style object tells how to map between Python
- # identifiers and Database identifiers:
- if not cls._style:
- if cls._connection and cls._connection.style:
- cls._style = cls._connection.style
- else:
- cls._style = styles.defaultStyle
+ if (new_attrs.has_key('_style') and not is_base):
+ deprecated("'_style' is deprecated; please set the 'style' "
+ "attribute in sqlmeta instead")
+ cls.sqlmeta.style = cls._style
+ del cls._style
# plainSetters are columns that haven't been overridden by the
# user, so we can contact the database directly to set them.
@@ -315,19 +370,12 @@
cls._SO_columnDict = {}
cls._SO_columns = []
- # If _table isn't given, use style default
- if not cls._table:
- cls._table = cls._style.pythonClassToDBTable(cls.__name__)
+ if (new_attrs.has_key('_idName') and not is_base):
+ deprecated("'_idName' is deprecated; please set the 'idName' "
+ "attribute in sqlmeta instead")
+ cls.sqlmeta.idName = cls._idName
+ del cls._idName
- # If _idName isn't given, use style default
- if not new_attrs.has_key('_idName'):
- cls._idName = cls._style.idForTable(cls._table)
-
- # We use the magic "q" attribute for accessing lazy
- # SQL where-clause generation. See the sql module for
- # more.
- cls.q = sqlbuilder.SQLObjectTable(cls)
-
# We have to check if there are columns in the inherited
# _columns where the attribute has been set to None in this
# class. If so, then we need to remove that column from
@@ -362,8 +410,18 @@
for idx in cls._indexes:
cls.addIndex(idx)
+ # We use the magic "q" attribute for accessing lazy
+ # SQL where-clause generation. See the sql module for
+ # more.
+ if not is_base:
+ cls.q = sqlbuilder.SQLObjectTable(cls)
+
classregistry.registry(cls._registry).addClass(cls)
+ _style = _sqlmeta_attr('style')
+ _table = _sqlmeta_attr('table')
+ _idName = _sqlmeta_attr('idName')
+
def get(cls, id, connection=None, selectResults=None):
assert id is not None, 'None is not a possible id for %s' % cls.__name
@@ -1329,7 +1387,7 @@
Return the accumulate result
"""
conn = self.ops.get('connection', self.sourceClass._connection)
- return conn.accumulateSelect(self,expression)
+ return conn.accumulateSelect(self, expression)
def count(self):
""" Counting elements of current select results """
|
|
From: <sub...@co...> - 2005-02-09 08:35:25
|
Author: ianb
Date: 2005-02-09 08:35:21 +0000 (Wed, 09 Feb 2005)
New Revision: 588
Modified:
trunk/SQLObject/sqlobject/tests/dbtest.py
Log:
typo/bug
Modified: trunk/SQLObject/sqlobject/tests/dbtest.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/dbtest.py 2005-02-09 08:35:01 UTC (rev 587)
+++ trunk/SQLObject/sqlobject/tests/dbtest.py 2005-02-09 08:35:21 UTC (rev 588)
@@ -115,6 +115,7 @@
else:
cls.clear(soClass)
for soClass in soClasses:
+ table = soClass._table
if not soClass._connection.tableExists(table):
cls.install(soClass)
installOrClear = classmethod(installOrClear)
|
|
From: <sub...@co...> - 2005-02-09 08:35:07
|
Author: ianb
Date: 2005-02-09 08:35:01 +0000 (Wed, 09 Feb 2005)
New Revision: 587
Modified:
trunk/SQLObject/sqlobject/sqlbuilder.py
Log:
Avoid tables with empty names
Modified: trunk/SQLObject/sqlobject/sqlbuilder.py
===================================================================
--- trunk/SQLObject/sqlobject/sqlbuilder.py 2005-02-09 08:34:41 UTC (rev 586)
+++ trunk/SQLObject/sqlobject/sqlbuilder.py 2005-02-09 08:35:01 UTC (rev 587)
@@ -329,6 +329,9 @@
def __init__(self, soClass):
self.soClass = soClass
+ assert soClass._table, (
+ "Bad table name in class %r: %r"
+ % (soClass, soClass._table))
Table.__init__(self, soClass._table)
def __getattr__(self, attr):
|
|
From: <sub...@co...> - 2005-02-09 08:34:43
|
Author: ianb
Date: 2005-02-09 08:34:41 +0000 (Wed, 09 Feb 2005)
New Revision: 586
Modified:
trunk/SQLObject/sqlobject/dbconnection.py
Log:
Don't print out as much debugging about the pool acquisition/release
Modified: trunk/SQLObject/sqlobject/dbconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/dbconnection.py 2005-02-09 08:27:56 UTC (rev 585)
+++ trunk/SQLObject/sqlobject/dbconnection.py 2005-02-09 08:34:41 UTC (rev 586)
@@ -181,6 +181,8 @@
conn.close()
def printDebug(self, conn, s, name, type='query'):
+ if name == 'Pool' and self.debug != 'Pool':
+ return
if type == 'query':
sep = ': '
else:
|
|
From: <sub...@co...> - 2005-02-09 08:28:00
|
Author: phd
Date: 2005-02-09 08:27:56 +0000 (Wed, 09 Feb 2005)
New Revision: 585
Modified:
trunk/SQLObject/sqlobject/col.py
Log:
Do not convert None to Binary.
Modified: trunk/SQLObject/sqlobject/col.py
===================================================================
--- trunk/SQLObject/sqlobject/col.py 2005-02-09 05:52:00 UTC (rev 584)
+++ trunk/SQLObject/sqlobject/col.py 2005-02-09 08:27:56 UTC (rev 585)
@@ -890,6 +890,8 @@
"""
def fromPython(self, value, state):
+ if value is None:
+ return None
return state.soObject._connection.createBinary(value)
class SOBLOBCol(SOStringCol):
|
|
From: <sub...@co...> - 2005-02-09 05:52:04
|
Author: ianb
Date: 2005-02-09 05:52:00 +0000 (Wed, 09 Feb 2005)
New Revision: 584
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
Added a sqlmeta buddy class/object, which will hold data in the
very near future.
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-02-09 05:40:19 UTC (rev 583)
+++ trunk/SQLObject/sqlobject/main.py 2005-02-09 05:52:00 UTC (rev 584)
@@ -134,6 +134,18 @@
"""
pass
+class sqlmeta(object):
+
+ """
+ This object is the object we use to keep track of all sorts of
+ information. Subclasses are made for each SQLObject subclass
+ (dynamically if necessary), and instances are created to go
+ alongside every SQLObject instance.
+ """
+
+ def __init__(self, instance):
+ self.instance = instance
+
# SQLObject is the superclass for all SQLObject classes, of
# course. All the deeper magic is done in MetaSQLObject, and
# only lesser magic is done here. All the actual work is done
@@ -192,7 +204,18 @@
# aren't using integer IDs
_idType = int
+ sqlmeta = sqlmeta
+
def __classinit__(cls, new_attrs):
+
+ if (not new_attrs.has_key('sqlmeta')
+ and not cls.__bases__ == (object,)):
+ # We have to create our own subclass, usually.
+ # type(className, bases_tuple, attr_dict) creates a new
+ # subclass:
+ cls.sqlmeta = type('sqlmeta', (cls.sqlmeta,), {})
+ cls.sqlmeta.soClass = cls
+
implicitColumns = []
implicitJoins = []
implicitIndexes = []
@@ -623,6 +646,10 @@
# created, unlike __init__ which would be called
# anytime the object was returned from cache.
self.id = id
+ # We shadow the sqlmeta class with an instance of sqlmeta
+ # that points to us (our sqlmeta buddy object; where the
+ # sqlmeta class is our class's buddy class)
+ self.sqlmeta = self.__class__.sqlmeta(self)
self._SO_writeLock = threading.Lock()
# If no connection was given, we'll inherit the class
|
|
From: <sub...@co...> - 2005-02-09 05:40:25
|
Author: ianb
Date: 2005-02-09 05:40:19 +0000 (Wed, 09 Feb 2005)
New Revision: 583
Modified:
trunk/SQLObject/sqlobject/main.py
Log:
Removed SQLObjectMeta and use DeclarativeMeta, with all the
logic in __classinit__. __classinit__ looks almost exactly
like DeclarativeMeta.__new__, except newClass renamed to cls
and d to new_attrs
Modified: trunk/SQLObject/sqlobject/main.py
===================================================================
--- trunk/SQLObject/sqlobject/main.py 2005-02-09 05:27:03 UTC (rev 582)
+++ trunk/SQLObject/sqlobject/main.py 2005-02-09 05:40:19 UTC (rev 583)
@@ -30,6 +30,7 @@
import joins
import index
import classregistry
+import declarative
import sys
if sys.version_info[:3] < (2, 2, 0):
@@ -42,167 +43,6 @@
True, False = 1==1, 0==1
-# This is the metaclass. It essentially takes a dictionary
-# of all the attributes (and thus methods) defined in the
-# class definition. It futzes with them, and spits out the
-# new class definition.
-class MetaSQLObject(type):
-
- def __new__(cls, className, bases, d):
-
- # We fix up the columns here -- replacing any strings with
- # simply-contructed Col objects, and searching the class
- # variables for instances of Col objects (which get put into
- # the _columns instance variable and deleted).
- columns = []
- for column in d.get('_columns', []):
- if isinstance(column, str):
- column = col.Col(column)
- columns.append(column)
- if columns:
- d['_columns'] = columns
-
- implicitColumns = []
- implicitJoins = []
- implicitIndexes = []
- for attr, value in d.items():
- if isinstance(value, col.Col):
- value.name = attr
- implicitColumns.append(value)
- del d[attr]
- continue
- if isinstance(value, joins.Join):
- value.joinMethodName = attr
- implicitJoins.append(value)
- del d[attr]
- continue
- if isinstance(value, index.DatabaseIndex):
- value.setName(attr)
- implicitIndexes.append(value)
- del d[attr]
- continue
-
- # We *don't* want to inherit _table, so we make sure it
- # is defined in this class (not a superclass)
- if not d.has_key('_table'):
- d['_table'] = None
-
-
- if d.has_key('_connection'):
- connection = d['_connection']
- del d['_connection']
- assert not d.has_key('connection')
- elif d.has_key('connection'):
- connection = d['connection']
- del d['connection']
- else:
- connection = None
-
- # We actually create the class.
- newClass = type.__new__(cls, className, bases, d)
- newClass._SO_finishedClassCreation = False
-
- # We append to _columns, but we don't want to change the
- # superclass's _columns list, so we make a copy if necessary
- if not d.has_key('_columns'):
- newClass._columns = newClass._columns[:]
- newClass._columns.extend(implicitColumns)
- if not d.has_key('_joins'):
- newClass._joins = newClass._joins[:]
- newClass._joins.extend(implicitJoins)
- if not d.has_key('_indexes'):
- newClass._indexes = newClass._indexes[:]
- newClass._indexes.extend(implicitIndexes)
-
- ######################################################
- # Set some attributes to their defaults, if necessary.
- # First we get the connection:
- if not connection and not getattr(newClass, '_connection', None):
- mod = sys.modules[newClass.__module__]
- # See if there's a __connection__ global in
- # the module, use it if there is.
- if hasattr(mod, '__connection__'):
- connection = mod.__connection__
-
- if connection or not hasattr(newClass, '_connection'):
- newClass.setConnection(connection)
-
- # The style object tells how to map between Python
- # identifiers and Database identifiers:
- if not newClass._style:
- if newClass._connection and newClass._connection.style:
- newClass._style = newClass._connection.style
- else:
- newClass._style = styles.defaultStyle
-
- # plainSetters are columns that haven't been overridden by the
- # user, so we can contact the database directly to set them.
- # Note that these can't set these in the SQLObject class
- # itself, because they specific to this subclass of SQLObject,
- # and cannot be shared among classes.
- newClass._SO_plainSetters = {}
- newClass._SO_plainGetters = {}
- newClass._SO_plainForeignSetters = {}
- newClass._SO_plainForeignGetters = {}
- newClass._SO_plainJoinGetters = {}
- newClass._SO_plainJoinAdders = {}
- newClass._SO_plainJoinRemovers = {}
-
- # This is a dictionary of columnName: columnObject
- newClass._SO_columnDict = {}
- newClass._SO_columns = []
-
- # If _table isn't given, use style default
- if not newClass._table:
- newClass._table = newClass._style.pythonClassToDBTable(className)
-
- # If _idName isn't given, use style default
- if not d.has_key('_idName'):
- newClass._idName = newClass._style.idForTable(newClass._table)
-
- # We use the magic "q" attribute for accessing lazy
- # SQL where-clause generation. See the sql module for
- # more.
- newClass.q = sqlbuilder.SQLObjectTable(newClass)
-
- # We have to check if there are columns in the inherited
- # _columns where the attribute has been set to None in this
- # class. If so, then we need to remove that column from
- # _columns.
- for column in newClass._columns[:]:
- if d.has_key(column.name) and d[column.name] is None:
- newClass._columns.remove(column)
-
- for column in newClass._columns:
- newClass.addColumn(column)
- if newClass._fromDatabase:
- newClass.addColumnsFromDatabase()
-
- ########################################
- # Now we do the joins:
-
- # We keep track of the different joins by index,
- # putting them in this list.
- newClass._SO_joinList = []
- newClass._SO_joinDict = {}
-
- for join in newClass._joins:
- newClass.addJoin(join)
-
- # We don't setup the properties until we're finished with the
- # batch adding of all the columns...
- newClass._SO_finishedClassCreation = True
- makeProperties(newClass)
-
- newClass._SO_indexList = []
- for idx in newClass._indexes:
- newClass.addIndex(idx)
-
- classregistry.registry(newClass._registry).addClass(newClass)
-
- # And return the class
- return newClass
-
def makeProperties(obj):
"""
This function takes a dictionary of methods and finds
@@ -302,7 +142,7 @@
# MetaSQLObject.
class SQLObject(object):
- __metaclass__ = MetaSQLObject
+ __metaclass__ = declarative.DeclarativeMeta
# When an object is being created, it has an instance
# variable _SO_creating, which is true. This way all the
@@ -352,6 +192,155 @@
# aren't using integer IDs
_idType = int
+ def __classinit__(cls, new_attrs):
+ implicitColumns = []
+ implicitJoins = []
+ implicitIndexes = []
+ for attr, value in new_attrs.items():
+ if isinstance(value, col.Col):
+ value.name = attr
+ implicitColumns.append(value)
+ delattr(cls, attr)
+ continue
+ if isinstance(value, joins.Join):
+ value.joinMethodName = attr
+ implicitJoins.append(value)
+ delattr(cls, attr)
+ continue
+ if isinstance(value, index.DatabaseIndex):
+ value.setName(attr)
+ implicitIndexes.append(value)
+ delattr(cls, attr)
+ continue
+
+ # We *don't* want to inherit _table, so we make sure it
+ # is defined in this class (not a superclass)
+ if not new_attrs.has_key('_table'):
+ cls._table = None
+
+ if new_attrs.has_key('_connection'):
+ connection = new_attrs['_connection']
+ del cls._connection
+ assert not new_attrs.has_key('connection')
+ elif new_attrs.has_key('connection'):
+ connection = new_attrs['connection']
+ del cls.connection
+ else:
+ connection = None
+
+ cls._SO_finishedClassCreation = False
+
+ # We fix up the columns here -- replacing any strings with
+ # simply-contructed Col objects, and searching the class
+ # variables for instances of Col objects (which get put into
+ # the _columns instance variable and deleted).
+ columns = []
+ for column in new_attrs.get('_columns', []):
+ if isinstance(column, str):
+ column = col.Col(column)
+ columns.append(column)
+ if columns:
+ cls._columns = columns
+
+ # We append to _columns, but we don't want to change the
+ # superclass's _columns list, so we make a copy if necessary
+ if not new_attrs.has_key('_columns'):
+ cls._columns = cls._columns[:]
+ cls._columns.extend(implicitColumns)
+ if not new_attrs.has_key('_joins'):
+ cls._joins = cls._joins[:]
+ cls._joins.extend(implicitJoins)
+ if not new_attrs.has_key('_indexes'):
+ cls._indexes = cls._indexes[:]
+ cls._indexes.extend(implicitIndexes)
+
+ ######################################################
+ # Set some attributes to their defaults, if necessary.
+ # First we get the connection:
+ if not connection and not getattr(cls, '_connection', None):
+ mod = sys.modules[cls.__module__]
+ # See if there's a __connection__ global in
+ # the module, use it if there is.
+ if hasattr(mod, '__connection__'):
+ connection = mod.__connection__
+
+ if connection or not hasattr(cls, '_connection'):
+ cls.setConnection(connection)
+
+ # The style object tells how to map between Python
+ # identifiers and Database identifiers:
+ if not cls._style:
+ if cls._connection and cls._connection.style:
+ cls._style = cls._connection.style
+ else:
+ cls._style = styles.defaultStyle
+
+ # plainSetters are columns that haven't been overridden by the
+ # user, so we can contact the database directly to set them.
+ # Note that these can't set these in the SQLObject class
+ # itself, because they specific to this subclass of SQLObject,
+ # and cannot be shared among classes.
+ cls._SO_plainSetters = {}
+ cls._SO_plainGetters = {}
+ cls._SO_plainForeignSetters = {}
+ cls._SO_plainForeignGetters = {}
+ cls._SO_plainJoinGetters = {}
+ cls._SO_plainJoinAdders = {}
+ cls._SO_plainJoinRemovers = {}
+
+ # This is a dictionary of columnName: columnObject
+ cls._SO_columnDict = {}
+ cls._SO_columns = []
+
+ # If _table isn't given, use style default
+ if not cls._table:
+ cls._table = cls._style.pythonClassToDBTable(cls.__name__)
+
+ # If _idName isn't given, use style default
+ if not new_attrs.has_key('_idName'):
+ cls._idName = cls._style.idForTable(cls._table)
+
+ # We use the magic "q" attribute for accessing lazy
+ # SQL where-clause generation. See the sql module for
+ # more.
+ cls.q = sqlbuilder.SQLObjectTable(cls)
+
+ # We have to check if there are columns in the inherited
+ # _columns where the attribute has been set to None in this
+ # class. If so, then we need to remove that column from
+ # _columns.
+ for column in cls._columns[:]:
+ if (new_attrs.has_key(column.name)
+ and new_attrs[column.name] is None):
+ cls._columns.remove(column)
+
+ for column in cls._columns:
+ cls.addColumn(column)
+ if cls._fromDatabase:
+ cls.addColumnsFromDatabase()
+
+ ########################################
+ # Now we do the joins:
+
+ # We keep track of the different joins by index,
+ # putting them in this list.
+ cls._SO_joinList = []
+ cls._SO_joinDict = {}
+
+ for join in cls._joins:
+ cls.addJoin(join)
+
+ # We don't setup the properties until we're finished with the
+ # batch adding of all the columns...
+ cls._SO_finishedClassCreation = True
+ makeProperties(cls)
+
+ cls._SO_indexList = []
+ for idx in cls._indexes:
+ cls.addIndex(idx)
+
+ classregistry.registry(cls._registry).addClass(cls)
+
def get(cls, id, connection=None, selectResults=None):
assert id is not None, 'None is not a possible id for %s' % cls.__name
|
|
From: <sub...@co...> - 2005-02-09 05:27:07
|
Author: ianb
Date: 2005-02-09 05:27:03 +0000 (Wed, 09 Feb 2005)
New Revision: 582
Modified:
trunk/SQLObject/sqlobject/declarative.py
Log:
Move the counting part into the class and out of the metaclass
Modified: trunk/SQLObject/sqlobject/declarative.py
===================================================================
--- trunk/SQLObject/sqlobject/declarative.py 2005-02-09 05:18:31 UTC (rev 581)
+++ trunk/SQLObject/sqlobject/declarative.py 2005-02-09 05:27:03 UTC (rev 582)
@@ -91,7 +91,6 @@
cls = type.__new__(meta, class_name, bases, new_attrs)
if new_attrs.has_key('__classinit__'):
cls.__classinit__ = staticmethod(cls.__classinit__.im_func)
- cls.declarative_count = counter.next()
cls.__classinit__(cls, new_attrs)
return cls
@@ -104,6 +103,7 @@
__metaclass__ = DeclarativeMeta
def __classinit__(cls, new_attrs):
+ cls.declarative_count = counter.next()
for name in cls.__mutableattributes__:
if not new_attrs.has_key(name):
setattr(cls, copy.copy(getattr(cls, name)))
|
|
From: <sub...@co...> - 2005-02-09 05:18:38
|
Author: ianb
Date: 2005-02-09 05:18:31 +0000 (Wed, 09 Feb 2005)
New Revision: 581
Modified:
trunk/SQLObject/sqlobject/tests/test_distinct.py
trunk/SQLObject/sqlobject/tests/test_joins.py
trunk/SQLObject/sqlobject/tests/test_style.py
Log:
More fixes to the tests to create/destroy classes in the right order.
Modified: trunk/SQLObject/sqlobject/tests/test_distinct.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_distinct.py 2005-02-09 04:50:46 UTC (rev 580)
+++ trunk/SQLObject/sqlobject/tests/test_distinct.py 2005-02-09 05:18:31 UTC (rev 581)
@@ -18,8 +18,7 @@
return result
def test_distinct():
- setupClass(Distinct1)
- setupClass(Distinct2)
+ setupClass([Distinct1, Distinct2])
obs = [Distinct1(n=i) for i in range(3)]
Distinct2(other=obs[0])
Distinct2(other=obs[0])
Modified: trunk/SQLObject/sqlobject/tests/test_joins.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_joins.py 2005-02-09 04:50:46 UTC (rev 580)
+++ trunk/SQLObject/sqlobject/tests/test_joins.py 2005-02-09 05:18:31 UTC (rev 581)
@@ -76,8 +76,7 @@
class TestJoin2:
def setup_method(self, meth):
- setupClass(PersonJoiner2)
- setupClass(AddressJoiner2)
+ setupClass([PersonJoiner2, AddressJoiner2])
p1 = PersonJoiner2(name='bob')
p2 = PersonJoiner2(name='sally')
for z in ['11111', '22222', '33333']:
Modified: trunk/SQLObject/sqlobject/tests/test_style.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_style.py 2005-02-09 04:50:46 UTC (rev 580)
+++ trunk/SQLObject/sqlobject/tests/test_style.py 2005-02-09 05:18:31 UTC (rev 581)
@@ -19,8 +19,7 @@
_style = AnotherStyle()
def test_style():
- setupClass(SOStyleTest2)
- setupClass(SOStyleTest1)
+ setupClass([SOStyleTest2, SOStyleTest1])
st1 = SOStyleTest1(a='something', st2=None)
st2 = SOStyleTest2(b='whatever')
st1.st2 = st2
|
|
From: <sub...@co...> - 2005-02-09 04:50:52
|
Author: ianb
Date: 2005-02-09 04:50:46 +0000 (Wed, 09 Feb 2005)
New Revision: 580
Modified:
trunk/SQLObject/sqlobject/tests/dbtest.py
trunk/SQLObject/sqlobject/tests/test_basic.py
Log:
Allow for a set of classes that need to be created; they are
destroyed in reverse order. This is needed with constraints where
one table depends on another.
Modified: trunk/SQLObject/sqlobject/tests/dbtest.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/dbtest.py 2005-02-09 04:34:12 UTC (rev 579)
+++ trunk/SQLObject/sqlobject/tests/dbtest.py 2005-02-09 04:50:46 UTC (rev 580)
@@ -43,17 +43,26 @@
}
-def setupClass(soClass):
+def setupClass(soClasses):
"""
- Makes sure the class has a corresponding and correct table.
- This won't recreate the table if it already exists. It will
- check that the table is properly defined (in case you change
- your table definition).
+ Makes sure the classes have a corresponding and correct table.
+ This won't recreate the table if it already exists. It will check
+ that the table is properly defined (in case you change your table
+ definition).
+
+ You can provide a single class or a list of classes; if a list
+ then classes will be created in the order you provide, and
+ destroyed in the opposite order. So if class A depends on class
+ B, then do setupClass([B, A]) and B won't be destroyed or cleared
+ until after A is destroyed or cleared.
"""
+ if not isinstance(soClasses, (list, tuple)):
+ soClasses = [soClasses]
connection = getConnection()
- soClass._connection = connection
- installOrClear(soClass)
- return soClass
+ for soClass in soClasses:
+ soClass._connection = connection
+ installOrClear(soClasses)
+ return soClasses
installedDBFilename = os.path.join(os.getcwd(), 'dbs_data.tmp')
@@ -82,27 +91,32 @@
createSQL = sqlobject.StringCol(notNull=True)
connectionURI = sqlobject.StringCol(notNull=True)
- def installOrClear(cls, soClass):
+ def installOrClear(cls, soClasses):
cls.setup()
- table = soClass._table
- if not soClass._connection.tableExists(table):
- cls.install(soClass)
- items = list(cls.selectBy(
- tableName=table,
- connectionURI=soClass._connection.uri()))
- if items:
- instance = items[0]
- sql = instance.createSQL
- else:
- sql = None
- newSQL = soClass.createTableSQL()
- if sql != newSQL:
- if sql is not None:
- instance.destroySelf()
- cls.drop(soClass)
- cls.install(soClass)
- else:
- cls.clear(soClass)
+ reversed = list(soClasses)[:]
+ reversed.reverse()
+ for soClass in reversed:
+ table = soClass._table
+ if not soClass._connection.tableExists(table):
+ continue
+ items = list(cls.selectBy(
+ tableName=table,
+ connectionURI=soClass._connection.uri()))
+ if items:
+ instance = items[0]
+ sql = instance.createSQL
+ else:
+ sql = None
+ newSQL = soClass.createTableSQL()
+ if sql != newSQL:
+ if sql is not None:
+ instance.destroySelf()
+ cls.drop(soClass)
+ else:
+ cls.clear(soClass)
+ for soClass in soClasses:
+ if not soClass._connection.tableExists(table):
+ cls.install(soClass)
installOrClear = classmethod(installOrClear)
def install(cls, soClass):
Modified: trunk/SQLObject/sqlobject/tests/test_basic.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_basic.py 2005-02-09 04:34:12 UTC (rev 579)
+++ trunk/SQLObject/sqlobject/tests/test_basic.py 2005-02-09 04:50:46 UTC (rev 580)
@@ -77,8 +77,7 @@
me = StringCol(length=10)
def test_foreignKey():
- setupClass(TestSO4)
- setupClass(TestSO3)
+ setupClass([TestSO4, TestSO3])
tc3 = TestSO3(name='a')
assert tc3.other is None
assert tc3.other2 is None
|
|
From: <sub...@co...> - 2005-02-09 04:34:16
|
Author: ianb
Date: 2005-02-09 04:34:12 +0000 (Wed, 09 Feb 2005)
New Revision: 579
Modified:
trunk/SQLObject/sqlobject/tests/test_basic.py
Log:
Create tables in correct order (for constraints)
Modified: trunk/SQLObject/sqlobject/tests/test_basic.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_basic.py 2005-02-08 16:48:34 UTC (rev 578)
+++ trunk/SQLObject/sqlobject/tests/test_basic.py 2005-02-09 04:34:12 UTC (rev 579)
@@ -77,8 +77,8 @@
me = StringCol(length=10)
def test_foreignKey():
+ setupClass(TestSO4)
setupClass(TestSO3)
- setupClass(TestSO4)
tc3 = TestSO3(name='a')
assert tc3.other is None
assert tc3.other2 is None
|
|
From: <sub...@co...> - 2005-02-08 16:48:37
|
Author: ianb
Date: 2005-02-08 16:48:34 +0000 (Tue, 08 Feb 2005)
New Revision: 578
Modified:
trunk/SQLObject/sqlobject/tests/test_auto.py
Log:
Added an unlimited-length text field for testing.
Modified: trunk/SQLObject/sqlobject/tests/test_auto.py
===================================================================
--- trunk/SQLObject/sqlobject/tests/test_auto.py 2005-02-08 16:47:54 UTC (rev 577)
+++ trunk/SQLObject/sqlobject/tests/test_auto.py 2005-02-08 16:48:34 UTC (rev 578)
@@ -73,6 +73,7 @@
age INT DEFAULT NULL,
created DATETIME NOT NULL,
happy char(1) DEFAULT 'Y' NOT NULL,
+ long_field TEXT,
wannahavefun TINYINT DEFAULT 0 NOT NULL
)
"""
@@ -85,6 +86,7 @@
age INT DEFAULT 0,
created VARCHAR(40) NOT NULL,
happy char(1) DEFAULT 'Y' NOT NULL,
+ long_field TEXT,
wannahavefun BOOL DEFAULT FALSE NOT NULL
)
"""
@@ -96,7 +98,8 @@
last_name VARCHAR(200) NOT NULL,
age INT DEFAULT 0,
created VARCHAR(40) NOT NULL,
- happy char(1) DEFAULT 'Y' NOT NULL
+ happy char(1) DEFAULT 'Y' NOT NULL,
+ long_field TEXT
)
"""
@@ -125,12 +128,16 @@
lastName='doe',
age=10,
created=now(),
- wannahavefun=False)
+ wannahavefun=False,
+ long_field='x'*1000)
jane = AutoTest(firstName='jane',
lastName='doe',
happy='N',
created=now(),
- wannahavefun=True)
+ wannahavefun=True,
+ long_field='x'*1000)
assert not john.wannahavefun
assert jane.wannahavefun
+ assert john.long_field == 'x'*1000
+ assert jane.long_field == 'x'*1000
del classregistry.registry(AutoTest._registry).classes['AutoTest']
|
|
From: <sub...@co...> - 2005-02-08 16:48:06
|
Author: ianb
Date: 2005-02-08 16:47:54 +0000 (Tue, 08 Feb 2005)
New Revision: 577
Modified:
trunk/SQLObject/sqlobject/include/validators.py
Log:
Minor change in method signature to make them more consistent
Modified: trunk/SQLObject/sqlobject/include/validators.py
===================================================================
--- trunk/SQLObject/sqlobject/include/validators.py 2005-02-08 16:47:12 UTC (rev 576)
+++ trunk/SQLObject/sqlobject/include/validators.py 2005-02-08 16:47:54 UTC (rev 577)
@@ -195,7 +195,7 @@
self._toPython,
self.validatePython)
- def fromPython(self, value, state):
+ def fromPython(self, value, state=None):
return self.attemptConvert(value, state,
self.validatePython,
self._fromPython,
@@ -227,7 +227,7 @@
def toPython(self, value, state=None):
return self.attemptConvert(value, state, toPython)
- def fromPython(self, value, state):
+ def fromPython(self, value, state=None):
return self.attemptConvert(value, state, fromPython)
def matchesProtocol(self, validator, state):
|
|
From: <sub...@co...> - 2005-02-08 16:47:18
|
Author: ianb
Date: 2005-02-08 16:47:12 +0000 (Tue, 08 Feb 2005)
New Revision: 576
Modified:
trunk/SQLObject/sqlobject/styles.py
Log:
Make the base style functional by adding a missing method
Modified: trunk/SQLObject/sqlobject/styles.py
===================================================================
--- trunk/SQLObject/sqlobject/styles.py 2005-02-08 11:08:52 UTC (rev 575)
+++ trunk/SQLObject/sqlobject/styles.py 2005-02-08 16:47:12 UTC (rev 576)
@@ -58,6 +58,9 @@
# keys, you can't really change this style.
return attr + "ID"
+ def tableReference(self, table):
+ return table + "_id"
+
class MixedCaseUnderscoreStyle(Style):
"""
|
|
From: <sub...@co...> - 2005-02-08 11:09:02
|
Author: phd
Date: 2005-02-08 11:08:52 +0000 (Tue, 08 Feb 2005)
New Revision: 575
Added:
home/phd/SQLObject/inheritance/sqlobject/inheritance/
home/phd/SQLObject/inheritance/sqlobject/inheritance/__init__.py
Removed:
home/phd/SQLObject/inheritance/sqlobject/inheritance.py
Modified:
home/phd/SQLObject/inheritance/setup.py
Log:
Moved sqlobject/inheritance.py to sqlobject/inheritance/__init__.py.
Modified: home/phd/SQLObject/inheritance/setup.py
===================================================================
--- home/phd/SQLObject/inheritance/setup.py 2005-02-08 08:00:25 UTC (rev 574)
+++ home/phd/SQLObject/inheritance/setup.py 2005-02-08 11:08:52 UTC (rev 575)
@@ -2,7 +2,7 @@
import warnings
warnings.filterwarnings("ignore", "Unknown distribution option")
-subpackages = ['firebird', 'include', 'mysql', 'postgres',
+subpackages = ['firebird', 'include', 'inheritance', 'mysql', 'postgres',
'sqlite', 'sybase', 'maxdb']
import sys
Copied: home/phd/SQLObject/inheritance/sqlobject/inheritance/__init__.py (from rev 571, home/phd/SQLObject/inheritance/sqlobject/inheritance.py)
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/inheritance.py 2005-02-07 11:02:13 UTC (rev 571)
+++ home/phd/SQLObject/inheritance/sqlobject/inheritance/__init__.py 2005-02-08 11:08:52 UTC (rev 575)
@@ -0,0 +1,192 @@
+from sqlobject import sqlbuilder
+from sqlobject import dbconnection
+from sqlobject import classregistry
+from sqlobject.main import SQLObject, SelectResults, True, False, makeProperties, getterName, setterName
+
+
+class InheritableSelectResults(SelectResults):
+ IterationClass = dbconnection.InheritableIteration
+
+ def __init__(self, sourceClass, clause, clauseTables=None,
+ **ops):
+ if clause is None or isinstance(clause, str) and clause == 'all':
+ clause = sqlbuilder.SQLTrueClause
+ tablesDict = sqlbuilder.tablesUsedDict(clause)
+ tablesDict[sourceClass._table] = 1
+ orderBy = ops.get('orderBy')
+ if orderBy and not isinstance(orderBy, basestring):
+ tablesDict.update(sqlbuilder.tablesUsedDict(orderBy))
+ #DSM: if this class has a parent, we need to link it
+ #DSM: and be sure the parent is in the table list.
+ #DSM: The following code is before clauseTables
+ #DSM: because if the user uses clauseTables
+ #DSM: (and normal string SELECT), he must know what he wants
+ #DSM: and will do himself the relationship between classes.
+ if type(clause) is not str:
+ tableRegistry = {}
+ allClasses = classregistry.registry(sourceClass._registry).allClasses()
+ for registryClass in allClasses:
+ if registryClass._table in tablesDict:
+ #DSM: By default, no parents are needed for the clauses
+ tableRegistry[registryClass] = registryClass
+ for registryClass in allClasses:
+ if registryClass._table in tablesDict:
+ currentClass = registryClass
+ while currentClass._parentClass:
+ currentClass = currentClass._parentClass
+ if tableRegistry.has_key(currentClass):
+ #DSM: Must keep the last parent needed
+ #DSM: (to limit the number of join needed)
+ tableRegistry[registryClass] = currentClass
+ #DSM: Remove this class as it is a parent one
+ #DSM: of a needed children
+ del tableRegistry[currentClass]
+ #DSM: Table registry contains only the last children
+ #DSM: or standalone classes
+ parentClause = []
+ for (currentClass, minParentClass) in tableRegistry.items():
+ while currentClass != minParentClass and currentClass._parentClass:
+ parentClass = currentClass._parentClass
+ parentClause.append(currentClass.q.id == parentClass.q.id)
+ currentClass = parentClass
+ tablesDict[currentClass._table] = 1
+ clause = reduce(sqlbuilder.AND, parentClause, clause)
+
+ super(InheritableSelectResults, self).__init__(sourceClass, clause, clauseTables,
+ **ops)
+
+
+class InheritableSQLObject(SQLObject):
+ SelectResultsClass = InheritableSelectResults
+
+ def get(cls, id, connection=None, selectResults=None, childResults=None, childUpdate=False):
+
+ val = super(InheritableSQLObject, cls).get(id, connection, selectResults)
+
+ #DSM: If we are updating a child, we should never return a child...
+ if childUpdate: return val
+ #DSM: If this class has a child, return the child
+ if hasattr(val, 'childName'):
+ childName = val.childName
+ if childName is not None:
+ return val._childClasses[childName].get(id, selectResults=childResults)
+ #DSM: Now, we know we are alone or the last child in a family...
+ #DSM: It's time to find our parents
+ inst = val
+ while inst._parentClass and not inst._parent:
+ inst._parent = inst._parentClass.get(id, childUpdate=True)
+ inst = inst._parent
+ #DSM: We can now return ourself
+ return val
+
+ get = classmethod(get)
+
+ def addColumn(cls, columnDef, changeSchema=False, connection=None, childUpdate=False):
+ #DSM: Try to add parent properties to the current class
+ #DSM: Only do this once if possible at object creation and once for
+ #DSM: each new dynamic column to refresh the current class
+ if childUpdate or cls._parentClass:
+ for col in cls._parentClass._columns:
+ cname = col.name
+ if cname == 'childName': continue
+ setattr(cls, getterName(cname), eval(
+ 'lambda self: self._parent.%s' % cname))
+ if not col.kw.has_key('immutable') or not col.kw['immutable']:
+ setattr(cls, setterName(cname), eval(
+ 'lambda self, val: setattr(self._parent, %s, val)'
+ % repr(cname)))
+ if childUpdate:
+ makeProperties(cls)
+ return
+
+ super(InheritableSQLObject, cls).addColumn(columnDef, changeSchema, connection)
+
+ #DSM: Update each child class if needed and existing (only for new
+ #DSM: dynamic column as no child classes exists at object creation)
+ for c in cls._childClasses.values():
+ c.addColumn(columnDef, childUpdate=True)
+
+ addColumn = classmethod(addColumn)
+
+ def delColumn(cls, column, changeSchema=False, connection=None):
+ super(InheritableSQLObject, cls).delColumn(column, changeSchema, connection)
+
+ #DSM: Update each child class if needed
+ #DSM: and delete properties for this column
+ for c in cls._childClasses.values():
+ delattr(c, name)
+
+ delColumn = classmethod(delColumn)
+
+ def addJoin(cls, joinDef, childUpdate=False):
+ #DSM: Try to add parent properties to the current class
+ #DSM: Only do this once if possible at object creation and once for
+ #DSM: each new dynamic join to refresh the current class
+ if childUpdate or cls._parentClass:
+ for jdef in cls._parentClass._joins:
+ join = jdef.withClass(cls)
+ jname = join.joinMethodName
+ jarn = join.addRemoveName
+ setattr(cls, getterName(jname),
+ eval('lambda self: self._parent.%s' % jname))
+ if hasattr(join, 'remove'):
+ setattr(cls, 'remove' + jarn,
+ eval('lambda self,o: self._parent.remove%s(o)' % jarn))
+ if hasattr(join, 'add'):
+ setattr(cls, 'add' + jarn,
+ eval('lambda self,o: self._parent.add%s(o)' % jarn))
+ if childUpdate:
+ makeProperties(cls)
+ return
+
+ super(InheritableSQLObject, cls).addJoin(joinDef)
+
+ #DSM: Update each child class if needed and existing (only for new
+ #DSM: dynamic join as no child classes exists at object creation)
+ for c in cls._childClasses.values():
+ c.addJoin(joinDef, childUpdate=True)
+
+ addJoin = classmethod(addJoin)
+
+ def delJoin(cls, joinDef):
+ super(InheritableSQLObject, cls).delJoin(joinDef)
+
+ #DSM: Update each child class if needed
+ #DSM: and delete properties for this join
+ for c in cls._childClasses.values():
+ delattr(c, meth)
+
+ delJoin = classmethod(delJoin)
+
+ def _create(self, id, **kw):
+
+ #DSM: If we were called by a children class,
+ #DSM: we must retreive the properties dictionary.
+ #DSM: Note: we can't use the ** call paremeter directly
+ #DSM: as we must be able to delete items from the dictionary
+ #DSM: (and our children must know that the items were removed!)
+ if kw.has_key('kw'):
+ kw = kw['kw']
+ #DSM: If we are the children of an inheritable class,
+ #DSM: we must first create our parent
+ if self._parentClass:
+ parentClass = self._parentClass
+ parent_kw = dict(
+ [(name, value) for (name, value) in kw.items()
+ if hasattr(parentClass, name)
+ ]
+ )
+ self._parent = parentClass(kw=parent_kw)
+ self._parent.childName = self._className
+ id = self._parent.id
+
+ super(InheritableSQLObject, self)._create(id, **kw)
+
+ def destroySelf(self):
+ #DSM: If this object has parents, recursivly kill them
+ if hasattr(self, '_parent') and self._parent:
+ self._parent.destroySelf()
+ super(InheritableSQLObject, self).destroySelf()
+
+
+__all__ = ['InheritableSQLObject']
Deleted: home/phd/SQLObject/inheritance/sqlobject/inheritance.py
===================================================================
--- home/phd/SQLObject/inheritance/sqlobject/inheritance.py 2005-02-08 08:00:25 UTC (rev 574)
+++ home/phd/SQLObject/inheritance/sqlobject/inheritance.py 2005-02-08 11:08:52 UTC (rev 575)
@@ -1,192 +0,0 @@
-import sqlbuilder
-import dbconnection
-import classregistry
-from main import SQLObject, SelectResults, True, False, makeProperties, getterName, setterName
-
-
-class InheritableSelectResults(SelectResults):
- IterationClass = dbconnection.InheritableIteration
-
- def __init__(self, sourceClass, clause, clauseTables=None,
- **ops):
- if clause is None or isinstance(clause, str) and clause == 'all':
- clause = sqlbuilder.SQLTrueClause
- tablesDict = sqlbuilder.tablesUsedDict(clause)
- tablesDict[sourceClass._table] = 1
- orderBy = ops.get('orderBy')
- if orderBy and not isinstance(orderBy, basestring):
- tablesDict.update(sqlbuilder.tablesUsedDict(orderBy))
- #DSM: if this class has a parent, we need to link it
- #DSM: and be sure the parent is in the table list.
- #DSM: The following code is before clauseTables
- #DSM: because if the user uses clauseTables
- #DSM: (and normal string SELECT), he must know what he wants
- #DSM: and will do himself the relationship between classes.
- if type(clause) is not str:
- tableRegistry = {}
- allClasses = classregistry.registry(sourceClass._registry).allClasses()
- for registryClass in allClasses:
- if registryClass._table in tablesDict:
- #DSM: By default, no parents are needed for the clauses
- tableRegistry[registryClass] = registryClass
- for registryClass in allClasses:
- if registryClass._table in tablesDict:
- currentClass = registryClass
- while currentClass._parentClass:
- currentClass = currentClass._parentClass
- if tableRegistry.has_key(currentClass):
- #DSM: Must keep the last parent needed
- #DSM: (to limit the number of join needed)
- tableRegistry[registryClass] = currentClass
- #DSM: Remove this class as it is a parent one
- #DSM: of a needed children
- del tableRegistry[currentClass]
- #DSM: Table registry contains only the last children
- #DSM: or standalone classes
- parentClause = []
- for (currentClass, minParentClass) in tableRegistry.items():
- while currentClass != minParentClass and currentClass._parentClass:
- parentClass = currentClass._parentClass
- parentClause.append(currentClass.q.id == parentClass.q.id)
- currentClass = parentClass
- tablesDict[currentClass._table] = 1
- clause = reduce(sqlbuilder.AND, parentClause, clause)
-
- super(InheritableSelectResults, self).__init__(sourceClass, clause, clauseTables,
- **ops)
-
-
-class InheritableSQLObject(SQLObject):
- SelectResultsClass = InheritableSelectResults
-
- def get(cls, id, connection=None, selectResults=None, childResults=None, childUpdate=False):
-
- val = super(InheritableSQLObject, cls).get(id, connection, selectResults)
-
- #DSM: If we are updating a child, we should never return a child...
- if childUpdate: return val
- #DSM: If this class has a child, return the child
- if hasattr(val, 'childName'):
- childName = val.childName
- if childName is not None:
- return val._childClasses[childName].get(id, selectResults=childResults)
- #DSM: Now, we know we are alone or the last child in a family...
- #DSM: It's time to find our parents
- inst = val
- while inst._parentClass and not inst._parent:
- inst._parent = inst._parentClass.get(id, childUpdate=True)
- inst = inst._parent
- #DSM: We can now return ourself
- return val
-
- get = classmethod(get)
-
- def addColumn(cls, columnDef, changeSchema=False, connection=None, childUpdate=False):
- #DSM: Try to add parent properties to the current class
- #DSM: Only do this once if possible at object creation and once for
- #DSM: each new dynamic column to refresh the current class
- if childUpdate or cls._parentClass:
- for col in cls._parentClass._columns:
- cname = col.name
- if cname == 'childName': continue
- setattr(cls, getterName(cname), eval(
- 'lambda self: self._parent.%s' % cname))
- if not col.kw.has_key('immutable') or not col.kw['immutable']:
- setattr(cls, setterName(cname), eval(
- 'lambda self, val: setattr(self._parent, %s, val)'
- % repr(cname)))
- if childUpdate:
- makeProperties(cls)
- return
-
- super(InheritableSQLObject, cls).addColumn(columnDef, changeSchema, connection)
-
- #DSM: Update each child class if needed and existing (only for new
- #DSM: dynamic column as no child classes exists at object creation)
- for c in cls._childClasses.values():
- c.addColumn(columnDef, childUpdate=True)
-
- addColumn = classmethod(addColumn)
-
- def delColumn(cls, column, changeSchema=False, connection=None):
- super(InheritableSQLObject, cls).delColumn(column, changeSchema, connection)
-
- #DSM: Update each child class if needed
- #DSM: and delete properties for this column
- for c in cls._childClasses.values():
- delattr(c, name)
-
- delColumn = classmethod(delColumn)
-
- def addJoin(cls, joinDef, childUpdate=False):
- #DSM: Try to add parent properties to the current class
- #DSM: Only do this once if possible at object creation and once for
- #DSM: each new dynamic join to refresh the current class
- if childUpdate or cls._parentClass:
- for jdef in cls._parentClass._joins:
- join = jdef.withClass(cls)
- jname = join.joinMethodName
- jarn = join.addRemoveName
- setattr(cls, getterName(jname),
- eval('lambda self: self._parent.%s' % jname))
- if hasattr(join, 'remove'):
- setattr(cls, 'remove' + jarn,
- eval('lambda self,o: self._parent.remove%s(o)' % jarn))
- if hasattr(join, 'add'):
- setattr(cls, 'add' + jarn,
- eval('lambda self,o: self._parent.add%s(o)' % jarn))
- if childUpdate:
- makeProperties(cls)
- return
-
- super(InheritableSQLObject, cls).addJoin(joinDef)
-
- #DSM: Update each child class if needed and existing (only for new
- #DSM: dynamic join as no child classes exists at object creation)
- for c in cls._childClasses.values():
- c.addJoin(joinDef, childUpdate=True)
-
- addJoin = classmethod(addJoin)
-
- def delJoin(cls, joinDef):
- super(InheritableSQLObject, cls).delJoin(joinDef)
-
- #DSM: Update each child class if needed
- #DSM: and delete properties for this join
- for c in cls._childClasses.values():
- delattr(c, meth)
-
- delJoin = classmethod(delJoin)
-
- def _create(self, id, **kw):
-
- #DSM: If we were called by a children class,
- #DSM: we must retreive the properties dictionary.
- #DSM: Note: we can't use the ** call paremeter directly
- #DSM: as we must be able to delete items from the dictionary
- #DSM: (and our children must know that the items were removed!)
- if kw.has_key('kw'):
- kw = kw['kw']
- #DSM: If we are the children of an inheritable class,
- #DSM: we must first create our parent
- if self._parentClass:
- parentClass = self._parentClass
- parent_kw = dict(
- [(name, value) for (name, value) in kw.items()
- if hasattr(parentClass, name)
- ]
- )
- self._parent = parentClass(kw=parent_kw)
- self._parent.childName = self._className
- id = self._parent.id
-
- super(InheritableSQLObject, self)._create(id, **kw)
-
- def destroySelf(self):
- #DSM: If this object has parents, recursivly kill them
- if hasattr(self, '_parent') and self._parent:
- self._parent.destroySelf()
- super(InheritableSQLObject, self).destroySelf()
-
-
-__all__ = ['InheritableSQLObject']
|
|
From: <sub...@co...> - 2005-02-08 08:00:30
|
Author: ianb
Date: 2005-02-08 08:00:25 +0000 (Tue, 08 Feb 2005)
New Revision: 574
Modified:
trunk/SQLObject/sqlobject/dbconnection.py
trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py
Log:
* Made dbconnection.DBConnection.uri() a bit more tollerant of missing
attributes
* Gave sqlite.SQLiteConnection a uri method, since it's not like the
other databases.
Modified: trunk/SQLObject/sqlobject/dbconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/dbconnection.py 2005-02-08 07:59:38 UTC (rev 573)
+++ trunk/SQLObject/sqlobject/dbconnection.py 2005-02-08 08:00:25 UTC (rev 574)
@@ -44,13 +44,14 @@
atexit.register(_closeConnection, weakref.ref(self))
def uri(self):
- auth = self.user or ''
+ auth = getattr(self, 'user', None) or ''
if auth:
if self.password:
auth = auth + '@' + self.password
auth = auth + ':'
else:
- assert not self.password, 'URIs cannot express passwords without usernames'
+ assert not getattr(self, 'password', None), (
+ 'URIs cannot express passwords without usernames')
uri = '%s://%s' % (self.dbName, auth)
if self.host:
uri += self.host + '/'
Modified: trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py
===================================================================
--- trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py 2005-02-08 07:59:38 UTC (rev 573)
+++ trunk/SQLObject/sqlobject/sqlite/sqliteconnection.py 2005-02-08 08:00:25 UTC (rev 574)
@@ -23,11 +23,18 @@
def connectionFromURI(cls, uri):
user, password, host, path, args = cls._parseURI(uri)
- assert host is None, "SQLite can only be used locally (with a URI like sqlite:///file or sql:/file, not %r)" % uri
- assert user is None and password is None, "You may not provide usernames or passwords for SQLite databases"
+ assert host is None, (
+ "SQLite can only be used locally (with a URI like "
+ "sqlite:///file or sqlite:/file, not %r)" % uri)
+ assert user is None and password is None, (
+ "You may not provide usernames or passwords for SQLite "
+ "databases")
return cls(filename=path, **args)
connectionFromURI = classmethod(connectionFromURI)
+ def uri(self):
+ return 'sqlite:///%s' % self.filename
+
def _setAutoCommit(self, conn, auto):
conn.autocommit = auto
|