Commit 515afd12 authored by Jeremy Hylton's avatar Jeremy Hylton

Use transaction package instead of get_transaction().

Add explanation for __getattr__ and friends.
parent 5bd99d83
...@@ -222,6 +222,8 @@ it with data, insert it into the \class{BTree} instance, and commit ...@@ -222,6 +222,8 @@ it with data, insert it into the \class{BTree} instance, and commit
this transaction. this transaction.
\begin{verbatim}# Create new User instance \begin{verbatim}# Create new User instance
import transaction
newuser = User() newuser = User()
# Add whatever attributes you want to track # Add whatever attributes you want to track
...@@ -233,18 +235,18 @@ newuser.first_name = 'Andrew' ; newuser.last_name = 'Kuchling' ...@@ -233,18 +235,18 @@ newuser.first_name = 'Andrew' ; newuser.last_name = 'Kuchling'
userdb[newuser.id] = newuser userdb[newuser.id] = newuser
# Commit the change # Commit the change
get_transaction().commit() transaction.commit()
\end{verbatim} \end{verbatim}
When you import the ZODB package, it adds a new function, The \module{transaction} module defines a few top-level functions for
\function{get_transaction()}, to Python's collection of built-in working with transactions. \method{commit()} writes any modified
functions. \function{get_transaction()} returns a \class{Transaction} objects to disk, making the changes permanent. \method{abort()} rolls
object, which has two important methods: \method{commit()} and
\method{abort()}. \method{commit()} writes any modified objects
to disk, making the changes permanent, while \method{abort()} rolls
back any changes that have been made, restoring the original state of back any changes that have been made, restoring the original state of
the objects. If you're familiar with database transactional the objects. If you're familiar with database transactional
semantics, this is all what you'd expect. semantics, this is all what you'd expect. \method{get()} returns a
\class{Transaction} object that has additional methods like
\method{status()}, to check the current state of the transaction, and
\method{note()}, to add a note to the transaction metadata.
Because the integration with Python is so complete, it's a lot like Because the integration with Python is so complete, it's a lot like
having transactional semantics for your program's variables, and you having transactional semantics for your program's variables, and you
...@@ -257,7 +259,7 @@ can experiment with transactions at the Python interpreter's prompt: ...@@ -257,7 +259,7 @@ can experiment with transactions at the Python interpreter's prompt:
>>> newuser.first_name = 'Bob' # Change first name >>> newuser.first_name = 'Bob' # Change first name
>>> newuser.first_name # Verify the change >>> newuser.first_name # Verify the change
'Bob' 'Bob'
>>> get_transaction().abort() # Abort transaction >>> transaction.abort() # Abort transaction
>>> newuser.first_name # The value has changed back >>> newuser.first_name # The value has changed back
'Andrew' 'Andrew'
\end{verbatim} \end{verbatim}
...@@ -340,7 +342,7 @@ would then look like this: ...@@ -340,7 +342,7 @@ would then look like this:
\begin{verbatim} \begin{verbatim}
def add_friend(self, friend): def add_friend(self, friend):
self.friends.append(otherUser) self.friends.append(otherUser)
self._p_changed = 1 self._p_changed = True
\end{verbatim} \end{verbatim}
Alternatively, you could use a ZODB-aware list or mapping type that Alternatively, you could use a ZODB-aware list or mapping type that
...@@ -355,17 +357,45 @@ and may make it into a future upstream release of Zope. ...@@ -355,17 +357,45 @@ and may make it into a future upstream release of Zope.
\subsubsection{\method{__getattr__}, \method{__delattr__}, and \method{__setattr__}} \subsubsection{\method{__getattr__}, \method{__delattr__}, and \method{__setattr__}}
% XXX This section could be out-of-date. I've got to remember how we ZODB allows persistent classes to have hook methods like
% decided to do this before the beta release. \method{__getattr__} and \method{__setattr__}. There are four special
methods that control attribute access; the rules for each are a little
Recent versions of ZODB allow writing persistent classes that have different.
\method{__getattr__}, \method{__delattr__}, or \method{__setattr__}
methods. The one minor complication is that the machinery for The \method{__getattr__} method works pretty much the same for
automatically detecting changes to the object is disabled while the persistent classes as it does for other classes. No special handling
\method{__getattr__}, \method{__delattr__}, or \method{__setattr__} is needed. If an object is a ghost, then it will be activated before
method is executing. This means that if the object is modified, the \method{__getattr__} is called.
object should be marked as dirty by setting the object's
\member{_p_changed} method to true. The other methods are more delicate. They will override the hooks
provided by \class{Persistent}, so user code must call special methods
to invoke those hooks anyway.
The \method{__getattribute__} method will be called for all attribute
access; it overrides the attribute access support inherited from
\class{Persistent}. A user-defined
\method{__getattribute__} must always give the \class{Persistent} base
class a chance to handle special attribute, as well as
\member{__dict__} or \member{__class__}. The user code should
call \method{_p_getattr}, passing the name of the attribute as the
only argument. If it returns True, the user code should call
\class{Persistent}'s \method{__getattribute__} to get the value. If
not, the custom user code can run.
A \method{__setattr__} hook will also override the \class{Persistent}
\method{__setattr__} hook. User code must treat it much like
\method{__getattribute__}. The user-defined code must call
\method{_p_setattr} first to all \class{Persistent} to handle special
attributes; \method{_p_setattr} takes the attribute name and value.
If it returns True, \class{Persistent} handled the attribute. If not,
the user code can run. If the user code modifies the object's state,
it must assigned to \member{_p_changed}.
A \method{__delattr__} hooks must be implemented the same was as a the
last two hooks. The user code must call \method{_p_delattr}, passing
the name of the attribute as an argument. If the call returns True,
\class{Persistent} handled the attribute; if not, the user code can
run.
\subsection{Writing Persistent Classes} \subsection{Writing Persistent Classes}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment