r818 - crux-2.2/ports/opt/python
Author: jue Date: 2006-02-24 09:54:10 +0100 (Fri, 24 Feb 2006) New Revision: 818 Added: crux-2.2/ports/opt/python/python-2.4.2-bsddb.patch Modified: crux-2.2/ports/opt/python/.md5sum crux-2.2/ports/opt/python/Pkgfile crux-2.2/ports/opt/python/python-2.4.2.patch Log: python: added patch for bdb 4.4.x Modified: crux-2.2/ports/opt/python/.md5sum =================================================================== --- crux-2.2/ports/opt/python/.md5sum 2006-02-24 08:17:08 UTC (rev 817) +++ crux-2.2/ports/opt/python/.md5sum 2006-02-24 08:54:10 UTC (rev 818) @@ -1,2 +1,3 @@ 98db1465629693fc434d4dc52db93838 Python-2.4.2.tar.bz2 -572d78932e9b229a9a8ed6fad2cac213 python-2.4.2.patch +3df7e7060e9a8dea0e46e1103b5bf7a0 python-2.4.2-bsddb.patch +84c40c182680d71e2d2330a4f38e5647 python-2.4.2.patch Modified: crux-2.2/ports/opt/python/Pkgfile =================================================================== --- crux-2.2/ports/opt/python/Pkgfile 2006-02-24 08:17:08 UTC (rev 817) +++ crux-2.2/ports/opt/python/Pkgfile 2006-02-24 08:54:10 UTC (rev 818) @@ -5,13 +5,16 @@ name=python version=2.4.2 -release=1 +release=2 source=(http://www.python.org/ftp/$name/$version/Python-$version.tar.bz2 \ - $name-$version.patch) + $name-$version.patch $name-$version-bsddb.patch) build () { cd Python-$version + patch -p1 < ../$name-$version.patch + patch -p1 < ../$name-$version-bsddb.patch + ./configure --prefix=/usr \ --enable-shared \ --with-threads \ @@ -22,6 +25,7 @@ ln -sf python2.4 $PKG/usr/bin/python ln -sf python2.4 $PKG/usr/lib/python ln -sf python2.4 $PKG/usr/include/python + rm -r $PKG/usr/lib/python/{test,{email,bsddb}/test} rm -r $PKG/usr/lib/python/distutils/tests } Added: crux-2.2/ports/opt/python/python-2.4.2-bsddb.patch =================================================================== --- crux-2.2/ports/opt/python/python-2.4.2-bsddb.patch 2006-02-24 08:17:08 UTC (rev 817) +++ crux-2.2/ports/opt/python/python-2.4.2-bsddb.patch 2006-02-24 08:54:10 UTC (rev 818) @@ -0,0 +1,1024 @@ +diff -Nru Python-2.4.2.orig/Lib/bsddb/__init__.py Python-2.4.2/Lib/bsddb/__init__.py +--- Python-2.4.2.orig/Lib/bsddb/__init__.py 2006-02-13 18:18:16.000000000 +0100 ++++ Python-2.4.2/Lib/bsddb/__init__.py 2006-01-27 07:17:25.000000000 +0100 +@@ -372,6 +372,8 @@ + try: + import thread + del thread ++ if db.version() < (3, 3, 0): ++ db.DB_THREAD = 0 + except ImportError: + db.DB_THREAD = 0 + +diff -Nru Python-2.4.2.orig/Lib/bsddb/db.py Python-2.4.2/Lib/bsddb/db.py +--- Python-2.4.2.orig/Lib/bsddb/db.py 2006-02-13 18:18:16.000000000 +0100 ++++ Python-2.4.2/Lib/bsddb/db.py 2006-01-27 07:17:25.000000000 +0100 +@@ -37,7 +37,7 @@ + # case we ever want to augment the stuff in _db in any way. For now + # it just simply imports everything from _db. + +-if __name__[:len('bsddb3.')] == 'bsddb3.': ++if __name__.startswith('bsddb3.'): + # import _pybsddb binary as it should be the more recent version from + # a standalone pybsddb addon package than the version included with + # python as bsddb._bsddb. +diff -Nru Python-2.4.2.orig/Lib/bsddb/dbobj.py Python-2.4.2/Lib/bsddb/dbobj.py +--- Python-2.4.2.orig/Lib/bsddb/dbobj.py 2006-02-13 18:18:16.000000000 +0100 ++++ Python-2.4.2/Lib/bsddb/dbobj.py 2006-01-27 07:28:12.000000000 +0100 +@@ -77,6 +77,8 @@ + return apply(self._cobj.txn_stat, args, kwargs) + def set_tx_max(self, *args, **kwargs): + return apply(self._cobj.set_tx_max, args, kwargs) ++ def set_tx_timestamp(self, *args, **kwargs): ++ return apply(self._cobj.set_tx_timestamp, args, kwargs) + def lock_detect(self, *args, **kwargs): + return apply(self._cobj.lock_detect, args, kwargs) + def lock_get(self, *args, **kwargs): +@@ -164,6 +166,8 @@ + return apply(self._cobj.rename, args, kwargs) + def set_bt_minkey(self, *args, **kwargs): + return apply(self._cobj.set_bt_minkey, args, kwargs) ++ def set_bt_compare(self, *args, **kwargs): ++ return apply(self._cobj.set_bt_compare, args, kwargs) + def set_cachesize(self, *args, **kwargs): + return apply(self._cobj.set_cachesize, args, kwargs) + def set_flags(self, *args, **kwargs): +diff -Nru Python-2.4.2.orig/Lib/bsddb/dbtables.py Python-2.4.2/Lib/bsddb/dbtables.py +--- Python-2.4.2.orig/Lib/bsddb/dbtables.py 2006-02-13 18:18:16.000000000 +0100 ++++ Python-2.4.2/Lib/bsddb/dbtables.py 2006-01-27 07:17:25.000000000 +0100 +@@ -15,7 +15,7 @@ + # This provides a simple database table interface built on top of + # the Python BerkeleyDB 3 interface. + # +-_cvsid = '$Id: dbtables.py,v 1.11 2004/08/08 00:54:20 tim_one Exp $' ++_cvsid = '$Id: dbtables.py 36901 2004-08-08 00:54:21Z tim_one $' + + import re + import sys +diff -Nru Python-2.4.2.orig/Modules/_bsddb.c Python-2.4.2/Modules/_bsddb.c +--- Python-2.4.2.orig/Modules/_bsddb.c 2006-02-13 18:18:17.000000000 +0100 ++++ Python-2.4.2/Modules/_bsddb.c 2006-01-30 01:22:16.000000000 +0100 +@@ -97,8 +97,8 @@ + #error "eek! DBVER can't handle minor versions > 9" + #endif + +-#define PY_BSDDB_VERSION "4.3.0" +-static char *rcs_id = "$Id: _bsddb.c,v 1.38.2.1 2004/12/16 09:48:37 greg Exp $"; ++#define PY_BSDDB_VERSION "4.4.2" ++static char *rcs_id = "$Id: _bsddb.c 42205 2006-01-30 00:22:08Z gregory.p.smith $"; + + + #ifdef WITH_THREAD +@@ -153,7 +153,7 @@ + + static PyObject* DBError; /* Base class, all others derive from this */ + static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */ +-static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY */ ++static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */ + static PyObject* DBKeyExistError; /* DB_KEYEXIST */ + static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */ + static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */ +@@ -212,10 +212,10 @@ + + struct behaviourFlags { + /* What is the default behaviour when DB->get or DBCursor->get returns a +- DB_NOTFOUND error? Return None or raise an exception? */ ++ DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */ + unsigned int getReturnsNone : 1; + /* What is the default behaviour for DBCursor.set* methods when DBCursor->get +- * returns a DB_NOTFOUND error? Return None or raise an exception? */ ++ * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */ + unsigned int cursorSetReturnsNone : 1; + }; + +@@ -244,6 +244,7 @@ + struct behaviourFlags moduleFlags; + #if (DBVER >= 33) + PyObject* associateCallback; ++ PyObject* btCompareCallback; + int primaryDBType; + #endif + #ifdef HAVE_WEAKREF +@@ -265,6 +266,7 @@ + typedef struct { + PyObject_HEAD + DB_TXN* txn; ++ PyObject *env; + #ifdef HAVE_WEAKREF + PyObject *in_weakreflist; /* List of weak references */ + #endif +@@ -649,7 +651,7 @@ + int dlen = -1; + int doff = -1; + int flags = 0; +- char* kwnames[] = { "flags", "dlen", "doff", NULL }; ++ static const char* kwnames[] = { "flags", "dlen", "doff", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames, + &flags, &dlen, &doff)) +@@ -672,7 +674,8 @@ + err = self->dbc->c_get(self->dbc, &key, &data, flags); + MYDB_END_ALLOW_THREADS; + +- if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->mydb->moduleFlags.getReturnsNone) { + Py_INCREF(Py_None); + retval = Py_None; + } +@@ -741,6 +744,7 @@ + self->myenvobj = NULL; + #if (DBVER >= 33) + self->associateCallback = NULL; ++ self->btCompareCallback = NULL; + self->primaryDBType = 0; + #endif + #ifdef HAVE_WEAKREF +@@ -815,6 +819,10 @@ + Py_DECREF(self->associateCallback); + self->associateCallback = NULL; + } ++ if (self->btCompareCallback != NULL) { ++ Py_DECREF(self->btCompareCallback); ++ self->btCompareCallback = NULL; ++ } + #endif + PyObject_Del(self); + } +@@ -905,7 +913,7 @@ + } + #endif + +- if (self->db_env) { ++ if (self->db_env && !self->closed) { + MYDB_BEGIN_ALLOW_THREADS; + self->db_env->close(self->db_env, 0); + MYDB_END_ALLOW_THREADS; +@@ -921,6 +929,8 @@ + DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type); + if (self == NULL) + return NULL; ++ Py_INCREF(myenv); ++ self->env = (PyObject*)myenv; + #ifdef HAVE_WEAKREF + self->in_weakreflist = NULL; + #endif +@@ -931,11 +941,10 @@ + #else + err = txn_begin(myenv->db_env, parent, &(self->txn), flags); + #endif +- /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs +- * list so that a DBEnv can refuse to close without aborting any open +- * open DBTxns and closing any open DBs first. */ + MYDB_END_ALLOW_THREADS; + if (makeDBError(err)) { ++ Py_DECREF(self->env); ++ PyObject_Del(self); + self = NULL; + } + return self; +@@ -966,6 +975,7 @@ + } + #endif + ++ Py_DECREF(self->env); + PyObject_Del(self); + } + +@@ -1140,9 +1150,10 @@ + #if (DBVER >= 41) + PyObject *txnobj = NULL; + DB_TXN *txn = NULL; +- char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL}; ++ static const char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", ++ NULL}; + #else +- char* kwnames[] = {"secondaryDB", "callback", "flags", NULL}; ++ static const char* kwnames[] = {"secondaryDB", "callback", "flags", NULL}; + #endif + + #if (DBVER >= 41) +@@ -1165,6 +1176,7 @@ + makeTypeError("DB", (PyObject*)secondaryDB); + return NULL; + } ++ CHECK_DB_NOT_CLOSED(secondaryDB); + if (callback == Py_None) { + callback = NULL; + } +@@ -1174,9 +1186,7 @@ + } + + /* Save a reference to the callback in the secondary DB. */ +- if (self->associateCallback != NULL) { +- Py_DECREF(self->associateCallback); +- } ++ Py_XDECREF(secondaryDB->associateCallback); + Py_INCREF(callback); + secondaryDB->associateCallback = callback; + secondaryDB->primaryDBType = _DB_get_type(self); +@@ -1210,8 +1220,8 @@ + MYDB_END_ALLOW_THREADS; + + if (err) { +- Py_DECREF(self->associateCallback); +- self->associateCallback = NULL; ++ Py_XDECREF(secondaryDB->associateCallback); ++ secondaryDB->associateCallback = NULL; + secondaryDB->primaryDBType = 0; + } + +@@ -1249,7 +1259,7 @@ + PyObject* retval = NULL; + DBT key, data; + DB_TXN *txn = NULL; +- char* kwnames[] = { "txn", "flags", NULL }; ++ static const char* kwnames[] = { "txn", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames, + &txnobj, &flags)) +@@ -1279,7 +1289,8 @@ + err = self->db->get(self->db, txn, &key, &data, flags|consume_flag); + MYDB_END_ALLOW_THREADS; + +- if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->moduleFlags.getReturnsNone) { + err = 0; + Py_INCREF(Py_None); + retval = Py_None; +@@ -1318,7 +1329,7 @@ + DBC* dbc; + PyObject* txnobj = NULL; + DB_TXN *txn = NULL; +- char* kwnames[] = { "txn", "flags", NULL }; ++ static const char* kwnames[] = { "txn", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames, + &txnobj, &flags)) +@@ -1343,7 +1354,7 @@ + PyObject* keyobj; + DBT key; + DB_TXN *txn = NULL; +- char* kwnames[] = { "key", "txn", "flags", NULL }; ++ static const char* kwnames[] = { "key", "txn", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames, + &keyobj, &txnobj, &flags)) +@@ -1395,7 +1406,8 @@ + int doff = -1; + DBT key, data; + DB_TXN *txn = NULL; +- char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL}; ++ static const char* kwnames[] = {"key", "default", "txn", "flags", "dlen", ++ "doff", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames, + &keyobj, &dfltobj, &txnobj, &flags, &dlen, +@@ -1424,12 +1436,13 @@ + err = self->db->get(self->db, txn, &key, &data, flags); + MYDB_END_ALLOW_THREADS; + +- if ((err == DB_NOTFOUND) && (dfltobj != NULL)) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) { + err = 0; + Py_INCREF(dfltobj); + retval = dfltobj; + } +- else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) { ++ else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->moduleFlags.getReturnsNone) { + err = 0; + Py_INCREF(Py_None); + retval = Py_None; +@@ -1461,7 +1474,8 @@ + int doff = -1; + DBT key, pkey, data; + DB_TXN *txn = NULL; +- char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL}; ++ static const char* kwnames[] = {"key", "default", "txn", "flags", "dlen", ++ "doff", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames, + &keyobj, &dfltobj, &txnobj, &flags, &dlen, +@@ -1493,12 +1507,13 @@ + err = self->db->pget(self->db, txn, &key, &pkey, &data, flags); + MYDB_END_ALLOW_THREADS; + +- if ((err == DB_NOTFOUND) && (dfltobj != NULL)) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) { + err = 0; + Py_INCREF(dfltobj); + retval = dfltobj; + } +- else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) { ++ else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->moduleFlags.getReturnsNone) { + err = 0; + Py_INCREF(Py_None); + retval = Py_None; +@@ -1510,7 +1525,7 @@ + + if (self->primaryDBType == DB_RECNO || + self->primaryDBType == DB_QUEUE) +- pkeyObj = PyInt_FromLong(*(long *)pkey.data); ++ pkeyObj = PyInt_FromLong(*(int *)pkey.data); + else + pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size); + +@@ -1519,14 +1534,22 @@ + PyObject *keyObj; + int type = _DB_get_type(self); + if (type == DB_RECNO || type == DB_QUEUE) +- keyObj = PyInt_FromLong(*(long *)key.data); ++ keyObj = PyInt_FromLong(*(int *)key.data); + else + keyObj = PyString_FromStringAndSize(key.data, key.size); ++#if (PY_VERSION_HEX >= 0x02040000) ++ retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); ++#else + retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj); ++#endif + } + else /* return just the pkey and data */ + { ++#if (PY_VERSION_HEX >= 0x02040000) ++ retval = PyTuple_Pack(2, pkeyObj, dataObj); ++#else + retval = Py_BuildValue("OO", pkeyObj, dataObj); ++#endif + } + FREE_DBT(pkey); + FREE_DBT(data); +@@ -1549,7 +1572,7 @@ + PyObject* retval = NULL; + DBT key, data; + DB_TXN *txn = NULL; +- char* kwnames[] = { "key", "txn", NULL }; ++ static const char* kwnames[] = { "key", "txn", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames, + &keyobj, &txnobj)) +@@ -1592,7 +1615,7 @@ + PyObject* retval = NULL; + DBT key, data; + DB_TXN *txn = NULL; +- char* kwnames[] = { "key", "data", "txn", "flags", NULL }; ++ static const char* kwnames[] = { "key", "data", "txn", "flags", NULL }; + + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames, +@@ -1623,7 +1646,8 @@ + err = self->db->get(self->db, txn, &key, &data, flags); + MYDB_END_ALLOW_THREADS; + +- if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->moduleFlags.getReturnsNone) { + err = 0; + Py_INCREF(Py_None); + retval = Py_None; +@@ -1742,7 +1766,7 @@ + DBT key; + DB_TXN *txn = NULL; + DB_KEY_RANGE range; +- char* kwnames[] = { "key", "txn", "flags", NULL }; ++ static const char* kwnames[] = { "key", "txn", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames, + &keyobj, &txnobj, &flags)) +@@ -1773,17 +1797,17 @@ + PyObject *txnobj = NULL; + DB_TXN *txn = NULL; + /* with dbname */ +- char* kwnames[] = { ++ static const char* kwnames[] = { + "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL}; + /* without dbname */ +- char* kwnames_basic[] = { ++ static const char* kwnames_basic[] = { + "filename", "dbtype", "flags", "mode", "txn", NULL}; + #else + /* with dbname */ +- char* kwnames[] = { ++ static const char* kwnames[] = { + "filename", "dbname", "dbtype", "flags", "mode", NULL}; + /* without dbname */ +- char* kwnames_basic[] = { ++ static const char* kwnames_basic[] = { + "filename", "dbtype", "flags", "mode", NULL}; + #endif + +@@ -1867,7 +1891,8 @@ + PyObject* keyobj, *dataobj, *retval; + DBT key, data; + DB_TXN *txn = NULL; +- char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL }; ++ static const char* kwnames[] = { "key", "data", "txn", "flags", "dlen", ++ "doff", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames, + &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff)) +@@ -1907,7 +1932,7 @@ + char* filename; + char* database = NULL; + int err, flags=0; +- char* kwnames[] = { "filename", "dbname", "flags", NULL}; ++ static const char* kwnames[] = { "filename", "dbname", "flags", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames, + &filename, &database, &flags)) +@@ -1959,6 +1984,160 @@ + RETURN_NONE(); + } + ++#if (DBVER >= 33) ++static int ++_default_cmp (const DBT *leftKey, ++ const DBT *rightKey) ++{ ++ int res; ++ int lsize = leftKey->size, rsize = rightKey->size; ++ ++ res = memcmp (leftKey->data, rightKey->data, ++ lsize < rsize ? lsize : rsize); ++ ++ if (res == 0) { ++ if (lsize < rsize) { ++ res = -1; ++ } ++ else if (lsize > rsize) { ++ res = 1; ++ } ++ } ++ return res; ++} ++ ++static int ++_db_compareCallback (DB* db, ++ const DBT *leftKey, ++ const DBT *rightKey) ++{ ++ int res = 0; ++ PyObject *args; ++ PyObject *result; ++ PyObject *leftObject; ++ PyObject *rightObject; ++ DBObject *self = (DBObject *) db->app_private; ++ ++ if (self == NULL || self->btCompareCallback == NULL) { ++ MYDB_BEGIN_BLOCK_THREADS; ++ PyErr_SetString (PyExc_TypeError, ++ (self == 0 ++ ? "DB_bt_compare db is NULL." ++ : "DB_bt_compare callback is NULL.")); ++ /* we're in a callback within the DB code, we can't raise */ ++ PyErr_Print (); ++ res = _default_cmp (leftKey, rightKey); ++ MYDB_END_BLOCK_THREADS; ++ } ++ else { ++ MYDB_BEGIN_BLOCK_THREADS; ++ ++ leftObject = PyString_FromStringAndSize (leftKey->data, leftKey->size); ++ rightObject = PyString_FromStringAndSize (rightKey->data, rightKey->size); ++ ++ args = PyTuple_New (2); ++ Py_INCREF (self); ++ PyTuple_SET_ITEM (args, 0, leftObject); /* steals reference */ ++ PyTuple_SET_ITEM (args, 1, rightObject); /* steals reference */ ++ ++ result = PyEval_CallObject (self->btCompareCallback, args); ++ if (result == 0) { ++ /* we're in a callback within the DB code, we can't raise */ ++ PyErr_Print (); ++ res = _default_cmp (leftKey, rightKey); ++ } ++ else if (PyInt_Check (result)) { ++ res = PyInt_AsLong (result); ++ } ++ else { ++ PyErr_SetString (PyExc_TypeError, ++ "DB_bt_compare callback MUST return an int."); ++ /* we're in a callback within the DB code, we can't raise */ ++ PyErr_Print (); ++ res = _default_cmp (leftKey, rightKey); ++ } ++ ++ Py_DECREF (args); ++ Py_XDECREF (result); ++ ++ MYDB_END_BLOCK_THREADS; ++ } ++ return res; ++} ++ ++static PyObject* ++DB_set_bt_compare (DBObject* self, PyObject* args) ++{ ++ int err; ++ PyObject *comparator; ++ PyObject *tuple, *emptyStr, *result; ++ ++ if (!PyArg_ParseTuple(args,"O:set_bt_compare", &comparator )) ++ return NULL; ++ ++ CHECK_DB_NOT_CLOSED (self); ++ ++ if (! PyCallable_Check (comparator)) { ++ makeTypeError ("Callable", comparator); ++ return NULL; ++ } ++ ++ /* ++ * Perform a test call of the comparator function with two empty ++ * string objects here. verify that it returns an int (0). ++ * err if not. ++ */ ++ tuple = PyTuple_New (2); ++ ++ emptyStr = PyString_FromStringAndSize (NULL, 0); ++ Py_INCREF(emptyStr); ++ PyTuple_SET_ITEM (tuple, 0, emptyStr); ++ PyTuple_SET_ITEM (tuple, 1, emptyStr); /* steals reference */ ++ result = PyEval_CallObject (comparator, tuple); ++ Py_DECREF (tuple); ++ if (result == 0 || !PyInt_Check(result)) { ++ PyErr_SetString (PyExc_TypeError, ++ "callback MUST return an int"); ++ return NULL; ++ } ++ else if (PyInt_AsLong(result) != 0) { ++ PyErr_SetString (PyExc_TypeError, ++ "callback failed to return 0 on two empty strings"); ++ return NULL; ++ } ++ ++ /* We don't accept multiple set_bt_compare operations, in order to ++ * simplify the code. This would have no real use, as one cannot ++ * change the function once the db is opened anyway */ ++ if (self->btCompareCallback != NULL) { ++ PyErr_SetString (PyExc_RuntimeError, "set_bt_compare () cannot be called more than once"); ++ return NULL; ++ } ++ ++ Py_INCREF (comparator); ++ self->btCompareCallback = comparator; ++ ++ /* This is to workaround a problem with un-initialized threads (see ++ comment in DB_associate) */ ++#ifdef WITH_THREAD ++ PyEval_InitThreads(); ++#endif ++ ++ err = self->db->set_bt_compare (self->db, ++ (comparator != NULL ? ++ _db_compareCallback : NULL)); ++ ++ if (err) { ++ /* restore the old state in case of error */ ++ Py_DECREF (comparator); ++ self->btCompareCallback = NULL; ++ } ++ ++ RETURN_IF_ERR (); ++ RETURN_NONE (); ++} ++#endif /* DBVER >= 33 */ ++ + + static PyObject* + DB_set_cachesize(DBObject* self, PyObject* args) +@@ -2171,9 +2350,9 @@ + #if (DBVER >= 43) + PyObject* txnobj = NULL; + DB_TXN *txn = NULL; +- char* kwnames[] = { "txn", "flags", NULL }; ++ static const char* kwnames[] = { "txn", "flags", NULL }; + #else +- char* kwnames[] = { "flags", NULL }; ++ static const char* kwnames[] = { "flags", NULL }; + #endif + + #if (DBVER >= 43) +@@ -2313,7 +2492,7 @@ + u_int32_t count=0; + PyObject* txnobj = NULL; + DB_TXN *txn = NULL; +- char* kwnames[] = { "txn", "flags", NULL }; ++ static const char* kwnames[] = { "txn", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames, + &txnobj, &flags)) +@@ -2357,7 +2536,8 @@ + char* dbName=NULL; + char* outFileName=NULL; + FILE* outFile=NULL; +- char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL }; ++ static const char* kwnames[] = { "filename", "dbname", "outfile", "flags", ++ NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames, + &fileName, &dbName, &outFileName, &flags)) +@@ -2414,7 +2594,7 @@ + int err; + u_int32_t flags=0; + char *passwd = NULL; +- char* kwnames[] = { "passwd", "flags", NULL }; ++ static const char* kwnames[] = { "passwd", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, + &passwd, &flags)) { +@@ -2584,7 +2764,15 @@ + err = self->db->get(self->db, txn, &key, &data, 0); + MYDB_END_ALLOW_THREADS; + FREE_DBT(key); +- return PyInt_FromLong((err == DB_BUFFER_SMALL) || (err == 0)); ++ ++ if (err == DB_BUFFER_SMALL || err == 0) { ++ return PyInt_FromLong(1); ++ } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { ++ return PyInt_FromLong(0); ++ } ++ ++ makeDBError(err); ++ return NULL; + } + + +@@ -2682,8 +2870,8 @@ + Py_DECREF(item); + } + +- /* DB_NOTFOUND is okay, it just means we got to the end */ +- if (err != DB_NOTFOUND && makeDBError(err)) { ++ /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */ ++ if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) { + Py_DECREF(list); + list = NULL; + } +@@ -2846,7 +3034,8 @@ + int dlen = -1; + int doff = -1; + DBT key, data; +- char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL }; ++ static const char* kwnames[] = { "key","data", "flags", "dlen", "doff", ++ NULL }; + + CLEAR_DBT(key); + CLEAR_DBT(data); +@@ -2890,7 +3079,8 @@ + err = self->dbc->c_get(self->dbc, &key, &data, flags); + MYDB_END_ALLOW_THREADS; + +- if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->mydb->moduleFlags.getReturnsNone) { + Py_INCREF(Py_None); + retval = Py_None; + } +@@ -2931,7 +3121,8 @@ + int dlen = -1; + int doff = -1; + DBT key, pkey, data; +- char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL }; ++ static const char* kwnames[] = { "key","data", "flags", "dlen", "doff", ++ NULL }; + + CLEAR_DBT(key); + CLEAR_DBT(data); +@@ -2977,7 +3168,8 @@ + err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags); + MYDB_END_ALLOW_THREADS; + +- if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->mydb->moduleFlags.getReturnsNone) { + Py_INCREF(Py_None); + retval = Py_None; + } +@@ -2991,24 +3183,32 @@ + + if (self->mydb->primaryDBType == DB_RECNO || + self->mydb->primaryDBType == DB_QUEUE) +- pkeyObj = PyInt_FromLong(*(long *)pkey.data); ++ pkeyObj = PyInt_FromLong(*(int *)pkey.data); + else + pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size); + +- if (flags & DB_SET_RECNO) /* return key, pkey and data */ ++ if (key.data && key.size) /* return key, pkey and data */ + { + PyObject *keyObj; + int type = _DB_get_type(self->mydb); + if (type == DB_RECNO || type == DB_QUEUE) +- keyObj = PyInt_FromLong(*(long *)key.data); ++ keyObj = PyInt_FromLong(*(int *)key.data); + else + keyObj = PyString_FromStringAndSize(key.data, key.size); ++#if (PY_VERSION_HEX >= 0x02040000) ++ retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); ++#else + retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj); ++#endif + FREE_DBT(key); + } + else /* return just the pkey and data */ + { ++#if (PY_VERSION_HEX >= 0x02040000) ++ retval = PyTuple_Pack(2, pkeyObj, dataObj); ++#else + retval = Py_BuildValue("OO", pkeyObj, dataObj); ++#endif + } + FREE_DBT(pkey); + FREE_DBT(data); +@@ -3083,7 +3283,8 @@ + int err, flags = 0; + PyObject* keyobj, *dataobj; + DBT key, data; +- char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL }; ++ static const char* kwnames[] = { "key", "data", "flags", "dlen", "doff", ++ NULL }; + int dlen = -1; + int doff = -1; + +@@ -3118,7 +3319,7 @@ + int err, flags = 0; + DBT key, data; + PyObject* retval, *keyobj; +- char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; ++ static const char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; + int dlen = -1; + int doff = -1; + +@@ -3144,7 +3345,8 @@ + MYDB_BEGIN_ALLOW_THREADS; + err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET); + MYDB_END_ALLOW_THREADS; +- if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->mydb->moduleFlags.cursorSetReturnsNone) { + Py_INCREF(Py_None); + retval = Py_None; + } +@@ -3187,7 +3389,7 @@ + int err, flags = 0; + DBT key, data; + PyObject* retval, *keyobj; +- char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; ++ static const char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; + int dlen = -1; + int doff = -1; + +@@ -3216,7 +3418,8 @@ + MYDB_BEGIN_ALLOW_THREADS; + err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE); + MYDB_END_ALLOW_THREADS; +- if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->mydb->moduleFlags.cursorSetReturnsNone) { + Py_INCREF(Py_None); + retval = Py_None; + } +@@ -3271,7 +3474,7 @@ + MYDB_BEGIN_ALLOW_THREADS; + err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH); + MYDB_END_ALLOW_THREADS; +- if ((err == DB_NOTFOUND) && returnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) { + Py_INCREF(Py_None); + retval = Py_None; + } +@@ -3376,7 +3579,7 @@ + PyObject* retval; + int dlen = -1; + int doff = -1; +- char* kwnames[] = { "recno","flags", "dlen", "doff", NULL }; ++ static const char* kwnames[] = { "recno","flags", "dlen", "doff", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames, + &irecno, &flags, &dlen, &doff)) +@@ -3411,7 +3614,8 @@ + MYDB_BEGIN_ALLOW_THREADS; + err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO); + MYDB_END_ALLOW_THREADS; +- if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->mydb->moduleFlags.cursorSetReturnsNone) { + Py_INCREF(Py_None); + retval = Py_None; + } +@@ -3479,7 +3683,8 @@ + MYDB_BEGIN_ALLOW_THREADS; + err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM); + MYDB_END_ALLOW_THREADS; +- if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) { ++ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) ++ && self->mydb->moduleFlags.getReturnsNone) { + Py_INCREF(Py_None); + retval = Py_None; + } +@@ -3568,7 +3773,8 @@ + char *database = NULL; + PyObject *txnobj = NULL; + DB_TXN *txn = NULL; +- char* kwnames[] = { "file", "database", "txn", "flags", NULL }; ++ static const char* kwnames[] = { "file", "database", "txn", "flags", ++ NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames, + &file, &database, &txnobj, &flags)) { +@@ -3595,7 +3801,8 @@ + char *newname = NULL; + PyObject *txnobj = NULL; + DB_TXN *txn = NULL; +- char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL }; ++ static const char* kwnames[] = { "file", "database", "newname", "txn", ++ "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames, + &file, &database, &newname, &txnobj, &flags)) { +@@ -3619,7 +3826,7 @@ + int err; + u_int32_t flags=0; + char *passwd = NULL; +- char* kwnames[] = { "passwd", "flags", NULL }; ++ static const char* kwnames[] = { "passwd", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, + &passwd, &flags)) { +@@ -3642,7 +3849,7 @@ + int err; + u_int32_t flags=0; + u_int32_t timeout = 0; +- char* kwnames[] = { "timeout", "flags", NULL }; ++ static const char* kwnames[] = { "timeout", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames, + &timeout, &flags)) { +@@ -3780,6 +3987,25 @@ + } + + ++#if (DBVER >= 33) ++static PyObject* ++DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args) ++{ ++ int err, lg_max; ++ ++ if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max)) ++ return NULL; ++ CHECK_ENV_NOT_CLOSED(self); ++ ++ MYDB_BEGIN_ALLOW_THREADS; ++ err = self->db_env->set_lg_regionmax(self->db_env, lg_max); ++ MYDB_END_ALLOW_THREADS; ++ RETURN_IF_ERR(); ++ RETURN_NONE(); ++} ++#endif ++ ++ + static PyObject* + DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args) + { +@@ -3910,7 +4136,7 @@ + int flags = 0; + PyObject* txnobj = NULL; + DB_TXN *txn = NULL; +- char* kwnames[] = { "parent", "flags", NULL }; ++ static const char* kwnames[] = { "parent", "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames, + &txnobj, &flags)) +@@ -3954,9 +4180,23 @@ + return NULL; + CHECK_ENV_NOT_CLOSED(self); + +- MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->set_tx_max(self->db_env, max); +- MYDB_END_ALLOW_THREADS; ++ RETURN_IF_ERR(); ++ RETURN_NONE(); ++} ++ ++ ++static PyObject* ++DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args) ++{ ++ int err; ++ time_t stamp; ++ ++ if (!PyArg_ParseTuple(args, "i:set_tx_timestamp", &stamp)) ++ return NULL; ++ CHECK_ENV_NOT_CLOSED(self); ++ ++ err = self->db_env->set_tx_timestamp(self->db_env, &stamp); + RETURN_IF_ERR(); + RETURN_NONE(); + } +@@ -4101,8 +4341,13 @@ + #endif + MAKE_ENTRY(nrequests); + MAKE_ENTRY(nreleases); +- MAKE_ENTRY(nnowaits); ++#if (DBVER < 44) ++ MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */ + MAKE_ENTRY(nconflicts); ++#else ++ MAKE_ENTRY(lock_nowait); ++ MAKE_ENTRY(lock_wait); ++#endif + MAKE_ENTRY(ndeadlocks); + MAKE_ENTRY(regsize); + MAKE_ENTRY(region_wait); +@@ -4400,6 +4645,9 @@ + {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS}, + {"rename", (PyCFunction)DB_rename, METH_VARARGS}, + {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS}, ++#if (DBVER >= 33) ++ {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS}, ++#endif + {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS}, + #if (DBVER >= 41) + {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS}, +@@ -4489,6 +4737,9 @@ + {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS}, + {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS}, + {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS}, ++#if (DBVER >= 33) ++ {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS}, ++#endif + {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS}, + {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS}, + #if (DBVER >= 32) +@@ -4502,6 +4753,7 @@ + {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS}, + {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS}, + {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS}, ++ {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS}, + {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS}, + {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS}, + {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS}, +@@ -4734,7 +4986,7 @@ + { + PyObject* dbenvobj = NULL; + int flags = 0; +- char* kwnames[] = { "dbEnv", "flags", NULL}; ++ static const char* kwnames[] = { "dbEnv", "flags", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames, + &dbenvobj, &flags)) +@@ -4821,6 +5073,8 @@ + + /* Create the module and add the functions */ + m = Py_InitModule(_bsddbModuleName, bsddb_methods); ++ if (m == NULL) ++ return; + + /* Add some symbolic constants to the module */ + d = PyModule_GetDict(m); +@@ -4938,7 +5192,11 @@ + ADD_INT(d, DB_LOCK_IREAD); + ADD_INT(d, DB_LOCK_IWR); + #if (DBVER >= 33) ++#if (DBVER < 44) + ADD_INT(d, DB_LOCK_DIRTY); ++#else ++ ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */ ++#endif + ADD_INT(d, DB_LOCK_WWRITE); + #endif + +@@ -5040,6 +5298,11 @@ + ADD_INT(d, DB_MULTIPLE_KEY); + #endif + ++#if (DBVER >= 44) ++ ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */ ++ ADD_INT(d, DB_READ_COMMITTED); ++#endif ++ + #if (DBVER >= 33) + ADD_INT(d, DB_DONOTINDEX); + #endif +@@ -5117,12 +5380,15 @@ + DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL); + PyDict_SetItemString(d, "DBError", DBError); + +- /* Some magic to make DBNotFoundError derive from both DBError and +- KeyError, since the API only supports using one base class. */ ++ /* Some magic to make DBNotFoundError and DBKeyEmptyError derive ++ * from both DBError and KeyError, since the API only supports ++ * using one base class. */ + PyDict_SetItemString(d, "KeyError", PyExc_KeyError); +- PyRun_String("class DBNotFoundError(DBError, KeyError): pass", ++ PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n" ++ "class DBKeyEmptyError(DBError, KeyError): pass", + Py_file_input, d, d); + DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError"); ++ DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError"); + PyDict_DelItemString(d, "KeyError"); + + Modified: crux-2.2/ports/opt/python/python-2.4.2.patch =================================================================== --- crux-2.2/ports/opt/python/python-2.4.2.patch 2006-02-24 08:17:08 UTC (rev 817) +++ crux-2.2/ports/opt/python/python-2.4.2.patch 2006-02-24 08:54:10 UTC (rev 818) @@ -66,7 +66,7 @@ -#DBLIB=$(DB)/lib -#_bsddb _bsddb.c -I$(DBINC) -L$(DBLIB) -ldb-$(DBLIBVER) +DB=/usr -+DBLIBVER=4.3 ++DBLIBVER=4.4 +DBINC=$(DB)/include +DBLIB=$(DB)/lib +_bsddb _bsddb.c -I$(DBINC) -L$(DBLIB) -ldb-$(DBLIBVER)
participants (1)
-
crux@crux.nu