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 @@
****************************************************************************/
#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
......@@ -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)
{
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;
else if (cmp == 0)
{
......@@ -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)
{
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;
else if (cmp==0)
{
......@@ -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)
{
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;
else if (cmp == 0)
{
......
......@@ -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
......@@ -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)
{
cmp=TEST_KEY(self->keys[i], key);
TEST_KEY_SET_OR(cmp, self->keys[i], key) return NULL;
if (PyErr_Occurred()) goto err;
if (cmp < 0) min=i;
......@@ -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)
{
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)
{
if (v) /* Assign value to key */
......@@ -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)
{
cmp=TEST_KEY(self->keys[i], key);
TEST_KEY_SET_OR(cmp, self->keys[i], key) return -1;
if (cmp < 0)
min=i;
else if (cmp == 0)
......
......@@ -30,7 +30,6 @@ DEFAULT_MAX_BTREE_SIZE
An int giving the maximum size (number of children) of an internal
btree node. Someday this will be tunable on BTree instances.
Macros for Keys
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
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
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
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)
K is a value of KEY_TYPE. If KEY_TYPE is a flavor of PyObject*, write
......@@ -130,4 +134,4 @@ MULTI_INT_UNION
The value doesn't matter. If defined, SetOpTemplate.c compiles
code for a multiunion() function (compute a union of many input sets
at high speed). This currently makes sense only for II sets, so
only _IIBTree.c defines it.
\ No newline at end of file
only _IIBTree.c defines it.
......@@ -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
......@@ -83,8 +83,8 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
while (i1.position >= 0 && i2.position >= 0 && i3.position >= 0)
{
cmp12=TEST_KEY(i1.key, i2.key);
cmp13=TEST_KEY(i1.key, i3.key);
TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
if (cmp12==0)
{
if (cmp13==0)
......@@ -142,7 +142,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
}
else
{ /* Both keys changed */
cmp23=TEST_KEY(i2.key, i3.key);
TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
if (cmp23==0)
{ /* dualing inserts or deletes */
merge_error(i1.position, i2.position, i3.position, 4);
......@@ -176,7 +176,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
while (i2.position >= 0 && i3.position >= 0)
{ /* New inserts */
cmp23=TEST_KEY(i2.key, i3.key);
TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
if (cmp23==0)
{ /* dualing inserts */
merge_error(i1.position, i2.position, i3.position, 6);
......@@ -196,7 +196,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
while (i1.position >= 0 && i2.position >= 0)
{ /* deleting i3 */
cmp12=TEST_KEY(i1.key, i2.key);
TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
if (cmp12 > 0)
{ /* insert i2 */
if (merge_output(r, &i2, mapping) < 0) goto err;
......@@ -216,7 +216,7 @@ bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
while (i1.position >= 0 && i3.position >= 0)
{ /* deleting i2 */
cmp13=TEST_KEY(i1.key, i3.key);
TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
if (cmp13 > 0)
{ /* insert i3 */
if (merge_output(r, &i3, mapping) < 0) goto err;
......
......@@ -16,7 +16,7 @@
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
static int
......@@ -223,7 +223,7 @@ set_operation(PyObject *s1, PyObject *s2,
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(c1)
......
......@@ -15,7 +15,7 @@ typedef unsigned char char6[6];
/* 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
......@@ -26,10 +26,10 @@ typedef unsigned char char6[6];
/*#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_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 INCREF_KEY(k)
#define COPY_KEY(KEY, E) (*(KEY)=*(E), (KEY)[1]=(E)[1])
......@@ -40,7 +40,7 @@ typedef unsigned char char6[6];
(STATUS)=0; }
/*#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 TEST_VALUE(K, T) strncmp(K,T,6)
#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_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 INCREF_KEY(k)
#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 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 DECREF_KEY(KEY) Py_DECREF(KEY)
#define COPY_KEY(KEY, E) KEY=(E)
......
......@@ -735,6 +735,23 @@ class TestOIBuckets(BucketTests, TestCase):
def setUp(self):
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():
TIOBTree = makeSuite(TestIOBTrees, 'test')
TOOBTree = makeSuite(TestOOBTrees, 'test')
......@@ -755,11 +772,13 @@ def test_suite():
TOOBucket = makeSuite(TestOOBuckets, 'test')
TOIBucket = makeSuite(TestOIBuckets, 'test')
TIIBucket = makeSuite(TestIIBuckets, 'test')
alltests = TestSuite((TIOSet, TOOSet, TOISet, TIISet,
TIOTreeSet, TOOTreeSet, TOITreeSet, TIITreeSet,
TIOBucket, TOOBucket, TOIBucket, TIIBucket,
TOOBTree, TIOBTree, TOIBTree, TIIBTree))
TOOBTree, TIOBTree, TOIBTree, TIIBTree,
makeSuite(TestCmpError),
))
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