summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-06-24 02:06:10 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-06-24 02:06:10 -0400
commit319aa982a1312d59076478a001d6c42eaa123e70 (patch)
treea0d59883c18fabe81833128604b4a8ea4b569e0f /examples
parente47f2e03ce02f1fa1b313970291a2c024620bd73 (diff)
downloadsqlalchemy-319aa982a1312d59076478a001d6c42eaa123e70.tar.gz
- [moved] The InstrumentationManager interface
and the entire related system of alternate class implementation is now moved out to sqlalchemy.ext.instrumentation. This is a seldom used system that adds significant complexity and overhead to the mechanics of class instrumentation. The new architecture allows it to remain unused until InstrumentationManager is actually imported, at which point it is bootstrapped into the core.
Diffstat (limited to 'examples')
-rw-r--r--examples/custom_attributes/custom_management.py119
1 files changed, 11 insertions, 108 deletions
diff --git a/examples/custom_attributes/custom_management.py b/examples/custom_attributes/custom_management.py
index 50b65a37e..5ab2236e7 100644
--- a/examples/custom_attributes/custom_management.py
+++ b/examples/custom_attributes/custom_management.py
@@ -1,60 +1,37 @@
-"""this example illustrates how to replace SQLAlchemy's class descriptors with
-a user-defined system.
+"""Illustrates customized class instrumentation, using
+the :mod:`sqlalchemy.ext.instrumentation` extension package.
-This sort of thing is appropriate for integration with frameworks that
-redefine class behaviors in their own way, such that SQLA's default
-instrumentation is not compatible.
+In this example, mapped classes are modified to
+store their state in a dictionary attached to an attribute
+named "_goofy_dict", instead of using __dict__.
+this example illustrates how to replace SQLAlchemy's class
+descriptors with a user-defined system.
-The example illustrates redefinition of instrumentation at the class level as
-well as the collection level, and redefines the storage of the class to store
-state within "instance._goofy_dict" instead of "instance.__dict__". Note that
-the default collection implementations can be used with a custom attribute
-system as well.
"""
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, Text,\
ForeignKey
-from sqlalchemy.orm import mapper, relationship, Session,\
- InstrumentationManager
+from sqlalchemy.orm import mapper, relationship, Session
from sqlalchemy.orm.attributes import set_attribute, get_attribute, \
del_attribute
from sqlalchemy.orm.instrumentation import is_instrumented
-from sqlalchemy.orm.collections import collection_adapter
+from sqlalchemy.ext.instrumentation import InstrumentationManager
class MyClassState(InstrumentationManager):
- def __init__(self, cls):
- self.states = {}
-
- def instrument_attribute(self, class_, key, attr):
- pass
-
- def install_descriptor(self, class_, key, attr):
- pass
-
- def uninstall_descriptor(self, class_, key, attr):
- pass
-
- def instrument_collection_class(self, class_, key, collection_class):
- return MyCollection
-
def get_instance_dict(self, class_, instance):
return instance._goofy_dict
def initialize_instance_dict(self, class_, instance):
instance.__dict__['_goofy_dict'] = {}
- def initialize_collection(self, key, state, factory):
- data = factory()
- return MyCollectionAdapter(key, state, data), data
-
def install_state(self, class_, instance, state):
- self.states[id(instance)] = state
+ instance.__dict__['_goofy_dict']['state'] = state
def state_getter(self, class_):
def find(instance):
- return self.states[id(instance)]
+ return instance.__dict__['_goofy_dict']['state']
return find
class MyClass(object):
@@ -85,78 +62,6 @@ class MyClass(object):
else:
del self._goofy_dict[key]
-class MyCollectionAdapter(object):
- """An wholly alternative instrumentation implementation."""
-
- def __init__(self, key, state, collection):
- self.key = key
- self.state = state
- self.collection = collection
- setattr(collection, '_sa_adapter', self)
-
- def unlink(self, data):
- setattr(data, '_sa_adapter', None)
-
- def adapt_like_to_iterable(self, obj):
- return iter(obj)
-
- def append_with_event(self, item, initiator=None):
- self.collection.add(item, emit=initiator)
-
- def append_multiple_without_event(self, items):
- self.collection.members.extend(items)
-
- def append_without_event(self, item):
- self.collection.add(item, emit=False)
-
- def remove_with_event(self, item, initiator=None):
- self.collection.remove(item, emit=initiator)
-
- def remove_without_event(self, item):
- self.collection.remove(item, emit=False)
-
- def clear_with_event(self, initiator=None):
- for item in list(self):
- self.remove_with_event(item, initiator)
- def clear_without_event(self):
- for item in list(self):
- self.remove_without_event(item)
- def __iter__(self):
- return iter(self.collection)
-
- def fire_append_event(self, item, initiator=None):
- if initiator is not False and item is not None:
- self.state.get_impl(self.key).\
- fire_append_event(self.state, self.state.dict, item,
- initiator)
-
- def fire_remove_event(self, item, initiator=None):
- if initiator is not False and item is not None:
- self.state.get_impl(self.key).\
- fire_remove_event(self.state, self.state.dict, item,
- initiator)
-
- def fire_pre_remove_event(self, initiator=None):
- self.state.get_impl(self.key).\
- fire_pre_remove_event(self.state, self.state.dict,
- initiator)
-
-class MyCollection(object):
- def __init__(self):
- self.members = list()
- def add(self, object, emit=None):
- self.members.append(object)
- collection_adapter(self).fire_append_event(object, emit)
- def remove(self, object, emit=None):
- collection_adapter(self).fire_pre_remove_event(object)
- self.members.remove(object)
- collection_adapter(self).fire_remove_event(object, emit)
- def __getitem__(self, index):
- return self.members[index]
- def __iter__(self):
- return iter(self.members)
- def __len__(self):
- return len(self.members)
if __name__ == '__main__':
meta = MetaData(create_engine('sqlite://'))
@@ -186,7 +91,6 @@ if __name__ == '__main__':
assert a1.name == 'a1'
assert a1.bs[0].name == 'b1'
- assert isinstance(a1.bs, MyCollection)
sess = Session()
sess.add(a1)
@@ -197,7 +101,6 @@ if __name__ == '__main__':
assert a1.name == 'a1'
assert a1.bs[0].name == 'b1'
- assert isinstance(a1.bs, MyCollection)
a1.bs.remove(a1.bs[0])