Thread: [SQL-CVS] r1321 - SQLObject/trunk/sqlobject
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
|
From: <sub...@co...> - 2005-11-26 21:13:28
|
Author: ianb
Date: 2005-11-26 21:13:23 +0000 (Sat, 26 Nov 2005)
New Revision: 1321
Modified:
SQLObject/trunk/sqlobject/boundattributes.py
SQLObject/trunk/sqlobject/declarative.py
SQLObject/trunk/sqlobject/joins.py
Log:
Update boundattributes, mostly trying to simplify it some; make declarative allow restricting the attributes you can set; change the new joins to use boundattributes
Modified: SQLObject/trunk/sqlobject/boundattributes.py
===================================================================
--- SQLObject/trunk/sqlobject/boundattributes.py 2005-11-26 20:57:28 UTC (rev 1320)
+++ SQLObject/trunk/sqlobject/boundattributes.py 2005-11-26 21:13:23 UTC (rev 1321)
@@ -27,6 +27,7 @@
'bind_attributes_local']
import declarative
+import events
class BoundAttribute(declarative.Declarative):
@@ -41,6 +42,8 @@
name, **attrs)`` and maybe ``set_object(added_class, name,
**attrs)`` (the default implementation of ``set_object``
just resets the attribute to whatever ``make_object`` returned).
+
+ Also see ``BoundFactory``.
"""
_private_variables = (
@@ -51,9 +54,11 @@
'_add_attrs',
'set_object',
'make_object',
+ 'clone_in_subclass',
)
_all_attrs = ()
+ clone_for_subclass = True
def __classinit__(cls, new_attrs):
declarative.Declarative.__classinit__(cls, new_attrs)
@@ -61,7 +66,7 @@
def __instanceinit__(self, new_attrs):
declarative.Declarative.__instanceinit__(self, new_attrs)
- self._all_attrs = self._add_attrs(self, new_attrs)
+ self.__dict__['_all_attrs'] = self._add_attrs(self, new_attrs)
def _add_attrs(this_object, new_attrs):
private = this_object._private_variables
@@ -82,6 +87,18 @@
attrs['added_class'] = added_class
attrs['attr_name'] = attr_name
obj = me.make_object(**attrs)
+
+ if self.clone_for_subclass:
+ def on_rebind(new_class_name, bases, new_attrs,
+ post_funcs, early_funcs):
+ def rebind(new_class):
+ me.set_object(
+ new_class, attr_name,
+ me.make_object(**attrs))
+ post_funcs.append(rebind)
+ events.listen(receiver=on_rebind, soClass=added_class,
+ signal=events.ClassCreateSignal, weak=False)
+
me.set_object(added_class, attr_name, obj)
__addtoclass__ = declarative.classinstancemethod(__addtoclass__)
@@ -96,29 +113,24 @@
make_object = classmethod(make_object)
+ def __setattr__(self, name, value):
+ self.__dict__['_all_attrs'] = self._add_attrs(self, {name: value})
+ self.__dict__[name] = value
+
class BoundFactory(BoundAttribute):
+ """
+ This will bind the attribute to whatever is given by
+ ``factory_class``. This factory should be a callable with the
+ signature ``factory_class(added_class, attr_name, *args, **kw)``.
+
+ The factory will be reinvoked (and the attribute rebound) for
+ every subclassing.
+ """
+
factory_class = None
+ _private_variables = (
+ BoundAttribute._private_variables + ('factory_class',))
def make_object(cls, added_class, attr_name, *args, **kw):
return cls.factory_class(added_class, attr_name, *args, **kw)
-
-def bind_attributes(cls, new_attrs):
- for name, value in new_attrs.items():
- if hasattr(value, '__addtoclass__'):
- value.__addtoclass__(cls, name)
-
-def bind_attributes_local(cls, new_attrs):
- new_bound_attributes = {}
- for name, value in getattr(cls, '__bound_attributes__', {}).items():
- if new_attrs.has_key(name):
- # The attribute is being REbound, so don't try to bind it
- # again.
- continue
- value.__addtoclass__(cls, name)
- new_bound_attributes[name] = value
- for name, value in new_attrs.items():
- if hasattr(value, '__addtoclass__'):
- value.__addtoclass__(cls, name)
- new_bound_attributes[name] = value
- cls.__bound_attributes__ = new_bound_attributes
Modified: SQLObject/trunk/sqlobject/declarative.py
===================================================================
--- SQLObject/trunk/sqlobject/declarative.py 2005-11-26 20:57:28 UTC (rev 1320)
+++ SQLObject/trunk/sqlobject/declarative.py 2005-11-26 21:13:23 UTC (rev 1321)
@@ -112,6 +112,8 @@
__metaclass__ = DeclarativeMeta
+ __restrict_attributes__ = None
+
def __classinit__(cls, new_attrs):
cls.declarative_count = counter.next()
for name in cls.__mutableattributes__:
@@ -119,6 +121,12 @@
setattr(cls, copy.copy(getattr(cls, name)))
def __instanceinit__(self, new_attrs):
+ if self.__restrict_attributes__ is not None:
+ for name in new_attrs:
+ if name not in self.__restrict_attributes__:
+ raise TypeError(
+ '%s() got an unexpected keyword argument %r'
+ % (self.__class__.__name__, name))
for name, value in new_attrs.items():
setattr(self, name, value)
if not new_attrs.has_key('declarative_count'):
Modified: SQLObject/trunk/sqlobject/joins.py
===================================================================
--- SQLObject/trunk/sqlobject/joins.py 2005-11-26 20:57:28 UTC (rev 1320)
+++ SQLObject/trunk/sqlobject/joins.py 2005-11-26 21:13:23 UTC (rev 1321)
@@ -268,43 +268,24 @@
+import boundattributes
-class ManyToMany(object):
-
- def __init__(self, otherClassName,
- intermediateTable=None,
- joinColumn=None,
- otherColumn=None,
- createJoinTable=True):
- self.otherClassName = otherClassName
- self.intermediateTable = intermediateTable
- self.joinColumn = joinColumn
- self.otherColumn = otherColumn
- self.createJoinTable = createJoinTable
-
- def __addtoclass__(self, soClass, name):
- setattr(soClass, name,
- SOManyToMany(soClass, name=name,
- otherClassName=self.otherClassName,
- intermediateTable=self.intermediateTable,
- joinColumn=self.joinColumn,
- otherColumn=self.otherColumn,
- createJoinTable=self.createJoinTable))
-
class SOManyToMany(object):
- def __init__(self, soClass, name, otherClassName,
+ def __init__(self, soClass, name, join,
intermediateTable, joinColumn, otherColumn,
- createJoinTable):
+ createJoinTable, **attrs):
self.name = name
self.intermediateTable = intermediateTable
self.joinColumn = joinColumn
self.otherColumn = otherColumn
self.createJoinTable = createJoinTable
self.soClass = self.otherClass = None
+ for name, value in attrs.items():
+ setattr(self, name, value)
classregistry.registry(
soClass.sqlmeta.registry).addClassCallback(
- otherClassName, self._setOtherClass)
+ join, self._setOtherClass)
classregistry.registry(
soClass.sqlmeta.registry).addClassCallback(
soClass.__name__, self._setThisClass)
@@ -345,10 +326,7 @@
& (sqlbuilder.Field(self.intermediateTable, self.joinColumn)
== obj.id))
select = self.otherClass.select(query)
- return _ManyToManySelectWrapper(obj, self, select)
-
- def __sqlrepr__(self, dbname):
- return self.query.__sqlrepr__(self, dbname)
+ return _ManyToManySelectWrapper(obj, self, select)
def event_CreateTableSignal(self, soClass, connection, extra_sql,
post_funcs):
@@ -359,6 +337,19 @@
if connection.tableExists(self.intermediateTable):
return
connection._SO_createJoinTable(self)
+
+class ManyToMany(boundattributes.BoundFactory):
+ factory_class = SOManyToMany
+ __restrict_attributes__ = (
+ 'join', 'intermediateTable',
+ 'joinColumn', 'otherColumn', 'createJoinTable')
+ __unpackargs__ = ('join',)
+
+ # Default values:
+ intermediateTable = None
+ joinColumn = None
+ otherColumn = None
+ createJoinTable = True
class _ManyToManySelectWrapper(object):
@@ -370,7 +361,7 @@
def __getattr__(self, attr):
# @@: This passes through private variable access too... should it?
# Also magic methods, like __str__
- return getattr(self.select, attr)
+ return getattr(self, select, attr)
def __repr__(self):
return '<%s for: %s>' % (self.__class__.__name__, repr(self.select))
@@ -385,7 +376,6 @@
return self.select[key]
def add(self, obj):
- print "Add", obj, "to", self.forObject
obj._connection._SO_intermediateInsert(
self.join.intermediateTable,
self.join.joinColumn,
@@ -405,28 +395,18 @@
obj = self.join.otherClass(**kw)
self.add(obj)
return obj
-
-class OneToMany(object):
-
- def __init__(self, otherClassName, joinColumn=None):
- self.otherClassName = otherClassName
- self.joinColumn = joinColumn
-
- def __addtoclass__(self, soClass, name):
- setattr(soClass, name,
- SOOneToMany(soClass, name=name,
- otherClassName=self.otherClassName,
- joinColumn=self.joinColumn))
class SOOneToMany(object):
- def __init__(self, soClass, name, otherClassName, joinColumn):
+ def __init__(self, soClass, name, join, joinColumn, **attrs):
self.soClass = soClass
self.name = name
self.joinColumn = joinColumn
+ for name, value in attrs.items():
+ setattr(self, name, value)
classregistry.registry(
soClass.sqlmeta.registry).addClassCallback(
- otherClassName, self._setOtherClass)
+ join, self._setOtherClass)
def _setOtherClass(self, otherClass):
self.otherClass = otherClass
@@ -443,6 +423,15 @@
select = self.otherClass.select(query)
return _OneToManySelectWrapper(obj, self, select)
+class OneToMany(boundattributes.BoundFactory):
+ factory_class = SOOneToMany
+ __restrict_attributes__ = (
+ 'join', 'joinColumn')
+ __unpackargs__ = ('join',)
+
+ # Default values:
+ joinColumn = None
+
class _OneToManySelectWrapper(object):
def __init__(self, forObject, join, select):
@@ -453,7 +442,7 @@
def __getattr__(self, attr):
# @@: This passes through private variable access too... should it?
# Also magic methods, like __str__
- return getattr(self, select, attr)
+ return getattr(self.select, attr)
def __repr__(self):
return '<%s for: %s>' % (self.__class__.__name__, repr(self.select))
|