[Zodb-checkins] CVS: ZODB/doc/guide - prog-zodb.tex:1.8
Jeremy Hylton
jeremy at zope.com
Fri Apr 16 15:11:17 EDT 2004
Update of /cvs-repository/ZODB/doc/guide
In directory cvs.zope.org:/tmp/cvs-serv17899/doc/guide
Modified Files:
prog-zodb.tex
Log Message:
Use transaction package instead of get_transaction().
Add explanation for __getattr__ and friends.
=== ZODB/doc/guide/prog-zodb.tex 1.7 => 1.8 ===
--- ZODB/doc/guide/prog-zodb.tex:1.7 Mon Jan 5 22:27:02 2004
+++ ZODB/doc/guide/prog-zodb.tex Fri Apr 16 15:11:16 2004
@@ -222,6 +222,8 @@
this transaction.
\begin{verbatim}# Create new User instance
+import transaction
+
newuser = User()
# Add whatever attributes you want to track
@@ -233,18 +235,18 @@
userdb[newuser.id] = newuser
# Commit the change
-get_transaction().commit()
+transaction.commit()
\end{verbatim}
-When you import the ZODB package, it adds a new function,
-\function{get_transaction()}, to Python's collection of built-in
-functions. \function{get_transaction()} returns a \class{Transaction}
-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
+The \module{transaction} module defines a few top-level functions for
+working with transactions. \method{commit()} writes any modified
+objects to disk, making the changes permanent. \method{abort()} rolls
back any changes that have been made, restoring the original state of
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
having transactional semantics for your program's variables, and you
@@ -257,7 +259,7 @@
>>> newuser.first_name = 'Bob' # Change first name
>>> newuser.first_name # Verify the change
'Bob'
->>> get_transaction().abort() # Abort transaction
+>>> transaction.abort() # Abort transaction
>>> newuser.first_name # The value has changed back
'Andrew'
\end{verbatim}
@@ -340,7 +342,7 @@
\begin{verbatim}
def add_friend(self, friend):
self.friends.append(otherUser)
- self._p_changed = 1
+ self._p_changed = True
\end{verbatim}
Alternatively, you could use a ZODB-aware list or mapping type that
@@ -355,17 +357,45 @@
\subsubsection{\method{__getattr__}, \method{__delattr__}, and \method{__setattr__}}
-% XXX This section could be out-of-date. I've got to remember how we
-% decided to do this before the beta release.
-
-Recent versions of ZODB allow writing persistent classes that have
-\method{__getattr__}, \method{__delattr__}, or \method{__setattr__}
-methods. The one minor complication is that the machinery for
-automatically detecting changes to the object is disabled while the
-\method{__getattr__}, \method{__delattr__}, or \method{__setattr__}
-method is executing. This means that if the object is modified, the
-object should be marked as dirty by setting the object's
-\member{_p_changed} method to true.
+ZODB allows persistent classes to have hook methods like
+\method{__getattr__} and \method{__setattr__}. There are four special
+methods that control attribute access; the rules for each are a little
+different.
+
+The \method{__getattr__} method works pretty much the same for
+persistent classes as it does for other classes. No special handling
+is needed. If an object is a ghost, then it will be activated before
+\method{__getattr__} is called.
+
+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}
More information about the Zodb-checkins
mailing list