diff --git a/.travis.yml b/.travis.yml index 3dd5b60..489799b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -85,14 +85,14 @@ script: - python --version - | if [[ "$WITH_COVERAGE" == "1" ]]; then - coverage run -m zope.testrunner --test-path=. --auto-color --auto-progress --verbose + python -m coverage run -m zope.testrunner --test-path=. --auto-color --auto-progress --verbose else - zope-testrunner --test-path=. --auto-color --auto-progress --verbose + python -m zope.testrunner --test-path=. --auto-color --auto-progress --verbose fi - python setup.py -q bdist_wheel after_success: - - if [[ "$WITH_COVERAGE" == "1" ]]; then coveralls; fi + - if [[ "$WITH_COVERAGE" == "1" ]]; then python -m coveralls; fi - | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then # macpython 3.5 doesn't support recent TLS protocols which causes twine diff --git a/BTrees/BTreeModuleTemplate.c b/BTrees/BTreeModuleTemplate.c index e693993..ee7aef1 100644 --- a/BTrees/BTreeModuleTemplate.c +++ b/BTrees/BTreeModuleTemplate.c @@ -77,28 +77,117 @@ static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;} #error "PY_LONG_LONG required but not defined" #endif +static int +longlong_handle_overflow(PY_LONG_LONG result, int overflow) +{ + if (overflow) + { + /* Python 3 tends to have an exception already set, Python 2 not so much */ + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_OverflowError, "couldn't convert integer to C long long"); + return 0; + } + else if (result == -1 && PyErr_Occurred()) + /* An exception has already been raised. */ + return 0; + return 1; +} + + #ifdef NEED_LONG_LONG_KEYS + +#if defined(ZODB_UNSIGNED_VALUE_INTS) || defined(ZODB_UNSIGNED_KEY_INTS) +static int +ulonglong_check(PyObject *ob) +{ +#ifndef PY3K + if (PyInt_Check(ob)) + { + long tmp; + tmp = PyInt_AS_LONG(ob); + if (tmp < 0) { + PyErr_SetString(PyExc_OverflowError, "unsigned value less than 0"); + return 0; + } + return 1; + } +#endif + + if (!PyLong_Check(ob)) + { + return 0; + } + + if (PyLong_AsUnsignedLongLong(ob) == (unsigned long long)-1 && PyErr_Occurred()) + { + return 0; + } + return 1; +} +#endif /* defined(ZODB_UNSIGNED_VALUE_INTS) || defined(ZODB_UNSIGNED_KEY_INTS) */ + static int longlong_check(PyObject *ob) { - if (INT_CHECK(ob)) +#ifndef PY3K + /* Python's small integers can always fit into a long long. */ + if (PyInt_Check(ob)) return 1; +#endif if (PyLong_Check(ob)) { int overflow; - (void)PyLong_AsLongLongAndOverflow(ob, &overflow); - if (overflow) - goto overflow; - return 1; + PY_LONG_LONG result; + result = PyLong_AsLongLongAndOverflow(ob, &overflow); + return longlong_handle_overflow(result, overflow); } return 0; -overflow: - PyErr_SetString(PyExc_ValueError, - "longlong_check: long integer out of range"); - return 0; } + #endif +#if defined(ZODB_UNSIGNED_VALUE_INTS) || defined(ZODB_UNSIGNED_KEY_INTS) +static PyObject * +ulonglong_as_object(unsigned PY_LONG_LONG val) +{ + if ((val > LONG_MAX)) + return PyLong_FromUnsignedLongLong(val); + return UINT_FROM_LONG((unsigned long)val); +} + +static int +ulonglong_convert(PyObject *ob, unsigned PY_LONG_LONG *value) +{ + unsigned PY_LONG_LONG val; + +#ifndef PY3K + if (PyInt_Check(ob)) + { + long tmp; + tmp = PyInt_AS_LONG(ob); + if (tmp < 0) { + PyErr_SetString(PyExc_OverflowError, "unsigned value less than 0"); + return 0; + } + (*value) = (unsigned PY_LONG_LONG)tmp; + return 1; + } +#endif + + if (!PyLong_Check(ob)) + { + PyErr_SetString(PyExc_TypeError, "expected integer key"); + return 0; + } + + val = PyLong_AsUnsignedLongLong(ob); + if (val == (unsigned long long)-1 && PyErr_Occurred()) + return 0; + (*value) = val; + return 1; +} +#endif /* defined(ZODB_UNSIGNED_VALUE_INTS) || defined(ZODB_UNSIGNED_KEY_INTS) */ + static PyObject * longlong_as_object(PY_LONG_LONG val) { @@ -107,10 +196,11 @@ longlong_as_object(PY_LONG_LONG val) return INT_FROM_LONG((long)val); } - static int longlong_convert(PyObject *ob, PY_LONG_LONG *value) { + PY_LONG_LONG val; + int overflow; #ifndef PY3K if (PyInt_Check(ob)) { @@ -124,20 +214,15 @@ longlong_convert(PyObject *ob, PY_LONG_LONG *value) PyErr_SetString(PyExc_TypeError, "expected integer key"); return 0; } - else + val = PyLong_AsLongLongAndOverflow(ob, &overflow); + if (!longlong_handle_overflow(val, overflow)) { - PY_LONG_LONG val; - int overflow; - val = PyLong_AsLongLongAndOverflow(ob, &overflow); - if (overflow) - goto overflow; - (*value) = val; - return 1; + return 0; } -overflow: - PyErr_SetString(PyExc_ValueError, "long integer out of range"); - return 0; + (*value) = val; + return 1; } + #endif /* NEED_LONG_LONG_SUPPORT */ @@ -424,30 +509,30 @@ static char *search_keywords[] = {"min", "max", static struct PyMethodDef module_methods[] = { {"difference", (PyCFunction) difference_m, METH_VARARGS, - "difference(o1, o2) -- " + "difference(o1, o2)\n" "compute the difference between o1 and o2" }, {"union", (PyCFunction) union_m, METH_VARARGS, - "union(o1, o2) -- compute the union of o1 and o2\n" + "union(o1, o2)\ncompute the union of o1 and o2\n" }, {"intersection", (PyCFunction) intersection_m, METH_VARARGS, - "intersection(o1, o2) -- " + "intersection(o1, o2)\n" "compute the intersection of o1 and o2" }, #ifdef MERGE {"weightedUnion", (PyCFunction) wunion_m, METH_VARARGS, - "weightedUnion(o1, o2 [, w1, w2]) -- compute the union of o1 and o2\n" + "weightedUnion(o1, o2 [, w1, w2])\ncompute the union of o1 and o2\n" "\nw1 and w2 are weights." }, {"weightedIntersection", (PyCFunction) wintersection_m, METH_VARARGS, - "weightedIntersection(o1, o2 [, w1, w2]) -- " + "weightedIntersection(o1, o2 [, w1, w2])\n" "compute the intersection of o1 and o2\n" "\nw1 and w2 are weights." }, #endif #ifdef MULTI_INT_UNION {"multiunion", (PyCFunction) multiunion_m, METH_VARARGS, - "multiunion(seq) -- compute union of a sequence of integer sets.\n" + "multiunion(seq)\ncompute union of a sequence of integer sets.\n" "\n" "Each element of seq must be an integer set, or convertible to one\n" "via the set iteration protocol. The union returned is an IISet." diff --git a/BTrees/IUBTree.py b/BTrees/IUBTree.py new file mode 100644 index 0000000..c1d537a --- /dev/null +++ b/BTrees/IUBTree.py @@ -0,0 +1,113 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'IUBucket', 'IUSet', 'IUBTree', 'IUTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IIntegerUnsignedBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_int +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_int as _to_key +from ._base import to_uint as _to_value +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 120 +_TREE_SIZE = 500 +using64bits = False + + +class IUBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class IUSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class IUBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class IUTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class IUTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +IUBucketPy._mapping_type = IUBucketPy._bucket_type = IUBucketPy +IUBucketPy._set_type = IUSetPy + +IUSetPy._mapping_type = IUBucketPy +IUSetPy._set_type = IUSetPy._bucket_type = IUSetPy + +IUBTreePy._mapping_type = IUBTreePy._bucket_type = IUBucketPy +IUBTreePy._set_type = IUSetPy + +IUTreeSetPy._mapping_type = IUBucketPy +IUTreeSetPy._set_type = IUTreeSetPy._bucket_type = IUSetPy + + +differencePy = _set_operation(_difference, IUSetPy) +unionPy = _set_operation(_union, IUSetPy) +intersectionPy = _set_operation(_intersection, IUSetPy) +multiunionPy = _set_operation(_multiunion, IUSetPy) +weightedUnionPy = _set_operation(_weightedUnion, IUSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, IUSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IIntegerUnsignedBTreeModule) diff --git a/BTrees/Interfaces.py b/BTrees/Interfaces.py index cc4dcce..2cbd2df 100644 --- a/BTrees/Interfaces.py +++ b/BTrees/Interfaces.py @@ -451,40 +451,78 @@ def multiunion(seq): class IBTreeFamily(Interface): """the 64-bit or 32-bit family""" + IF = Attribute('The IIntegerFloatBTreeModule for this family') + II = Attribute('The IIntegerIntegerBTreeModule for this family') IO = Attribute('The IIntegerObjectBTreeModule for this family') + IU = Attribute('The IIntegerUnsignedBTreeModule for this family') + + UF = Attribute('The IUnsignedFloatBTreeModule for this family') + UI = Attribute('The IUnsignedIntegerBTreeModule for this family') + UO = Attribute('The IUnsignedObjectBTreeModule for this family') + UU = Attribute('The IUnsignedUnsignedBTreeModule for this family') + OI = Attribute('The IObjectIntegerBTreeModule for this family') - II = Attribute('The IIntegerIntegerBTreeModule for this family') - IF = Attribute('The IIntegerFloatBTreeModule for this family') OO = Attribute('The IObjectObjectBTreeModule for this family') - maxint = Attribute('The maximum integer storable in this family') - minint = Attribute('The minimum integer storable in this family') + OU = Attribute('The IObjectUnsignedBTreeModule for this family') + + maxint = Attribute('The maximum signed integer storable in this family') + maxuint = Attribute('The maximum unsigned integer storable in this family') + minint = Attribute('The minimum signed integer storable in this family') -class IIntegerObjectBTreeModule(IBTreeModule, IMerge): - """keys, or set values, are integers; values are objects. +class _IMergeBTreeModule(IBTreeModule, IMerge): + family = Attribute('The IBTreeFamily of this module') + + +class IIntegerObjectBTreeModule(_IMergeBTreeModule): + """keys, or set values, are signed integers; values are objects. describes IOBTree and LOBTree""" - family = Attribute('The IBTreeFamily of this module') + +class IUnsignedObjectBTreeModule(_IMergeBTreeModule): + """ + As for `IIntegerObjectBTreeModule` with unsigned integers. + """ -class IObjectIntegerBTreeModule(IBTreeModule, IIMerge): - """keys, or set values, are objects; values are integers. +class IObjectIntegerBTreeModule(_IMergeBTreeModule): + """keys, or set values, are objects; values are signed integers. Object keys (and set values) must sort reliably (for instance, *not* on object id)! Homogenous key types recommended. describes OIBTree and LOBTree""" - family = Attribute('The IBTreeFamily of this module') +class IObjectUnsignedBTreeModule(_IMergeBTreeModule): + """ + As for `IObjectIntegerBTreeModule` with unsigned integers. + """ -class IIntegerIntegerBTreeModule(IBTreeModule, IIMerge, IMergeIntegerKey): - """keys, or set values, are integers; values are also integers. + +class IIntegerIntegerBTreeModule(_IMergeBTreeModule, IMergeIntegerKey): + """keys, or set values, are signed integers; values are also signed integers. describes IIBTree and LLBTree""" - family = Attribute('The IBTreeFamily of this module') + +class IUnsignedUnsignedBTreeModule(_IMergeBTreeModule, IMergeIntegerKey): + """ + As for `IIntegerIntegerBTreeModule` with unsigned integers. + """ + + +class IUnsignedIntegerBTreeModule(_IMergeBTreeModule, IMergeIntegerKey): + """ + As for `IIntegerIntegerBTreeModule` with unsigned integers for keys only. + """ + + +class IIntegerUnsignedBTreeModule(_IMergeBTreeModule, IMergeIntegerKey): + """ + As for `IIntegerIntegerBTreeModule` with unsigned integers for values only. + """ class IObjectObjectBTreeModule(IBTreeModule, IMerge): @@ -499,12 +537,15 @@ class IObjectObjectBTreeModule(IBTreeModule, IMerge): # the OO flavor of BTrees. -class IIntegerFloatBTreeModule(IBTreeModule, IMerge): - """keys, or set values, are integers; values are floats. +class IIntegerFloatBTreeModule(_IMergeBTreeModule): + """keys, or set values, are signed integers; values are floats. describes IFBTree and LFBTree""" - family = Attribute('The IBTreeFamily of this module') +class IUnsignedFloatBTreeModule(_IMergeBTreeModule): + """ + As for `IIntegerFloatBTreeModule` with unsigned integers. + """ try: diff --git a/BTrees/LQBTree.py b/BTrees/LQBTree.py new file mode 100644 index 0000000..cffcd1c --- /dev/null +++ b/BTrees/LQBTree.py @@ -0,0 +1,113 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'LQBucket', 'LQSet', 'LQBTree', 'LQTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IIntegerUnsignedBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_int +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_long as _to_key +from ._base import to_ulong as _to_value +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 120 +_TREE_SIZE = 500 +using64bits = True + + +class LQBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class LQSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class LQBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class LQTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class LQTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +LQBucketPy._mapping_type = LQBucketPy._bucket_type = LQBucketPy +LQBucketPy._set_type = LQSetPy + +LQSetPy._mapping_type = LQBucketPy +LQSetPy._set_type = LQSetPy._bucket_type = LQSetPy + +LQBTreePy._mapping_type = LQBTreePy._bucket_type = LQBucketPy +LQBTreePy._set_type = LQSetPy + +LQTreeSetPy._mapping_type = LQBucketPy +LQTreeSetPy._set_type = LQTreeSetPy._bucket_type = LQSetPy + + +differencePy = _set_operation(_difference, LQSetPy) +unionPy = _set_operation(_union, LQSetPy) +intersectionPy = _set_operation(_intersection, LQSetPy) +multiunionPy = _set_operation(_multiunion, LQSetPy) +weightedUnionPy = _set_operation(_weightedUnion, LQSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, LQSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IIntegerUnsignedBTreeModule) diff --git a/BTrees/OQBTree.py b/BTrees/OQBTree.py new file mode 100644 index 0000000..45b8a92 --- /dev/null +++ b/BTrees/OQBTree.py @@ -0,0 +1,111 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'OQBucket', 'OQSet', 'OQBTree', 'OQTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IObjectUnsignedBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_int +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import set_operation as _set_operation +from ._base import to_ob as _to_key +from ._base import to_ulong as _to_value +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 60 +_TREE_SIZE = 250 +using64bits = True + + +class OQBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class OQSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class OQBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class OQTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class OQTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +OQBucketPy._mapping_type = OQBucketPy._bucket_type = OQBucketPy +OQBucketPy._set_type = OQSetPy + +OQSetPy._mapping_type = OQBucketPy +OQSetPy._set_type = OQSetPy._bucket_type = OQSetPy + +OQBTreePy._mapping_type = OQBTreePy._bucket_type = OQBucketPy +OQBTreePy._set_type = OQSetPy + +OQTreeSetPy._mapping_type = OQBucketPy +OQTreeSetPy._set_type = OQTreeSetPy._bucket_type = OQSetPy + + +differencePy = _set_operation(_difference, OQSetPy) +unionPy = _set_operation(_union, OQSetPy) +intersectionPy = _set_operation(_intersection, OQSetPy) +weightedUnionPy = _set_operation(_weightedUnion, OQSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, OQSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IObjectUnsignedBTreeModule) diff --git a/BTrees/OUBTree.py b/BTrees/OUBTree.py new file mode 100644 index 0000000..739041c --- /dev/null +++ b/BTrees/OUBTree.py @@ -0,0 +1,110 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'OUBucket', 'OUSet', 'OUBTree', 'OUTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IObjectUnsignedBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_float +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import set_operation as _set_operation +from ._base import to_ob as _to_key +from ._base import to_uint as _to_value +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 60 +_TREE_SIZE = 250 +using64bits = True + +class OUBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class OUSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class OUBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class OUTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class OUTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +OUBucketPy._mapping_type = OUBucketPy._bucket_type = OUBucketPy +OUBucketPy._set_type = OUSetPy + +OUSetPy._mapping_type = OUBucketPy +OUSetPy._set_type = OUSetPy._bucket_type = OUSetPy + +OUBTreePy._mapping_type = OUBTreePy._bucket_type = OUBucketPy +OUBTreePy._set_type = OUSetPy + +OUTreeSetPy._mapping_type = OUBucketPy +OUTreeSetPy._set_type = OUTreeSetPy._bucket_type = OUSetPy + + +differencePy = _set_operation(_difference, OUSetPy) +unionPy = _set_operation(_union, OUSetPy) +intersectionPy = _set_operation(_intersection, OUSetPy) +weightedUnionPy = _set_operation(_weightedUnion, OUSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, OUSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IObjectUnsignedBTreeModule) diff --git a/BTrees/QFBTree.py b/BTrees/QFBTree.py new file mode 100644 index 0000000..0b48c33 --- /dev/null +++ b/BTrees/QFBTree.py @@ -0,0 +1,113 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'QFBucket', 'QFSet', 'QFBTree', 'QFTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IUnsignedFloatBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_float +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_ulong as _to_key +from ._base import to_float as _to_value +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 120 +_TREE_SIZE = 500 +using64bits = True + + +class QFBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class QFSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class QFBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class QFTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class QFTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +QFBucketPy._mapping_type = QFBucketPy._bucket_type = QFBucketPy +QFBucketPy._set_type = QFSetPy + +QFSetPy._mapping_type = QFBucketPy +QFSetPy._set_type = QFSetPy._bucket_type = QFSetPy + +QFBTreePy._mapping_type = QFBTreePy._bucket_type = QFBucketPy +QFBTreePy._set_type = QFSetPy + +QFTreeSetPy._mapping_type = QFBucketPy +QFTreeSetPy._set_type = QFTreeSetPy._bucket_type = QFSetPy + + +differencePy = _set_operation(_difference, QFSetPy) +unionPy = _set_operation(_union, QFSetPy) +intersectionPy = _set_operation(_intersection, QFSetPy) +multiunionPy = _set_operation(_multiunion, QFSetPy) +weightedUnionPy = _set_operation(_weightedUnion, QFSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, QFSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IUnsignedFloatBTreeModule) diff --git a/BTrees/QLBTree.py b/BTrees/QLBTree.py new file mode 100644 index 0000000..24efc75 --- /dev/null +++ b/BTrees/QLBTree.py @@ -0,0 +1,113 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'QLBucket', 'QLSet', 'QLBTree', 'QLTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IUnsignedIntegerBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_int +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_ulong as _to_key +from ._base import to_long as _to_value +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 120 +_TREE_SIZE = 500 +using64bits = True + + +class QLBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class QLSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class QLBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class QLTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class QLTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +QLBucketPy._mapping_type = QLBucketPy._bucket_type = QLBucketPy +QLBucketPy._set_type = QLSetPy + +QLSetPy._mapping_type = QLBucketPy +QLSetPy._set_type = QLSetPy._bucket_type = QLSetPy + +QLBTreePy._mapping_type = QLBTreePy._bucket_type = QLBucketPy +QLBTreePy._set_type = QLSetPy + +QLTreeSetPy._mapping_type = QLBucketPy +QLTreeSetPy._set_type = QLTreeSetPy._bucket_type = QLSetPy + + +differencePy = _set_operation(_difference, QLSetPy) +unionPy = _set_operation(_union, QLSetPy) +intersectionPy = _set_operation(_intersection, QLSetPy) +multiunionPy = _set_operation(_multiunion, QLSetPy) +weightedUnionPy = _set_operation(_weightedUnion, QLSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, QLSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IUnsignedIntegerBTreeModule) diff --git a/BTrees/QOBTree.py b/BTrees/QOBTree.py new file mode 100644 index 0000000..e246c37 --- /dev/null +++ b/BTrees/QOBTree.py @@ -0,0 +1,96 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'QOBucket', 'QOSet', 'QOBTree', 'QOTreeSet', + 'union', 'intersection', 'difference', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IUnsignedObjectBTreeModule +from ._base import Bucket +from ._base import MERGE_WEIGHT_default +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_ulong as _to_key +from ._base import to_ob as _to_value +from ._base import union as _union +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 60 +_TREE_SIZE = 500 +using64bits = True + + +class QOBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE_WEIGHT = MERGE_WEIGHT_default + + +class QOSetPy(Set): + _to_key = _to_key + + +class QOBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE_WEIGHT = MERGE_WEIGHT_default + + +class QOTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + + +class QOTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +QOBucketPy._mapping_type = QOBucketPy._bucket_type = QOBucketPy +QOBucketPy._set_type = QOSetPy + +QOSetPy._mapping_type = QOBucketPy +QOSetPy._set_type = QOSetPy._bucket_type = QOSetPy + +QOBTreePy._mapping_type = QOBTreePy._bucket_type = QOBucketPy +QOBTreePy._set_type = QOSetPy + +QOTreeSetPy._mapping_type = QOBucketPy +QOTreeSetPy._set_type = QOTreeSetPy._bucket_type = QOSetPy + + +differencePy = _set_operation(_difference, QOSetPy) +unionPy = _set_operation(_union, QOSetPy) +intersectionPy = _set_operation(_intersection, QOSetPy) +multiunionPy = _set_operation(_multiunion, QOSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IUnsignedObjectBTreeModule) diff --git a/BTrees/QQBTree.py b/BTrees/QQBTree.py new file mode 100644 index 0000000..27c7f6b --- /dev/null +++ b/BTrees/QQBTree.py @@ -0,0 +1,113 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'QQBucket', 'QQSet', 'QQBTree', 'QQTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IUnsignedUnsignedBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_int +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_ulong as _to_key +_to_value = _to_key +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 120 +_TREE_SIZE = 500 +using64bits = True + + +class QQBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class QQSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class QQBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class QQTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class QQTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +QQBucketPy._mapping_type = QQBucketPy._bucket_type = QQBucketPy +QQBucketPy._set_type = QQSetPy + +QQSetPy._mapping_type = QQBucketPy +QQSetPy._set_type = QQSetPy._bucket_type = QQSetPy + +QQBTreePy._mapping_type = QQBTreePy._bucket_type = QQBucketPy +QQBTreePy._set_type = QQSetPy + +QQTreeSetPy._mapping_type = QQBucketPy +QQTreeSetPy._set_type = QQTreeSetPy._bucket_type = QQSetPy + + +differencePy = _set_operation(_difference, QQSetPy) +unionPy = _set_operation(_union, QQSetPy) +intersectionPy = _set_operation(_intersection, QQSetPy) +multiunionPy = _set_operation(_multiunion, QQSetPy) +weightedUnionPy = _set_operation(_weightedUnion, QQSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, QQSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IUnsignedUnsignedBTreeModule) diff --git a/BTrees/SetOpTemplate.c b/BTrees/SetOpTemplate.c index 7164ada..f50a03f 100644 --- a/BTrees/SetOpTemplate.c +++ b/BTrees/SetOpTemplate.c @@ -129,7 +129,7 @@ initSetIteration(SetIteration *i, PyObject *s, int useValues) #endif else { - PyErr_SetString(PyExc_TypeError, "invalid argument"); + PyErr_SetString(PyExc_TypeError, "set operation: invalid argument, cannot iterate"); return -1; } @@ -143,7 +143,7 @@ initSetIteration(SetIteration *i, PyObject *s, int useValues) #endif static int -copyRemaining(Bucket *r, SetIteration *i, int merge, +copyRemaining(Bucket *r, SetIteration *i, int merge, /* See comment # 42 */ #ifdef MERGE @@ -209,7 +209,7 @@ set_operation(PyObject *s1, PyObject *s2, difference is one. This works fine in the int value and float value cases but makes no sense in the object value case. In the object value case, we don't do merging, so we don't use the weights, so it - doesn't matter what they are. + doesn't matter what they are. */ #ifdef MERGE VALUE_TYPE w1, VALUE_TYPE w2, @@ -427,7 +427,7 @@ wunion_m(PyObject *ignored, PyObject *args) PyObject *o1, *o2; VALUE_TYPE w1 = 1, w2 = 1; - UNLESS(PyArg_ParseTuple(args, "OO|" VALUE_PARSE VALUE_PARSE, + UNLESS(PyArg_ParseTuple(args, "OO|" VALUE_PARSE VALUE_PARSE, &o1, &o2, &w1, &w2) ) return NULL; @@ -437,7 +437,7 @@ wunion_m(PyObject *ignored, PyObject *args) return Py_BuildValue(VALUE_PARSE "O", w1, o1); o1 = set_operation(o1, o2, 1, 1, w1, w2, 1, 1, 1); - if (o1) + if (o1) ASSIGN(o1, Py_BuildValue(VALUE_PARSE "O", (VALUE_TYPE)1, o1)); return o1; @@ -449,7 +449,7 @@ wintersection_m(PyObject *ignored, PyObject *args) PyObject *o1, *o2; VALUE_TYPE w1 = 1, w2 = 1; - UNLESS(PyArg_ParseTuple(args, "OO|" VALUE_PARSE VALUE_PARSE, + UNLESS(PyArg_ParseTuple(args, "OO|" VALUE_PARSE VALUE_PARSE, &o1, &o2, &w1, &w2) ) return NULL; diff --git a/BTrees/SetTemplate.c b/BTrees/SetTemplate.c index bec7f96..35523c0 100644 --- a/BTrees/SetTemplate.c +++ b/BTrees/SetTemplate.c @@ -37,7 +37,7 @@ _Set_update(Bucket *self, PyObject *seq) { int n=0, ind=0; PyObject *iter, *v; - + iter = PyObject_GetIter(seq); if (iter == NULL) return -1; @@ -177,49 +177,49 @@ set_setstate(Bucket *self, PyObject *args) static struct PyMethodDef Set_methods[] = { {"__getstate__", (PyCFunction) bucket_getstate, METH_VARARGS, - "__getstate__() -- Return the picklable state of the object"}, + "__getstate__()\nReturn the picklable state of the object"}, {"__setstate__", (PyCFunction) set_setstate, METH_VARARGS, - "__setstate__() -- Set the state of the object"}, + "__setstate__()\nSet the state of the object"}, {"keys", (PyCFunction) bucket_keys, METH_VARARGS | METH_KEYWORDS, - "keys() -- Return the keys"}, + "keys()\nReturn the keys"}, {"has_key", (PyCFunction) bucket_has_key, METH_O, - "has_key(key) -- Test whether the bucket contains the given key"}, + "has_key(key)\nTest whether the bucket contains the given key"}, {"clear", (PyCFunction) bucket_clear, METH_VARARGS, - "clear() -- Remove all of the items from the bucket"}, + "clear()\nRemove all of the items from the bucket"}, {"maxKey", (PyCFunction) Bucket_maxKey, METH_VARARGS, - "maxKey([key]) -- Find the maximum key\n\n" + "maxKey([key])\nFind the maximum key\n\n" "If an argument is given, find the maximum <= the argument"}, {"minKey", (PyCFunction) Bucket_minKey, METH_VARARGS, - "minKey([key]) -- Find the minimum key\n\n" + "minKey([key])\nFind the minimum key\n\n" "If an argument is given, find the minimum >= the argument"}, #ifdef PERSISTENT {"_p_resolveConflict", (PyCFunction) bucket__p_resolveConflict, METH_VARARGS, - "_p_resolveConflict() -- Reinitialize from a newly created copy"}, + "_p_resolveConflict()\nReinitialize from a newly created copy"}, {"_p_deactivate", (PyCFunction) bucket__p_deactivate, METH_VARARGS | METH_KEYWORDS, - "_p_deactivate() -- Reinitialize from a newly created copy"}, + "_p_deactivate()\nReinitialize from a newly created copy"}, #endif {"add", (PyCFunction)Set_insert, METH_VARARGS, - "add(id) -- Add a key to the set"}, + "add(id)\nAdd a key to the set"}, {"insert", (PyCFunction)Set_insert, METH_VARARGS, - "insert(id) -- Add a key to the set"}, + "insert(id)\nAdd a key to the set"}, {"update", (PyCFunction)Set_update, METH_VARARGS, - "update(seq) -- Add the items from the given sequence to the set"}, + "update(seq)\nAdd the items from the given sequence to the set"}, {"remove", (PyCFunction)Set_remove, METH_VARARGS, - "remove(id) -- Remove an id from the set"}, + "remove(id)\nRemove an id from the set"}, {NULL, NULL} /* sentinel */ }; diff --git a/BTrees/UFBTree.py b/BTrees/UFBTree.py new file mode 100644 index 0000000..517a9d9 --- /dev/null +++ b/BTrees/UFBTree.py @@ -0,0 +1,112 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'UFBucket', 'UFSet', 'UFBTree', 'UFTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IUnsignedFloatBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_float +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_uint as _to_key +from ._base import to_float as _to_value +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 120 +_TREE_SIZE = 500 +using64bits = False + +class UFBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class UFSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class UFBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class UFTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_float + + +class UFTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +UFBucketPy._mapping_type = UFBucketPy._bucket_type = UFBucketPy +UFBucketPy._set_type = UFSetPy + +UFSetPy._mapping_type = UFBucketPy +UFSetPy._set_type = UFSetPy._bucket_type = UFSetPy + +UFBTreePy._mapping_type = UFBTreePy._bucket_type = UFBucketPy +UFBTreePy._set_type = UFSetPy + +UFTreeSetPy._mapping_type = UFBucketPy +UFTreeSetPy._set_type = UFTreeSetPy._bucket_type = UFSetPy + + +differencePy = _set_operation(_difference, UFSetPy) +unionPy = _set_operation(_union, UFSetPy) +intersectionPy = _set_operation(_intersection, UFSetPy) +multiunionPy = _set_operation(_multiunion, UFSetPy) +weightedUnionPy = _set_operation(_weightedUnion, UFSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, UFSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IUnsignedFloatBTreeModule) diff --git a/BTrees/UIBTree.py b/BTrees/UIBTree.py new file mode 100644 index 0000000..a701ee8 --- /dev/null +++ b/BTrees/UIBTree.py @@ -0,0 +1,113 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'UIBucket', 'UISet', 'UIBTree', 'UITreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IUnsignedIntegerBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_int +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_uint as _to_key +from ._base import to_int as _to_value +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 120 +_TREE_SIZE = 500 +using64bits = False + + +class UIBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class UISetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class UIBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class UITreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class UITreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +UIBucketPy._mapping_type = UIBucketPy._bucket_type = UIBucketPy +UIBucketPy._set_type = UISetPy + +UISetPy._mapping_type = UIBucketPy +UISetPy._set_type = UISetPy._bucket_type = UISetPy + +UIBTreePy._mapping_type = UIBTreePy._bucket_type = UIBucketPy +UIBTreePy._set_type = UISetPy + +UITreeSetPy._mapping_type = UIBucketPy +UITreeSetPy._set_type = UITreeSetPy._bucket_type = UISetPy + + +differencePy = _set_operation(_difference, UISetPy) +unionPy = _set_operation(_union, UISetPy) +intersectionPy = _set_operation(_intersection, UISetPy) +multiunionPy = _set_operation(_multiunion, UISetPy) +weightedUnionPy = _set_operation(_weightedUnion, UISetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, UISetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IUnsignedIntegerBTreeModule) diff --git a/BTrees/UOBTree.py b/BTrees/UOBTree.py new file mode 100644 index 0000000..2a82f38 --- /dev/null +++ b/BTrees/UOBTree.py @@ -0,0 +1,95 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'UOBucket', 'UOSet', 'UOBTree', 'UOTreeSet', + 'union', 'intersection', 'difference', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IUnsignedObjectBTreeModule +from ._base import Bucket +from ._base import MERGE_WEIGHT_default +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_uint as _to_key +from ._base import to_ob as _to_value +from ._base import union as _union +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 60 +_TREE_SIZE = 500 +using64bits = False + + +class UOBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE_WEIGHT = MERGE_WEIGHT_default + + +class UOSetPy(Set): + _to_key = _to_key + + +class UOBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE_WEIGHT = MERGE_WEIGHT_default + + +class UOTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + +class UOTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +UOBucketPy._mapping_type = UOBucketPy._bucket_type = UOBucketPy +UOBucketPy._set_type = UOSetPy + +UOSetPy._mapping_type = UOBucketPy +UOSetPy._set_type = UOSetPy._bucket_type = UOSetPy + +UOBTreePy._mapping_type = UOBTreePy._bucket_type = UOBucketPy +UOBTreePy._set_type = UOSetPy + +UOTreeSetPy._mapping_type = UOBucketPy +UOTreeSetPy._set_type = UOTreeSetPy._bucket_type = UOSetPy + + +differencePy = _set_operation(_difference, UOSetPy) +unionPy = _set_operation(_union, UOSetPy) +intersectionPy = _set_operation(_intersection, UOSetPy) +multiunionPy = _set_operation(_multiunion, UOSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IUnsignedObjectBTreeModule) diff --git a/BTrees/UUBTree.py b/BTrees/UUBTree.py new file mode 100644 index 0000000..3c3a89d --- /dev/null +++ b/BTrees/UUBTree.py @@ -0,0 +1,113 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet', + 'UUBucket', 'UUSet', 'UUBTree', 'UUTreeSet', + 'union', 'intersection', 'difference', + 'weightedUnion', 'weightedIntersection', 'multiunion', + ) + +from zope.interface import moduleProvides + +from .Interfaces import IUnsignedUnsignedBTreeModule +from ._base import Bucket +from ._base import MERGE +from ._base import MERGE_WEIGHT_numeric +from ._base import MERGE_DEFAULT_int +from ._base import Set +from ._base import Tree as BTree +from ._base import TreeSet +from ._base import _TreeIterator +from ._base import difference as _difference +from ._base import intersection as _intersection +from ._base import multiunion as _multiunion +from ._base import set_operation as _set_operation +from ._base import to_uint as _to_key +_to_value = _to_key +from ._base import union as _union +from ._base import weightedIntersection as _weightedIntersection +from ._base import weightedUnion as _weightedUnion +from ._base import _fix_pickle +from ._compat import import_c_extension + +_BUCKET_SIZE = 120 +_TREE_SIZE = 500 +using64bits = False + + +class UUBucketPy(Bucket): + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class UUSetPy(Set): + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class UUBTreePy(BTree): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + _to_value = _to_value + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class UUTreeSetPy(TreeSet): + max_leaf_size = _BUCKET_SIZE + max_internal_size = _TREE_SIZE + _to_key = _to_key + MERGE = MERGE + MERGE_WEIGHT = MERGE_WEIGHT_numeric + MERGE_DEFAULT = MERGE_DEFAULT_int + + +class UUTreeIteratorPy(_TreeIterator): + pass + + +# Can't declare forward refs, so fix up afterwards: + +UUBucketPy._mapping_type = UUBucketPy._bucket_type = UUBucketPy +UUBucketPy._set_type = UUSetPy + +UUSetPy._mapping_type = UUBucketPy +UUSetPy._set_type = UUSetPy._bucket_type = UUSetPy + +UUBTreePy._mapping_type = UUBTreePy._bucket_type = UUBucketPy +UUBTreePy._set_type = UUSetPy + +UUTreeSetPy._mapping_type = UUBucketPy +UUTreeSetPy._set_type = UUTreeSetPy._bucket_type = UUSetPy + + +differencePy = _set_operation(_difference, UUSetPy) +unionPy = _set_operation(_union, UUSetPy) +intersectionPy = _set_operation(_intersection, UUSetPy) +multiunionPy = _set_operation(_multiunion, UUSetPy) +weightedUnionPy = _set_operation(_weightedUnion, UUSetPy) +weightedIntersectionPy = _set_operation(_weightedIntersection, UUSetPy) + +import_c_extension(globals()) + +_fix_pickle(globals(), __name__) + +moduleProvides(IUnsignedUnsignedBTreeModule) diff --git a/BTrees/_IUBTree.c b/BTrees/_IUBTree.c new file mode 100644 index 0000000..d375fa6 --- /dev/null +++ b/BTrees/_IUBTree.c @@ -0,0 +1,43 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id$\n" + +/* IIBTree - int32_t key, uint32_t value BTree + + Implements a collection using int type keys + and int type values +*/ + +/* Setup template macros */ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "IU" + +#define DEFAULT_MAX_BUCKET_SIZE 120 +#define DEFAULT_MAX_BTREE_SIZE 500 + +#define ZODB_UNSIGNED_VALUE_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "intvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__IUBTree +#else +#define INITMODULE init_IUBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_LQBTree.c b/BTrees/_LQBTree.c new file mode 100644 index 0000000..d10c458 --- /dev/null +++ b/BTrees/_LQBTree.c @@ -0,0 +1,44 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id: _IIBTree.c 25186 2004-06-02 15:07:33Z jim $\n" + +/* IIBTree - int64_t key, uint64_t value BTree + + Implements a collection using int type keys + and int type values +*/ + +/* Setup template macros */ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "LQ" + +#define DEFAULT_MAX_BUCKET_SIZE 120 +#define DEFAULT_MAX_BTREE_SIZE 500 + +#define ZODB_64BIT_INTS +#define ZODB_UNSIGNED_VALUE_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "intvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__LQBTree +#else +#define INITMODULE init_LQBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_OQBTree.c b/BTrees/_OQBTree.c new file mode 100644 index 0000000..931c966 --- /dev/null +++ b/BTrees/_OQBTree.c @@ -0,0 +1,42 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id: _OIBTree.c 25186 2004-06-02 15:07:33Z jim $\n" + +/* OQBTree - object key, uint64_t value BTree + + Implements a collection using object type keys + and int type values +*/ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "OQ" + +#define DEFAULT_MAX_BUCKET_SIZE 60 +#define DEFAULT_MAX_BTREE_SIZE 250 + +#define ZODB_64BIT_INTS +#define ZODB_UNSIGNED_VALUE_INTS + +#include "_compat.h" +#include "objectkeymacros.h" +#include "intvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__OQBTree +#else +#define INITMODULE init_OQBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_OUBTree.c b/BTrees/_OUBTree.c new file mode 100644 index 0000000..d51d5d2 --- /dev/null +++ b/BTrees/_OUBTree.c @@ -0,0 +1,41 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id$\n" + +/* OUBTree - object key, uint32_t value BTree + + Implements a collection using object type keys + and int type values +*/ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "OU" + +#define DEFAULT_MAX_BUCKET_SIZE 60 +#define DEFAULT_MAX_BTREE_SIZE 250 + +#define ZODB_UNSIGNED_VALUE_INTS + +#include "_compat.h" +#include "objectkeymacros.h" +#include "intvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__OUBTree +#else +#define INITMODULE init_OUBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_QFBTree.c b/BTrees/_QFBTree.c new file mode 100644 index 0000000..445519f --- /dev/null +++ b/BTrees/_QFBTree.c @@ -0,0 +1,44 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id: _IFBTree.c 67074 2006-04-17 19:13:39Z fdrake $\n" + +/* QFBTree - uint64_t key, float value BTree + + Implements a collection using int type keys + and float type values +*/ + +/* Setup template macros */ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "QF" + +#define DEFAULT_MAX_BUCKET_SIZE 120 +#define DEFAULT_MAX_BTREE_SIZE 500 + +#define ZODB_64BIT_INTS +#define ZODB_UNSIGNED_KEY_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "floatvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__QFBTree +#else +#define INITMODULE init_QFBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_QLBTree.c b/BTrees/_QLBTree.c new file mode 100644 index 0000000..ea6b983 --- /dev/null +++ b/BTrees/_QLBTree.c @@ -0,0 +1,44 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id: _IIBTree.c 25186 2004-06-02 15:07:33Z jim $\n" + +/* QLBTree - uint64_t key, int64_t value BTree + + Implements a collection using int type keys + and int type values +*/ + +/* Setup template macros */ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "QL" + +#define DEFAULT_MAX_BUCKET_SIZE 120 +#define DEFAULT_MAX_BTREE_SIZE 500 + +#define ZODB_64BIT_INTS +#define ZODB_UNSIGNED_KEY_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "intvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__QLBTree +#else +#define INITMODULE init_QLBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_QOBTree.c b/BTrees/_QOBTree.c new file mode 100644 index 0000000..feae077 --- /dev/null +++ b/BTrees/_QOBTree.c @@ -0,0 +1,42 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id: _IOBTree.c 25186 2004-06-02 15:07:33Z jim $\n" + +/* QOBTree - uint64_t key, object value BTree + + Implements a collection using int type keys + and object type values +*/ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "QO" + +#define DEFAULT_MAX_BUCKET_SIZE 60 +#define DEFAULT_MAX_BTREE_SIZE 500 + +#define ZODB_64BIT_INTS +#define ZODB_UNSIGNED_KEY_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "objectvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__QOBTree +#else +#define INITMODULE init_QOBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_QQBTree.c b/BTrees/_QQBTree.c new file mode 100644 index 0000000..5ee9a46 --- /dev/null +++ b/BTrees/_QQBTree.c @@ -0,0 +1,45 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id: _IIBTree.c 25186 2004-06-02 15:07:33Z jim $\n" + +/* QQBTree - uint64_t key, uint64_t value BTree + + Implements a collection using int type keys + and int type values +*/ + +/* Setup template macros */ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "QQ" + +#define DEFAULT_MAX_BUCKET_SIZE 120 +#define DEFAULT_MAX_BTREE_SIZE 500 + +#define ZODB_64BIT_INTS +#define ZODB_UNSIGNED_KEY_INTS +#define ZODB_UNSIGNED_VALUE_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "intvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__QQBTree +#else +#define INITMODULE init_QQBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_UFBTree.c b/BTrees/_UFBTree.c new file mode 100644 index 0000000..ed74ac5 --- /dev/null +++ b/BTrees/_UFBTree.c @@ -0,0 +1,42 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id$\n" + +/* IFBTree - unsigned int key, float value BTree + + Implements a collection using int type keys + and float type values +*/ + +/* Setup template macros */ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "UF" + +#define DEFAULT_MAX_BUCKET_SIZE 120 +#define DEFAULT_MAX_BTREE_SIZE 500 +#define ZODB_UNSIGNED_KEY_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "floatvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__UFBTree +#else +#define INITMODULE init_UFBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_UIBTree.c b/BTrees/_UIBTree.c new file mode 100644 index 0000000..1f99968 --- /dev/null +++ b/BTrees/_UIBTree.c @@ -0,0 +1,42 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id$\n" + +/* IIBTree - unsigned int key, int value BTree + + Implements a collection using int type keys + and int type values +*/ + +/* Setup template macros */ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "UI" + +#define DEFAULT_MAX_BUCKET_SIZE 120 +#define DEFAULT_MAX_BTREE_SIZE 500 +#define ZODB_UNSIGNED_KEY_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "intvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__UIBTree +#else +#define INITMODULE init_UIBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_UOBTree.c b/BTrees/_UOBTree.c new file mode 100644 index 0000000..6eafa50 --- /dev/null +++ b/BTrees/_UOBTree.c @@ -0,0 +1,39 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id$\n" + +/* UOBTree - unsigned int key, object value BTree + + Implements a collection using unsigned int type keys + and object type values +*/ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "UO" + +#define DEFAULT_MAX_BUCKET_SIZE 60 +#define DEFAULT_MAX_BTREE_SIZE 500 +#define ZODB_UNSIGNED_KEY_INTS +#include "_compat.h" +#include "intkeymacros.h" +#include "objectvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__UOBTree +#else +#define INITMODULE init_UOBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/_UUBTree.c b/BTrees/_UUBTree.c new file mode 100644 index 0000000..b675a3e --- /dev/null +++ b/BTrees/_UUBTree.c @@ -0,0 +1,43 @@ +/*############################################################################ +# +# Copyright (c) 2004 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################*/ + +#define MASTER_ID "$Id$\n" + +/* IIBTree - unsigned int key, unsigned int value BTree + + Implements a collection using int type keys + and int type values +*/ + +/* Setup template macros */ + +#define PERSISTENT + +#define MOD_NAME_PREFIX "UU" + +#define DEFAULT_MAX_BUCKET_SIZE 120 +#define DEFAULT_MAX_BTREE_SIZE 500 +#define ZODB_UNSIGNED_KEY_INTS +#define ZODB_UNSIGNED_VALUE_INTS + +#include "_compat.h" +#include "intkeymacros.h" +#include "intvaluemacros.h" + +#ifdef PY3K +#define INITMODULE PyInit__UUBTree +#else +#define INITMODULE init_UUBTree +#endif +#include "BTreeModuleTemplate.c" diff --git a/BTrees/__init__.py b/BTrees/__init__.py index ab65d67..16052be 100644 --- a/BTrees/__init__.py +++ b/BTrees/__init__.py @@ -18,15 +18,38 @@ @zope.interface.implementer(BTrees.Interfaces.IBTreeFamily) class _Family(object): - from BTrees import OOBTree as OO + _BITSIZE = 0 + minint = maxint = maxuint = 0 + + def __str__(self): + return ( + "BTree family using {} bits. " + "Supports signed integer values from {:,} to {:,} " + "and maximum unsigned integer value {:,}." + ).format(self._BITSIZE, self.minint, self.maxint, self.maxuint) + + def __repr__(self): + return "<%s>" % ( + self + ) class _Family32(_Family): + _BITSIZE = 32 from BTrees import OIBTree as OI + from BTrees import OUBTree as OU + + from BTrees import IFBTree as IF from BTrees import IIBTree as II from BTrees import IOBTree as IO - from BTrees import IFBTree as IF + from BTrees import IUBTree as IU + from BTrees import UFBTree as UF + from BTrees import UIBTree as UI + from BTrees import UOBTree as UO + from BTrees import UUBTree as UU + + maxuint = int(2**32) maxint = int(2**31-1) minint = -maxint - 1 @@ -34,11 +57,21 @@ def __reduce__(self): return _family32, () class _Family64(_Family): + _BITSIZE = 64 from BTrees import OLBTree as OI + from BTrees import OQBTree as OU + + from BTrees import LFBTree as IF from BTrees import LLBTree as II from BTrees import LOBTree as IO - from BTrees import LFBTree as IF + from BTrees import LQBTree as IU + from BTrees import QFBTree as UF + from BTrees import QLBTree as UI + from BTrees import QOBTree as UO + from BTrees import QQBTree as UU + + maxuint = 2**64 maxint = 2**63-1 minint = -maxint - 1 @@ -53,17 +86,16 @@ def _family64(): return family64 _family64.__safe_for_unpickling__ = True - +#: 32-bit BTree family. family32 = _Family32() -family64 = _Family64() - -BTrees.family64.IO.family = family64 -BTrees.family64.OI.family = family64 -BTrees.family64.IF.family = family64 -BTrees.family64.II.family = family64 +#: 64-bit BTree family. +family64 = _Family64() -BTrees.family32.IO.family = family32 -BTrees.family32.OI.family = family32 -BTrees.family32.IF.family = family32 -BTrees.family32.II.family = family32 +for _family in family32, family64: + for _mod_name in ( + "OI", "OU", + 'IO', "II", "IF", "IU", + "UO", "UU", "UF", "UI", + ): + getattr(_family, _mod_name).family = _family diff --git a/BTrees/_base.py b/BTrees/_base.py index fdc7447..6df3b76 100644 --- a/BTrees/_base.py +++ b/BTrees/_base.py @@ -1509,6 +1509,20 @@ def to_int(self, v): return int(v) +# PyPy can raise ValueError converting a negative number to a +# unsigned value. +uint_pack, uint_unpack = _packer_unpacker('I') + +def to_uint(self, v): + try: + uint_pack(index(v)) + except (struct_error, TypeError, ValueError): + if isinstance(v, int_types): + raise OverflowError("Value out of range", v) + raise TypeError('non-negative 32-bit integer expected') + + return int(v) + float_pack = _packer_unpacker('f')[0] def to_float(self, v): @@ -1526,11 +1540,24 @@ def to_long(self, v): long_pack(index(v)) except (struct_error, TypeError): if isinstance(v, int_types): - raise ValueError("Value out of range", v) + raise OverflowError("Value out of range", v) raise TypeError('64-bit integer expected') return int(v) +ulong_pack, ulong_unpack = _packer_unpacker('Q') + +def to_ulong(self, v): + try: + ulong_pack(index(v)) + except (struct_error, TypeError, ValueError): + if isinstance(v, int_types): + raise OverflowError("Value out of range", v) + raise TypeError('non-negative 64-bit integer expected') + + return int(v) + + def to_bytes(l): def to(self, v): if not (isinstance(v, bytes) and len(v) == l): @@ -1538,7 +1565,7 @@ def to(self, v): return v return to -tos = dict(I=to_int, L=to_long, F=to_float, O=to_ob) +tos = dict(I=to_int, L=to_long, F=to_float, O=to_ob, U=to_uint, Q=to_ulong) MERGE_DEFAULT_int = 1 MERGE_DEFAULT_float = 1.0 diff --git a/BTrees/_compat.h b/BTrees/_compat.h index 9454da2..dd4e03d 100644 --- a/BTrees/_compat.h +++ b/BTrees/_compat.h @@ -23,7 +23,15 @@ #define INTERN PyUnicode_InternFromString #define INT_FROM_LONG(x) PyLong_FromLong(x) #define INT_CHECK(x) PyLong_Check(x) +/* PyLong_AS_LONG isn't a documnted API function. But because of + * an issue in persistent/_compat.h, if we define it to be + * the documented function, PyLong_AsLong, we get + * warnings about macro redefinition. See + * https://github.com/zopefoundation/persistent/issues/125 +*/ #define INT_AS_LONG(x) PyLong_AS_LONG(x) +#define UINT_FROM_LONG(x) PyLong_FromUnsignedLong(x) +#define UINT_AS_LONG(x) PyLong_AsUnsignedLong(x) #define TEXT_FROM_STRING PyUnicode_FromString #define TEXT_FORMAT PyUnicode_Format @@ -43,6 +51,8 @@ #define INT_FROM_LONG(x) PyInt_FromLong(x) #define INT_CHECK(x) PyInt_Check(x) #define INT_AS_LONG(x) PyInt_AS_LONG(x) +#define UINT_FROM_LONG(x) PyInt_FromSize_t(x) +#define UINT_AS_LONG(x) PyInt_AsUnsignedLongMask(x) #define TEXT_FROM_STRING PyString_FromString #define TEXT_FORMAT PyString_Format diff --git a/BTrees/check.py b/BTrees/check.py index 068bd93..6503762 100644 --- a/BTrees/check.py +++ b/BTrees/check.py @@ -32,24 +32,57 @@ that doesn't exist in the actual BTree). """ +# 32-bit signed int from BTrees.IFBTree import IFBTree, IFBucket, IFSet, IFTreeSet from BTrees.IFBTree import IFBTreePy, IFBucketPy, IFSetPy, IFTreeSetPy from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet from BTrees.IIBTree import IIBTreePy, IIBucketPy, IISetPy, IITreeSetPy from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet from BTrees.IOBTree import IOBTreePy, IOBucketPy, IOSetPy, IOTreeSetPy +from BTrees.IUBTree import IUBTree, IUBucket, IUSet, IUTreeSet +from BTrees.IUBTree import IUBTreePy, IUBucketPy, IUSetPy, IUTreeSetPy + +# 32-bit unsigned int +from BTrees.UFBTree import UFBTree, UFBucket, UFSet, UFTreeSet +from BTrees.UFBTree import UFBTreePy, UFBucketPy, UFSetPy, UFTreeSetPy +from BTrees.UIBTree import UIBTree, UIBucket, UISet, UITreeSet +from BTrees.UIBTree import UIBTreePy, UIBucketPy, UISetPy, UITreeSetPy +from BTrees.UOBTree import UOBTree, UOBucket, UOSet, UOTreeSet +from BTrees.UOBTree import UOBTreePy, UOBucketPy, UOSetPy, UOTreeSetPy +from BTrees.UUBTree import UUBTree, UUBucket, UUSet, UUTreeSet +from BTrees.UUBTree import UUBTreePy, UUBucketPy, UUSetPy, UUTreeSetPy + +# 64-bit signed int from BTrees.LFBTree import LFBTree, LFBucket, LFSet, LFTreeSet from BTrees.LFBTree import LFBTreePy, LFBucketPy, LFSetPy, LFTreeSetPy from BTrees.LLBTree import LLBTree, LLBucket, LLSet, LLTreeSet from BTrees.LLBTree import LLBTreePy, LLBucketPy, LLSetPy, LLTreeSetPy from BTrees.LOBTree import LOBTree, LOBucket, LOSet, LOTreeSet from BTrees.LOBTree import LOBTreePy, LOBucketPy, LOSetPy, LOTreeSetPy +from BTrees.LQBTree import LQBTree, LQBucket, LQSet, LQTreeSet +from BTrees.LQBTree import LQBTreePy, LQBucketPy, LQSetPy, LQTreeSetPy + +# 64-bit unsigned int +from BTrees.QFBTree import QFBTree, QFBucket, QFSet, QFTreeSet +from BTrees.QFBTree import QFBTreePy, QFBucketPy, QFSetPy, QFTreeSetPy +from BTrees.QLBTree import QLBTree, QLBucket, QLSet, QLTreeSet +from BTrees.QLBTree import QLBTreePy, QLBucketPy, QLSetPy, QLTreeSetPy +from BTrees.QOBTree import QOBTree, QOBucket, QOSet, QOTreeSet +from BTrees.QOBTree import QOBTreePy, QOBucketPy, QOSetPy, QOTreeSetPy +from BTrees.QQBTree import QQBTree, QQBucket, QQSet, QQTreeSet +from BTrees.QQBTree import QQBTreePy, QQBucketPy, QQSetPy, QQTreeSetPy + + from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet from BTrees.OIBTree import OIBTreePy, OIBucketPy, OISetPy, OITreeSetPy from BTrees.OLBTree import OLBTree, OLBucket, OLSet, OLTreeSet from BTrees.OLBTree import OLBTreePy, OLBucketPy, OLSetPy, OLTreeSetPy from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet from BTrees.OOBTree import OOBTreePy, OOBucketPy, OOSetPy, OOTreeSetPy +from BTrees.OUBTree import OUBTree, OUBucket, OUSet, OUTreeSet +from BTrees.OUBTree import OUBTreePy, OUBucketPy, OUSetPy, OUTreeSetPy +from BTrees.OQBTree import OQBTree, OQBucket, OQSet, OQTreeSet +from BTrees.OQBTree import OQBTreePy, OQBucketPy, OQSetPy, OQTreeSetPy from BTrees.utils import positive_id from BTrees.utils import oid_repr @@ -59,17 +92,22 @@ from ._compat import compare _type2kind = {} -for kv in ('OO', - 'II', 'IO', 'OI', 'IF', - 'LL', 'LO', 'OL', 'LF', - ): +_FAMILIES = ( + 'OO', 'OI', 'OU', 'OL', 'OQ', + 'II', 'IO', 'IF', 'IU', + 'LL', 'LO', 'LF', 'LQ', + 'UU', 'UO', 'UF', 'UI', + 'QQ', 'QO', 'QF', 'QL', + # Note that fs is missing from this list. +) +for kv in _FAMILIES: for name, kind in ( - ('BTree', (TYPE_BTREE, True)), - ('Bucket', (TYPE_BUCKET, True)), - ('TreeSet', (TYPE_BTREE, False)), - ('Set', (TYPE_BUCKET, False)), - ): - _type2kind[globals()[kv+name]] = kind + ('BTree', (TYPE_BTREE, True)), + ('Bucket', (TYPE_BUCKET, True)), + ('TreeSet', (TYPE_BTREE, False)), + ('Set', (TYPE_BUCKET, False)), + ): + _type2kind[globals()[kv + name]] = kind py = kv + name + 'Py' _type2kind[globals()[py]] = kind @@ -122,10 +160,7 @@ def classify(obj): # ) _btree2bucket = {} -for kv in ('OO', - 'II', 'IO', 'OI', 'IF', - 'LL', 'LO', 'OL', 'LF', - ): +for kv in _FAMILIES: _btree2bucket[globals()[kv+'BTree']] = globals()[kv+'Bucket'] py = kv + 'BTreePy' _btree2bucket[globals()[py]] = globals()[kv+'BucketPy'] diff --git a/BTrees/intkeymacros.h b/BTrees/intkeymacros.h index f9244b5..3af0f69 100644 --- a/BTrees/intkeymacros.h +++ b/BTrees/intkeymacros.h @@ -1,6 +1,8 @@ #define KEYMACROS_H "$Id$\n" +#ifndef ZODB_UNSIGNED_KEY_INTS +/* signed keys */ #ifdef ZODB_64BIT_INTS /* PY_LONG_LONG as key */ #define NEED_LONG_LONG_SUPPORT @@ -12,7 +14,7 @@ if (!longlong_convert((ARG), &TARGET)) \ { \ (STATUS)=0; (TARGET)=0; \ - } + } #else /* C int as key */ #define KEY_TYPE int @@ -31,6 +33,43 @@ PyErr_SetString(PyExc_TypeError, "expected integer key"); \ (STATUS)=0; (TARGET)=0; } #endif +#else +/* Unsigned keys */ +#ifdef ZODB_64BIT_INTS +/* PY_LONG_LONG as key */ +#define NEED_LONG_LONG_SUPPORT +#define NEED_LONG_LONG_KEYS +#define KEY_TYPE unsigned PY_LONG_LONG +#define KEY_CHECK ulonglong_check +#define COPY_KEY_TO_OBJECT(O, K) O=ulonglong_as_object(K) +#define COPY_KEY_FROM_ARG(TARGET, ARG, STATUS) \ + if (!ulonglong_convert((ARG), &TARGET)) \ + { \ + (STATUS)=0; (TARGET)=0; \ + } +#else +/* C int as key */ +#define KEY_TYPE unsigned int +#define KEY_CHECK INT_CHECK +#define COPY_KEY_TO_OBJECT(O, K) O=UINT_FROM_LONG(K) +#define COPY_KEY_FROM_ARG(TARGET, ARG, STATUS) \ + if (INT_CHECK(ARG)) { \ + long vcopy = INT_AS_LONG(ARG); \ + if (PyErr_Occurred()) { (STATUS)=0; (TARGET)=0; } \ + else if (vcopy < 0) { \ + PyErr_SetString(PyExc_OverflowError, "can't convert negative value to unsigned int"); \ + (STATUS)=0; (TARGET)=0; \ + } \ + else if ((unsigned int)vcopy != vcopy) { \ + PyErr_SetString(PyExc_TypeError, "integer out of range"); \ + (STATUS)=0; (TARGET)=0; \ + } \ + else TARGET = vcopy; \ + } else { \ + PyErr_SetString(PyExc_TypeError, "expected integer key"); \ + (STATUS)=0; (TARGET)=0; } +#endif +#endif /* ZODB_SIGNED_KEY_INTS */ #undef KEY_TYPE_IS_PYOBJECT #define TEST_KEY_SET_OR(V, K, T) if ( ( (V) = (((K) < (T)) ? -1 : (((K) > (T)) ? 1: 0)) ) , 0 ) diff --git a/BTrees/intvaluemacros.h b/BTrees/intvaluemacros.h index 0253bf6..2f0dfbe 100644 --- a/BTrees/intvaluemacros.h +++ b/BTrees/intvaluemacros.h @@ -1,6 +1,16 @@ #define VALUEMACROS_H "$Id$\n" +/* + VALUE_PARSE is used exclusively in SetOpTemplate.c to accept the weight + values for merging. The PyArg_ParseTuple function it uses has no trivial way + to express "unsigned with check", so in the unsigned case, passing negative + values as weights will produce weird output no matter what VALUE_PARSE we + use (because it will immediately get cast to an unsigned). +*/ + +#ifndef ZODB_UNSIGNED_VALUE_INTS +/*signed values */ #ifdef ZODB_64BIT_INTS #define NEED_LONG_LONG_SUPPORT #define VALUE_TYPE PY_LONG_LONG @@ -10,7 +20,7 @@ if (!longlong_convert((ARG), &TARGET)) \ { \ (STATUS)=0; (TARGET)=0; \ - } + } #else #define VALUE_TYPE int #define VALUE_PARSE "i" @@ -30,9 +40,47 @@ (STATUS)=0; (TARGET)=0; } #endif +#else +/* unsigned values */ +#ifdef ZODB_64BIT_INTS +/* unsigned, 64-bit values */ +#define NEED_LONG_LONG_SUPPORT +#define VALUE_TYPE unsigned PY_LONG_LONG +#define VALUE_PARSE "K" +#define COPY_VALUE_TO_OBJECT(O, K) O=ulonglong_as_object(K) +#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \ + if (!ulonglong_convert((ARG), &TARGET)) \ + { \ + (STATUS)=0; (TARGET)=0; \ + } +#else +/* unsigned, 32-bit values */ +#define VALUE_TYPE unsigned int +#define VALUE_PARSE "I" +#define COPY_VALUE_TO_OBJECT(O, K) O=UINT_FROM_LONG(K) + +#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \ + if (INT_CHECK(ARG)) { \ + long vcopy = INT_AS_LONG(ARG); \ + if (PyErr_Occurred()) { (STATUS)=0; (TARGET)=0; } \ + else if (vcopy < 0) { \ + PyErr_SetString(PyExc_OverflowError, "can't convert negative value to unsigned int"); \ + (STATUS)=0; (TARGET)=0; \ + } \ + else if ((unsigned int)vcopy != vcopy) { \ + PyErr_SetString(PyExc_TypeError, "integer out of range"); \ + (STATUS)=0; (TARGET)=0; \ + } \ + else TARGET = vcopy; \ + } else { \ + PyErr_SetString(PyExc_TypeError, "expected integer key"); \ + (STATUS)=0; (TARGET)=0; } + +#endif +#endif #undef VALUE_TYPE_IS_PYOBJECT -#define TEST_VALUE(K, T) (((K) < (T)) ? -1 : (((K) > (T)) ? 1: 0)) +#define TEST_VALUE(K, T) (((K) < (T)) ? -1 : (((K) > (T)) ? 1: 0)) #define VALUE_SAME(VALUE, TARGET) ( (VALUE) == (TARGET) ) #define DECLARE_VALUE(NAME) VALUE_TYPE NAME #define DECREF_VALUE(k) diff --git a/BTrees/tests/common.py b/BTrees/tests/common.py index 7d9755d..8aacbb3 100644 --- a/BTrees/tests/common.py +++ b/BTrees/tests/common.py @@ -56,7 +56,52 @@ def _skip_if_pure_py_and_py_test(self): # one normal/C and one with Py in the name for the Py test. raise unittest.SkipTest("Redundant with the C test") -class Base(object): +# pylint:disable=too-many-lines +# pylint:disable=no-member,protected-access,unused-variable,import-error +# pylint:disable=line-too-long,unidiomatic-typecheck,abstract-method +# pylint:disable=redefined-builtin + +#: The exceptions that can be raised by failed +#: unsigned conversions. The OverflowError is raised +#: by the interpreter and is nicer than the manual error. +UnsignedError = (TypeError, OverflowError) + +def uses_negative_keys_and_values(func): + """ + Apply this decorator to tests that use negative keys and values. + + If the underlying mapping doesn't support that, it will + be expected to raise a TypeError or OverflowError. + """ + @functools.wraps(func) + def test(self): + if not (self.SUPPORTS_NEGATIVE_KEYS and self.SUPPORTS_NEGATIVE_VALUES): + with self.assertRaises(UnsignedError): + func(self) + else: + func(self) + return test + +class SignedMixin(object): + SUPPORTS_NEGATIVE_KEYS = True + SUPPORTS_NEGATIVE_VALUES = True + #: The values to pass to ``random.randrange()`` to generate + #: valid keys. + KEY_RANDRANGE_ARGS = (-2000, 2001) + + +class UnsignedMixin(object): + SUPPORTS_NEGATIVE_KEYS = False + SUPPORTS_NEGATIVE_VALUES = False + KEY_RANDRANGE_ARGS = (0, 4002) + +class UnsignedValuesMixin(SignedMixin): + SUPPORTS_NEGATIVE_VALUES = False + +class UnsignedKeysMixin(UnsignedMixin): + SUPPORTS_NEGATIVE_VALUES = True + +class Base(SignedMixin): # Tests common to all types: sets, buckets, and BTrees db = None @@ -141,9 +186,9 @@ def testLoadAndStore(self): root2 = self._getRoot() if hasattr(t, 'items'): - self.assertEqual(list(root2[i].items()) , list(t.items())) + self.assertEqual(list(root2[i].items()), list(t.items())) else: - self.assertEqual(list(root2[i].keys()) , list(t.keys())) + self.assertEqual(list(root2[i].keys()), list(t.keys())) self._closeRoot(root) self._closeRoot(root2) @@ -170,9 +215,9 @@ def testGhostUnghost(self): root2[i]._p_deactivate() transaction.commit() if hasattr(t, 'items'): - self.assertEqual(list(root2[i].items()) , list(t.items())) + self.assertEqual(list(root2[i].items()), list(t.items())) else: - self.assertEqual(list(root2[i].keys()) , list(t.keys())) + self.assertEqual(list(root2[i].keys()), list(t.keys())) self._closeRoot(root) self._closeRoot(root2) @@ -204,12 +249,16 @@ def testSimpleExclusiveKeyRange(self): self.assertEqual(list(t.keys(excludemax=True)), [0, 1]) self.assertEqual(list(t.keys(excludemin=True, excludemax=True)), [1]) - self.assertEqual(list(t.keys(-1, 3, excludemin=True, excludemax=True)), - [0, 1, 2]) + for low, high, expected in ((-1, 3, [0, 1, 2]), (-1, 2, [0, 1])): + if self.SUPPORTS_NEGATIVE_KEYS: + self.assertEqual(list(t.keys(low, high, excludemin=True, excludemax=True)), + expected) + else: + with self.assertRaises(UnsignedError): + t.keys(low, high, excludemin=True, excludemax=True) + self.assertEqual(list(t.keys(0, 3, excludemin=True, excludemax=True)), [1, 2]) - self.assertEqual(list(t.keys(-1, 2, excludemin=True, excludemax=True)), - [0, 1]) self.assertEqual(list(t.keys(0, 2, excludemin=True, excludemax=True)), [1]) @@ -354,11 +403,12 @@ class NonSub(object): class MappingBase(Base): # Tests common to mappings (buckets, btrees) + SUPPORTS_NEGATIVE_VALUES = True def _populate(self, t, l): # Make some data for i in range(l): - t[i]=i + t[i] = i def testShortRepr(self): # test the repr because buckets have a complex repr implementation @@ -407,21 +457,21 @@ def _getitemfail(self): return self._makeOne()[1] def testGetReturnsDefault(self): - self.assertEqual(self._makeOne().get(1) , None) - self.assertEqual(self._makeOne().get(1, 'foo') , 'foo') + self.assertEqual(self._makeOne().get(1), None) + self.assertEqual(self._makeOne().get(1, 'foo'), 'foo') def testSetItemGetItemWorks(self): t = self._makeOne() t[1] = 1 a = t[1] - self.assertEqual(a , 1, repr(a)) + self.assertEqual(a, 1, repr(a)) def testReplaceWorks(self): t = self._makeOne() t[1] = 1 - self.assertEqual(t[1] , 1, t[1]) + self.assertEqual(t[1], 1, t[1]) t[1] = 2 - self.assertEqual(t[1] , 2, t[1]) + self.assertEqual(t[1], 2, t[1]) def testLen(self): import random @@ -433,7 +483,7 @@ def testLen(self): t[k] = x added[k] = x addl = added.keys() - self.assertEqual(len(t) , len(addl), len(t)) + self.assertEqual(len(t), len(addl), len(t)) def testHasKeyWorks(self): from .._compat import PY2 @@ -464,12 +514,13 @@ def testValuesWorks1(self): t[99-x] = x for x in range(40): - lst = sorted(t.values(0+x,99-x)) - self.assertEqual(lst, list(range(0+x,99-x+1))) + lst = sorted(t.values(0 + x, 99 - x)) + self.assertEqual(lst, list(range(0 + x, 99 - x + 1))) - lst = sorted(t.values(max=99-x, min=0+x)) - self.assertEqual(lst, list(range(0+x,99-x+1))) + lst = sorted(t.values(max=99 - x, min=0 + x)) + self.assertEqual(lst, list(range(0 + x, 99 - x + 1))) + @uses_negative_keys_and_values def testValuesNegativeIndex(self): t = self._makeOne() L = [-3, 6, -11, 4] @@ -488,19 +539,20 @@ def testKeysWorks(self): v = t.keys() i = 0 for x in v: - self.assertEqual(x,i) + self.assertEqual(x, i) i = i + 1 self.assertRaises(IndexError, lambda: v[i]) for x in range(40): - lst = t.keys(0+x,99-x) - self.assertEqual(list(lst), list(range(0+x, 99-x+1))) + lst = t.keys(0 + x, 99 - x) + self.assertEqual(list(lst), list(range(0 + x, 99 - x + 1))) lst = t.keys(max=99-x, min=0+x) self.assertEqual(list(lst), list(range(0+x, 99-x+1))) self.assertEqual(len(v), 100) + @uses_negative_keys_and_values def testKeysNegativeIndex(self): t = self._makeOne() L = [-3, 6, -11, 4] @@ -536,6 +588,8 @@ def testItemsWorks(self): self.assertEqual(items, list(zip(range(12, 21), range(24, 43, 2)))) def testItemsNegativeIndex(self): + if not (self.SUPPORTS_NEGATIVE_KEYS and self.SUPPORTS_NEGATIVE_VALUES): + self.skipTest("Needs negative keys and values") t = self._makeOne() L = [-3, 6, -11, 4] for i in L: @@ -601,14 +655,14 @@ def testClear(self): def testUpdate(self): import random t = self._makeOne() - d={} - l=[] + d = {} + l = [] for i in range(10000): - k=random.randrange(-2000, 2001) - d[k]=i + k = random.randrange(*self.KEY_RANDRANGE_ARGS) + d[k] = i l.append((k, i)) - items= sorted(d.items()) + items = sorted(d.items()) t.update(d) self.assertEqual(list(t.items()), items) @@ -633,12 +687,14 @@ def testUpdateFromPersistentMapping(self): def testEmptyRangeSearches(self): t = self._makeOne() - t.update([(1,1), (5,5), (9,9)]) - self.assertEqual(list(t.keys(-6,-4)), [], list(t.keys(-6,-4))) - self.assertEqual(list(t.keys(2,4)), [], list(t.keys(2,4))) - self.assertEqual(list(t.keys(6,8)), [], list(t.keys(6,8))) - self.assertEqual(list(t.keys(10,12)), [], list(t.keys(10,12))) - self.assertEqual(list(t.keys(9, 1)), [], list(t.keys(9, 1))) + t.update([(1, 1), (5, 5), (9, 9)]) + if self.SUPPORTS_NEGATIVE_KEYS: + self.assertEqual(list(t.keys(-6, -4)), []) + + self.assertEqual(list(t.keys(2, 4)), []) + self.assertEqual(list(t.keys(6, 8)), []) + self.assertEqual(list(t.keys(10, 12)), []) + self.assertEqual(list(t.keys(9, 1)), []) # For IITreeSets, this one was returning 31 for len(keys), and # list(keys) produced a list with 100 elements. @@ -662,6 +718,7 @@ def testSlicing(self): # "BTreeItems slice contains 1 too many elements". from .._compat import xrange t = self._makeOne() + val_multiplier = -2 if self.SUPPORTS_NEGATIVE_VALUES else 2 for n in range(10): t.clear() self.assertEqual(len(t), 0) @@ -669,8 +726,9 @@ def testSlicing(self): keys = [] values = [] items = [] + for key in range(n): - value = -2 * key + value = key * val_multiplier t[key] = value keys.append(key) values.append(value) @@ -730,13 +788,15 @@ def testSlicing(self): self.assertEqual(len(tslice), 60) self.assertEqual(list(tslice), list(zip(range(20, 80), [1]*60))) + @uses_negative_keys_and_values def testIterators(self): t = self._makeOne() for keys in [], [-2], [1, 4], list(range(-170, 2000, 6)): t.clear() for k in keys: - t[k] = -3 * k + val = -3 * k + t[k] = val self.assertEqual(list(t), keys) @@ -759,6 +819,7 @@ def testIterators(self): self.assertEqual(list(t.itervalues()), list(t.values())) self.assertEqual(list(t.iteritems()), list(t.items())) + @uses_negative_keys_and_values def testRangedIterators(self): t = self._makeOne() @@ -838,6 +899,10 @@ def dup(x): if meth is None: continue + __traceback_info__ = meth + + supports_negative = self.SUPPORTS_NEGATIVE_KEYS + self.assertEqual(list(meth()), []) self.assertEqual(list(meth(excludemin=True)), []) self.assertEqual(list(meth(excludemax=True)), []) @@ -862,16 +927,19 @@ def dup(x): self.assertEqual(list(meth(excludemin=True)), f([1, 2])) self.assertEqual(list(meth(excludemax=True)), f([0, 1])) self.assertEqual(list(meth(excludemin=True, excludemax=True)), - f([1])) - self.assertEqual(list(meth(-1, 3, excludemin=True, - excludemax=True)), - f([0, 1, 2])) + f([1])) + if supports_negative: + self.assertEqual(list(meth(-1, 2, excludemin=True, + excludemax=True)), + f([0, 1])) + + self.assertEqual(list(meth(-1, 3, excludemin=True, + excludemax=True)), + f([0, 1, 2])) + self.assertEqual(list(meth(0, 3, excludemin=True, excludemax=True)), f([1, 2])) - self.assertEqual(list(meth(-1, 2, excludemin=True, - excludemax=True)), - f([0, 1])) self.assertEqual(list(meth(0, 2, excludemin=True, excludemax=True)), f([1])) @@ -930,6 +998,16 @@ def testPop(self): # Too many arguments. self.assertRaises(TypeError, t.pop, 1, 2, 3) +class UnsignedMappingBase(UnsignedMixin, MappingBase): + pass + +class UnsignedValuesMappingBase(UnsignedValuesMixin, MappingBase): + pass + +class UnsignedKeysMappingBase(UnsignedKeysMixin, MappingBase): + pass + + class BTreeTests(MappingBase): # Tests common to all BTrees @@ -943,7 +1021,7 @@ def _getTargetClass(self): return type(self._makeOne()) raise NotImplementedError() - def _makeOne(self, *args): + def _makeOne(self, *args): # pylint:disable=arguments-differ return self._getTargetClass()(*args) def _checkIt(self, t): @@ -961,8 +1039,8 @@ def testDeleteNoChildrenWorks(self): t[10] = 500 t[4] = 99 del t[4] - diff = lsubtract(t.keys(), [1,2,3,5,6,10]) - self.assertEqual(diff , [], diff) + diff = lsubtract(t.keys(), [1, 2, 3, 5, 6, 10]) + self.assertEqual(diff, [], diff) self._checkIt(t) def testDeleteOneChildWorks(self): @@ -975,8 +1053,8 @@ def testDeleteOneChildWorks(self): t[10] = 500 t[4] = 99 del t[3] - diff = lsubtract(t.keys(), [1,2,4,5,6,10]) - self.assertEqual(diff , [], diff) + diff = lsubtract(t.keys(), [1, 2, 4, 5, 6, 10]) + self.assertEqual(diff, [], diff) self._checkIt(t) def testDeleteTwoChildrenNoInorderSuccessorWorks(self): @@ -989,8 +1067,8 @@ def testDeleteTwoChildrenNoInorderSuccessorWorks(self): t[10] = 500 t[4] = 99 del t[2] - diff = lsubtract(t.keys(), [1,3,4,5,6,10]) - self.assertEqual(diff , [], diff) + diff = lsubtract(t.keys(), [1, 3, 4, 5, 6, 10]) + self.assertEqual(diff, [], diff) self._checkIt(t) def testDeleteTwoChildrenInorderSuccessorWorks(self): @@ -1005,8 +1083,8 @@ def testDeleteTwoChildrenInorderSuccessorWorks(self): t[6] = 99 t[4] = 150 del t[3] - diff = lsubtract(t.keys(), [1,4,5,6,7,8,10]) - self.assertEqual(diff , [], diff) + diff = lsubtract(t.keys(), [1, 4, 5, 6, 7, 8, 10]) + self.assertEqual(diff, [], diff) self._checkIt(t) def testDeleteRootWorks(self): @@ -1021,8 +1099,8 @@ def testDeleteRootWorks(self): t[6] = 99 t[4] = 150 del t[7] - diff = lsubtract(t.keys(), [1,3,4,5,6,8,10]) - self.assertEqual(diff , [], diff) + diff = lsubtract(t.keys(), [1, 3, 4, 5, 6, 8, 10]) + self.assertEqual(diff, [], diff) self._checkIt(t) def testRandomNonOverlappingInserts(self): @@ -1037,7 +1115,7 @@ def testRandomNonOverlappingInserts(self): added[k] = 1 addl = sorted(added.keys()) diff = lsubtract(list(t.keys()), addl) - self.assertEqual(diff , [], (diff, addl, list(t.keys()))) + self.assertEqual(diff, [], (diff, addl, list(t.keys()))) self._checkIt(t) def testRandomOverlappingInserts(self): @@ -1051,7 +1129,7 @@ def testRandomOverlappingInserts(self): added[k] = 1 addl = sorted(added.keys()) diff = lsubtract(t.keys(), addl) - self.assertEqual(diff , [], diff) + self.assertEqual(diff, [], diff) self._checkIt(t) def testRandomDeletes(self): @@ -1071,12 +1149,12 @@ def testRandomDeletes(self): del t[k] deleted.append(k) if k in t: - self.fail( "had problems deleting %s" % k ) + self.fail("had problems deleting %s" % k) badones = [] for x in deleted: if x in t: badones.append(x) - self.assertEqual(badones , [], (badones, added, deleted)) + self.assertEqual(badones, [], (badones, added, deleted)) self._checkIt(t) def testTargetedDeletes(self): @@ -1091,7 +1169,7 @@ def testTargetedDeletes(self): del t[x] except KeyError: pass - self.assertEqual(realseq(t.keys()) , [], realseq(t.keys())) + self.assertEqual(realseq(t.keys()), [], realseq(t.keys())) self._checkIt(t) def testPathologicalRightBranching(self): @@ -1099,10 +1177,10 @@ def testPathologicalRightBranching(self): r = list(range(1000)) for x in r: t[x] = 1 - self.assertEqual(realseq(t.keys()) , r, realseq(t.keys())) + self.assertEqual(realseq(t.keys()), r, realseq(t.keys())) for x in r: del t[x] - self.assertEqual(realseq(t.keys()) , [], realseq(t.keys())) + self.assertEqual(realseq(t.keys()), [], realseq(t.keys())) self._checkIt(t) def testPathologicalLeftBranching(self): @@ -1111,11 +1189,11 @@ def testPathologicalLeftBranching(self): revr = list(reversed(r[:])) for x in revr: t[x] = 1 - self.assertEqual(realseq(t.keys()) , r, realseq(t.keys())) + self.assertEqual(realseq(t.keys()), r, realseq(t.keys())) for x in revr: del t[x] - self.assertEqual(realseq(t.keys()) , [], realseq(t.keys())) + self.assertEqual(realseq(t.keys()), [], realseq(t.keys())) self._checkIt(t) def testSuccessorChildParentRewriteExerciseCase(self): @@ -1165,7 +1243,7 @@ def testSuccessorChildParentRewriteExerciseCase(self): del t[x] except KeyError: if x in t: - self.assertEqual(1,2,"failed to delete %s" % x) + self.assertEqual(1, 2, "failed to delete %s" % x) self._checkIt(t) def testRangeSearchAfterSequentialInsert(self): @@ -1174,16 +1252,16 @@ def testRangeSearchAfterSequentialInsert(self): for x in r: t[x] = 0 diff = lsubtract(list(t.keys(0, 100)), r) - self.assertEqual(diff , [], diff) + self.assertEqual(diff, [], diff) # The same thing with no bounds diff = lsubtract(list(t.keys(None, None)), r) - self.assertEqual(diff , [], diff) + self.assertEqual(diff, [], diff) # The same thing with each bound set and the other # explicitly None diff = lsubtract(list(t.keys(0, None)), r) - self.assertEqual(diff , [], diff) - diff = lsubtract(list(t.keys(None,100)), r) - self.assertEqual(diff , [], diff) + self.assertEqual(diff, [], diff) + diff = lsubtract(list(t.keys(None, 100)), r) + self.assertEqual(diff, [], diff) self._checkIt(t) def testRangeSearchAfterRandomInsert(self): @@ -1202,7 +1280,15 @@ def testRangeSearchAfterRandomInsert(self): def testPathologicalRangeSearch(self): t = self._makeOne() # Build a 2-level tree with at least two buckets. - for i in range(200): + if self.SUPPORTS_NEGATIVE_KEYS: + range_begin = 0 + firstkey_offset = 1 + else: + range_begin = 1 + firstkey_offset = 0 + + before_range_begin = range_begin - 1 + for i in range(range_begin, 200 + range_begin): t[i] = i items, dummy = t.__getstate__() self.assertTrue(len(items) > 2) # at least two buckets and a key @@ -1210,9 +1296,9 @@ def testPathologicalRangeSearch(self): # second bucket are >= firstkey, and firstkey is the first key in # the second bucket. firstkey = items[1] - therange = t.keys(-1, firstkey) - self.assertEqual(len(therange), firstkey + 1) - self.assertEqual(list(therange), list(range(firstkey + 1))) + therange = t.keys(before_range_begin, firstkey) + self.assertEqual(len(therange), firstkey + firstkey_offset) + self.assertEqual(list(therange), list(range(range_begin, firstkey + 1))) # Now for the tricky part. If we delete firstkey, the second bucket # loses its smallest key, but firstkey remains in the BTree node. # If we then do a high-end range search on firstkey, the BTree node @@ -1222,17 +1308,17 @@ def testPathologicalRangeSearch(self): # to "go backwards" in the BTree then; if it doesn't, it will # erroneously claim that the range is empty. del t[firstkey] - therange = t.keys(min=-1, max=firstkey) - self.assertEqual(len(therange), firstkey) - self.assertEqual(list(therange), list(range(firstkey))) + therange = t.keys(min=before_range_begin, max=firstkey) + self.assertEqual(len(therange), firstkey - range_begin) + self.assertEqual(list(therange), list(range(range_begin, firstkey))) self._checkIt(t) def testInsertMethod(self): t = self._makeOne() t[0] = 1 - self.assertEqual(t.insert(0, 1) , 0) - self.assertEqual(t.insert(1, 1) , 1) - self.assertEqual(lsubtract(list(t.keys()), [0,1]) , []) + self.assertEqual(t.insert(0, 1), 0) + self.assertEqual(t.insert(1, 1), 1) + self.assertEqual(lsubtract(list(t.keys()), [0, 1]), []) self._checkIt(t) def testDamagedIterator(self): @@ -1376,6 +1462,15 @@ def test_legacy_py_pickle(self): self.assertEqual(s2, s) +class UnsignedBTreeTests(UnsignedMixin, BTreeTests): + pass + +class UnsignedValuesBTreeTests(UnsignedValuesMixin, BTreeTests): + pass + +class UnsignedKeysBTreeTests(UnsignedKeysMixin, BTreeTests): + pass + class NormalSetTests(Base): # Test common to all set types @@ -1408,14 +1503,14 @@ def testShortRepr(self): def testInsertReturnsValue(self): t = self._makeOne() - self.assertEqual(t.insert(5) , 1) - self.assertEqual(t.add(4) , 1) + self.assertEqual(t.insert(5), 1) + self.assertEqual(t.add(4), 1) def testDuplicateInsert(self): t = self._makeOne() t.insert(5) - self.assertEqual(t.insert(5) , 0) - self.assertEqual(t.add(5) , 0) + self.assertEqual(t.insert(5), 0) + self.assertEqual(t.add(5), 0) def testInsert(self): from .._compat import PY2 @@ -1442,8 +1537,10 @@ def testRemoveSucceeds(self): from .._compat import xrange t = self._makeOne() r = xrange(10000) - for x in r: t.insert(x) - for x in r: t.remove(x) + for x in r: + t.insert(x) + for x in r: + t.remove(x) def testRemoveFails(self): self.assertRaises(KeyError, self._removenonexistent) @@ -1466,7 +1563,7 @@ def testKeys(self): t.insert(x) diff = lsubtract(t.keys(), r) self.assertEqual(diff, []) - diff = lsubtract(t.keys(None,None), r) + diff = lsubtract(t.keys(None, None), r) self.assertEqual(diff, []) @@ -1474,10 +1571,11 @@ def testClear(self): from .._compat import xrange t = self._makeOne() r = xrange(1000) - for x in r: t.insert(x) + for x in r: + t.insert(x) t.clear() diff = lsubtract(t.keys(), []) - self.assertEqual(diff , [], diff) + self.assertEqual(diff, [], diff) def testMaxKeyMinKey(self): t = self._makeOne() @@ -1489,14 +1587,14 @@ def testMaxKeyMinKey(self): t.insert(10) t.insert(6) t.insert(4) - self.assertEqual(t.maxKey() , 10) - self.assertEqual(t.maxKey(None) , 10) - self.assertEqual(t.maxKey(6) , 6) - self.assertEqual(t.maxKey(9) , 8) - self.assertEqual(t.minKey() , 1) - self.assertEqual(t.minKey(None) , 1) - self.assertEqual(t.minKey(3) , 3) - self.assertEqual(t.minKey(9) , 10) + self.assertEqual(t.maxKey(), 10) + self.assertEqual(t.maxKey(None), 10) + self.assertEqual(t.maxKey(6), 6) + self.assertEqual(t.maxKey(9), 8) + self.assertEqual(t.minKey(), 1) + self.assertEqual(t.minKey(None), 1) + self.assertEqual(t.minKey(3), 3) + self.assertEqual(t.minKey(9), 10) self.assertTrue(t.minKey() in t) self.assertTrue(t.minKey()-1 not in t) self.assertTrue(t.maxKey() in t) @@ -1519,11 +1617,11 @@ def testMaxKeyMinKey(self): def testUpdate(self): import random t = self._makeOne() - d={} - l=[] + d = {} + l = [] for i in range(10000): - k=random.randrange(-2000, 2001) - d[k]=i + k = random.randrange(*self.KEY_RANDRANGE_ARGS) + d[k] = i l.append(k) items = sorted(d.keys()) @@ -1534,11 +1632,13 @@ def testUpdate(self): def testEmptyRangeSearches(self): t = self._makeOne() t.update([1, 5, 9]) - self.assertEqual(list(t.keys(-6,-4)), [], list(t.keys(-6,-4))) - self.assertEqual(list(t.keys(2,4)), [], list(t.keys(2,4))) - self.assertEqual(list(t.keys(6,8)), [], list(t.keys(6,8))) - self.assertEqual(list(t.keys(10,12)), [], list(t.keys(10,12))) - self.assertEqual(list(t.keys(9,1)), [], list(t.keys(9,1))) + if self.SUPPORTS_NEGATIVE_KEYS: + self.assertEqual(list(t.keys(-6, -4)), []) + + self.assertEqual(list(t.keys(2, 4)), []) + self.assertEqual(list(t.keys(6, 8)), []) + self.assertEqual(list(t.keys(10, 12)), []) + self.assertEqual(list(t.keys(9, 1)), []) # For IITreeSets, this one was returning 31 for len(keys), and # list(keys) produced a list with 100 elements. @@ -1588,6 +1688,11 @@ def testIterator(self): for keys in [], [-2], [1, 4], list(range(-170, 2000, 6)): t.clear() + if keys and keys[0] < 0 and not self.SUPPORTS_NEGATIVE_KEYS: + with self.assertRaises(UnsignedError): + t.update(keys) + continue + t.update(keys) self.assertEqual(list(t), keys) @@ -1667,22 +1772,33 @@ def register(self, arg): # Whether or not doing `t.add(0)` again would result in # _p_changed being set depends on whether this is a TreeSet or a plain Set + +class UnsignedNormalSetTests(UnsignedMixin, NormalSetTests): + pass + + class ExtendedSetTests(NormalSetTests): def testLen(self): from .._compat import xrange t = self._makeOne() r = xrange(10000) - for x in r: t.insert(x) - self.assertEqual(len(t) , 10000, len(t)) + for x in r: + t.insert(x) + self.assertEqual(len(t), 10000, len(t)) def testGetItem(self): from .._compat import xrange t = self._makeOne() r = xrange(10000) - for x in r: t.insert(x) for x in r: - self.assertEqual(t[x] , x) + t.insert(x) + for x in r: + self.assertEqual(t[x], x) + + +class UnsignedExtendedSetTests(UnsignedMixin, ExtendedSetTests): + pass class InternalKeysMappingTest(object): @@ -1801,9 +1917,9 @@ def testBadBadKeyAfterFirst(self): self.assertRaises(TypeError, t.update, [1, '']) def testNonIntegerInsertRaises(self): - self.assertRaises(TypeError,self._insertstringraises) - self.assertRaises(TypeError,self._insertfloatraises) - self.assertRaises(TypeError,self._insertnoneraises) + self.assertRaises(TypeError, self._insertstringraises) + self.assertRaises(TypeError, self._insertfloatraises) + self.assertRaises(TypeError, self._insertnoneraises) def _insertstringraises(self): self._makeOne().insert('a') @@ -1821,7 +1937,7 @@ def _insertnoneraises(self): SMALLEST_POSITIVE_33_BITS = LARGEST_32_BITS + 1 LARGEST_NEGATIVE_33_BITS = SMALLEST_32_BITS - 1 -LARGEST_64_BITS = 0x7fffffffffffffff +LARGEST_64_BITS = 0x7fffffffffffffff # Signed. 2**63 - 1 SMALLEST_64_BITS = -LARGEST_64_BITS - 1 SMALLEST_POSITIVE_65_BITS = LARGEST_64_BITS + 1 @@ -1863,13 +1979,13 @@ def testLongIntKeysWork(self): assert o1 != o2 # Test some small key values first: - zero_long = self._makeLong(0) - t[zero_long] = o1 - self.assertEqual(t[0], o1) - t[0] = o2 - self.assertEqual(t[zero_long], o2) - self.assertEqual(list(t.keys()), [0]) - self.assertEqual(list(t.keys(None,None)), [0]) + one_long = self._makeLong(1) + t[one_long] = o1 + self.assertEqual(t[1], o1) + t[1] = o2 + self.assertEqual(t[one_long], o2) + self.assertEqual(list(t.keys()), [1]) + self.assertEqual(list(t.keys(None, None)), [1]) # Test some large key values too: k1 = SMALLEST_POSITIVE_33_BITS @@ -1881,23 +1997,22 @@ def testLongIntKeysWork(self): self.assertEqual(t[k1], o1) self.assertEqual(t[k2], o2) self.assertEqual(t[k3], o1) - self.assertEqual(list(t.keys()), [k3, 0, k1, k2]) - self.assertEqual(list(t.keys(k3,None)), [k3, 0, k1, k2]) - self.assertEqual(list(t.keys(None,k2)), [k3, 0, k1, k2]) + self.assertEqual(list(t.keys()), [k3, 1, k1, k2]) + self.assertEqual(list(t.keys(k3, None)), [k3, 1, k1, k2]) + self.assertEqual(list(t.keys(None, k2)), [k3, 1, k1, k2]) def testLongIntKeysOutOfRange(self): self._skip_if_not_64bit() o1, o2 = self.getTwoValues() t = self._makeOne() k1 = SMALLEST_POSITIVE_65_BITS if self.SUPPORTS_NEGATIVE_KEYS else 2**64 + 1 - with self.assertRaises((OverflowError, ValueError)): + with self.assertRaises(OverflowError): t[k1] = o1 t = self._makeOne() - with self.assertRaises((OverflowError, ValueError)): + with self.assertRaises(OverflowError): t[LARGEST_NEGATIVE_65_BITS] = o1 - class TestLongIntValues(TestLongIntSupport): SUPPORTS_NEGATIVE_VALUES = True def testLongIntValuesWork(self): @@ -1916,25 +2031,25 @@ def testLongIntValuesWork(self): self.assertEqual(t[k1], v1) self.assertEqual(t[k2], v2) self.assertEqual(list(t.values()), [v1, v2]) - self.assertEqual(list(t.values(None,None)), [v1, v2]) + self.assertEqual(list(t.values(None, None)), [v1, v2]) def testLongIntValuesOutOfRange(self): self._skip_if_not_64bit() k1, k2 = self.getTwoKeys() t = self._makeOne() v1 = SMALLEST_POSITIVE_65_BITS if self.SUPPORTS_NEGATIVE_VALUES else 2**64 + 1 - with self.assertRaises((OverflowError, ValueError)): + with self.assertRaises(OverflowError): t[k1] = v1 t = self._makeOne() - with self.assertRaises((OverflowError, ValueError)): + with self.assertRaises(OverflowError): t[k1] = LARGEST_NEGATIVE_65_BITS # Given a mapping builder (IIBTree, OOBucket, etc), return a function # that builds an object of that type given only a list of keys. def makeBuilder(mapbuilder): - def result(keys=[], mapbuilder=mapbuilder): + def result(keys=(), mapbuilder=mapbuilder): return mapbuilder(list(zip(keys, keys))) return result @@ -1947,7 +2062,7 @@ def setUp(self): super(SetResult, self).setUp() _skip_if_pure_py_and_py_test(self) - self.Akeys = [1, 3, 5, 6 ] + self.Akeys = [1, 3, 5, 6] self.Bkeys = [ 2, 3, 4, 6, 7] self.As = [makeset(self.Akeys) for makeset in self.builders()] self.Bs = [makeset(self.Bkeys) for makeset in self.builders()] @@ -2061,7 +2176,7 @@ def testDifference(self): self.assertEqual(list(C), want) def testLargerInputs(self): - from BTrees.IIBTree import IISet + from BTrees.IIBTree import IISet # pylint:disable=no-name-in-module from random import randint MAXSIZE = 200 MAXVAL = 400 @@ -2091,11 +2206,11 @@ def testLargerInputs(self): # builders -- sequence of constructors, taking items # union, intersection -- the module routines of those names # mkbucket -- the module bucket builder -class Weighted(object): +class Weighted(SignedMixin): def setUp(self): - self.Aitems = [(1, 10), (3, 30), (5, 50), (6, 60)] - self.Bitems = [(2, 21), (3, 31), (4, 41), (6, 61), (7, 71)] + self.Aitems = [(1, 10), (3, 30), (5, 50), (6, 60)] + self.Bitems = [(2, 21), (3, 31), (4, 41), (6, 61), (7, 71)] self.As = [make(self.Aitems) for make in self.builders()] self.Bs = [make(self.Bitems) for make in self.builders()] @@ -2171,6 +2286,8 @@ def testUnion(self): self.assertEqual(got_s.items(), want_s) for w1, w2 in self.weights: + if (w1 < 0 or w2 < 0) and not self.SUPPORTS_NEGATIVE_VALUES: + continue want_w, want_s = self._wunion(A, B, w1, w2) got_w, got_s = self.weightedUnion()(A, B, w1, w2) self.assertEqual(got_w, want_w) @@ -2203,6 +2320,8 @@ def testIntersection(self): self.assertEqual(got_s.items(), want_s) for w1, w2 in self.weights: + if (w1 < 0 or w2 < 0) and not self.SUPPORTS_NEGATIVE_VALUES: + continue want_w, want_s = self._wintersection(A, B, w1, w2) got_w, got_s = self.weightedIntersection()(A, B, w1, w2) self.assertEqual(got_w, want_w) @@ -2227,7 +2346,7 @@ def isaset(thing): # multiunion, union # mkset, mktreeset # mkbucket, mkbtree -class MultiUnion(object): +class MultiUnion(SignedMixin): def setUp(self): super(MultiUnion, self).setUp() @@ -2237,10 +2356,13 @@ def testEmpty(self): self.assertEqual(len(self.multiunion([])), 0) def testOne(self): - for sequence in ([3], - list(range(20)), - list(range(-10, 0, 2)) + list(range(1, 10, 2)), - ): + for sequence in ( + [3], + list(range(20)), + list(range(-10, 0, 2)) + list(range(1, 10, 2)), + ): + if min(sequence) < 0 and not self.SUPPORTS_NEGATIVE_KEYS: + continue seq1 = sequence[:] seq2 = list(reversed(sequence[:])) seqsorted = sorted(sequence[:]) @@ -2276,13 +2398,19 @@ def testLotsOfLittleOnes(self): inputs = [] mkset, mktreeset = self.mkset, self.mktreeset for i in range(N): - base = i * 4 - N - inputs.append(mkset([base, base+1])) - inputs.append(mktreeset([base+2, base+3])) + if self.SUPPORTS_NEGATIVE_KEYS: + base = i * 4 - N + else: + base = i * 4 + inputs.append(mkset([base, base + 1])) + inputs.append(mktreeset([base + 2, base + 3])) shuffle(inputs) output = self.multiunion(inputs) - self.assertEqual(len(output), N*4) - self.assertEqual(list(output), list(range(-N, 3*N))) + self.assertEqual(len(output), N * 4) + if self.SUPPORTS_NEGATIVE_KEYS: + self.assertEqual(list(output), list(range(-N, 3 * N))) + else: + self.assertEqual(list(output), list(range(N * 4))) def testFunkyKeyIteration(self): # The internal set iteration protocol allows "iterating over" a @@ -2299,7 +2427,7 @@ def testFunkyKeyIteration(self): self.assertEqual(list(fast), list(range(N))) -class ConflictTestBase(object): +class ConflictTestBase(SignedMixin, object): # Tests common to all types: sets, buckets, and BTrees storage = None @@ -2307,6 +2435,10 @@ class ConflictTestBase(object): def setUp(self): super(ConflictTestBase, self).setUp() _skip_if_pure_py_and_py_test(self) + def identity(x): + return x + self.key_tx = abs if not self.SUPPORTS_NEGATIVE_KEYS else identity + self.val_tx = abs if not self.SUPPORTS_NEGATIVE_VALUES else identity def tearDown(self): import transaction @@ -2328,44 +2460,45 @@ def openDB(self): return self.db -def _test_merge(o1, o2, o3, expect, message='failed to merge', should_fail=0): - from BTrees.Interfaces import BTreesConflictError - s1 = o1.__getstate__() - s2 = o2.__getstate__() - s3 = o3.__getstate__() - expected = expect.__getstate__() - if expected is None: - expected = ((((),),),) + def _test_merge(self, o1, o2, o3, expect, message='failed to merge', should_fail=False): + from BTrees.Interfaces import BTreesConflictError + s1 = o1.__getstate__() + s2 = o2.__getstate__() + s3 = o3.__getstate__() + expected = expect.__getstate__() + if expected is None: + expected = ((((),),),) - if should_fail: - try: - merged = o1._p_resolveConflict(s1, s2, s3) - except BTreesConflictError as err: - pass + if should_fail: + with self.assertRaises(BTreesConflictError): + __traceback_info__ = message + o1._p_resolveConflict(s1, s2, s3) else: - assert 0, message - else: - merged = o1._p_resolveConflict(s1, s2, s3) - assert merged == expected, message + merged = o1._p_resolveConflict(s1, s2, s3) + self.assertEqual(merged, expected, message) class MappingConflictTestBase(ConflictTestBase): # Tests common to mappings (buckets, btrees). + def _deletefail(self): t = self._makeOne() del t[1] def _setupConflict(self): - - l=[ -5124, -7377, 2274, 8801, -9901, 7327, 1565, 17, -679, + key_tx = self.key_tx + l = [ + -5124, -7377, 2274, 8801, -9901, 7327, 1565, 17, -679, 3686, -3607, 14, 6419, -5637, 6040, -4556, -8622, 3847, 7191, - -4067] - - - e1=[(-1704, 0), (5420, 1), (-239, 2), (4024, 3), (-6984, 4)] - e2=[(7745, 0), (4868, 1), (-2548, 2), (-2711, 3), (-3154, 4)] + -4067 + ] + l = [key_tx(v) for v in l] + e1 = [(-1704, 0), (5420, 1), (-239, 2), (4024, 3), (-6984, 4)] + e1 = [(key_tx(k), v) for k, v in e1] + e2 = [(7745, 0), (4868, 1), (-2548, 2), (-2711, 3), (-3154, 4)] + e2 = [(key_tx(k), v) for k, v in e2] base = self._makeOne() base.update([(i, i*i) for i in l[:20]]) @@ -2373,7 +2506,7 @@ def _setupConflict(self): b2 = type(base)(base) bm = type(base)(base) - items=base.items() + items = base.items() return base, b1, b2, bm, e1, e2, items @@ -2387,66 +2520,67 @@ def testMergeDelete(self): del bm[items[5][0]] del bm[items[-1][0]] del bm[items[-2][0]] - _test_merge(base, b1, b2, bm, 'merge delete') + self._test_merge(base, b1, b2, bm, 'merge delete') def testMergeDeleteAndUpdate(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() del b1[items[1][0]] - b2[items[5][0]]=1 + b2[items[5][0]] = 1 del b1[items[-1][0]] - b2[items[-2][0]]=2 + b2[items[-2][0]] = 2 del bm[items[1][0]] - bm[items[5][0]]=1 + bm[items[5][0]] = 1 del bm[items[-1][0]] - bm[items[-2][0]]=2 - _test_merge(base, b1, b2, bm, 'merge update and delete') + bm[items[-2][0]] = 2 + self._test_merge(base, b1, b2, bm, 'merge update and delete') def testMergeUpdate(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() - b1[items[0][0]]=1 - b2[items[5][0]]=2 - b1[items[-1][0]]=3 - b2[items[-2][0]]=4 - bm[items[0][0]]=1 - bm[items[5][0]]=2 - bm[items[-1][0]]=3 - bm[items[-2][0]]=4 - _test_merge(base, b1, b2, bm, 'merge update') + b1[items[0][0]] = 1 + b2[items[5][0]] = 2 + b1[items[-1][0]] = 3 + b2[items[-2][0]] = 4 + bm[items[0][0]] = 1 + bm[items[5][0]] = 2 + bm[items[-1][0]] = 3 + bm[items[-2][0]] = 4 + self._test_merge(base, b1, b2, bm, 'merge update') def testFailMergeDelete(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() del b1[items[0][0]] del b2[items[0][0]] - _test_merge(base, b1, b2, bm, 'merge conflicting delete', - should_fail=1) + self._test_merge(base, b1, b2, bm, 'merge conflicting delete', + should_fail=1) def testFailMergeUpdate(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() - b1[items[0][0]]=1 - b2[items[0][0]]=2 - _test_merge(base, b1, b2, bm, 'merge conflicting update', - should_fail=1) + b1[items[0][0]] = 1 + b2[items[0][0]] = 2 + self._test_merge(base, b1, b2, bm, 'merge conflicting update', + should_fail=1) def testFailMergeDeleteAndUpdate(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() del b1[items[0][0]] - b2[items[0][0]]=-9 - _test_merge(base, b1, b2, bm, 'merge conflicting update and delete', - should_fail=1) + b2[items[0][0]] = self.val_tx(-9) + self._test_merge(base, b1, b2, bm, 'merge conflicting update and delete', + should_fail=1) def testMergeInserts(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() - b1[-99999]=-99999 - b1[e1[0][0]]=e1[0][1] - b2[99999]=99999 - b2[e1[2][0]]=e1[2][1] + b1[self.key_tx(-99999)] = self.val_tx(-99999) + b1[e1[0][0]] = e1[0][1] + b2[99999] = 99999 + b2[e1[2][0]] = e1[2][1] - bm[-99999]=-99999 - bm[e1[0][0]]=e1[0][1] - bm[99999]=99999 - bm[e1[2][0]]=e1[2][1] - _test_merge(base, b1, b2, bm, 'merge insert') + bm[self.key_tx(-99999)] = self.val_tx(-99999) + bm[e1[0][0]] = e1[0][1] + bm[99999] = 99999 + bm[e1[2][0]] = e1[2][1] + self._test_merge(base, b1, b2, bm, 'merge insert', + should_fail=not self.SUPPORTS_NEGATIVE_KEYS) def testMergeInsertsFromEmpty(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() @@ -2461,7 +2595,7 @@ def testMergeInsertsFromEmpty(self): b2.update(e2) bm.update(e2) - _test_merge(base, b1, b2, bm, 'merge insert from empty') + self._test_merge(base, b1, b2, bm, 'merge insert from empty') def testFailMergeEmptyAndFill(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() @@ -2471,7 +2605,7 @@ def testFailMergeEmptyAndFill(self): b2.update(e2) bm.update(e2) - _test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1) + self._test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1) def testMergeEmpty(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() @@ -2479,36 +2613,49 @@ def testMergeEmpty(self): b1.clear() bm.clear() - _test_merge(base, b1, b2, bm, 'empty one and not other', should_fail=1) + self._test_merge(base, b1, b2, bm, 'empty one and not other', should_fail=1) def testFailMergeInsert(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() - b1[-99999]=-99999 - b1[e1[0][0]]=e1[0][1] - b2[99999]=99999 - b2[e1[0][0]]=e1[0][1] - _test_merge(base, b1, b2, bm, 'merge conflicting inserts', - should_fail=1) + b1[self.key_tx(-99999)] = self.val_tx(-99999) + b1[e1[0][0]] = e1[0][1] + b2[99999] = 99999 + b2[e1[0][0]] = e1[0][1] + self._test_merge(base, b1, b2, bm, 'merge conflicting inserts', + should_fail=1) + +class UnsignedMappingConflictTestBase(UnsignedMixin, MappingConflictTestBase): + pass + +class UnsignedValuesMappingConflictTestBase(UnsignedValuesMixin, MappingConflictTestBase): + pass + +class UnsignedKeysMappingConflictTestBase(UnsignedKeysMixin, MappingConflictTestBase): + pass + class SetConflictTestBase(ConflictTestBase): "Set (as opposed to TreeSet) specific tests." def _setupConflict(self): - l=[ -5124, -7377, 2274, 8801, -9901, 7327, 1565, 17, -679, + l = [self.key_tx(x) for x in [ + -5124, -7377, 2274, 8801, -9901, 7327, 1565, 17, -679, 3686, -3607, 14, 6419, -5637, 6040, -4556, -8622, 3847, 7191, - -4067] + -4067]] - e1=[-1704, 5420, -239, 4024, -6984] - e2=[7745, 4868, -2548, -2711, -3154] + e1 = [self.key_tx(x) for x in + [-1704, 5420, -239, 4024, -6984]] + e2 = [self.key_tx(x) for x in + [7745, 4868, -2548, -2711, -3154]] base = self._makeOne() base.update(l) - b1=base.__class__(base) - b2=base.__class__(base) - bm=base.__class__(base) + b1 = base.__class__(base) + b2 = base.__class__(base) + bm = base.__class__(base) - items=base.keys() + items = base.keys() return base, b1, b2, bm, e1, e2, items @@ -2522,28 +2669,29 @@ def testMergeDelete(self): bm.remove(items[5]) bm.remove(items[-1]) bm.remove(items[-2]) - _test_merge(base, b1, b2, bm, 'merge delete') + self._test_merge(base, b1, b2, bm, 'merge delete') def testFailMergeDelete(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() b1.remove(items[0]) b2.remove(items[0]) - _test_merge(base, b1, b2, bm, 'merge conflicting delete', - should_fail=1) + self._test_merge(base, b1, b2, bm, 'merge conflicting delete', + should_fail=1) def testMergeInserts(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() - b1.insert(-99999) + b1.insert(self.key_tx(-99999)) b1.insert(e1[0]) b2.insert(99999) b2.insert(e1[2]) - bm.insert(-99999) + bm.insert(self.key_tx(-99999)) bm.insert(e1[0]) bm.insert(99999) bm.insert(e1[2]) - _test_merge(base, b1, b2, bm, 'merge insert') + self._test_merge(base, b1, b2, bm, 'merge insert', + should_fail=not self.SUPPORTS_NEGATIVE_KEYS) def testMergeInsertsFromEmpty(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() @@ -2558,7 +2706,7 @@ def testMergeInsertsFromEmpty(self): b2.update(e2) bm.update(e2) - _test_merge(base, b1, b2, bm, 'merge insert from empty') + self._test_merge(base, b1, b2, bm, 'merge insert from empty') def testFailMergeEmptyAndFill(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() @@ -2568,7 +2716,7 @@ def testFailMergeEmptyAndFill(self): b2.update(e2) bm.update(e2) - _test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1) + self._test_merge(base, b1, b2, bm, 'merge insert from empty', should_fail=1) def testMergeEmpty(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() @@ -2576,17 +2724,19 @@ def testMergeEmpty(self): b1.clear() bm.clear() - _test_merge(base, b1, b2, bm, 'empty one and not other', should_fail=1) + self._test_merge(base, b1, b2, bm, 'empty one and not other', should_fail=1) def testFailMergeInsert(self): base, b1, b2, bm, e1, e2, items = self._setupConflict() - b1.insert(-99999) + b1.insert(self.key_tx(-99999)) b1.insert(e1[0]) b2.insert(99999) b2.insert(e1[0]) - _test_merge(base, b1, b2, bm, 'merge conflicting inserts', - should_fail=1) + self._test_merge(base, b1, b2, bm, 'merge conflicting inserts', + should_fail=1) +class UnsignedSetConflictTestBase(UnsignedMixin, SetConflictTestBase): + pass ## utility functions @@ -2597,7 +2747,7 @@ def lsubtract(l1, l2): list(filter(lambda x, l2=l2: x not in l2, l1))) def realseq(itemsob): - return [x for x in itemsob] + return list(itemsob) def permutations(x): # Return a list of all permutations of list x. diff --git a/BTrees/tests/testBTrees.py b/BTrees/tests/testBTrees.py index 8337914..b289cf3 100644 --- a/BTrees/tests/testBTrees.py +++ b/BTrees/tests/testBTrees.py @@ -442,8 +442,18 @@ def test32(self): BTrees.family32.II, BTrees.IIBTree) self.assertEqual( BTrees.family32.IF, BTrees.IFBTree) + self.assertEqual( + BTrees.family32.UO, BTrees.UOBTree) + self.assertEqual( + BTrees.family32.OU, BTrees.OUBTree) + self.assertEqual( + BTrees.family32.UU, BTrees.UUBTree) + self.assertEqual( + BTrees.family32.UF, BTrees.UFBTree) self.assertEqual( BTrees.family32.OO, BTrees.OOBTree) + self.assertEqual( + BTrees.family32.OU, BTrees.OUBTree) s = IOTreeSet() s.insert(BTrees.family32.maxint) self.assertTrue(BTrees.family32.maxint in s) @@ -474,8 +484,18 @@ def test64(self): BTrees.family64.II, BTrees.LLBTree) self.assertEqual( BTrees.family64.IF, BTrees.LFBTree) + self.assertEqual( + BTrees.family64.UO, BTrees.QOBTree) + self.assertEqual( + BTrees.family64.OU, BTrees.OQBTree) + self.assertEqual( + BTrees.family64.UU, BTrees.QQBTree) + self.assertEqual( + BTrees.family64.UF, BTrees.QFBTree) self.assertEqual( BTrees.family64.OO, BTrees.OOBTree) + self.assertEqual( + BTrees.family64.OU, BTrees.OQBTree) s = LOTreeSet() s.insert(BTrees.family64.maxint) self.assertTrue(BTrees.family64.maxint in s) @@ -484,8 +504,8 @@ def test64(self): self.assertTrue(BTrees.family64.minint in s) s = LOTreeSet() # XXX why oh why do we expect ValueError here, but TypeError in test32? - self.assertRaises(ValueError, s.insert, BTrees.family64.maxint + 1) - self.assertRaises(ValueError, s.insert, BTrees.family64.minint - 1) + self.assertRaises((TypeError, OverflowError), s.insert, BTrees.family64.maxint + 1) + self.assertRaises((TypeError, OverflowError), s.insert, BTrees.family64.minint - 1) self.check_pickling(BTrees.family64) def check_pickling(self, family): diff --git a/BTrees/tests/test_IUBTree.py b/BTrees/tests/test_IUBTree.py new file mode 100644 index 0000000..31ffc45 --- /dev/null +++ b/BTrees/tests/test_IUBTree.py @@ -0,0 +1,429 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedValuesBTreeTests as BTreeTests +from .common import ExtendedSetTests +from .common import I_SetsBase +from .common import InternalKeysMappingTest +from .common import UnsignedValuesMappingBase as MappingBase +from .common import UnsignedValuesMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import NormalSetTests +from .common import SetConflictTestBase +from .common import SetResult +from .common import Weighted +from .common import itemsToSet +from .common import makeBuilder +from .common import UnsignedValuesMixin +from .common import UnsignedError + + +# pylint:disable=no-name-in-module,arguments-differ + +class IUBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUBTree + return IUBTree + + +class IUBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUBTreePy + return IUBTreePy + + +class IUBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUBucket + return IUBucket + + +class IUBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUBucketPy + return IUBucketPy + + +class IUTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUTreeSet + return IUTreeSet + + +class IUTreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUTreeSetPy + return IUTreeSetPy + + +class IUSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUSet + return IUSet + + +class IUSetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUSetPy + return IUSetPy + + +class _IUBTreeTestBase(BTreeTests): + + def testIUBTreeOverflow(self): + good = set() + b = self._makeOne() + + def trial(i): + i = int(i) + try: + b[i] = i + except UnsignedError: + pass + else: + good.add(i) + b[0] = i + self.assertEqual(b[0], i) + + for i in range((1<<31) - 3, (1<<31) + 3): + trial(i) + trial(-i) + + del b[0] + self.assertEqual(sorted(good), sorted(b)) + + +class IUBTreeTest(_IUBTreeTestBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.IUBTree import IUBTree + return IUBTree() + + +class IUBTreeTestPy(_IUBTreeTestBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.IUBTree import IUBTreePy + return IUBTreePy() + + +class _TestIUBTreesBase(object): + + def testNonIntegerKeyRaises(self): + self.assertRaises(TypeError, self._stringraiseskey) + self.assertRaises(TypeError, self._floatraiseskey) + self.assertRaises(TypeError, self._noneraiseskey) + + def testNonIntegerValueRaises(self): + self.assertRaises(TypeError, self._stringraisesvalue) + self.assertRaises(TypeError, self._floatraisesvalue) + self.assertRaises(TypeError, self._noneraisesvalue) + + def _stringraiseskey(self): + self._makeOne()['c'] = 1 + + def _floatraiseskey(self): + self._makeOne()[2.5] = 1 + + def _noneraiseskey(self): + self._makeOne()[None] = 1 + + def _stringraisesvalue(self): + self._makeOne()[1] = 'c' + + def _floatraisesvalue(self): + self._makeOne()[1] = 1.4 + + def _noneraisesvalue(self): + self._makeOne()[1] = None + + +class TestIUBTrees(_TestIUBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.IUBTree import IUBTree + return IUBTree() + + +class TestIUBTreesPy(_TestIUBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.IUBTree import IUBTreePy + return IUBTreePy() + + +class TestIUSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.IUBTree import IUSet + return IUSet() + + +class TestIUSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.IUBTree import IUSetPy + return IUSetPy() + + +class TestIUTreeSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.IUBTree import IUTreeSet + return IUTreeSet() + + +class TestIUTreeSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.IUBTree import IUTreeSetPy + return IUTreeSetPy() + + +class PureIU(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.IUBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.IUBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.IUBTree import difference + return difference(*args) + + def builders(self): + from BTrees.IUBTree import IUBTree + from BTrees.IUBTree import IUBucket + from BTrees.IUBTree import IUTreeSet + from BTrees.IUBTree import IUSet + return IUSet, IUTreeSet, makeBuilder(IUBTree), makeBuilder(IUBucket) + + +class PureIUPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.IUBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.IUBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.IUBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.IUBTree import IUBTreePy + from BTrees.IUBTree import IUBucketPy + from BTrees.IUBTree import IUTreeSetPy + from BTrees.IUBTree import IUSetPy + return (IUSetPy, IUTreeSetPy, + makeBuilder(IUBTreePy), makeBuilder(IUBucketPy)) + + +class TestIUMultiUnion(UnsignedValuesMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.IUBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.IUBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.IUBTree import IUSet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.IUBTree import IUTreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.IUBTree import IUBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.IUBTree import IUBTree as mkbtree + return mkbtree(*args) + + +class TestIUMultiUnionPy(UnsignedValuesMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.IUBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.IUBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.IUBTree import IUSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.IUBTree import IUTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.IUBTree import IUBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.IUBTree import IUBTreePy as mkbtree + return mkbtree(*args) + + +class TestWeightedIU(UnsignedValuesMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.IUBTree import weightedUnion + return weightedUnion + + def weightedIntersection(self): + from BTrees.IUBTree import weightedIntersection + return weightedIntersection + + def union(self): + from BTrees.IUBTree import union + return union + + def intersection(self): + from BTrees.IUBTree import intersection + return intersection + + def mkbucket(self, *args): + from BTrees.IUBTree import IUBucket as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.IUBTree import IUBTree + from BTrees.IUBTree import IUBucket + from BTrees.IUBTree import IUTreeSet + from BTrees.IUBTree import IUSet + return IUBucket, IUBTree, itemsToSet(IUSet), itemsToSet(IUTreeSet) + + +class TestWeightedIUPy(UnsignedValuesMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.IUBTree import weightedUnionPy + return weightedUnionPy + + def weightedIntersection(self): + from BTrees.IUBTree import weightedIntersectionPy + return weightedIntersectionPy + + def union(self): + from BTrees.IUBTree import unionPy + return unionPy + + def intersection(self): + from BTrees.IUBTree import intersectionPy + return intersectionPy + + def mkbucket(self, *args): + from BTrees.IUBTree import IUBucketPy as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.IUBTree import IUBTreePy + from BTrees.IUBTree import IUBucketPy + from BTrees.IUBTree import IUTreeSetPy + from BTrees.IUBTree import IUSetPy + return (IUBucketPy, IUBTreePy, + itemsToSet(IUSetPy), itemsToSet(IUTreeSetPy)) + + +class IUBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUBTree + return IUBTree + + +class IUBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUBTreePy + return IUBTreePy + + +class IUBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUBucket + return IUBucket + + +class IUBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUBucketPy + return IUBucketPy + + +class IUTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUTreeSet + return IUTreeSet + + +class IUTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUTreeSetPy + return IUTreeSetPy + + +class IUSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUSet + return IUSet + + +class IUSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.IUBTree import IUSetPy + return IUSetPy + + +class IUModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'IU' + + def _getModule(self): + import BTrees + return BTrees.IUBTree + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IIntegerUnsignedBTreeModule diff --git a/BTrees/tests/test_LQBTree.py b/BTrees/tests/test_LQBTree.py new file mode 100644 index 0000000..4270938 --- /dev/null +++ b/BTrees/tests/test_LQBTree.py @@ -0,0 +1,366 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedValuesBTreeTests as BTreeTests +from .common import ExtendedSetTests +from .common import I_SetsBase +from .common import InternalKeysMappingTest +from .common import UnsignedValuesMappingBase as MappingBase +from .common import UnsignedValuesMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import NormalSetTests +from .common import SetConflictTestBase +from .common import SetResult +from .common import TestLongIntKeys +from .common import TestLongIntValues +from .common import Weighted +from .common import itemsToSet +from .common import makeBuilder +from .common import UnsignedValuesMixin + +# pylint:disable=no-name-in-module,arguments-differ + +class LQBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQBTree + return LQBTree + + +class LQBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQBTreePy + return LQBTreePy + + +class LQBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQBucket + return LQBucket + + +class LQBucketTestPy(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQBucketPy + return LQBucketPy + + +class LQTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQTreeSet + return LQTreeSet + + +class LQTreeSetTestPy(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQTreeSetPy + return LQTreeSetPy + + +class LQSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQSet + return LQSet + + +class LQSetTestPy(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQSetPy + return LQSetPy + + +class LQBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues, + unittest.TestCase): + + def _makeOne(self): + from BTrees.LQBTree import LQBTree + return LQBTree() + def getTwoValues(self): + return 1, 2 + + +class LQBTreeTestPy(BTreeTests, TestLongIntKeys, TestLongIntValues, + unittest.TestCase): + + def _makeOne(self): + from BTrees.LQBTree import LQBTreePy + return LQBTreePy() + def getTwoValues(self): + return 1, 2 + + +class TestLQSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.LQBTree import LQSet + return LQSet() + + +class TestLQSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.LQBTree import LQSetPy + return LQSetPy() + + +class TestLQTreeSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.LQBTree import LQTreeSet + return LQTreeSet() + + +class TestLQTreeSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.LQBTree import LQTreeSetPy + return LQTreeSetPy() + + +class PureLQ(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.LQBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.LQBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.LQBTree import difference + return difference(*args) + + def builders(self): + from BTrees.LQBTree import LQBTree + from BTrees.LQBTree import LQBucket + from BTrees.LQBTree import LQTreeSet + from BTrees.LQBTree import LQSet + return LQSet, LQTreeSet, makeBuilder(LQBTree), makeBuilder(LQBucket) + + +class PureLQPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.LQBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.LQBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.LQBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.LQBTree import LQBTreePy + from BTrees.LQBTree import LQBucketPy + from BTrees.LQBTree import LQTreeSetPy + from BTrees.LQBTree import LQSetPy + return (LQSetPy, LQTreeSetPy, + makeBuilder(LQBTreePy), makeBuilder(LQBucketPy)) + + +class TestLQMultiUnion(MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.LQBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.LQBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.LQBTree import LQSet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.LQBTree import LQTreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.LQBTree import LQBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.LQBTree import LQBTree as mkbtree + return mkbtree(*args) + + +class TestLQMultiUnionPy(MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.LQBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.LQBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.LQBTree import LQSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.LQBTree import LQTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.LQBTree import LQBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.LQBTree import LQBTreePy as mkbtree + return mkbtree(*args) + + +class TestWeightedLQ(UnsignedValuesMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.LQBTree import weightedUnion + return weightedUnion + + def weightedIntersection(self): + from BTrees.LQBTree import weightedIntersection + return weightedIntersection + + def union(self): + from BTrees.LQBTree import union + return union + + def intersection(self): + from BTrees.LQBTree import intersection + return intersection + + def mkbucket(self, *args): + from BTrees.LQBTree import LQBucket as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.LQBTree import LQBTree + from BTrees.LQBTree import LQBucket + from BTrees.LQBTree import LQTreeSet + from BTrees.LQBTree import LQSet + return LQBucket, LQBTree, itemsToSet(LQSet), itemsToSet(LQTreeSet) + + +class TestWeightedLQPy(UnsignedValuesMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.LQBTree import weightedUnionPy + return weightedUnionPy + + def weightedIntersection(self): + from BTrees.LQBTree import weightedIntersectionPy + return weightedIntersectionPy + + def union(self): + from BTrees.LQBTree import unionPy + return unionPy + + def intersection(self): + from BTrees.LQBTree import intersectionPy + return intersectionPy + + def mkbucket(self, *args): + from BTrees.LQBTree import LQBucketPy as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.LQBTree import LQBTreePy + from BTrees.LQBTree import LQBucketPy + from BTrees.LQBTree import LQTreeSetPy + from BTrees.LQBTree import LQSetPy + return (LQBucketPy, LQBTreePy, + itemsToSet(LQSetPy), itemsToSet(LQTreeSetPy)) + + +class LQBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQBTree + return LQBTree + + +class LQBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQBTreePy + return LQBTreePy + + +class LQBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQBucket + return LQBucket + + +class LQBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQBucketPy + return LQBucketPy + + +class LQTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQTreeSet + return LQTreeSet + + +class LQTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQTreeSetPy + return LQTreeSetPy + + +class LQSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQSet + return LQSet + + +class LQSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.LQBTree import LQSetPy + return LQSetPy + + +class LQModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'LQ' + + def _getModule(self): + import BTrees + return BTrees.LQBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IIntegerUnsignedBTreeModule diff --git a/BTrees/tests/test_OQBTree.py b/BTrees/tests/test_OQBTree.py new file mode 100644 index 0000000..71b5045 --- /dev/null +++ b/BTrees/tests/test_OQBTree.py @@ -0,0 +1,306 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedValuesBTreeTests as BTreeTests +from .common import ExtendedSetTests +from .common import InternalKeysMappingTest +from .common import UnsignedValuesMappingBase as MappingBase +from .common import UnsignedValuesMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import NormalSetTests +from .common import SetConflictTestBase +from .common import SetResult +from .common import TestLongIntValues +from .common import Weighted +from .common import itemsToSet +from .common import makeBuilder +from .common import _skip_on_32_bits +from .common import UnsignedValuesMixin + +# pylint:disable=no-name-in-module,arguments-differ + +class OQBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQBTree + return OQBTree + + +class OQBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQBTreePy + return OQBTreePy + + +class OQBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQBucket + return OQBucket + + +class OQBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQBucketPy + return OQBucketPy + + +class OQTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQTreeSet + return OQTreeSet + + +class OQTreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQTreeSetPy + return OQTreeSetPy + + +class OQSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQSet + return OQSet + + +class OQSetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQSetPy + return OQSetPy + + +class OQBTreeTest(BTreeTests, TestLongIntValues, unittest.TestCase): + + def _makeOne(self): + from BTrees.OQBTree import OQBTree + return OQBTree() + + def getTwoKeys(self): + return "abc", "def" + + @_skip_on_32_bits + def test_extremes(self): + from BTrees.tests.common import SMALLEST_POSITIVE_65_BITS + from BTrees.tests.common import LARGEST_64_BITS + from BTrees.tests.common import LARGEST_NEGATIVE_65_BITS + btree = self._makeOne() + btree['ZERO'] = 0 + btree['SMALLEST_64_BITS'] = 0 + btree['LARGEST_64_BITS'] = LARGEST_64_BITS + btree['SMALLEST_POSITIVE_65_BITS'] = SMALLEST_POSITIVE_65_BITS + with self.assertRaises((ValueError, OverflowError)): + btree['TOO_BIG'] = 2**65 + + self.assertRaises((ValueError, OverflowError), btree.__setitem__, + 'LARGEST_NEGATIVE_65_BITS', LARGEST_NEGATIVE_65_BITS) + + +class OQBTreePyTest(BTreeTests, TestLongIntValues, unittest.TestCase): + + def _makeOne(self): + from BTrees.OQBTree import OQBTreePy + return OQBTreePy() + + def getTwoKeys(self): + return "abc", "def" + + +class PureOQ(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.OQBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.OQBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.OQBTree import difference + return difference(*args) + + def builders(self): + from BTrees.OQBTree import OQBTree + from BTrees.OQBTree import OQBucket + from BTrees.OQBTree import OQTreeSet + from BTrees.OQBTree import OQSet + return OQSet, OQTreeSet, makeBuilder(OQBTree), makeBuilder(OQBucket) + + +class PureOQPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.OQBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.OQBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.OQBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.OQBTree import OQBTreePy + from BTrees.OQBTree import OQBucketPy + from BTrees.OQBTree import OQTreeSetPy + from BTrees.OQBTree import OQSetPy + return (OQSetPy, OQTreeSetPy, + makeBuilder(OQBTreePy), makeBuilder(OQBucketPy)) + + +class TestWeightedOQ(UnsignedValuesMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.OQBTree import weightedUnion + return weightedUnion + + def weightedIntersection(self): + from BTrees.OQBTree import weightedIntersection + return weightedIntersection + + def union(self): + from BTrees.OQBTree import union + return union + + def intersection(self): + from BTrees.OQBTree import intersection + return intersection + + def mkbucket(self, *args): + from BTrees.OQBTree import OQBucket as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.OQBTree import OQBTree + from BTrees.OQBTree import OQBucket + from BTrees.OQBTree import OQTreeSet + from BTrees.OQBTree import OQSet + return OQBucket, OQBTree, itemsToSet(OQSet), itemsToSet(OQTreeSet) + + +class TestWeightedOQPy(Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.OQBTree import weightedUnionPy + return weightedUnionPy + + def weightedIntersection(self): + from BTrees.OQBTree import weightedIntersectionPy + return weightedIntersectionPy + + def union(self): + from BTrees.OQBTree import unionPy + return unionPy + + def intersection(self): + from BTrees.OQBTree import intersectionPy + return intersectionPy + + def mkbucket(self, *args): + from BTrees.OQBTree import OQBucketPy as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.OQBTree import OQBTreePy + from BTrees.OQBTree import OQBucketPy + from BTrees.OQBTree import OQTreeSetPy + from BTrees.OQBTree import OQSetPy + return (OQBucketPy, OQBTreePy, + itemsToSet(OQSetPy), itemsToSet(OQTreeSetPy)) + + +class OQBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQBucket + return OQBucket + + +class OQBucketPyConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQBucketPy + return OQBucketPy + + +class OQSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQSet + return OQSet + + +class OQSetPyConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQSetPy + return OQSetPy + + +class OQBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQBTree + return OQBTree + + +class OQBTreePyConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQBTreePy + return OQBTreePy + + +class OQTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQTreeSet + return OQTreeSet + + +class OQTreeSetPyConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OQBTree import OQTreeSetPy + return OQTreeSetPy + + +class OQModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'OQ' + + def _getModule(self): + import BTrees + return BTrees.OQBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IObjectUnsignedBTreeModule + + def test_multiunion_not_present(self): + try: + from BTrees.OQBTree import multiunion + except ImportError: + pass + else: + self.fail("OQBTree shouldn't have multiunion") diff --git a/BTrees/tests/test_OUBTree.py b/BTrees/tests/test_OUBTree.py new file mode 100644 index 0000000..f035e92 --- /dev/null +++ b/BTrees/tests/test_OUBTree.py @@ -0,0 +1,320 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + + +from .common import UnsignedValuesBTreeTests as BTreeTests +from .common import ExtendedSetTests +from .common import InternalKeysMappingTest +from .common import UnsignedValuesMappingBase as MappingBase +from .common import UnsignedValuesMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import NormalSetTests +from .common import SetConflictTestBase +from .common import SetResult +from .common import TestLongIntValues +from .common import TypeTest +from .common import Weighted +from .common import itemsToSet +from .common import makeBuilder +from .common import UnsignedValuesMixin + + +class OUBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUBTree + return OUBTree + + +class OUBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUBTreePy + return OUBTreePy + + +class OUBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUBucket + return OUBucket + + +class OUBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUBucketPy + return OUBucketPy + + +class OUTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUTreeSet + return OUTreeSet + + +class OUTreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUTreeSetPy + return OUTreeSetPy + + +class OUSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUSet + return OUSet + + +class OUSetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUSetPy + return OUSetPy + + +class OUBTreeTest(BTreeTests, unittest.TestCase): + + def _makeOne(self): + from BTrees.OUBTree import OUBTree + return OUBTree() + + +class OUBTreePyTest(BTreeTests, unittest.TestCase): + def _makeOne(self): + from BTrees.OUBTree import OUBTreePy + return OUBTreePy() + + +class _TestOUBTreesBase(TypeTest): + + def _stringraises(self): + self._makeOne()[1] = 'c' + + def _floatraises(self): + self._makeOne()[1] = 1.4 + + def _noneraises(self): + self._makeOne()[1] = None + + def testEmptyFirstBucketReportedByGuido(self): + from .._compat import xrange + b = self._makeOne() + for i in xrange(29972): # reduce to 29971 and it works + b[i] = i + for i in xrange(30): # reduce to 29 and it works + del b[i] + b[i+40000] = i + + self.assertEqual(b.keys()[0], 30) + + +class TestOUBTrees(_TestOUBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.OUBTree import OUBTree + return OUBTree() + + +class TestOUBTreesPy(_TestOUBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.OUBTree import OUBTreePy + return OUBTreePy() + + +class PureOU(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.OUBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.OUBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.OUBTree import difference + return difference(*args) + + def builders(self): + from BTrees.OUBTree import OUBTree + from BTrees.OUBTree import OUBucket + from BTrees.OUBTree import OUTreeSet + from BTrees.OUBTree import OUSet + return OUSet, OUTreeSet, makeBuilder(OUBTree), makeBuilder(OUBucket) + + +class PureOUPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.OUBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.OUBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.OUBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.OUBTree import OUBTreePy + from BTrees.OUBTree import OUBucketPy + from BTrees.OUBTree import OUTreeSetPy + from BTrees.OUBTree import OUSetPy + return (OUSetPy, OUTreeSetPy, + makeBuilder(OUBTreePy), makeBuilder(OUBucketPy)) + + +class TestWeightedOU(UnsignedValuesMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.OUBTree import weightedUnion + return weightedUnion + + def weightedIntersection(self): + from BTrees.OUBTree import weightedIntersection + return weightedIntersection + + def union(self): + from BTrees.OUBTree import union + return union + + def intersection(self): + from BTrees.OUBTree import intersection + return intersection + + def mkbucket(self, *args): + from BTrees.OUBTree import OUBucket as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.OUBTree import OUBTree + from BTrees.OUBTree import OUBucket + from BTrees.OUBTree import OUTreeSet + from BTrees.OUBTree import OUSet + return OUBucket, OUBTree, itemsToSet(OUSet), itemsToSet(OUTreeSet) + + +class TestWeightedOUPy(Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.OUBTree import weightedUnionPy + return weightedUnionPy + + def weightedIntersection(self): + from BTrees.OUBTree import weightedIntersectionPy + return weightedIntersectionPy + + def union(self): + from BTrees.OUBTree import unionPy + return unionPy + + def intersection(self): + from BTrees.OUBTree import intersectionPy + return intersectionPy + + def mkbucket(self, *args): + from BTrees.OUBTree import OUBucketPy as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.OUBTree import OUBTreePy + from BTrees.OUBTree import OUBucketPy + from BTrees.OUBTree import OUTreeSetPy + from BTrees.OUBTree import OUSetPy + return (OUBucketPy, OUBTreePy, + itemsToSet(OUSetPy), itemsToSet(OUTreeSetPy)) + + +class OUBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUBucket + return OUBucket + + +class OUBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUBucketPy + return OUBucketPy + + +class OUSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUSet + return OUSet + + +class OUSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUSetPy + return OUSetPy + + +class OUBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUBTree + return OUBTree + + +class OUBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUBTreePy + return OUBTreePy + + +class OUTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUTreeSet + return OUTreeSet + + +class OUTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.OUBTree import OUTreeSetPy + return OUTreeSetPy + + +class OUModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'OU' + + def _getModule(self): + import BTrees + return BTrees.OUBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IObjectUnsignedBTreeModule + + def test_multiunion_not_present(self): + try: + from BTrees.OUBTree import multiunion + except ImportError: + pass + else: + self.fail("OUBTree shouldn't have multiunion") diff --git a/BTrees/tests/test_QFBTree.py b/BTrees/tests/test_QFBTree.py new file mode 100644 index 0000000..efb4aad --- /dev/null +++ b/BTrees/tests/test_QFBTree.py @@ -0,0 +1,273 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedKeysBTreeTests as BTreeTests +from .common import UnsignedExtendedSetTests as ExtendedSetTests +from .common import InternalKeysMappingTest +from .common import UnsignedKeysMappingBase as MappingBase +from .common import UnsignedKeysMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import UnsignedNormalSetTests as NormalSetTests +from .common import UnsignedSetConflictTestBase as SetConflictTestBase +from .common import SetResult +from .common import TestLongIntKeys +from .common import makeBuilder +from .common import UnsignedKeysMixin + +# pylint: disable=no-name-in-module,arguments-differ + +class QFBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFBTree + return QFBTree + + +class QFBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFBTreePy + return QFBTreePy + + +class QFBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFBucket + return QFBucket + + +class QFBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFBucketPy + return QFBucketPy + + +class QFTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFTreeSet + return QFTreeSet + + +class QFTreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFTreeSetPy + return QFTreeSetPy + + +class QFSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFSet + return QFSet + + +class QFSetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFSetPy + return QFSetPy + + +class QFBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase): + + def _makeOne(self): + from BTrees.QFBTree import QFBTree + return QFBTree() + + def getTwoValues(self): + return 0.5, 1.5 + + +class QFBTreePyTest(BTreeTests, TestLongIntKeys, unittest.TestCase): + + def _makeOne(self): + from BTrees.QFBTree import QFBTreePy + return QFBTreePy() + + def getTwoValues(self): + return 0.5, 1.5 + + +class TestQFMultiUnion(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.QFBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.QFBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.QFBTree import QFSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.QFBTree import QFTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.QFBTree import QFBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.QFBTree import QFBTreePy as mkbtree + return mkbtree(*args) + + +class TestQFMultiUnionPy(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.QFBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.QFBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.QFBTree import QFSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.QFBTree import QFTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.QFBTree import QFBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.QFBTree import QFBTreePy as mkbtree + return mkbtree(*args) + + +class PureQF(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.QFBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.QFBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.QFBTree import difference + return difference(*args) + + def builders(self): + from BTrees.QFBTree import QFBTree + from BTrees.QFBTree import QFBucket + from BTrees.QFBTree import QFTreeSet + from BTrees.QFBTree import QFSet + return QFSet, QFTreeSet, makeBuilder(QFBTree), makeBuilder(QFBucket) + + +class PureQFPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.QFBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.QFBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.QFBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.QFBTree import QFBTreePy + from BTrees.QFBTree import QFBucketPy + from BTrees.QFBTree import QFTreeSetPy + from BTrees.QFBTree import QFSetPy + return (QFSetPy, QFTreeSetPy, + makeBuilder(QFBTreePy), makeBuilder(QFBucketPy)) + + +class QFBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFBTree + return QFBTree + + +class QFBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFBTreePy + return QFBTreePy + + +class QFBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFBucket + return QFBucket + + +class QFBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFBucketPy + return QFBucketPy + + +class QFTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFTreeSet + return QFTreeSet + + +class QFTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFTreeSetPy + return QFTreeSetPy + + +class QFSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFSet + return QFSet + + +class QFSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QFBTree import QFSetPy + return QFSetPy + + +class QFModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'QF' + + def _getModule(self): + import BTrees + return BTrees.QFBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IUnsignedFloatBTreeModule diff --git a/BTrees/tests/test_QLBTree.py b/BTrees/tests/test_QLBTree.py new file mode 100644 index 0000000..4fad84c --- /dev/null +++ b/BTrees/tests/test_QLBTree.py @@ -0,0 +1,367 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import I_SetsBase +from .common import TestLongIntValues +from .common import Weighted +from .common import itemsToSet + +from .common import UnsignedKeysBTreeTests as BTreeTests +from .common import UnsignedExtendedSetTests as ExtendedSetTests +from .common import InternalKeysMappingTest +from .common import UnsignedKeysMappingBase as MappingBase +from .common import UnsignedKeysMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import UnsignedNormalSetTests as NormalSetTests +from .common import UnsignedSetConflictTestBase as SetConflictTestBase +from .common import SetResult +from .common import TestLongIntKeys +from .common import makeBuilder +from .common import UnsignedKeysMixin + +# pylint: disable=no-name-in-module,arguments-differ + +class QLBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLBTree + return QLBTree + + +class QLBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLBTreePy + return QLBTreePy + + +class QLBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLBucket + return QLBucket + + +class QLBucketTestPy(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLBucketPy + return QLBucketPy + + +class QLTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLTreeSet + return QLTreeSet + + +class QLTreeSetTestPy(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLTreeSetPy + return QLTreeSetPy + + +class QLSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLSet + return QLSet + + +class QLSetTestPy(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLSetPy + return QLSetPy + + +class QLBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues, + unittest.TestCase): + + def _makeOne(self): + from BTrees.QLBTree import QLBTree + return QLBTree() + def getTwoValues(self): + return 1, 2 + + +class QLBTreeTestPy(BTreeTests, TestLongIntKeys, TestLongIntValues, + unittest.TestCase): + + def _makeOne(self): + from BTrees.QLBTree import QLBTreePy + return QLBTreePy() + def getTwoValues(self): + return 1, 2 + + +class TestQLSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QLBTree import QLSet + return QLSet() + + +class TestQLSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QLBTree import QLSetPy + return QLSetPy() + + +class TestQLTreeSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QLBTree import QLTreeSet + return QLTreeSet() + + +class TestQLTreeSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QLBTree import QLTreeSetPy + return QLTreeSetPy() + + +class PureQL(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.QLBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.QLBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.QLBTree import difference + return difference(*args) + + def builders(self): + from BTrees.QLBTree import QLBTree + from BTrees.QLBTree import QLBucket + from BTrees.QLBTree import QLTreeSet + from BTrees.QLBTree import QLSet + return QLSet, QLTreeSet, makeBuilder(QLBTree), makeBuilder(QLBucket) + + +class PureQLPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.QLBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.QLBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.QLBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.QLBTree import QLBTreePy + from BTrees.QLBTree import QLBucketPy + from BTrees.QLBTree import QLTreeSetPy + from BTrees.QLBTree import QLSetPy + return (QLSetPy, QLTreeSetPy, + makeBuilder(QLBTreePy), makeBuilder(QLBucketPy)) + + +class TestQLMultiUnion(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.QLBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.QLBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.QLBTree import QLSet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.QLBTree import QLTreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.QLBTree import QLBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.QLBTree import QLBTree as mkbtree + return mkbtree(*args) + + +class TestQLMultiUnionPy(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.QLBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.QLBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.QLBTree import QLSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.QLBTree import QLTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.QLBTree import QLBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.QLBTree import QLBTreePy as mkbtree + return mkbtree(*args) + + +class TestWeightedQL(UnsignedKeysMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.QLBTree import weightedUnion + return weightedUnion + + def weightedIntersection(self): + from BTrees.QLBTree import weightedIntersection + return weightedIntersection + + def union(self): + from BTrees.QLBTree import union + return union + + def intersection(self): + from BTrees.QLBTree import intersection + return intersection + + def mkbucket(self, *args): + from BTrees.QLBTree import QLBucket as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.QLBTree import QLBTree + from BTrees.QLBTree import QLBucket + from BTrees.QLBTree import QLTreeSet + from BTrees.QLBTree import QLSet + return QLBucket, QLBTree, itemsToSet(QLSet), itemsToSet(QLTreeSet) + + +class TestWeightedQLPy(UnsignedKeysMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.QLBTree import weightedUnionPy + return weightedUnionPy + + def weightedIntersection(self): + from BTrees.QLBTree import weightedIntersectionPy + return weightedIntersectionPy + + def union(self): + from BTrees.QLBTree import unionPy + return unionPy + + def intersection(self): + from BTrees.QLBTree import intersectionPy + return intersectionPy + + def mkbucket(self, *args): + from BTrees.QLBTree import QLBucketPy as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.QLBTree import QLBTreePy + from BTrees.QLBTree import QLBucketPy + from BTrees.QLBTree import QLTreeSetPy + from BTrees.QLBTree import QLSetPy + return (QLBucketPy, QLBTreePy, + itemsToSet(QLSetPy), itemsToSet(QLTreeSetPy)) + + +class QLBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLBTree + return QLBTree + + +class QLBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLBTreePy + return QLBTreePy + + +class QLBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLBucket + return QLBucket + + +class QLBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLBucketPy + return QLBucketPy + + +class QLTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLTreeSet + return QLTreeSet + + +class QLTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLTreeSetPy + return QLTreeSetPy + + +class QLSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLSet + return QLSet + + +class QLSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QLBTree import QLSetPy + return QLSetPy + + +class QLModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'QL' + + def _getModule(self): + import BTrees + return BTrees.QLBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IUnsignedIntegerBTreeModule diff --git a/BTrees/tests/test_QOBTree.py b/BTrees/tests/test_QOBTree.py new file mode 100644 index 0000000..2fdc599 --- /dev/null +++ b/BTrees/tests/test_QOBTree.py @@ -0,0 +1,312 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedKeysBTreeTests as BTreeTests +from .common import UnsignedExtendedSetTests as ExtendedSetTests +from .common import I_SetsBase +from .common import InternalKeysMappingTest +from .common import UnsignedKeysMappingBase as MappingBase +from .common import UnsignedKeysMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import UnsignedNormalSetTests as NormalSetTests +from .common import UnsignedSetConflictTestBase as SetConflictTestBase +from .common import SetResult +from .common import TestLongIntKeys +from .common import makeBuilder +from .common import UnsignedKeysMixin + +# pylint:disable=no-name-in-module,arguments-differ + +class QOBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOBTree + return QOBTree + + +class QOBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOBTreePy + return QOBTreePy + + +class QOBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOBucket + return QOBucket + + +class QOBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOBucketPy + return QOBucketPy + + +class QOTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOTreeSet + return QOTreeSet + + +class QOTreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOTreeSetPy + return QOTreeSetPy + + +class QOSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOSet + return QOSet + + +class QOSetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOSetPy + return QOSetPy + + +class QOBTreeTest(BTreeTests, TestLongIntKeys, unittest.TestCase): + + def _makeOne(self): + from BTrees.QOBTree import QOBTree + return QOBTree() + + +class QOBTreePyTest(BTreeTests, TestLongIntKeys, unittest.TestCase): + + def _makeOne(self): + from BTrees.QOBTree import QOBTreePy + return QOBTreePy() + + +class TestQOSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QOBTree import QOSet + return QOSet() + + +class TestQOSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QOBTree import QOSetPy + return QOSetPy() + + +class TestQOTreeSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QOBTree import QOTreeSet + return QOTreeSet() + + +class TestQOTreeSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QOBTree import QOTreeSetPy + return QOTreeSetPy() + + +class TestQOMultiUnion(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.QOBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.QOBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.QOBTree import QOSet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.QOBTree import QOTreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.QOBTree import QOBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.QOBTree import QOBTree as mkbtree + return mkbtree(*args) + + +class TestQOMultiUnionPy(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.QOBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.QOBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.QOBTree import QOSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.QOBTree import QOTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.QOBTree import QOBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.QOBTree import QOBTreePy as mkbtree + return mkbtree(*args) + + +class PureQO(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.QOBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.QOBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.QOBTree import difference + return difference(*args) + + def builders(self): + from BTrees.QOBTree import QOBTree + from BTrees.QOBTree import QOBucket + from BTrees.QOBTree import QOTreeSet + from BTrees.QOBTree import QOSet + return QOSet, QOTreeSet, makeBuilder(QOBTree), makeBuilder(QOBucket) + + +class PureQOPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.QOBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.QOBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.QOBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.QOBTree import QOBTreePy + from BTrees.QOBTree import QOBucketPy + from BTrees.QOBTree import QOTreeSetPy + from BTrees.QOBTree import QOSetPy + return (QOSetPy, QOTreeSetPy, + makeBuilder(QOBTreePy), makeBuilder(QOBucketPy)) + + +class QOBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOBTree + return QOBTree + + +class QOBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOBTreePy + return QOBTreePy + + +class QOBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOBucket + return QOBucket + + +class QOBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOBucketPy + return QOBucketPy + + +class QOTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOTreeSet + return QOTreeSet + + +class QOTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOTreeSetPy + return QOTreeSetPy + + +class QOSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOSet + return QOSet + + +class QOSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QOBTree import QOSetPy + return QOSetPy + + +class QOModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'QO' + + def _getModule(self): + import BTrees + return BTrees.QOBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IUnsignedObjectBTreeModule + + def test_weightedUnion_not_present(self): + try: + from BTrees.QOBTree import weightedUnion + except ImportError: + pass + else: + self.fail("QOBTree shouldn't have weightedUnion") + + def test_weightedIntersection_not_present(self): + try: + from BTrees.QOBTree import weightedIntersection + except ImportError: + pass + else: + self.fail("QOBTree shouldn't have weightedIntersection") diff --git a/BTrees/tests/test_QQBTree.py b/BTrees/tests/test_QQBTree.py new file mode 100644 index 0000000..ed75f67 --- /dev/null +++ b/BTrees/tests/test_QQBTree.py @@ -0,0 +1,368 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## + +import unittest + +from .common import UnsignedBTreeTests as BTreeTests +from .common import UnsignedExtendedSetTests as ExtendedSetTests +from .common import I_SetsBase +from .common import InternalKeysMappingTest +from .common import UnsignedMappingBase as MappingBase +from .common import UnsignedMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import UnsignedNormalSetTests as NormalSetTests +from .common import UnsignedSetConflictTestBase as SetConflictTestBase +from .common import SetResult +from .common import TestLongIntKeys +from .common import TestLongIntValues +from .common import Weighted +from .common import itemsToSet +from .common import makeBuilder +from .common import UnsignedMixin + + +# pylint:disable=no-name-in-module,arguments-differ + +class QQBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQBTree + return QQBTree + + +class QQBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQBTreePy + return QQBTreePy + + +class QQBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQBucket + return QQBucket + + +class QQBucketTestPy(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQBucketPy + return QQBucketPy + + +class QQTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQTreeSet + return QQTreeSet + + +class QQTreeSetTestPy(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQTreeSetPy + return QQTreeSetPy + + +class QQSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQSet + return QQSet + + +class QQSetTestPy(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQSetPy + return QQSetPy + + +class QQBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues, + unittest.TestCase): + + def _makeOne(self): + from BTrees.QQBTree import QQBTree + return QQBTree() + def getTwoValues(self): + return 1, 2 + + +class QQBTreeTestPy(BTreeTests, TestLongIntKeys, TestLongIntValues, + unittest.TestCase): + + def _makeOne(self): + from BTrees.QQBTree import QQBTreePy + return QQBTreePy() + def getTwoValues(self): + return 1, 2 + + +class TestQQSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QQBTree import QQSet + return QQSet() + + +class TestQQSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QQBTree import QQSetPy + return QQSetPy() + + +class TestQQTreeSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QQBTree import QQTreeSet + return QQTreeSet() + + +class TestQQTreeSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.QQBTree import QQTreeSetPy + return QQTreeSetPy() + + +class PureQQ(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.QQBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.QQBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.QQBTree import difference + return difference(*args) + + def builders(self): + from BTrees.QQBTree import QQBTree + from BTrees.QQBTree import QQBucket + from BTrees.QQBTree import QQTreeSet + from BTrees.QQBTree import QQSet + return QQSet, QQTreeSet, makeBuilder(QQBTree), makeBuilder(QQBucket) + + +class PureQQPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.QQBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.QQBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.QQBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.QQBTree import QQBTreePy + from BTrees.QQBTree import QQBucketPy + from BTrees.QQBTree import QQTreeSetPy + from BTrees.QQBTree import QQSetPy + return (QQSetPy, QQTreeSetPy, + makeBuilder(QQBTreePy), makeBuilder(QQBucketPy)) + + +class TestQQMultiUnion(UnsignedMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.QQBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.QQBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.QQBTree import QQSet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.QQBTree import QQTreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.QQBTree import QQBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.QQBTree import QQBTree as mkbtree + return mkbtree(*args) + + +class TestQQMultiUnionPy(UnsignedMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.QQBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.QQBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.QQBTree import QQSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.QQBTree import QQTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.QQBTree import QQBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.QQBTree import QQBTreePy as mkbtree + return mkbtree(*args) + + +class TestWeightedQQ(UnsignedMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.QQBTree import weightedUnion + return weightedUnion + + def weightedIntersection(self): + from BTrees.QQBTree import weightedIntersection + return weightedIntersection + + def union(self): + from BTrees.QQBTree import union + return union + + def intersection(self): + from BTrees.QQBTree import intersection + return intersection + + def mkbucket(self, *args): + from BTrees.QQBTree import QQBucket as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.QQBTree import QQBTree + from BTrees.QQBTree import QQBucket + from BTrees.QQBTree import QQTreeSet + from BTrees.QQBTree import QQSet + return QQBucket, QQBTree, itemsToSet(QQSet), itemsToSet(QQTreeSet) + + +class TestWeightedQQPy(UnsignedMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.QQBTree import weightedUnionPy + return weightedUnionPy + + def weightedIntersection(self): + from BTrees.QQBTree import weightedIntersectionPy + return weightedIntersectionPy + + def union(self): + from BTrees.QQBTree import unionPy + return unionPy + + def intersection(self): + from BTrees.QQBTree import intersectionPy + return intersectionPy + + def mkbucket(self, *args): + from BTrees.QQBTree import QQBucketPy as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.QQBTree import QQBTreePy + from BTrees.QQBTree import QQBucketPy + from BTrees.QQBTree import QQTreeSetPy + from BTrees.QQBTree import QQSetPy + return (QQBucketPy, QQBTreePy, + itemsToSet(QQSetPy), itemsToSet(QQTreeSetPy)) + + +class QQBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQBTree + return QQBTree + + +class QQBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQBTreePy + return QQBTreePy + + +class QQBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQBucket + return QQBucket + + +class QQBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQBucketPy + return QQBucketPy + + +class QQTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQTreeSet + return QQTreeSet + + +class QQTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQTreeSetPy + return QQTreeSetPy + + +class QQSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQSet + return QQSet + + +class QQSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.QQBTree import QQSetPy + return QQSetPy + + +class QQModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'QQ' + + def _getModule(self): + import BTrees + return BTrees.QQBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IUnsignedUnsignedBTreeModule diff --git a/BTrees/tests/test_UFBTree.py b/BTrees/tests/test_UFBTree.py new file mode 100644 index 0000000..15813be --- /dev/null +++ b/BTrees/tests/test_UFBTree.py @@ -0,0 +1,313 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedKeysBTreeTests as BTreeTests +from .common import UnsignedExtendedSetTests as ExtendedSetTests +from .common import InternalKeysMappingTest +from .common import UnsignedKeysMappingBase as MappingBase +from .common import UnsignedKeysMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import UnsignedNormalSetTests as NormalSetTests +from .common import UnsignedSetConflictTestBase as SetConflictTestBase +from .common import SetResult +from .common import makeBuilder +from .common import UnsignedKeysMixin + + +# pylint:disable=no-name-in-module,arguments-differ + +class UFBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFBTree + return UFBTree + + +class UFBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFBTreePy + return UFBTreePy + + +class UFBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFBucket + return UFBucket + + +class UFBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFBucketPy + return UFBucketPy + + +class UFTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFTreeSet + return UFTreeSet + + +class UFTreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFTreeSetPy + return UFTreeSetPy + + +class UFSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFSet + return UFSet + + +class UFSetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFSetPy + return UFSetPy + + +class UFBTreeTest(BTreeTests, unittest.TestCase): + + def _makeOne(self): + from BTrees.UFBTree import UFBTree + return UFBTree() + + +class UFBTreePyTest(BTreeTests, unittest.TestCase): + + def _makeOne(self): + from BTrees.UFBTree import UFBTreePy + return UFBTreePy() + + +class _TestUFBTreesBase(object): + + def testNonIntegerKeyRaises(self): + self.assertRaises(TypeError, self._stringraiseskey) + self.assertRaises(TypeError, self._floatraiseskey) + self.assertRaises(TypeError, self._noneraiseskey) + + def testNonNumericValueRaises(self): + self.assertRaises(TypeError, self._stringraisesvalue) + self.assertRaises(TypeError, self._noneraisesvalue) + self._makeOne()[1] = 1 + self._makeOne()[1] = 1.0 + + def _stringraiseskey(self): + self._makeOne()['c'] = 1 + + def _floatraiseskey(self): + self._makeOne()[2.5] = 1 + + def _noneraiseskey(self): + self._makeOne()[None] = 1 + + def _stringraisesvalue(self): + self._makeOne()[1] = 'c' + + def _floatraisesvalue(self): + self._makeOne()[1] = 1.4 + + def _noneraisesvalue(self): + self._makeOne()[1] = None + + +class TestUFBTrees(_TestUFBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UFBTree import UFBTree + return UFBTree() + + +class TestUFBTreesPy(_TestUFBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UFBTree import UFBTreePy + return UFBTreePy() + + +class TestUFMultiUnion(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.UFBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.UFBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.UFBTree import UFSet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.UFBTree import UFTreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.UFBTree import UFBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.UFBTree import UFBTree as mkbtree + return mkbtree(*args) + + +class TestUFMultiUnionPy(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.UFBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.UFBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.UFBTree import UFSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.UFBTree import UFTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.UFBTree import UFBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.UFBTree import UFBTreePy as mkbtree + return mkbtree(*args) + + +class PureUF(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.UFBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.UFBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.UFBTree import difference + return difference(*args) + + def builders(self): + from BTrees.UFBTree import UFBTree + from BTrees.UFBTree import UFBucket + from BTrees.UFBTree import UFTreeSet + from BTrees.UFBTree import UFSet + return UFSet, UFTreeSet, makeBuilder(UFBTree), makeBuilder(UFBucket) + + +class PureUFPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.UFBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.UFBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.UFBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.UFBTree import UFBTreePy + from BTrees.UFBTree import UFBucketPy + from BTrees.UFBTree import UFTreeSetPy + from BTrees.UFBTree import UFSetPy + return (UFSetPy, UFTreeSetPy, + makeBuilder(UFBTreePy), makeBuilder(UFBucketPy)) + + +class UFBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFBTree + return UFBTree + + +class UFBTreePyConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFBTreePy + return UFBTreePy + + +class UFBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFBucket + return UFBucket + + +class UFBucketPyConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFBucketPy + return UFBucketPy + + +class UFTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFTreeSet + return UFTreeSet + + +class UFTreeSetPyConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFTreeSetPy + return UFTreeSetPy + + +class UFSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFSet + return UFSet + + +class UFSetPyConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UFBTree import UFSetPy + return UFSetPy + + +class UFModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'UF' + + def _getModule(self): + import BTrees + return BTrees.UFBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IUnsignedFloatBTreeModule diff --git a/BTrees/tests/test_UIBTree.py b/BTrees/tests/test_UIBTree.py new file mode 100644 index 0000000..5f822ee --- /dev/null +++ b/BTrees/tests/test_UIBTree.py @@ -0,0 +1,437 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedKeysBTreeTests as BTreeTests +from .common import UnsignedExtendedSetTests as ExtendedSetTests +from .common import I_SetsBase +from .common import InternalKeysMappingTest +from .common import UnsignedKeysMappingBase as MappingBase +from .common import UnsignedKeysMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import UnsignedNormalSetTests as NormalSetTests +from .common import UnsignedSetConflictTestBase as SetConflictTestBase +from .common import SetResult +from .common import Weighted +from .common import itemsToSet +from .common import makeBuilder +from .common import UnsignedKeysMixin +from .common import UnsignedError + + + +# pylint:disable=no-name-in-module,arguments-differ + +class UIBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UIBTree + return UIBTree + + +class UIBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UIBTreePy + return UIBTreePy + + +class UIBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UIBucket + return UIBucket + + +class UIBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UIBucketPy + return UIBucketPy + + +class UITreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UITreeSet + return UITreeSet + + +class UITreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UITreeSetPy + return UITreeSetPy + + +class UISetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UISet + return UISet + + +class UISetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UISetPy + return UISetPy + + +class _UIBTreeTestBase(BTreeTests): + + def testUIBTreeOverflow(self): + good = set() + b = self._makeOne() + + def trial(i): + i = int(i) + try: + b[i] = 0 + except (UnsignedError): + __traceback_info__ = i + if i > 2 ** 31: + with self.assertRaises(UnsignedError): + b[0] = i + else: + good.add(i) + if i < 2 ** 31: + b[0] = i + self.assertEqual(b[0], i) + else: + with self.assertRaises(UnsignedError): + b[0] = i + + for i in range((1<<31) - 3, (1<<31) + 3): + trial(i) + trial(-i) + + del b[0] + self.assertEqual(sorted(good), sorted(b)) + + +class UIBTreeTest(_UIBTreeTestBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UIBTree import UIBTree + return UIBTree() + + +class UIBTreeTestPy(_UIBTreeTestBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UIBTree import UIBTreePy + return UIBTreePy() + + +class _TestUIBTreesBase(object): + + def testNonIntegerKeyRaises(self): + self.assertRaises(TypeError, self._stringraiseskey) + self.assertRaises(TypeError, self._floatraiseskey) + self.assertRaises(TypeError, self._noneraiseskey) + + def testNonIntegerValueRaises(self): + self.assertRaises(TypeError, self._stringraisesvalue) + self.assertRaises(TypeError, self._floatraisesvalue) + self.assertRaises(TypeError, self._noneraisesvalue) + + def _stringraiseskey(self): + self._makeOne()['c'] = 1 + + def _floatraiseskey(self): + self._makeOne()[2.5] = 1 + + def _noneraiseskey(self): + self._makeOne()[None] = 1 + + def _stringraisesvalue(self): + self._makeOne()[1] = 'c' + + def _floatraisesvalue(self): + self._makeOne()[1] = 1.4 + + def _noneraisesvalue(self): + self._makeOne()[1] = None + + +class TestUIBTrees(_TestUIBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UIBTree import UIBTree + return UIBTree() + + +class TestUIBTreesPy(_TestUIBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UIBTree import UIBTreePy + return UIBTreePy() + + +class TestUISets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UIBTree import UISet + return UISet() + + +class TestUISetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UIBTree import UISetPy + return UISetPy() + + +class TestUITreeSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UIBTree import UITreeSet + return UITreeSet() + + +class TestUITreeSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UIBTree import UITreeSetPy + return UITreeSetPy() + + +class PureUI(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.UIBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.UIBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.UIBTree import difference + return difference(*args) + + def builders(self): + from BTrees.UIBTree import UIBTree + from BTrees.UIBTree import UIBucket + from BTrees.UIBTree import UITreeSet + from BTrees.UIBTree import UISet + return UISet, UITreeSet, makeBuilder(UIBTree), makeBuilder(UIBucket) + + +class PureUIPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.UIBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.UIBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.UIBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.UIBTree import UIBTreePy + from BTrees.UIBTree import UIBucketPy + from BTrees.UIBTree import UITreeSetPy + from BTrees.UIBTree import UISetPy + return (UISetPy, UITreeSetPy, + makeBuilder(UIBTreePy), makeBuilder(UIBucketPy)) + + +class TestUIMultiUnion(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.UIBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.UIBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.UIBTree import UISet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.UIBTree import UITreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.UIBTree import UIBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.UIBTree import UIBTree as mkbtree + return mkbtree(*args) + + +class TestUIMultiUnionPy(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.UIBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.UIBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.UIBTree import UISetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.UIBTree import UITreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.UIBTree import UIBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.UIBTree import UIBTreePy as mkbtree + return mkbtree(*args) + + +class TestWeightedUI(UnsignedKeysMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.UIBTree import weightedUnion + return weightedUnion + + def weightedIntersection(self): + from BTrees.UIBTree import weightedIntersection + return weightedIntersection + + def union(self): + from BTrees.UIBTree import union + return union + + def intersection(self): + from BTrees.UIBTree import intersection + return intersection + + def mkbucket(self, *args): + from BTrees.UIBTree import UIBucket as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.UIBTree import UIBTree + from BTrees.UIBTree import UIBucket + from BTrees.UIBTree import UITreeSet + from BTrees.UIBTree import UISet + return UIBucket, UIBTree, itemsToSet(UISet), itemsToSet(UITreeSet) + + +class TestWeightedUIPy(Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.UIBTree import weightedUnionPy + return weightedUnionPy + + def weightedIntersection(self): + from BTrees.UIBTree import weightedIntersectionPy + return weightedIntersectionPy + + def union(self): + from BTrees.UIBTree import unionPy + return unionPy + + def intersection(self): + from BTrees.UIBTree import intersectionPy + return intersectionPy + + def mkbucket(self, *args): + from BTrees.UIBTree import UIBucketPy as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.UIBTree import UIBTreePy + from BTrees.UIBTree import UIBucketPy + from BTrees.UIBTree import UITreeSetPy + from BTrees.UIBTree import UISetPy + return (UIBucketPy, UIBTreePy, + itemsToSet(UISetPy), itemsToSet(UITreeSetPy)) + + +class UIBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UIBTree + return UIBTree + + +class UIBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UIBTreePy + return UIBTreePy + + +class UIBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UIBucket + return UIBucket + + +class UIBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UIBucketPy + return UIBucketPy + + +class UITreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UITreeSet + return UITreeSet + + +class UITreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UITreeSetPy + return UITreeSetPy + + +class UISetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UISet + return UISet + + +class UISetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UIBTree import UISetPy + return UISetPy + + +class UIModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'UI' + + def _getModule(self): + import BTrees + return BTrees.UIBTree + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IUnsignedIntegerBTreeModule diff --git a/BTrees/tests/test_UOBTree.py b/BTrees/tests/test_UOBTree.py new file mode 100644 index 0000000..37ef33b --- /dev/null +++ b/BTrees/tests/test_UOBTree.py @@ -0,0 +1,349 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedKeysBTreeTests as BTreeTests +from .common import UnsignedExtendedSetTests as ExtendedSetTests +from .common import I_SetsBase +from .common import InternalKeysMappingTest +from .common import UnsignedKeysMappingBase as MappingBase +from .common import UnsignedKeysMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import UnsignedNormalSetTests as NormalSetTests +from .common import UnsignedSetConflictTestBase as SetConflictTestBase +from .common import SetResult +from .common import TypeTest +from .common import TestLongIntKeys +from .common import makeBuilder +from .common import UnsignedKeysMixin +from .common import UnsignedError + + +# pylint:disable=no-name-in-module,arguments-differ + +class UOBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOBTree + return UOBTree + + +class UOBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOBTreePy + return UOBTreePy + + +class UOBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOBucket + return UOBucket + + +class UOBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOBucketPy + return UOBucketPy + + +class UOTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOTreeSet + return UOTreeSet + + +class UOTreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOTreeSetPy + return UOTreeSetPy + + +class UOSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOSet + return UOSet + + +class UOSetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOSetPy + return UOSetPy + + +class UOBTreeTest(BTreeTests, unittest.TestCase): + + def _makeOne(self): + from BTrees.UOBTree import UOBTree + return UOBTree() + + +class UOBTreePyTest(BTreeTests, unittest.TestCase): + + def _makeOne(self): + from BTrees.UOBTree import UOBTreePy + return UOBTreePy() + + +class _TestUOBTreesBase(TypeTest): + + def _stringraises(self): + self._makeOne()['c'] = 1 + + def _floatraises(self): + self._makeOne()[2.5] = 1 + + def _noneraises(self): + self._makeOne()[None] = 1 + + def testStringAllowedInContains(self): + self.assertFalse('key' in self._makeOne()) + + def testStringKeyRaisesKeyErrorWhenMissing(self): + self.assertRaises(KeyError, self._makeOne().__getitem__, 'key') + + def testStringKeyReturnsDefaultFromGetWhenMissing(self): + self.assertEqual(self._makeOne().get('key', 42), 42) + +class TestUOBTrees(_TestUOBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UOBTree import UOBTree + return UOBTree() + + +class TestUOBTreesPy(_TestUOBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UOBTree import UOBTreePy + return UOBTreePy() + + +class TestUOSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UOBTree import UOSet + return UOSet() + + +class TestUOSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UOBTree import UOSetPy + return UOSetPy() + + +class TestUOTreeSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UOBTree import UOTreeSet + return UOTreeSet() + + +class TestUOTreeSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UOBTree import UOTreeSetPy + return UOTreeSetPy() + + +class PureUO(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.UOBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.UOBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.UOBTree import difference + return difference(*args) + + def builders(self): + from BTrees.UOBTree import UOBTree + from BTrees.UOBTree import UOBucket + from BTrees.UOBTree import UOTreeSet + from BTrees.UOBTree import UOSet + return UOSet, UOTreeSet, makeBuilder(UOBTree), makeBuilder(UOBucket) + + +class PureUOPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.UOBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.UOBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.UOBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.UOBTree import UOBTreePy + from BTrees.UOBTree import UOBucketPy + from BTrees.UOBTree import UOTreeSetPy + from BTrees.UOBTree import UOSetPy + return (UOSetPy, UOTreeSetPy, + makeBuilder(UOBTreePy), makeBuilder(UOBucketPy)) + + +class TestUOMultiUnion(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.UOBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.UOBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.UOBTree import UOSet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.UOBTree import UOTreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.UOBTree import UOBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.UOBTree import UOBTree as mkbtree + return mkbtree(*args) + + +class TestUOMultiUnionPy(UnsignedKeysMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.UOBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.UOBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.UOBTree import UOSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.UOBTree import UOTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.UOBTree import UOBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.UOBTree import UOBTreePy as mkbtree + return mkbtree(*args) + + +class UOBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOBTree + return UOBTree + + +class UOBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOBTreePy + return UOBTreePy + + +class UOBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOBucket + return UOBucket + + +class UOBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOBucketPy + return UOBucketPy + + +class UOTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOTreeSet + return UOTreeSet + + +class UOTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOTreeSetPy + return UOTreeSetPy + + +class UOSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOSet + return UOSet + + +class UOSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UOBTree import UOSetPy + return UOSetPy + + +class UOModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'UO' + + def _getModule(self): + import BTrees + return BTrees.UOBTree + + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IUnsignedObjectBTreeModule + + def test_weightedUnion_not_present(self): + try: + from BTrees.UOBTree import weightedUnion + except ImportError: + pass + else: + self.fail("UOBTree shouldn't have weightedUnion") + + def test_weightedIntersection_not_present(self): + try: + from BTrees.UOBTree import weightedIntersection + except ImportError: + pass + else: + self.fail("UOBTree shouldn't have weightedIntersection") diff --git a/BTrees/tests/test_UUBTree.py b/BTrees/tests/test_UUBTree.py new file mode 100644 index 0000000..0ce0d9e --- /dev/null +++ b/BTrees/tests/test_UUBTree.py @@ -0,0 +1,432 @@ +############################################################################## +# +# Copyright (c) 2001-2012 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +import unittest + +from .common import UnsignedBTreeTests as BTreeTests +from .common import UnsignedExtendedSetTests as ExtendedSetTests +from .common import I_SetsBase +from .common import InternalKeysMappingTest +from .common import UnsignedMappingBase as MappingBase +from .common import UnsignedMappingConflictTestBase as MappingConflictTestBase +from .common import ModuleTest +from .common import MultiUnion +from .common import UnsignedNormalSetTests as NormalSetTests +from .common import UnsignedSetConflictTestBase as SetConflictTestBase +from .common import SetResult +from .common import TestLongIntKeys +from .common import TestLongIntValues +from .common import Weighted +from .common import itemsToSet +from .common import makeBuilder +from .common import UnsignedMixin +from .common import UnsignedError + + + +class UUBTreeInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUBTree + return UUBTree + + +class UUBTreePyInternalKeyTest(InternalKeysMappingTest, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUBTreePy + return UUBTreePy + + +class UUBucketTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUBucket + return UUBucket + + +class UUBucketPyTest(MappingBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUBucketPy + return UUBucketPy + + +class UUTreeSetTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUTreeSet + return UUTreeSet + + +class UUTreeSetPyTest(NormalSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUTreeSetPy + return UUTreeSetPy + + +class UUSetTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUSet + return UUSet + + +class UUSetPyTest(ExtendedSetTests, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUSetPy + return UUSetPy + + +class _UUBTreeTestBase(BTreeTests): + + def testUUBTreeOverflow(self): + good = set() + b = self._makeOne() + + def trial(i): + i = int(i) + try: + b[i] = 0 + except UnsignedError: + with self.assertRaises(UnsignedError): + b[0] = i + else: + good.add(i) + b[0] = i + self.assertEqual(b[0], i) + + for i in range((1<<31) - 3, (1<<31) + 3): + __traceback_info__ = i + trial(i) + trial(-i) + + del b[0] + self.assertEqual(sorted(good), sorted(b)) + + +class UUBTreeTest(_UUBTreeTestBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UUBTree import UUBTree + return UUBTree() + + +class UUBTreeTestPy(_UUBTreeTestBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UUBTree import UUBTreePy + return UUBTreePy() + + +class _TestUUBTreesBase(object): + + def testNonIntegerKeyRaises(self): + self.assertRaises(TypeError, self._stringraiseskey) + self.assertRaises(TypeError, self._floatraiseskey) + self.assertRaises(TypeError, self._noneraiseskey) + + def testNonIntegerValueRaises(self): + self.assertRaises(TypeError, self._stringraisesvalue) + self.assertRaises(TypeError, self._floatraisesvalue) + self.assertRaises(TypeError, self._noneraisesvalue) + + def _stringraiseskey(self): + self._makeOne()['c'] = 1 + + def _floatraiseskey(self): + self._makeOne()[2.5] = 1 + + def _noneraiseskey(self): + self._makeOne()[None] = 1 + + def _stringraisesvalue(self): + self._makeOne()[1] = 'c' + + def _floatraisesvalue(self): + self._makeOne()[1] = 1.4 + + def _noneraisesvalue(self): + self._makeOne()[1] = None + + +class TestUUBTrees(_TestUUBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UUBTree import UUBTree + return UUBTree() + + +class TestUUBTreesPy(_TestUUBTreesBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UUBTree import UUBTreePy + return UUBTreePy() + + +class TestUUSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UUBTree import UUSet + return UUSet() + + +class TestUUSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UUBTree import UUSetPy + return UUSetPy() + + +class TestUUTreeSets(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UUBTree import UUTreeSet + return UUTreeSet() + + +class TestUUTreeSetsPy(I_SetsBase, unittest.TestCase): + + def _makeOne(self): + from BTrees.UUBTree import UUTreeSetPy + return UUTreeSetPy() + + +class PureUU(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.UUBTree import union + return union(*args) + + def intersection(self, *args): + from BTrees.UUBTree import intersection + return intersection(*args) + + def difference(self, *args): + from BTrees.UUBTree import difference + return difference(*args) + + def builders(self): + from BTrees.UUBTree import UUBTree + from BTrees.UUBTree import UUBucket + from BTrees.UUBTree import UUTreeSet + from BTrees.UUBTree import UUSet + return UUSet, UUTreeSet, makeBuilder(UUBTree), makeBuilder(UUBucket) + + +class PureUUPy(SetResult, unittest.TestCase): + + def union(self, *args): + from BTrees.UUBTree import unionPy + return unionPy(*args) + + def intersection(self, *args): + from BTrees.UUBTree import intersectionPy + return intersectionPy(*args) + + def difference(self, *args): + from BTrees.UUBTree import differencePy + return differencePy(*args) + + def builders(self): + from BTrees.UUBTree import UUBTreePy + from BTrees.UUBTree import UUBucketPy + from BTrees.UUBTree import UUTreeSetPy + from BTrees.UUBTree import UUSetPy + return (UUSetPy, UUTreeSetPy, + makeBuilder(UUBTreePy), makeBuilder(UUBucketPy)) + + +class TestUUMultiUnion(UnsignedMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.UUBTree import multiunion + return multiunion(*args) + + def union(self, *args): + from BTrees.UUBTree import union + return union(*args) + + def mkset(self, *args): + from BTrees.UUBTree import UUSet as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.UUBTree import UUTreeSet as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.UUBTree import UUBucket as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.UUBTree import UUBTree as mkbtree + return mkbtree(*args) + + +class TestUUMultiUnionPy(UnsignedMixin, MultiUnion, unittest.TestCase): + + def multiunion(self, *args): + from BTrees.UUBTree import multiunionPy + return multiunionPy(*args) + + def union(self, *args): + from BTrees.UUBTree import unionPy + return unionPy(*args) + + def mkset(self, *args): + from BTrees.UUBTree import UUSetPy as mkset + return mkset(*args) + + def mktreeset(self, *args): + from BTrees.UUBTree import UUTreeSetPy as mktreeset + return mktreeset(*args) + + def mkbucket(self, *args): + from BTrees.UUBTree import UUBucketPy as mkbucket + return mkbucket(*args) + + def mkbtree(self, *args): + from BTrees.UUBTree import UUBTreePy as mkbtree + return mkbtree(*args) + + +class TestWeightedUU(UnsignedMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.UUBTree import weightedUnion + return weightedUnion + + def weightedIntersection(self): + from BTrees.UUBTree import weightedIntersection + return weightedIntersection + + def union(self): + from BTrees.UUBTree import union + return union + + def intersection(self): + from BTrees.UUBTree import intersection + return intersection + + def mkbucket(self, *args): + from BTrees.UUBTree import UUBucket as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.UUBTree import UUBTree + from BTrees.UUBTree import UUBucket + from BTrees.UUBTree import UUTreeSet + from BTrees.UUBTree import UUSet + return UUBucket, UUBTree, itemsToSet(UUSet), itemsToSet(UUTreeSet) + + +class TestWeightedUUPy(UnsignedMixin, Weighted, unittest.TestCase): + + def weightedUnion(self): + from BTrees.UUBTree import weightedUnionPy + return weightedUnionPy + + def weightedIntersection(self): + from BTrees.UUBTree import weightedIntersectionPy + return weightedIntersectionPy + + def union(self): + from BTrees.UUBTree import unionPy + return unionPy + + def intersection(self): + from BTrees.UUBTree import intersectionPy + return intersectionPy + + def mkbucket(self, *args): + from BTrees.UUBTree import UUBucketPy as mkbucket + return mkbucket(*args) + + def builders(self): + from BTrees.UUBTree import UUBTreePy + from BTrees.UUBTree import UUBucketPy + from BTrees.UUBTree import UUTreeSetPy + from BTrees.UUBTree import UUSetPy + return (UUBucketPy, UUBTreePy, + itemsToSet(UUSetPy), itemsToSet(UUTreeSetPy)) + + +class UUBTreeConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUBTree + return UUBTree + + +class UUBTreeConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUBTreePy + return UUBTreePy + + +class UUBucketConflictTests(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUBucket + return UUBucket + + +class UUBucketConflictTestsPy(MappingConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUBucketPy + return UUBucketPy + + +class UUTreeSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUTreeSet + return UUTreeSet + + +class UUTreeSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUTreeSetPy + return UUTreeSetPy + + +class UUSetConflictTests(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUSet + return UUSet + + +class UUSetConflictTestsPy(SetConflictTestBase, unittest.TestCase): + + def _getTargetClass(self): + from BTrees.UUBTree import UUSetPy + return UUSetPy + + +class UUModuleTest(ModuleTest, unittest.TestCase): + + prefix = 'UU' + + def _getModule(self): + import BTrees + return BTrees.UUBTree + def _getInterface(self): + import BTrees.Interfaces + return BTrees.Interfaces.IUnsignedUnsignedBTreeModule diff --git a/BTrees/tests/test__base.py b/BTrees/tests/test__base.py index ccc2a62..f27c56e 100644 --- a/BTrees/tests/test__base.py +++ b/BTrees/tests/test__base.py @@ -2963,7 +2963,7 @@ def test_to_long_w_long_in_range(self): def test_to_long_w_overflow(self): from BTrees._base import to_long faux_self = object() - self.assertRaises(ValueError, to_long, faux_self, 2**64) + self.assertRaises(OverflowError, to_long, faux_self, 2**64) def test_to_long_w_invalid(self): from BTrees._base import to_long diff --git a/CHANGES.rst b/CHANGES.rst index ccc2d14..8dd2d21 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,14 +2,22 @@ BTrees Changelog ================== -4.6.2 (unreleased) +4.7.0 (unreleased) ================== -- Nothing changed yet. +- Add unsigned variants of the trees. These use the initial "U" for + 32-bit data and "Q" for 64-bit data (for "quad", which is similar to + what the C ``printf`` function uses and the Python struct module + uses). - Fix the value for ``BTrees.OIBTree.using64bits`` when using the pure Python implementation (PyPy and when ``PURE_PYTHON`` is in the environment). +- Make the errors that are raised when values are out of range more + consistent between Python 2 and Python 3 and between 32-bit and + 64-bit variants. + + 4.6.1 (2019-11-07) ================== diff --git a/doc-requirements.txt b/doc-requirements.txt index 5429a4e..7da0dda 100644 --- a/doc-requirements.txt +++ b/doc-requirements.txt @@ -1,3 +1,4 @@ +sphinx >= 1.8 pip>=8.1.2 setuptools>=23.0.0 repoze.sphinx.autointerface diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 0000000..9e467e0 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,9 @@ +/* + sphinx_rtd_theme pulls from wyrm, which applies white-space: nowrap to tables. + https://github.com/snide/wyrm/blob/fd41b56978f009e8c33cb26f384dd0dfaf430a7d/sass/wyrm_core/_table.sass#L144 + That makes it hard to have a table with more than three columns without + pointless scrolling. +*/ +.wrapped td, .wrapped th { + white-space: normal !important; +} diff --git a/docs/api.rst b/docs/api.rst index 1774616..39cdece 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -6,108 +6,151 @@ Protocol APIs ============= -.. automodule:: BTrees.Interfaces +.. module:: BTrees.Interfaces + +.. autointerface:: ICollection +.. autointerface:: IReadSequence +.. autointerface:: IKeyed +.. autointerface:: ISetMutable +.. autointerface:: ISized +.. autointerface:: IKeySequence +.. autointerface:: IMinimalDictionary +.. autointerface:: IDictionaryIsh +.. autointerface:: IMerge +.. autointerface:: IIMerge +.. autointerface:: IMergeIntegerKey + +BTree Family APIs +----------------- +.. autointerface:: ISet +.. autointerface:: ITreeSet +.. autointerface:: IBTree +.. autointerface:: IBTreeFamily + +There are two families defined: + +.. autodata:: BTrees.family32 +.. autodata:: BTrees.family64 + +Module APIs +----------- +.. autointerface:: IBTreeModule +.. autointerface:: IObjectObjectBTreeModule +.. autointerface:: IIntegerObjectBTreeModule +.. autointerface:: IObjectIntegerBTreeModule +.. autointerface:: IIntegerIntegerBTreeModule +.. autointerface:: IIntegerFloatBTreeModule - .. autointerface:: ICollection - :members: - :member-order: bysource - .. autointerface:: IReadSequence - :members: - :member-order: bysource +Utilities +========= - .. autointerface:: IKeyed - :members: - :member-order: bysource +.. automodule:: BTrees.Length - .. autointerface:: ISetMutable - :members: - :member-order: bysource +.. automodule:: BTrees.check - .. autointerface:: ISized - :members: - :member-order: bysource - .. autointerface:: IKeySequence - :members: - :member-order: bysource +BTree Data Structure Variants +============================= - .. autointerface:: IMinimalDictionary - :members: - :member-order: bysource +Integer Keys +------------ - .. autointerface:: IDictionaryIsh - :members: - :member-order: bysource +Float Values +~~~~~~~~~~~~ +.. automodule:: BTrees.IFBTree - .. autointerface:: IMerge - :members: - :member-order: bysource +Integer Values +~~~~~~~~~~~~~~ +.. automodule:: BTrees.IIBTree - .. autointerface:: IIMerge - :members: - :member-order: bysource +Object Values +~~~~~~~~~~~~~ +.. automodule:: BTrees.IOBTree - .. autointerface:: IMergeIntegerKey - :members: - :member-order: bysource +Unsigned Integer Values +~~~~~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.IUBTree - BTree Family APIs - ----------------- +Long Integer Keys +----------------- - .. autointerface:: ISet - :members: - :member-order: bysource +Float Values +~~~~~~~~~~~~ +.. automodule:: BTrees.LFBTree - .. autointerface:: ITreeSet - :members: - :member-order: bysource +Long Integer Values +~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.LLBTree - .. autointerface:: IBTree - :members: - :member-order: bysource - .. autointerface:: IBTreeFamily - :members: - :member-order: bysource +Object Values +~~~~~~~~~~~~~ +.. automodule:: BTrees.LOBTree - Module APIs - ----------- +Quad Unsigned Integer Values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.LQBTree - .. autointerface:: IBTreeModule - :members: - :member-order: bysource - .. autointerface:: IObjectObjectBTreeModule - :members: - :member-order: bysource +Object Keys +----------- - .. autointerface:: IIntegerObjectBTreeModule - :members: - :member-order: bysource +Integer Values +~~~~~~~~~~~~~~ +.. automodule:: BTrees.OIBTree - .. autointerface:: IObjectIntegerBTreeModule - :members: - :member-order: bysource +Long Integer Values +~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.OLBTree - .. autointerface:: IIntegerIntegerBTreeModule - :members: - :member-order: bysource +Object Values +~~~~~~~~~~~~~ +.. automodule:: BTrees.OOBTree - .. autointerface:: IIntegerFloatBTreeModule - :members: - :member-order: bysource +Quad Unsigned Integer Values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.OQBTree -Utilities -========= +Unsigned Integer Values +~~~~~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.OUBTree -.. automodule:: BTrees.Length - .. autoclass:: Length - :members: +Quad Unsigned Integer Keys +-------------------------- - .. automethod:: __call__ +Float Values +~~~~~~~~~~~~ +.. automodule:: BTrees.QFBTree +Long Integer Values +~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.QLBTree -.. automodule:: BTrees.check - :members: +Object Values +~~~~~~~~~~~~~ +.. automodule:: BTrees.QOBTree + +Quad Unsigned Integer Values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.QQBTree + +Unsigned Integer Keys +--------------------- + +Float Values +~~~~~~~~~~~~ +.. automodule:: BTrees.UFBTree + +Integer Values +~~~~~~~~~~~~~~ +.. automodule:: BTrees.UIBTree + +Object Values +~~~~~~~~~~~~~ +.. automodule:: BTrees.UOBTree + +Unsigned Integer Values +~~~~~~~~~~~~~~~~~~~~~~~ +.. automodule:: BTrees.UUBTree diff --git a/docs/conf.py b/docs/conf.py index b0c9634..1ca3dfc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,6 +12,14 @@ # serve to show the default. #import sys, os +import sys +import os +import pkg_resources +# We actually have slightly better results by documenting the +# C objects right now. +# os.environ['PURE_PYTHON'] = '1' +sys.path.append(os.path.abspath('../')) +rqmt = pkg_resources.require('BTrees')[0] # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -21,7 +29,7 @@ # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +needs_sphinx = '1.8' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. @@ -34,6 +42,18 @@ 'repoze.sphinx.autointerface', ] +# Sphinx 1.8+ prefers this to `autodoc_default_flags`. It's documented that +# either True or None mean the same thing as just setting the flag, but +# only None works in 1.8 (True works in 2.0) +autodoc_default_options = { + 'members': None, + 'show-inheritance': None, + 'special-members': None, + 'undoc-members': None, +} +autodoc_member_order = 'groupwise' +autoclass_content = 'both' + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -55,9 +75,9 @@ # built documents. # # The short X.Y version. -version = '4.0' +version = '%s.%s' % tuple(map(int, rqmt.version.split('.')[:2])) # The full version, including alpha/beta/rc tags. -release = '4.0.2dev' +release = rqmt.version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -128,6 +148,9 @@ # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] +html_css_files = [ + 'custom.css' +] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. diff --git a/docs/overview.rst b/docs/overview.rst index 1dbdcb6..249220b 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -14,40 +14,98 @@ important consequences -- see below). Nodes are then only unpickled and brought into memory as they're accessed, so the entire tree doesn't have to occupy memory (unless you really are touching every single key). -The BTrees package provides a large collection of related data structures. -There are variants of the data structures specialized to integers, which -are faster and use less memory. There are five modules that handle the -different variants. The first two letters of the module name specify the -types of the keys and values in mappings -- O for any object, I for 32-bit -signed integer, and (new in ZODB 3.4) F for 32-bit C float. For example, -the :mod:`BTrees.IOBTree` module provides a mapping with integer keys and -arbitrary objects as values. - -The four data structures provide by each module are a BTree, a Bucket, a -TreeSet, and a Set. The BTree and Bucket types are mappings and support -all the usual mapping methods, e.g. :func:`~BTrees.Interfaces.ISetMutable.update` and :func:`~BTrees.Interfaces.IKeyed.keys`. The -TreeSet and Set types are similar to mappings but they have no values; they -support the methods that make sense for a mapping with no keys, e.g. -:func:`~BTrees.Interfaces.IKeyed.keys` but not :func:`~BTrees.Interfaces.IMinimalDictionary.items`. The Bucket and Set types are the -individual building blocks for BTrees and TreeSets, respectively. A Bucket -or Set can be used when you are sure that it will have few elements. If -the data structure will grow large, you should use a BTree or TreeSet. Like -Python lists, Buckets and Sets are allocated in one contiguous piece, and -insertions and deletions can take time proportional to the number of -existing elements. Also like Python lists, a Bucket or Set is a single -object, and is pickled and unpickled in its entirety. BTrees and TreeSets -are multi-level tree structures with much better (logarithmic) worst- case -time bounds, and the tree structure is built out of multiple objects, which -ZODB can load individually as needed. - -The five modules are named :mod:`~BTrees.OOBTree`, :mod:`~BTrees.IOBTree`, :mod:`~BTrees.OIBTree`, -:mod:`~BTrees.IIBTree`, and (new in ZODB 3.4) :mod:`~BTrees.IFBTree`. The two letter -prefixes are repeated in the data types names. The :mod:`~BTrees.OOBTree` -module defines the following types: :class:`~BTrees.OOBTree.OOBTree`, :class:`~BTrees.OOBTree.OOBucket`, -:class:`~BTrees.OOBTree.OOSet`, and :class:`~BTrees.OOBTree.OOTreeSet`. Similarly, the other four modules +Related Data Structures +======================= + +The BTrees package provides a large collection of related data +structures. The most general data structures store arbitrary ordered_ +objects. There are variants of the data structures specialized to +numbers, which are faster and more memory efficient than those dealing +with objects. There are several modules that handle the different +variants. The first two letters of the module name specify the types +of the keys and values in mappings. For example, the +:mod:`BTrees.IOBTree` module provides a mapping with 32-bit integer +keys and arbitrary objects as values. + +.. list-table:: Data Type Notation + :widths: auto + :class: wrapped + :header-rows: 1 + + * - Letter + - Mnemonic Device + - Data Type + - Notes + * - O + - "Object" + - Any sortable Python object + - + * - I + - "Integer" + - 32-bit signed integer + - Values from ``-2**31 - 1`` through ``2**31 - 1`` (about plus or + minus two billion) + * - L + - "Long integer" + - 64-bit signed integer + - Values from ``-2**63 - 1`` through + ``2**63 - 1`` (about plus or minus nine quintillion) + * - F + - "Float" + - 32-bit C-language ``float`` + - New in ZODB 3.4 + * - U + - "Unsigned" + - 32-bit unsigned integer + - (New in BTrees 4.7.0) Values from 0 through ``2**32`` (about four billion) + * - Q + - "Quad" + - 64-bit unsigned integer + - Values from 0 through ``2**64`` (about 18 quintillion) (New in BTrees 4.7.0) + + +The four data structures provide by each module are a BTree, a Bucket, +a TreeSet, and a Set. The BTree and Bucket types are mappings and +support all the usual mapping methods, e.g. +:func:`~BTrees.Interfaces.ISetMutable.update` and +:func:`~BTrees.Interfaces.IKeyed.keys`. The TreeSet and Set types are +similar to mappings but they have no values; they support the methods +that make sense for a mapping with no keys, e.g. +:func:`~BTrees.Interfaces.IKeyed.keys` but not +:func:`~BTrees.Interfaces.IMinimalDictionary.items`. The Bucket and +Set types are the individual building blocks for BTrees and TreeSets, +respectively. A Bucket or Set can be used when you are sure that it +will have few elements. If the data structure will grow large, you +should use a BTree or TreeSet. Like Python lists, Buckets and Sets are +allocated in one contiguous piece, and insertions and deletions can +take time proportional to the number of existing elements. Also like +Python lists, a Bucket or Set is a single object, and is pickled and +unpickled in its entirety. BTrees and TreeSets are multi-level tree +structures with much better (logarithmic) worst- case time bounds, and +the tree structure is built out of multiple objects, which ZODB can +load individually as needed. + +The two letter prefixes are repeated in the data types names. For +example, the +:mod:`BTrees.OOBTree` module defines the following types: +:class:`BTrees.OOBTree.OOBTree`, :class:`BTrees.OOBTree.OOBucket`, +:class:`BTrees.OOBTree.OOSet`, and +:class:`BTrees.OOBTree.OOTreeSet`. Similarly, the other modules each define their own variants of those four types. -The :func:`keys`, :func:`values`, and :func:`items` methods on BTree and +For convenience, BTrees groups the most closely related data +structures together into a "family" (defined by +:class:`BTrees.Interfaces.IBTreeFamily`). :obj:`BTrees.family32` +groups 32-bit data structures, while :obj:`BTrees.family64` contains +64-bit data structures. It is a common practice for code that creates +BTrees to be parameterized on the family so that the caller can choose +the desired characteristics. + + +Behaviour +========= + +The `keys`, :func:`values`, and :func:`items` methods on BTree and TreeSet types do not materialize a list with all of the data. Instead, they return lazy sequences that fetch data from the BTree as needed. They also support optional arguments to specify the minimum and maximum values @@ -144,6 +202,7 @@ may not be true in future releases. If the interfaces don't specify a behavior, then whether that behavior appears to work, and exactly happens if it does appear to work, are undefined and should not be relied on. +.. _ordered: Total Ordering and Persistence ============================== @@ -375,7 +434,8 @@ BTree node sizes BTrees (and TreeSets) are made up of a tree of Buckets (and Sets) and internal nodes. There are maximum sizes of these notes configured for -the various key and value types: +the various key and value types (unsigned and quad unsigned follow +integer and long, respectively): ======== ========== ========================== ============================= Key Type Value Type Maximum Bucket or Set Size Maximum BTree or TreeSet Size diff --git a/setup.py b/setup.py index 80af198..44ee388 100644 --- a/setup.py +++ b/setup.py @@ -104,9 +104,44 @@ def __str__(self): "BTrees/sorters.c", ] -FLAVORS = {"O": "object", "I": "int", "F": "float", 'L': 'int'} +FLAVORS = { + "O": "object", + "F": "float", + "I": "int", # Signed 32-bit + "L": "int", # Signed 64-bit + "U": "int", # Unsigned 32-bit + "Q": "int" # Unsigned 64-bit (from the printf "q" modifier for quad_t) +} # XXX should 'fs' be in ZODB instead? -FAMILIES = ("OO", "IO", "OI", "II", "IF", "fs", "LO", "OL", "LL", "LF") +FAMILIES = ( + # Signed 32-bit keys + "IO", # object value + "II", # self value + "IF", # float value + "IU", # opposite sign value + # Unsigned 32-bit keys + "UO", # object value + "UU", # self value + "UF", # float value + "UI", # opposite sign value + # Signed 64-bit keys + "LO", # object value + "LL", # self value + "LF", # float value + "LQ", # opposite sign value + # Unsigned 64-bit keys + "QO", # object value + "QQ", # self value + "QF", # float value + "QL", # opposite sign value + # Object keys + "OO", # object + "OI", # 32-bit signed + "OU", # 32-bit unsigned + "OL", # 64-bit signed + "OQ", # 64-bit unsigned + "fs", +) KEY_H = "BTrees/%skeymacros.h" VALUE_H = "BTrees/%svaluemacros.h"