If you need to permanently deinstrument a class, just dispose of the mapper:
sqlalchemy.orm.class_mapper(Worker).dispose()
SQLAlchemy instrumentation lives as property descriptors on the class object. So if you need separate deinstrumented versions of objects you'll need to create a version of the class that doesn't have the descriptors in it's type hierarchy.
A good way would be to have a persistent subclass for each model class and create the mappers to the persistent classes. Here's a class decorator that creates the subclass for you and adds it as a class attribute on the original:
def deinstrumentable(cls):
"""Create a deinstrumentable subclass of the class."""
def deinstrument(self):
"""Create a non-instrumented copy of the object."""
obj = cls.__new__(cls)
obj.__dict__.update(self.__dict__)
del obj._sa_instance_state
return obj
persistent = type('Persisted%s' % cls.__name__, (cls,), {
'Base': cls,
'deinstrument': deinstrument
})
return persistent
You would use it in the definition like this:
@deinstrumentable
class Worker(object):
def earnings(self):
return self.wage*self.hours
mapper(Worker, workers)
And when you have a persistent object, you can create a deinstrumented version of it like this:
worker = session.query(Worker).first()
detached_worker = worker.deinstrument()
You can create a deinstrumented version directly like this:
detached_worker = Worker.Base()