Commit e4a89f07 authored by Jim Fulton's avatar Jim Fulton

With new-style classes, is is no longer possible to override slots

(special '__' methods) on an instance-by instance basis. Changed the
handling of the length so that the __len__ method looks for a __len__
dictionary key. It would be better not to use a __len__ attribute name
for the BTree length object, but such a change would be problematic
for old instances.
parent 1b76d0d5
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
"""Simple column indices""" """Simple column indices"""
__version__='$Revision: 1.20 $'[11:-2] __version__='$Revision: 1.21 $'[11:-2]
import sys import sys
from cgi import escape from cgi import escape
...@@ -21,8 +21,6 @@ from types import StringType, ListType, IntType, TupleType ...@@ -21,8 +21,6 @@ from types import StringType, ListType, IntType, TupleType
from Globals import Persistent from Globals import Persistent
from Acquisition import Implicit from Acquisition import Implicit
import BTree
import IOBTree
from zLOG import LOG, ERROR from zLOG import LOG, ERROR
from BTrees.OOBTree import OOBTree, OOSet from BTrees.OOBTree import OOBTree, OOSet
...@@ -95,11 +93,27 @@ class UnIndex(Persistent, Implicit, SimpleItem): ...@@ -95,11 +93,27 @@ class UnIndex(Persistent, Implicit, SimpleItem):
except: except:
self.indexed_attrs = [ self.id ] self.indexed_attrs = [ self.id ]
# It was a mistake to use a __len__ attribute here, but it's not
# worth changing at this point, as there is old data with this
# attribute name. :( See __len__ method docstring
self.__len__ = BTrees.Length.Length()
self.__len__=BTrees.Length.Length() # see __len__ method docstring
self.clear() self.clear()
def getId(self): return self.id def __len__(self):
"""Return the number of objects indexed.
"""
# The instance __len__ attr isn't effective because
# Python cached this method in a slot,
__len__ = self.__dict__.get('__len__')
if __len__ is not None:
return __len__()
return len(self._unindex)
def getId(self):
return self.id
def clear(self): def clear(self):
# inplace opportunistic conversion from old-style to new style BTrees # inplace opportunistic conversion from old-style to new style BTrees
...@@ -140,15 +154,6 @@ class UnIndex(Persistent, Implicit, SimpleItem): ...@@ -140,15 +154,6 @@ class UnIndex(Persistent, Implicit, SimpleItem):
def __nonzero__(self): def __nonzero__(self):
return not not self._unindex return not not self._unindex
def __len__(self):
"""Return the number of objects indexed.
This method is only called for indexes which have "old" BTrees,
and the *only* reason that UnIndexes maintain a __len__ is for
the searching code in the catalog during sorting.
"""
return len(self._unindex)
def histogram(self): def histogram(self):
"""Return a mapping which provides a histogram of the number of """Return a mapping which provides a histogram of the number of
elements found at each point in the index.""" elements found at each point in the index."""
......
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
""" """
Transient Object Container Class ('timeslice'-based design). Transient Object Container Class ('timeslice'-based design).
$Id: Transience.py,v 1.33 2003/11/18 13:17:08 tseaver Exp $ $Id: Transience.py,v 1.34 2003/11/28 16:46:11 jim Exp $
""" """
__version__='$Revision: 1.33 $'[11:-2] __version__='$Revision: 1.34 $'[11:-2]
import Globals import Globals
from Globals import HTMLFile from Globals import HTMLFile
...@@ -427,8 +427,16 @@ class TransientObjectContainer(SimpleItem): ...@@ -427,8 +427,16 @@ class TransientObjectContainer(SimpleItem):
# our "__len__" is the length of _index. # our "__len__" is the length of _index.
# we need to maintain the length of the index structure separately # we need to maintain the length of the index structure separately
# because getting the length of a BTree is very expensive. # because getting the length of a BTree is very expensive.
try: self.__len__.set(0) # Note that it is a mistake to use the __len__ attr this way,
except AttributeError: self.__len__ = self.getLen = Length() # because length methods are cached in C slots and out instance
# attr won't be used for len(foo) in new-style classes.
# See the __len__ method below. I (Jim) am not changing this now
# on account of ols instances. With some effort, we could fix this,
# bit I'm not up for it now.
try:
self.__len__.set(0)
except AttributeError:
self.__len__ = Length()
# set up last_timeslice and deindex_next integer pointers # set up last_timeslice and deindex_next integer pointers
# we set them to the current timeslice as it's the only sane # we set them to the current timeslice as it's the only sane
...@@ -438,6 +446,12 @@ class TransientObjectContainer(SimpleItem): ...@@ -438,6 +446,12 @@ class TransientObjectContainer(SimpleItem):
finally: finally:
self.lock.release() self.lock.release()
def __len__(self):
return self.__dict__['__len__']()
def getLen(self):
return self.__len__
def _getCurrentBucket(self): def _getCurrentBucket(self):
""" """
Do housekeeping if necessary, then return the 'current' bucket. Do housekeeping if necessary, then return the 'current' bucket.
......
...@@ -76,7 +76,13 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -76,7 +76,13 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base):
# object unique identifier to the rid, and self.paths is a # object unique identifier to the rid, and self.paths is a
# mapping of the rid to the unique identifier. # mapping of the rid to the unique identifier.
self.__len__=BTrees.Length.Length() # Note that it was unfortunate to use __len__ as the attribute
# name here. New-style classes cache slot methods in C slot
# pointers. The result is that instances can't override slots.
# This is not easy to change on account of old objects with
# __len__ attr.
self.__len__ = BTrees.Length.Length()
self.clear() self.clear()
if brains is not None: if brains is not None:
...@@ -84,6 +90,14 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -84,6 +90,14 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base):
self.updateBrains() self.updateBrains()
def __len__(self):
try:
return self.__dict__['__len__']()
except KeyError:
# Fallback for *really* old catalogs that don't have
# Length objects.
return len(self.data)
def clear(self): def clear(self):
""" clear catalog """ """ clear catalog """
...@@ -122,11 +136,6 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base): ...@@ -122,11 +136,6 @@ class Catalog(Persistent, Acquisition.Implicit, ExtensionClass.Base):
if hasattr(index, '__of__'): index=index.__of__(self) if hasattr(index, '__of__'): index=index.__of__(self)
index._convertBTrees(threshold) index._convertBTrees(threshold)
def __len__(self):
# NOTE, this is never called for new catalogs, since
# each instance overrides this.
return len(self.data)
def updateBrains(self): def updateBrains(self):
self.useBrains(self._v_brains) self.useBrains(self._v_brains)
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
"""Simple column indices""" """Simple column indices"""
__version__='$Revision: 1.33 $'[11:-2] __version__='$Revision: 1.34 $'[11:-2]
from Globals import Persistent from Globals import Persistent
from Acquisition import Implicit from Acquisition import Implicit
...@@ -75,9 +75,22 @@ class UnIndex(Persistent, Implicit): ...@@ -75,9 +75,22 @@ class UnIndex(Persistent, Implicit):
self.ignore_ex=ignore_ex # currently unimplimented self.ignore_ex=ignore_ex # currently unimplimented
self.call_methods=call_methods self.call_methods=call_methods
self.__len__=BTrees.Length.Length() # see __len__ method docstring # Note that it was unfortunate to use __len__ as the attribute
# name here. New-style classes cache slot methods in C slot
# pointers. The result is that instances can't override slots.
# This is not easy to change on account of old objects with
# __len__ attr.
self.__len__=BTrees.Length.Length()
self.clear() self.clear()
def __len__(self):
try:
return self.__dict__['__len__']()
except KeyError:
# Fallback for really old indexes
return len(self._unindex)
def clear(self): def clear(self):
# inplace opportunistic conversion from old-style to new style BTrees # inplace opportunistic conversion from old-style to new style BTrees
try: self.__len__.set(0) try: self.__len__.set(0)
...@@ -117,15 +130,6 @@ class UnIndex(Persistent, Implicit): ...@@ -117,15 +130,6 @@ class UnIndex(Persistent, Implicit):
def __nonzero__(self): def __nonzero__(self):
return not not self._unindex return not not self._unindex
def __len__(self):
"""Return the number of objects indexed.
This method is only called for indexes which have "old" BTrees,
and the *only* reason that UnIndexes maintain a __len__ is for
the searching code in the catalog during sorting.
"""
return len(self._unindex)
def histogram(self): def histogram(self):
"""Return a mapping which provides a histogram of the number of """Return a mapping which provides a histogram of the number of
elements found at each point in the index.""" elements found at each point in the index."""
......
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