Commit e374dcfd authored by Gary Poster's avatar Gary Poster

- Normalize names in modules so that BTrees, Buckets, Sets, and TreeSets can

  all be accessed with those names in the modules (e.g.,
  BTrees.IOBTree.BTree).  This is in addition to the older names (e.g.,
  BTrees.IOBTree.IOBTree).  This allows easier drop-in replacement, which can
  especially be simplify code for packages that want to support both 32-bit and
  64-bit BTrees.

- Describe the interfaces for each module and actually declare the interfaces
  for each.

- Fix module references so klass.__module__ points to the Python wrapper
  module, not the C extension.
parent ca827539
......@@ -11,6 +11,19 @@ BTrees
(For now, we're retaining compile-time support for making the
regular integer BTrees 64-bit.)
- Normalize names in modules so that BTrees, Buckets, Sets, and TreeSets can
all be accessed with those names in the modules (e.g.,
BTrees.IOBTree.BTree). This is in addition to the older names (e.g.,
BTrees.IOBTree.IOBTree). This allows easier drop-in replacement, which can
especially be simplify code for packages that want to support both 32-bit and
64-bit BTrees.
- Describe the interfaces for each module and actually declare the interfaces
for each.
- Fix module references so klass.__module__ points to the Python wrapper
module, not the C extension.
What's new in ZODB3 3.7.0?
==========================
......
......@@ -38,15 +38,17 @@
PER_ACCESSED(OBJ); \
} while (0)
/*
The tp_name slots of the various BTree types contain the fully
qualified names of the types, e.g. zodb.btrees.OOBTree.OOBTree.
The full name is usd to support pickling and because it is not
possible to modify the __module__ slot of a type dynamically. (This
may be a bug in Python 2.2).
*/
#define MODULE_NAME "BTrees._" MOD_NAME_PREFIX "BTree."
/* The tp_name slots of the various BTree types contain the fully
* qualified names of the types, e.g. zodb.btrees.OOBTree.OOBTree.
* The full name is usd to support pickling and because it is not
* possible to modify the __module__ slot of a type dynamically. (This
* may be a bug in Python 2.2).
*
* The MODULE_NAME here used to be "BTrees._". We actually want the module
* name to point to the Python module rather than the C, so the underline
* is now removed.
*/
#define MODULE_NAME "BTrees." MOD_NAME_PREFIX "BTree."
static PyObject *sort_str, *reverse_str, *__setstate___str,
*_bucket_type_str;
......@@ -527,6 +529,23 @@ INITMODULE (void)
if (PyDict_SetItemString(d, MOD_NAME_PREFIX "TreeIterator",
(PyObject *)&BTreeIter_Type) < 0)
return;
/* We also want to be able to access these constants without the prefix
* so that code can more easily exchange modules (particularly the integer
* and long modules, but also others). The TreeIterator is only internal,
* so we don't bother to expose that.
*/
if (PyDict_SetItemString(d, "Bucket",
(PyObject *)&BucketType) < 0)
return;
if (PyDict_SetItemString(d, "BTree",
(PyObject *)&BTreeType) < 0)
return;
if (PyDict_SetItemString(d, "Set",
(PyObject *)&SetType) < 0)
return;
if (PyDict_SetItemString(d, "TreeSet",
(PyObject *)&TreeSetType) < 0)
return;
#if defined(ZODB_64BIT_INTS) && defined(NEED_LONG_LONG_SUPPORT)
if (PyDict_SetItemString(d, "using64bits", Py_True) < 0)
return;
......
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _IFBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IIntegerFloatBTreeModule)
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _IIBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IIntegerIntegerBTreeModule)
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _IOBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IIntegerObjectBTreeModule)
......@@ -12,7 +12,7 @@
#
##############################################################################
from zope.interface import Interface
from zope.interface import Interface, Attribute
class ICollection(Interface):
......@@ -233,6 +233,7 @@ class IDictionaryIsh(IMinimalDictionary):
raised.
"""
class IBTree(IDictionaryIsh):
def insert(key, value):
......@@ -304,6 +305,37 @@ class IMerge(Interface):
"""
class IBTreeModule(Interface):
"""These are available in all modules (IOBTree, OIBTree, OOBTree, IIBTree,
IFBTree, LFBTree, LOBTree, OLBTree, and LLBTree).
"""
BTree = Attribute(
"""The IBTree for this module.
Also available as [prefix]BTree, as in IOBTree.""")
Bucket = Attribute(
"""The leaf-node data buckets used by the BTree.
(IBucket is not currently defined in this file, but is essentially
IDictionaryIsh, with the exception of __nonzero__, as of this
writing.)
Also available as [prefix]Bucket, as in IOBucket.""")
TreeSet = Attribute(
"""The ITreeSet for this module.
Also available as [prefix]TreeSet, as in IOTreeSet.""")
Set = Attribute(
"""The ISet for this module: the leaf-node data buckets used by the
TreeSet.
Also available as [prefix]BTree, as in IOSet.""")
class IIMerge(IMerge):
"""Merge collections with integer value type.
......@@ -408,6 +440,37 @@ class IMergeIntegerKey(IMerge):
linear-time pass.
"""
class IIntegerObjectBTreeModule(IBTreeModule, IMerge):
"""keys, or set values, are integers; values are objects.
describes IOBTree and LOBTree"""
class IObjectIntegerBTreeModule(IBTreeModule, IIMerge):
"""keys, or set values, are objects; values are integers.
Object keys (and set values) must sort reliably (for instance, *not* on
object id)! Homogenous key types recommended.
describes OIBTree and LOBTree"""
class IIntegerIntegerBTreeModule(IBTreeModule, IIMerge, IMergeIntegerKey):
"""keys, or set values, are integers; values are also integers.
describes IIBTree and LLBTree"""
class IObjectObjectBTreeModule(IBTreeModule, IMerge):
"""keys, or set values, are objects; values are also objects.
Object keys (and set values) must sort reliably (for instance, *not* on
object id)! Homogenous key types recommended.
describes OOBTree"""
class IIntegerFloatBTreeModule(IBTreeModule, IMerge):
"""keys, or set values, are integers; values are floats.
describes IFBTree and LFBTree"""
###############################################################
# IMPORTANT NOTE
#
......
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _LFBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IIntegerFloatBTreeModule)
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _LLBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IIntegerIntegerBTreeModule)
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _LOBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IIntegerObjectBTreeModule)
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _OIBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IObjectIntegerBTreeModule)
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _OLBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IObjectIntegerBTreeModule)
......@@ -12,5 +12,10 @@
#
##############################################################################
import zope.interface
import BTrees.Interfaces
# hack to overcome dynamic-linking headache.
from _OOBTree import *
zope.interface.moduleProvides(BTrees.Interfaces.IObjectObjectBTreeModule)
......@@ -14,6 +14,7 @@
import random
from unittest import TestCase, TestSuite, TextTestRunner, makeSuite
from types import ClassType
import zope.interface.verify
from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
......@@ -25,6 +26,17 @@ from BTrees.LLBTree import LLBTree, LLBucket, LLSet, LLTreeSet
from BTrees.LFBTree import LFBTree, LFBucket, LFSet, LFTreeSet
from BTrees.OLBTree import OLBTree, OLBucket, OLSet, OLTreeSet
import BTrees.OOBTree
import BTrees.IOBTree
import BTrees.IIBTree
import BTrees.IFBTree
import BTrees.OIBTree
import BTrees.LOBTree
import BTrees.LLBTree
import BTrees.LFBTree
import BTrees.OLBTree
import BTrees.Interfaces
from BTrees.IIBTree import using64bits
from BTrees.check import check
......@@ -1648,6 +1660,22 @@ class TestCmpError(TestCase):
self.fail('incomarable objects should not be allowed into '
'the tree')
# test for presence of generic names in module
class ModuleTest(TestCase):
module = None
prefix = None
iface = None
def testNames(self):
for name in ('Bucket', 'BTree', 'Set', 'TreeSet'):
klass = getattr(self.module, name)
self.assertEqual(klass.__module__, self.module.__name__)
self.assert_(klass is getattr(self.module, self.prefix + name))
def testModuleProvides(self):
self.assert_(
zope.interface.verify.verifyObject(self.iface, self.module))
def test_suite():
s = TestSuite()
......@@ -1662,6 +1690,25 @@ def test_suite():
klass = ClassType(kv + name + 'Test', bases,
dict(t_class=globals()[kv+name]))
s.addTest(makeSuite(klass))
for kv, iface in (
('OO', BTrees.Interfaces.IObjectObjectBTreeModule),
('IO', BTrees.Interfaces.IIntegerObjectBTreeModule),
('LO', BTrees.Interfaces.IIntegerObjectBTreeModule),
('OI', BTrees.Interfaces.IObjectIntegerBTreeModule),
('OL', BTrees.Interfaces.IObjectIntegerBTreeModule),
('II', BTrees.Interfaces.IIntegerIntegerBTreeModule),
('LL', BTrees.Interfaces.IIntegerIntegerBTreeModule),
('IF', BTrees.Interfaces.IIntegerFloatBTreeModule),
('LF', BTrees.Interfaces.IIntegerFloatBTreeModule)):
s.addTest(
makeSuite(
ClassType(
kv + 'ModuleTest',
(ModuleTest,),
dict(
prefix=kv,
module=getattr(BTrees, kv + 'BTree'),
iface=iface))))
for klass in (
IIBTreeTest, IFBTreeTest, IOBTreeTest, OIBTreeTest,
......@@ -1670,7 +1717,7 @@ def test_suite():
# Note: there is no TestOOBTrees. The next three are
# checking for assorted TypeErrors, and when both keys
# and values oare objects (OO), there's nothing to test.
# and values are objects (OO), there's nothing to test.
TestIIBTrees, TestIFBTrees, TestIOBTrees, TestOIBTrees,
TestIOSets,
DegenerateBTree,
......
......@@ -61,8 +61,8 @@ Trans #00000 tid=... time=... offset=52
data #00000 oid=0000000000000000 size=66 class=persistent.mapping.PersistentMapping
Trans #00001 tid=... time=... offset=207
status=' ' user='' description='added an OOBTree'
data #00000 oid=0000000000000000 size=114 class=persistent.mapping.PersistentMapping
data #00001 oid=0000000000000001 size=30 class=BTrees._OOBTree.OOBTree
data #00000 oid=0000000000000000 size=113 class=persistent.mapping.PersistentMapping
data #00001 oid=0000000000000001 size=29 class=BTrees.OOBTree.OOBTree
Now we see two transactions and two changed objects.
......
......@@ -94,12 +94,12 @@ oid 0x00 persistent.mapping.PersistentMapping 2 revisions
tid user=''
tid description='added an OOBTree'
new revision persistent.mapping.PersistentMapping at 207
references 0x01 BTrees._OOBTree.OOBTree at 207
oid 0x01 BTrees._OOBTree.OOBTree 1 revision
references 0x01 BTrees.OOBTree.OOBTree at 207
oid 0x01 BTrees.OOBTree.OOBTree 1 revision
tid 0x... offset=168 ...
tid user=''
tid description='added an OOBTree'
new revision BTrees._OOBTree.OOBTree at 363
new revision BTrees.OOBTree.OOBTree at 362
referenced by 0x00 persistent.mapping.PersistentMapping at 207
So there are two revisions of oid 0 now, and the second references oid 1.
......@@ -122,22 +122,22 @@ oid 0x00 persistent.mapping.PersistentMapping 2 revisions
tid user=''
tid description='added an OOBTree'
new revision persistent.mapping.PersistentMapping at 207
references 0x01 BTrees._OOBTree.OOBTree at 207
tid 0x... offset=443 ...
references 0x01 BTrees.OOBTree.OOBTree at 207
tid 0x... offset=441 ...
tid user=''
tid description='circling back to the root'
referenced by 0x01 BTrees._OOBTree.OOBTree at 491
oid 0x01 BTrees._OOBTree.OOBTree 2 revisions
referenced by 0x01 BTrees.OOBTree.OOBTree at 489
oid 0x01 BTrees.OOBTree.OOBTree 2 revisions
tid 0x... offset=168 ...
tid user=''
tid description='added an OOBTree'
new revision BTrees._OOBTree.OOBTree at 363
new revision BTrees.OOBTree.OOBTree at 362
referenced by 0x00 persistent.mapping.PersistentMapping at 207
tid 0x... offset=443 ...
tid 0x... offset=441 ...
tid user=''
tid description='circling back to the root'
new revision BTrees._OOBTree.OOBTree at 491
references 0x00 persistent.mapping.PersistentMapping at 491
new revision BTrees.OOBTree.OOBTree at 489
references 0x00 persistent.mapping.PersistentMapping at 489
oid 0x02 <unknown> 0 revisions
this oid was not defined (no data record for it found)
......
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