Commit 6b92cb69 authored by Toby Dickenson's avatar Toby Dickenson

long overdue merge of toby-cmp-error-branch. btrees no longer ignore...

long overdue merge of toby-cmp-error-branch. btrees no longer ignore exceptions raised by the key comparison function
parent 58112635
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
****************************************************************************/ ****************************************************************************/
#define BTREETEMPLATE_C "$Id: BTreeTemplate.c,v 1.29 2002/05/30 21:47:39 jim Exp $\n" #define BTREETEMPLATE_C "$Id: BTreeTemplate.c,v 1.30 2002/05/31 09:41:07 htrd Exp $\n"
/* /*
** _BTree_get ** _BTree_get
...@@ -34,7 +34,7 @@ _BTree_get(BTree *self, PyObject *keyarg, int has_key) ...@@ -34,7 +34,7 @@ _BTree_get(BTree *self, PyObject *keyarg, int has_key)
{ {
for (min=0, max=self->len, i=max/2; max-min > 1; i=(min+max)/2) for (min=0, max=self->len, i=max/2; max-min > 1; i=(min+max)/2)
{ {
cmp=TEST_KEY(self->data[i].key, key); TEST_KEY_SET_OR(cmp, self->data[i].key, key) return NULL;
if (cmp < 0) min=i; if (cmp < 0) min=i;
else if (cmp == 0) else if (cmp == 0)
{ {
...@@ -360,7 +360,7 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value, ...@@ -360,7 +360,7 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
for (min=0, max=self->len, i=max/2; max-min > 1; i=(max+min)/2) for (min=0, max=self->len, i=max/2; max-min > 1; i=(max+min)/2)
{ {
d=self->data+i; d=self->data+i;
cmp=TEST_KEY(d->key, key); TEST_KEY_SET_OR(cmp, d->key, key) return -1;
if (cmp < 0) min=i; if (cmp < 0) min=i;
else if (cmp==0) else if (cmp==0)
{ {
...@@ -838,7 +838,7 @@ BTree_findRangeEnd(BTree *self, PyObject *keyarg, int low, ...@@ -838,7 +838,7 @@ BTree_findRangeEnd(BTree *self, PyObject *keyarg, int low,
for (min=0, max=self->len, i=max/2; max-min > 1; i=(min+max)/2) for (min=0, max=self->len, i=max/2; max-min > 1; i=(min+max)/2)
{ {
cmp=TEST_KEY(self->data[i].key, key); TEST_KEY_SET_OR(cmp, self->data[i].key, key) return -1;
if (cmp < 0) min=i; if (cmp < 0) min=i;
else if (cmp == 0) else if (cmp == 0)
{ {
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
****************************************************************************/ ****************************************************************************/
#define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.29 2002/03/27 10:14:01 htrd Exp $\n" #define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.30 2002/05/31 09:41:07 htrd Exp $\n"
/* /*
** _bucket_get ** _bucket_get
...@@ -41,7 +41,7 @@ _bucket_get(Bucket *self, PyObject *keyarg, int has_key) ...@@ -41,7 +41,7 @@ _bucket_get(Bucket *self, PyObject *keyarg, int has_key)
for (min=0, max=self->len, i=max/2, l=max; i != l; l=i, i=(min+max)/2) for (min=0, max=self->len, i=max/2, l=max; i != l; l=i, i=(min+max)/2)
{ {
cmp=TEST_KEY(self->keys[i], key); TEST_KEY_SET_OR(cmp, self->keys[i], key) return NULL;
if (PyErr_Occurred()) goto err; if (PyErr_Occurred()) goto err;
if (cmp < 0) min=i; if (cmp < 0) min=i;
...@@ -137,7 +137,8 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v, ...@@ -137,7 +137,8 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
for (min=0, max=l=self->len, i=max/2; i != l; l=i, i=(min+max)/2) for (min=0, max=l=self->len, i=max/2; i != l; l=i, i=(min+max)/2)
{ {
if ((cmp=TEST_KEY(self->keys[i], key)) < 0) min=i; TEST_KEY_SET_OR(cmp, self->keys[i], key) return -1;
if (cmp < 0) min=i;
else if (cmp==0) else if (cmp==0)
{ {
if (v) /* Assign value to key */ if (v) /* Assign value to key */
...@@ -441,7 +442,7 @@ Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int *offset) ...@@ -441,7 +442,7 @@ Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int *offset)
for (min=0, max=self->len, i=max/2, l=max; i != l; l=i, i=(min+max)/2) for (min=0, max=self->len, i=max/2, l=max; i != l; l=i, i=(min+max)/2)
{ {
cmp=TEST_KEY(self->keys[i], key); TEST_KEY_SET_OR(cmp, self->keys[i], key) return -1;
if (cmp < 0) if (cmp < 0)
min=i; min=i;
else if (cmp == 0) else if (cmp == 0)
......
...@@ -30,7 +30,6 @@ DEFAULT_MAX_BTREE_SIZE ...@@ -30,7 +30,6 @@ DEFAULT_MAX_BTREE_SIZE
An int giving the maximum size (number of children) of an internal An int giving the maximum size (number of children) of an internal
btree node. Someday this will be tunable on BTree instances. btree node. Someday this will be tunable on BTree instances.
Macros for Keys Macros for Keys
KEY_TYPE KEY_TYPE
...@@ -42,12 +41,17 @@ Tests whether the PyObject* K can be converted to the (C) key type ...@@ -42,12 +41,17 @@ Tests whether the PyObject* K can be converted to the (C) key type
non-zero for true). When it returns false, its caller should probably non-zero for true). When it returns false, its caller should probably
set a TypeError exception. set a TypeError exception.
TEST_KEY(K, T) TEST_KEY_SET_OR(V, K, T)
Like Python's cmp(). Compares K(ey) to T(arget), where K & T are C Like Python's cmp(). Compares K(ey) to T(arget), where K & T are C
data values of type KEY_TYPE). Return an int data values of type KEY_TYPE).
< 0 if K < T < 0 if K < T
== 0 if K == T == 0 if K == T
> 0 if K > T > 0 if K > T
The value is assigned to V. This macro acts like an 'if',
where the following statement is executed only if a Python exception
has been raised because the values could not be compared.
DECREF_KEY(K) DECREF_KEY(K)
K is a value of KEY_TYPE. If KEY_TYPE is a flavor of PyObject*, write K is a value of KEY_TYPE. If KEY_TYPE is a flavor of PyObject*, write
...@@ -130,4 +134,4 @@ MULTI_INT_UNION ...@@ -130,4 +134,4 @@ MULTI_INT_UNION
The value doesn't matter. If defined, SetOpTemplate.c compiles The value doesn't matter. If defined, SetOpTemplate.c compiles
code for a multiunion() function (compute a union of many input sets code for a multiunion() function (compute a union of many input sets
at high speed). This currently makes sense only for II sets, so at high speed). This currently makes sense only for II sets, so
only _IIBTree.c defines it. only _IIBTree.c defines it.
\ No newline at end of file
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
****************************************************************************/ ****************************************************************************/
#define MERGETEMPLATE_C "$Id: MergeTemplate.c,v 1.9 2002/02/11 23:40:40 gvanrossum Exp $\n" #define MERGETEMPLATE_C "$Id: MergeTemplate.c,v 1.10 2002/05/31 09:41:07 htrd Exp $\n"
/**************************************************************************** /****************************************************************************
Set operations Set operations
...@@ -83,8 +83,8 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3) ...@@ -83,8 +83,8 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
while (i1.position >= 0 && i2.position >= 0 && i3.position >= 0) while (i1.position >= 0 && i2.position >= 0 && i3.position >= 0)
{ {
cmp12=TEST_KEY(i1.key, i2.key); TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
cmp13=TEST_KEY(i1.key, i3.key); TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
if (cmp12==0) if (cmp12==0)
{ {
if (cmp13==0) if (cmp13==0)
...@@ -142,7 +142,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3) ...@@ -142,7 +142,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
} }
else else
{ /* Both keys changed */ { /* Both keys changed */
cmp23=TEST_KEY(i2.key, i3.key); TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
if (cmp23==0) if (cmp23==0)
{ /* dualing inserts or deletes */ { /* dualing inserts or deletes */
merge_error(i1.position, i2.position, i3.position, 4); merge_error(i1.position, i2.position, i3.position, 4);
...@@ -176,7 +176,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3) ...@@ -176,7 +176,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
while (i2.position >= 0 && i3.position >= 0) while (i2.position >= 0 && i3.position >= 0)
{ /* New inserts */ { /* New inserts */
cmp23=TEST_KEY(i2.key, i3.key); TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
if (cmp23==0) if (cmp23==0)
{ /* dualing inserts */ { /* dualing inserts */
merge_error(i1.position, i2.position, i3.position, 6); merge_error(i1.position, i2.position, i3.position, 6);
...@@ -196,7 +196,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3) ...@@ -196,7 +196,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
while (i1.position >= 0 && i2.position >= 0) while (i1.position >= 0 && i2.position >= 0)
{ /* deleting i3 */ { /* deleting i3 */
cmp12=TEST_KEY(i1.key, i2.key); TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
if (cmp12 > 0) if (cmp12 > 0)
{ /* insert i2 */ { /* insert i2 */
if (merge_output(r, &i2, mapping) < 0) goto err; if (merge_output(r, &i2, mapping) < 0) goto err;
...@@ -216,7 +216,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3) ...@@ -216,7 +216,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
while (i1.position >= 0 && i3.position >= 0) while (i1.position >= 0 && i3.position >= 0)
{ /* deleting i2 */ { /* deleting i2 */
cmp13=TEST_KEY(i1.key, i3.key); TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
if (cmp13 > 0) if (cmp13 > 0)
{ /* insert i3 */ { /* insert i3 */
if (merge_output(r, &i3, mapping) < 0) goto err; if (merge_output(r, &i3, mapping) < 0) goto err;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
Set operations Set operations
****************************************************************************/ ****************************************************************************/
#define SETOPTEMPLATE_C "$Id: SetOpTemplate.c,v 1.13 2002/05/30 21:00:30 tim_one Exp $\n" #define SETOPTEMPLATE_C "$Id: SetOpTemplate.c,v 1.14 2002/05/31 09:41:07 htrd Exp $\n"
#ifdef INTSET_H #ifdef INTSET_H
static int static int
...@@ -223,7 +223,7 @@ set_operation(PyObject *s1, PyObject *s2, ...@@ -223,7 +223,7 @@ set_operation(PyObject *s1, PyObject *s2,
while (i1.position >= 0 && i2.position >= 0) while (i1.position >= 0 && i2.position >= 0)
{ {
cmp=TEST_KEY(i1.key, i2.key); TEST_KEY_SET_OR(cmp, i1.key, i2.key) return NULL;
if(cmp < 0) if(cmp < 0)
{ {
if(c1) if(c1)
......
...@@ -15,7 +15,7 @@ typedef unsigned char char6[6]; ...@@ -15,7 +15,7 @@ typedef unsigned char char6[6];
/* Setup template macros */ /* Setup template macros */
#define MASTER_ID "$Id: _fsBTree.c,v 1.2 2002/02/12 22:33:07 gvanrossum Exp $\n" #define MASTER_ID "$Id: _fsBTree.c,v 1.3 2002/05/31 09:41:07 htrd Exp $\n"
#define PERSISTENT #define PERSISTENT
...@@ -26,10 +26,10 @@ typedef unsigned char char6[6]; ...@@ -26,10 +26,10 @@ typedef unsigned char char6[6];
/*#include "intkeymacros.h"*/ /*#include "intkeymacros.h"*/
#define KEYMACROS_H "$Id: _fsBTree.c,v 1.2 2002/02/12 22:33:07 gvanrossum Exp $\n" #define KEYMACROS_H "$Id: _fsBTree.c,v 1.3 2002/05/31 09:41:07 htrd Exp $\n"
#define KEY_TYPE char2 #define KEY_TYPE char2
#define KEY_CHECK(K) (PyString_Check(K) && PyString_GET_SIZE(K)==2) #define KEY_CHECK(K) (PyString_Check(K) && PyString_GET_SIZE(K)==2)
#define TEST_KEY(K, T) ((*(K) < *(T) || (*(K) == *(T) && (K)[1] < (T)[1])) ? -1 : ((*(K) == *(T) && (K)[1] == (T)[1]) ? 0 : 1)) #define TEST_KEY_SET_OR(V, K, T) if ( ( (V) = ((*(K) < *(T) || (*(K) == *(T) && (K)[1] < (T)[1])) ? -1 : ((*(K) == *(T) && (K)[1] == (T)[1]) ? 0 : 1)) ), 0 )
#define DECREF_KEY(KEY) #define DECREF_KEY(KEY)
#define INCREF_KEY(k) #define INCREF_KEY(k)
#define COPY_KEY(KEY, E) (*(KEY)=*(E), (KEY)[1]=(E)[1]) #define COPY_KEY(KEY, E) (*(KEY)=*(E), (KEY)[1]=(E)[1])
...@@ -40,7 +40,7 @@ typedef unsigned char char6[6]; ...@@ -40,7 +40,7 @@ typedef unsigned char char6[6];
(STATUS)=0; } (STATUS)=0; }
/*#include "intvaluemacros.h"*/ /*#include "intvaluemacros.h"*/
#define VALUEMACROS_H "$Id: _fsBTree.c,v 1.2 2002/02/12 22:33:07 gvanrossum Exp $\n" #define VALUEMACROS_H "$Id: _fsBTree.c,v 1.3 2002/05/31 09:41:07 htrd Exp $\n"
#define VALUE_TYPE char6 #define VALUE_TYPE char6
#define TEST_VALUE(K, T) strncmp(K,T,6) #define TEST_VALUE(K, T) strncmp(K,T,6)
#define DECLARE_VALUE(NAME) VALUE_TYPE NAME #define DECLARE_VALUE(NAME) VALUE_TYPE NAME
......
#define KEYMACROS_H "$Id: intkeymacros.h,v 1.7 2001/10/10 20:36:58 jeremy Exp $\n" #define KEYMACROS_H "$Id: intkeymacros.h,v 1.8 2002/05/31 09:41:07 htrd Exp $\n"
#define KEY_TYPE int #define KEY_TYPE int
#define KEY_CHECK PyInt_Check #define KEY_CHECK PyInt_Check
#define TEST_KEY(K, T) (((K) < (T)) ? -1 : (((K) > (T)) ? 1: 0)) #define TEST_KEY_SET_OR(V, K, T) if ( ( (V) = (((K) < (T)) ? -1 : (((K) > (T)) ? 1: 0)) ) , 0 )
#define DECREF_KEY(KEY) #define DECREF_KEY(KEY)
#define INCREF_KEY(k) #define INCREF_KEY(k)
#define COPY_KEY(KEY, E) (KEY=(E)) #define COPY_KEY(KEY, E) (KEY=(E))
......
#define KEYMACROS_H "$Id: objectkeymacros.h,v 1.2 2001/03/20 13:52:00 jim Exp $\n" #define KEYMACROS_H "$Id: objectkeymacros.h,v 1.3 2002/05/31 09:41:07 htrd Exp $\n"
#define KEY_TYPE PyObject * #define KEY_TYPE PyObject *
#define TEST_KEY(KEY, TARGET) PyObject_Compare((KEY),(TARGET)) #define TEST_KEY_SET_OR(V, KEY, TARGET) if ( ( (V) = PyObject_Compare((KEY),(TARGET)) ), PyErr_Occurred() )
#define INCREF_KEY(k) Py_INCREF(k) #define INCREF_KEY(k) Py_INCREF(k)
#define DECREF_KEY(KEY) Py_DECREF(KEY) #define DECREF_KEY(KEY) Py_DECREF(KEY)
#define COPY_KEY(KEY, E) KEY=(E) #define COPY_KEY(KEY, E) KEY=(E)
......
...@@ -735,6 +735,23 @@ class TestOIBuckets(BucketTests, TestCase): ...@@ -735,6 +735,23 @@ class TestOIBuckets(BucketTests, TestCase):
def setUp(self): def setUp(self):
self.t = OIBucket() self.t = OIBucket()
# cmp error propagation tests
class DoesntLikeBeingCompared:
def __cmp__(self,other):
raise ValueError('incomparable')
class TestCmpError(TestCase):
def testFoo(self):
t = OOBTree()
t['hello world'] = None
try:
t[DoesntLikeBeingCompared()] = None
except ValueError,e:
assert str(e)=='incomparable'
else:
raise ValueError('incomarable objects should not be allowed into the tree')
def test_suite(): def test_suite():
TIOBTree = makeSuite(TestIOBTrees, 'test') TIOBTree = makeSuite(TestIOBTrees, 'test')
TOOBTree = makeSuite(TestOOBTrees, 'test') TOOBTree = makeSuite(TestOOBTrees, 'test')
...@@ -755,11 +772,13 @@ def test_suite(): ...@@ -755,11 +772,13 @@ def test_suite():
TOOBucket = makeSuite(TestOOBuckets, 'test') TOOBucket = makeSuite(TestOOBuckets, 'test')
TOIBucket = makeSuite(TestOIBuckets, 'test') TOIBucket = makeSuite(TestOIBuckets, 'test')
TIIBucket = makeSuite(TestIIBuckets, 'test') TIIBucket = makeSuite(TestIIBuckets, 'test')
alltests = TestSuite((TIOSet, TOOSet, TOISet, TIISet, alltests = TestSuite((TIOSet, TOOSet, TOISet, TIISet,
TIOTreeSet, TOOTreeSet, TOITreeSet, TIITreeSet, TIOTreeSet, TOOTreeSet, TOITreeSet, TIITreeSet,
TIOBucket, TOOBucket, TOIBucket, TIIBucket, TIOBucket, TOOBucket, TOIBucket, TIIBucket,
TOOBTree, TIOBTree, TOIBTree, TIIBTree)) TOOBTree, TIOBTree, TOIBTree, TIIBTree,
makeSuite(TestCmpError),
))
return alltests return alltests
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment