[Zodb-checkins] CVS: ZODB3/Doc/guide - prog-zodb.tex:1.2.4.4
Jeremy Hylton
jeremy@zope.com
Fri, 4 Oct 2002 14:44:28 -0400
Update of /cvs-repository/ZODB3/Doc/guide
In directory cvs.zope.org:/tmp/cvs-serv24551
Modified Files:
Tag: ZODB3-3_1-branch
prog-zodb.tex
Log Message:
Remove discussion of isinstance and and issublcass.
They seem to work fine in 2.1 and up.
=== ZODB3/Doc/guide/prog-zodb.tex 1.2.4.3 => 1.2.4.4 ===
--- ZODB3/Doc/guide/prog-zodb.tex:1.2.4.3 Fri Oct 4 14:40:56 2002
+++ ZODB3/Doc/guide/prog-zodb.tex Fri Oct 4 14:44:27 2002
@@ -314,11 +314,6 @@
arithmetic operations: \method{__radd__}, \method{__rsub__}, and so
forth.
-\item Python's built-in \function{isinstance()} and \function{issubclass()}
-functions don't work properly on ExtensionClasses. Solution: use
-custom \function{isinstance()} and \function{issubclass()} functions
-that handle ExtensionClasses correctly.
-
\item Recent versions of the ZODB allow writing a class with
\method{__setattr__} , \method{__getattr__}, or \method{__delattr__} methods. (Older versions didn't support this at all.)
If you write such a \method{__setattr__} or \method{__delattr__} method,
@@ -423,100 +418,6 @@
\function{type()} doesn't return the \code{InstanceType} object, so
no attempt is ever made to call \method{__cmp__}. Perhaps Python 2.2
will repair this.
-
-\subsubsection{Fixing \function{isinstance} and \function{issubclass}}
-
-Python's built-in functions
-\function{isinstance()} and \function{issubclass} don't
-work on ExtensionClass instances, for much the same reason that
-\method{__cmp__} is never called; in some bits of the Python core code,
-branches are taken only if an object is of the \class{InstanceType}
-type, and this can never be true for an ExtensionClass instance.
-Python 2.1 tried to fix this, and changed these functions slightly in
-an effort to make them work for ExtensionClasses; unfortunately, the
-changes didn't work.
-
-The solution is to use customized versions of these functions that
-handle ExtensionClasses specially and fall back to the built-in
-version otherwise. Here are the versions we've written at the MEMS Exchange:
-
-\begin{verbatim}
-# The built-in 'isinstance()' and 'issubclass()' won't work on
-# ExtensionClasses, so you have to use the versions supplied here.
-# (But those versions work fine on regular instances and classes too,
-# so you should *always* use them.)
-
-def issubclass (class1, class2):
- """A version of 'issubclass' that works with extension classes
- as well as regular Python classes.
- """
-
- # Both class objects are regular Python classes, so use the
- # built-in 'issubclass()'.
- if type(class1) is ClassType and type(class2) is ClassType:
- return __builtin__.issubclass(class1, class2)
-
- # Both so-called class objects have a '__bases__' attribute: ie.,
- # they aren't regular Python classes, but they sure look like them.
- # Assume they are extension classes and reimplement what the builtin
- # 'issubclass()' does behind the scenes.
- elif hasattr(class1, '__bases__') and hasattr(class2, '__bases__'):
- # XXX it appears that "ec.__class__ is type(ec)" for an
- # extension class 'ec': could we/should we use this as an
- # additional check for extension classes?
-
- # Breadth-first traversal of class1's superclass tree. Order
- # doesn't matter because we're just looking for a "yes/no"
- # answer from the tree; if we were trying to resolve a name,
- # order would be important!
- stack = [class1]
- while stack:
- if stack[0] is class2:
- return 1
- stack.extend(list(stack[0].__bases__))
- del stack[0]
- else:
- return 0
-
- # Not a regular class, not an extension class: blow up for consistency
- # with builtin 'issubclass()"
- else:
- raise TypeError, "arguments must be class or ExtensionClass objects"
-
-# issubclass ()
-
-def isinstance (object, klass):
- """A version of 'isinstance' that works with extension classes
- as well as regular Python classes."""
-
- if type(klass) is TypeType:
- return __builtin__.isinstance(object, klass)
- elif hasattr(object, '__class__'):
- return issubclass(object.__class__, klass)
- else:
- return 0
-\end{verbatim}
-
-I'd recommend putting these functions in a module that always gets
-imported. The convention on my work project is to put them in
-\file{mems/lib/base.py}, which contains various fundamental classes
-and functions for our system, and access them like this:
-
-\begin{verbatim}
-from mems.lib import base
-...
-if base.isinstance(object, Class): ...
-\end{verbatim}
-
-Don't insert the modified functions into Python's
-\module{__builtin__} module, or import just the
-\function{isinstance()} and \function{issubclass} functions.
-If you consistently use \function{base.isinstance()}, then forgetting
-to import the \module{base} module will result in a
-\exception{NameError} exception. In the
-case of a forgotten import, calling the functions directly would use
-Python's built-in versions, leading to subtle bugs that might not be
-noticed for some time.
\subsubsection{\method{__getattr__}, \method{__delattr__}, and \method{__setattr__}}