Several issues here. One is you can't tinker with the mapper inside of instrument_class() - that is much too early in the initialization phase. 0.7 will have an event called "mapper_configured" which you can use for this purpose. For now, use an alternate mapper() function of your own, which calls sqlalchemy.orm.mapper() first, then adds your special properties, or better yet just populates the "properties" dictionary that's passed to mapper() with the additional attributes.
Second, you can't add a Column to a mapper() that isn't bound to a Table. You should be augmenting the creation of the Table object, not the mapper, here. Some suggestions for this are at http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions (see the "created" column that gets added), as well as the examples/versioning recipe in the distribution. Third, your ValidComparator doesn't make sense, its implementing __eq__() but is disregarding the "other" being passed. If that were me I'd use a hybrid "method", which is an extension in version 0.7, but is just as usable in 0.6 if you follow along with the examples/derived_attributes example: from examples.derived_attributes.attributes import method class MyClass(object): # .... @method def valid_at(self, other): # you could implement Python datetime logic here raise NotImplementedError() @valid_at.expression def valid_at(cls, other): # class level "expression" return and_(cls.valid_from < other, cls.valid_to > other) some documentation on the feature as added in 0.7 is at http://www.sqlalchemy.org/docs/07/orm/extensions/hybrid.html , but the concepts in the "derived_attributes" example in 0.6 are identical. On Feb 11, 2011, at 8:07 AM, jajadinimueter wrote: > Hi > > I'd like to setup a small versioning extension. Thus I set up a > MepperExtension an overwitten the instrument_class method: > > class VersionExtension(MapperExtension): > """ > With this extension it should be possible to load a versioned > entity with: > >>>> > db.session.query(Address).filter_by(valid_at=datetime.date.today()).all() > > Declaring a versioned object is done by calling > versioned_entity(allow_overlap=False) method. > When passing allow_overlap=True there can be multiple versions of > this entity at the same > time. > """ > > def instrument_class(self, mapper, clazz): > > mapper.add_property('valid_from', > ColumnProperty(Column('valid_from', DateTime, nullable=False))) > mapper.add_property('valid_to', > ColumnProperty(Column('valid_to', DateTime, nullable=True))) > > class ValidComparator(PropComparator): > def __eq__(self, other): > valid_at = self.__clause_element__() > clazz = mapper.class_ > return and_( > or_( > and_(clazz.valid_from<=valid_at, > clazz.valid_to>=valid_at), > and_(clazz.valid_from<=valid_at, > clazz.valid_to==None), > > ) > ) > > mapper.add_property('valid_at', > ComparableProperty(ValidComparator)) > > return EXT_CONTINUE > > The problem is, this fails with the error >> AttributeError: 'Mapper' > object has no attribute 'columns' [1] > > Did anyone encounter this problem as well or does anyone know what I'm > doing wrong? > > Regards, > Florian > > [1] > Traceback (most recent call last): > File "/Users/fm/dev/wlib/roopio/src/roopio/tests/regressiontests/ > test_versioning.py", line 56, in test_versioned > class Entity(db.Base): > File "/Library/Frameworks/Python.framework/Versions/3.1/lib/ > python3.1/site-packages/SQLAlchemy-0.6.5-py3.1.egg/sqlalchemy/ext/ > declarative.py", line 1231, in __init__ > _as_declarative(cls, classname, cls.__dict__) > File "/Library/Frameworks/Python.framework/Versions/3.1/lib/ > python3.1/site-packages/SQLAlchemy-0.6.5-py3.1.egg/sqlalchemy/ext/ > declarative.py", line 1224, in _as_declarative > **mapper_args) > File "/Users/fm/dev/wlib/wlib/src/wlib/db/__init__.py", line 35, in > mapper > return orm.mapper(cls, *args, **kwargs) > File "/Library/Frameworks/Python.framework/Versions/3.1/lib/ > python3.1/site-packages/SQLAlchemy-0.6.5-py3.1.egg/sqlalchemy/orm/ > __init__.py", line 861, in mapper > return Mapper(class_, local_table, *args, **params) > File "/Library/Frameworks/Python.framework/Versions/3.1/lib/ > python3.1/site-packages/SQLAlchemy-0.6.5-py3.1.egg/sqlalchemy/orm/ > mapper.py", line 215, in __init__ > self._configure_class_instrumentation() > File "/Library/Frameworks/Python.framework/Versions/3.1/lib/ > python3.1/site-packages/SQLAlchemy-0.6.5-py3.1.egg/sqlalchemy/orm/ > mapper.py", line 391, in _configure_class_instrumentation > self.extension.instrument_class(self, self.class_) > File "/Library/Frameworks/Python.framework/Versions/3.1/lib/ > python3.1/site-packages/SQLAlchemy-0.6.5-py3.1.egg/sqlalchemy/orm/ > util.py", line 241, in _do > ret = getattr(ext, method)(*args, **kwargs) > File "/Users/fm/dev/wlib/roopio/src/roopio/tests/regressiontests/ > test_versioning.py", line 24, in instrument_class > mapper.add_property('valid_from', > ColumnProperty(Column('valid_from', DateTime, nullable=False))) > File "/Library/Frameworks/Python.framework/Versions/3.1/lib/ > python3.1/site-packages/SQLAlchemy-0.6.5-py3.1.egg/sqlalchemy/orm/ > mapper.py", line 857, in add_property > self._configure_property(key, prop, init=self.compiled) > File "/Library/Frameworks/Python.framework/Versions/3.1/lib/ > python3.1/site-packages/SQLAlchemy-0.6.5-py3.1.egg/sqlalchemy/orm/ > mapper.py", line 730, in _configure_property > self.columns[key] = col > AttributeError: 'Mapper' object has no attribute 'columns' > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
