Transaction hooks make it easy to change specific behavior of default transaction classes. You can customize the following behaviors:
This document also functions as a doctest:
>>> from schevo.test import DocTest
Define each subclass as an inner class of the entity class that you are overriding. Begin the class name with an underscore, then the name of the transaction you are overriding. Inherit from the name of the transaction in the T namespace. For example:
class Foo(E.Entity): bar = f.string() count = f.integer() class _Create(T.Create): ... class _Delete(T.Delete): ... class _Update(T.Update): ...
You can also create custom transactions that have names that differ from the standard ones shown above. Remember to set up a t method so you can create instances of your new transaction:
class Foo(E.Entity): bar = f.string() count = f.integer() def t_custom_update(self, **kw): return E.Foo._CustomUpdate(self, **kw) class _CustomUpdate(T.Update): ...
Overriding __init__ or _execute in most Transaction subclasses is not allowed. If you attempt to do so, Schevo will raise a schevo.error.TransactionExecuteRedefinitionRestricted exception:
>>> t = DocTest(""" ... class Foo(E.Entity): ... ... bar = f.string() ... ... class _Create(T.Create): ... ... def _execute(self, db): ... pass ... """) Traceback (most recent call last): ... TransactionExecuteRedefinitionRestricted: ...
Classes that have a _restrict_subclasses attribute set to True enforce the above restriction. They include the following:
When implementing the hooks listed below, remember that you can raise an exception at any point to veto an operation. Any changes to the database made by the transaction will be reversed, and control will return to the parent transaction execution, if one exists.
Subclasses of Create, Delete, and Update transactions that are defined as inner classes of an entity class inherit the field definitions from the entity class.
When a field with a new name is defined in a transaction subclass, it is added to the end of the existing field definitions. For example, the Update class here has three fields, bar, count, and baz:
class Foo(E.Entity): bar = f.string() count = f.integer() class _Update(T.Update): baz = f.entity('Baz')
When a field with an existing name is defined, it replaces the old field definition and is added to the end. For example, the Update class here has two fields, count and bar:
class Foo(E.Entity): bar = f.string() count = f.integer() class _Update(T.Update): bar = f.entity('Bar')
To change the properties of a field without changing the order of it, make those changes in the _setup method by using the f namespace:
class Foo(E.Entity): bar = f.string() count = f.integer() class _Update(T.Update): def _setup(self): self.f.count.hidden = True