Here's the patch. This includes:
* the OS X build fixes I included in my previous patches, with a
few tweaks (actually check for Python.h)
* changes to the Python bindings to properly support 'L' fields,
handle overflow, and throw dummy exceptions
* the beginnings of a test suite for the Python bindings, using
the test.regrtest module since it's the closest standard module
Python has to MetaKit's Tcl tests; a corresponding test-python
target in Makefile.in
* a few more build changes - scxx dependencies were wrong
A couple of further questions:
* The other problem I had with Mk4py was its inability to deal with
Unicode strings. Is there any precedent in the other language
bindings for what to do here? Do 'S' fields have any encoding
information associated with them?
* Currently, the int type conversion matrix looks something like this:
Python type MetaKit type Result
----------- ------------ ------
int I ok
long int <= 32 bits I ok
long int > 32 bits I TypeError
float I ok, truncated
float/int > 32 bits I TypeError
long int <= 64 bits L ok
long int > 64 bits L ValueError
float L ok, truncated
float/int > 64 bits L ValueError
string I, L TypeError
A few of these conversions are debatable - should Mk4py truncate a
float? Should it try to convert a string to an int/long int if
possible?
I've got finals coming up so I won't be able to do anything further
until next Tuesday.
--
=Nicholas Riley <[EMAIL PROTECTED]> | <http://www.uiuc.edu/ph/www/njriley>
Pablo Research Group, Department of Computer Science and
Medical Scholars Program, University of Illinois at Urbana-Champaign
diff -uNr -X metakit-files-to-ignore-when-diffing metakit-2.4.8/python/PyRowRef.cpp
metakit-2.4.8+njr2/python/PyRowRef.cpp
--- metakit-2.4.8/python/PyRowRef.cpp Wed Dec 19 10:26:00 2001
+++ metakit-2.4.8+njr2/python/PyRowRef.cpp Fri Dec 13 09:56:04 2002
@@ -58,7 +58,7 @@
PyErr_Clear();
return Py_FindMethod(RowRefMethods, (PyObject* )o, nm);
}
- catch (...) { return 0; }
+ catch (...) { return NULL; }
}
static int PyRowRef_setattr(PyRowRef *o, char *nm, PyObject* v) {
@@ -72,7 +72,7 @@
Py_DECREF(p);
return 0;
}
- PyErr_SetString(PyExc_AttributeError, "delete of non-existing attribute");
+ PyErr_SetString(PyExc_AttributeError, "delete of nonexistent attribute");
return -1;
}
catch (...) { return -1; }
@@ -122,8 +122,8 @@
// with thanks to Niki Spahiev for improving conversions and error checks
void PyRowRef::setFromPython(const c4_RowRef& row, const c4_Property& prop, PyObject*
attr) {
switch (prop.Type()) {
- case 'I':
- if (PyInt_Check(attr))
+ case 'I':
+ if (PyInt_CheckExact(attr))
((const c4_IntProp&) prop) (row) = PyInt_AS_LONG(attr);
else if (attr != Py_None)
{
@@ -132,16 +132,20 @@
}
break;
#ifdef HAVE_LONG_LONG
- case 'L':
- if (PyInt_Check(attr))
+ case 'L':
+ if (PyInt_CheckExact(attr))
((const c4_LongProp&) prop) (row) = PyInt_AS_LONG(attr);
- else if (PyLong_Check(attr))
- ((const c4_LongProp&) prop) (row) = PyLong_AsLong(attr);
+ else if (PyLong_Check(attr)) {
+ long long number = PyLong_AsLongLong(attr);
+ if (number == -1 && PyErr_Occurred() != NULL)
+ Fail(PyExc_ValueError, "long int too large to convert to C long long");
+ ((const c4_LongProp&) prop) (row) = number;
+ }
else if (attr != Py_None)
- {
- PWONumber number (attr);
- ((const c4_LongProp&) prop) (row) = (long) number;
- }
+ {
+ PWONumber number (attr);
+ ((const c4_LongProp&) prop) (row) = (long long) number;
+ }
break;
#endif
case 'F':
@@ -163,7 +167,7 @@
}
break;
case 'S':
- if (PyString_Check(attr)) {
+ if (PyString_CheckExact(attr)) {
c4_Bytes temp (PyString_AS_STRING(attr),
PyString_GET_SIZE(attr) + 1, false);
prop (row).SetData(temp);
@@ -191,13 +195,16 @@
break;
case 'B':
case 'M':
- if (PyString_Check(attr)) {
+ if (PyString_CheckExact(attr)) {
c4_Bytes temp (PyString_AS_STRING(attr),
PyString_GET_SIZE(attr), false);
prop (row).SetData(temp);
}
else if (attr != Py_None)
Fail(PyExc_TypeError, "wrong type for ByteProp");
+ default:
+ PyErr_Format(PyExc_TypeError, "unknown property type '%c'", prop.Type());
+ throw PWDPyException;
}
}
@@ -214,9 +221,9 @@
case 'F':
((const c4_FloatProp&) prop) (row) = 0.0;
break;
- case 'D':
- ((const c4_DoubleProp&) prop) (row) = 0.0;
- break;
+ case 'D':
+ ((const c4_DoubleProp&) prop) (row) = 0.0;
+ break;
case 'S':
((const c4_StringProp&) prop) (row) = "";
break;
@@ -229,6 +236,10 @@
c4_Bytes temp;
prop (row).SetData(temp);
}
+ break;
+ default:
+ PyErr_Format(PyExc_TypeError, "unknown property type '%c'", prop.Type());
+ throw PWDPyException;
}
}
@@ -240,7 +251,7 @@
}
#ifdef HAVE_LONG_LONG
case 'L': {
- return PyLong_FromLong((long) ((const c4_LongProp&)prop)(*this));
+ return PyLong_FromLongLong((long long) ((const c4_LongProp&)prop)(*this));
}
#endif
case 'F': {
@@ -265,6 +276,7 @@
PWOString rslt((const char*)temp.Contents(), temp.Size());
return rslt.disOwn();
}
+ default:
+ return PyErr_Format(PyExc_TypeError, "unknown property type '%c'", prop.Type());
}
- return 0;
}
diff -uNr -X metakit-files-to-ignore-when-diffing metakit-2.4.8/python/scxx/PWOBase.h
metakit-2.4.8+njr2/python/scxx/PWOBase.h
--- metakit-2.4.8/python/scxx/PWOBase.h Mon Dec 3 16:50:59 2001
+++ metakit-2.4.8+njr2/python/scxx/PWOBase.h Fri Dec 13 09:11:20 2002
@@ -10,7 +10,17 @@
#include <Python.h>
#include <limits.h>
+// Dummy, minimal exception thrown when a Python exception is generated
+// (after PyErr_Format, PyErr_SetString, etc.)
+class PWDException
+{
+ public:
+ PWDException() {}
+} extern const& PWDPyException;
+
+// functions throw PWDPyException
void Fail(PyObject*, const char* msg);
+void FailIfPyErr();
class PWOBase
{
diff -uNr -X metakit-files-to-ignore-when-diffing metakit-2.4.8/python/scxx/PWOImp.cpp
metakit-2.4.8+njr2/python/scxx/PWOImp.cpp
--- metakit-2.4.8/python/scxx/PWOImp.cpp Mon Dec 3 16:50:59 2001
+++ metakit-2.4.8+njr2/python/scxx/PWOImp.cpp Fri Dec 13 09:12:05 2002
@@ -7,6 +7,10 @@
#include "PWOMapping.h"
#include "PWOCallable.h"
+// dummy exception singleton
+const PWDException PWDPyExceptionObj;
+const PWDException& PWDPyException = PWDPyExceptionObj;
+
// incref new owner, and decref old owner, and adjust to new owner
void PWOBase::GrabRef(PyObject* newObj)
{
@@ -37,24 +41,30 @@
static PWOTuple _empty;
PyObject *rslt = PyEval_CallObjectWithKeywords(*this, _empty, NULL);
if (rslt == 0)
- throw 1;
+ throw PWDPyException;
return rslt;
}
PWOBase PWOCallable::call(PWOTuple& args) const {
PyObject *rslt = PyEval_CallObjectWithKeywords(*this, args, NULL);
if (rslt == 0)
- throw 1;
+ throw PWDPyException;
return rslt;
}
PWOBase PWOCallable::call(PWOTuple& args, PWOMapping& kws) const {
PyObject *rslt = PyEval_CallObjectWithKeywords(*this, args, kws);
if (rslt == 0)
- throw 1;
+ throw PWDPyException;
return rslt;
}
void Fail(PyObject* exc, const char* msg)
{
PyErr_SetString(exc, msg);
- throw 1;
+ throw PWDPyException;
+}
+
+void FailIfPyErr()
+{
+ PyObject *exc = PyErr_Occurred();
+ if (exc != NULL) throw PWDPyException;
}
diff -uNr -X metakit-files-to-ignore-when-diffing
metakit-2.4.8/python/scxx/PWOMapping.h metakit-2.4.8+njr2/python/scxx/PWOMapping.h
--- metakit-2.4.8/python/scxx/PWOMapping.h Fri Feb 1 09:32:51 2002
+++ metakit-2.4.8+njr2/python/scxx/PWOMapping.h Tue Dec 10 17:10:37 2002
@@ -56,7 +56,7 @@
//PyDict_GetItemString
PWOMappingMmbr operator [] (const char* key) {
PyObject* rslt = PyMapping_GetItemString(_obj, (char*) key);
- if (rslt==0)
+ if (rslt == NULL)
PyErr_Clear();
PWOString _key(key);
return PWOMappingMmbr(rslt, *this, _key);
@@ -64,7 +64,7 @@
//PyDict_GetItem
PWOMappingMmbr operator [] (PyObject* key) {
PyObject* rslt = PyDict_GetItem(_obj, key);
- //if (rslt==0)
+ //if (rslt == NULL)
// Fail(PyExc_KeyError, "Key not found");
return PWOMappingMmbr(rslt, *this, key);
};
diff -uNr -X metakit-files-to-ignore-when-diffing
metakit-2.4.8/python/scxx/PWONumber.h metakit-2.4.8+njr2/python/scxx/PWONumber.h
--- metakit-2.4.8/python/scxx/PWONumber.h Mon Dec 3 16:50:59 2001
+++ metakit-2.4.8+njr2/python/scxx/PWONumber.h Fri Dec 13 09:56:23 2002
@@ -15,6 +15,9 @@
PWONumber(int i) : PWOBase (PyInt_FromLong(i)) { LoseRef(_obj); }
PWONumber(long i) : PWOBase (PyInt_FromLong(i)) { LoseRef(_obj); }
PWONumber(unsigned long i) : PWOBase (PyLong_FromUnsignedLong(i)) { LoseRef(_obj); }
+#ifdef HAVE_LONG_LONG
+ PWONumber(long long i) : PWOBase (PyLong_FromLongLong(i)) { LoseRef(_obj); }
+#endif
PWONumber(double d) : PWOBase (PyFloat_FromDouble(d)) { LoseRef(_obj); }
PWONumber(const PWONumber& other) : PWOBase(other) {};
@@ -35,27 +38,27 @@
virtual void _violentTypeCheck() {
if (!PyNumber_Check(_obj)) {
GrabRef(0);
- Fail(PyExc_TypeError, "Not a number");
+ Fail(PyExc_TypeError, "not a number");
}
};
//PyNumber_Absolute
PWONumber abs() const {
PyObject* rslt = PyNumber_Absolute(_obj);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Failed to get absolute value");
return LoseRef(rslt);
};
//PyNumber_Add
PWONumber operator+(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Add(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for +");
return LoseRef(rslt);
};
//PyNumber_And
PWONumber operator&(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_And(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for &");
return LoseRef(rslt);
};
@@ -63,115 +66,126 @@
//PyNumber_Divide
PWONumber operator/(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Divide(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for /");
return LoseRef(rslt);
};
//PyNumber_Divmod
PWOSequence divmod(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Divmod(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for divmod");
return LoseRef(rslt);
};
//PyNumber_Float
- operator double () const {
- PyObject* F = PyNumber_Float(_obj);
- if (F==0)
+ operator double () const {
+ PyObject* F = PyNumber_Float(_obj);
+ if (F == NULL)
Fail(PyExc_TypeError, "Cannot convert to double");
- double r = PyFloat_AS_DOUBLE(F);
- Py_DECREF(F);
- return r;
- };
+ double r = PyFloat_AS_DOUBLE(F);
+ Py_DECREF(F);
+ return r;
+ };
+ /* // no easy, safe way to do this
operator float () const {
double rslt = (double) *this;
- //if (rslt > INT_MAX)
- // Fail(PyExc_TypeError, "Cannot convert to a float");
return (float) rslt;
- };
+ }; */
//PyNumber_Int
- operator long () const {
- PyObject* Int = PyNumber_Int(_obj);
- if (Int==0)
- Fail(PyExc_TypeError, "Cannot convert to long");
- long r = PyInt_AS_LONG(Int);
- Py_DECREF(Int);
- return r;
- };
+ operator long () const {
+ PyObject* Int = PyNumber_Int(_obj);
+ if (Int == NULL)
+ Fail(PyExc_TypeError, "can't convert to int");
+ long r = PyInt_AsLong(_obj);
+ if (r == -1) FailIfPyErr();
+ return r;
+ };
operator int () const {
long rslt = (long) *this;
if (rslt > INT_MAX)
- Fail(PyExc_TypeError, "Cannot convert to an int");
+ Fail(PyExc_ValueError, "int too large to convert to C int");
return (int) rslt;
};
//PyNumber_Invert
PWONumber operator~ () const {
PyObject* rslt = PyNumber_Invert(_obj);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper type for ~");
return LoseRef(rslt);
};
//PyNumber_Long
+#ifdef HAVE_LONG_LONG
+ operator long long () const {
+ PyObject* Long = PyNumber_Long(_obj);
+ if (Long == NULL)
+ Fail(PyExc_TypeError, "can't convert to long int");
+ long r = PyLong_AsLongLong(Long);
+ if (r == -1 && PyErr_Occurred() != NULL)
+ Fail(PyExc_ValueError, "long int too large to convert to C long long");
+ Py_DECREF(Long);
+ return r;
+ };
+#endif
//PyNumber_Lshift
PWONumber operator<<(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Lshift(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for <<");
return LoseRef(rslt);
};
//PyNumber_Multiply
PWONumber operator*(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Multiply(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for *");
return LoseRef(rslt);
};
//PyNumber_Negative
PWONumber operator- () const {
PyObject* rslt = PyNumber_Negative(_obj);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper type for unary -");
return LoseRef(rslt);
};
//PyNumber_Or
PWONumber operator|(const PWONumber& rhs) const {
- PyObject* rslt = PyNumber_Or(_obj, rhs);
- if (rslt==0)
+ PyObject* rslt = PyNumber_Or(_obj, rhs);
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for |");
return LoseRef(rslt);
};
//PyNumber_Positive
PWONumber operator+ () const {
PyObject* rslt = PyNumber_Positive(_obj);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper type for unary +");
return LoseRef(rslt);
};
//PyNumber_Remainder
PWONumber operator%(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Remainder(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for %");
return LoseRef(rslt);
};
//PyNumber_Rshift
PWONumber operator>>(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Rshift(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for >>");
return LoseRef(rslt);
};
//PyNumber_Subtract
PWONumber operator-(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Subtract(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for -");
return LoseRef(rslt);
};
//PyNumber_Xor
PWONumber operator^(const PWONumber& rhs) const {
PyObject* rslt = PyNumber_Xor(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for ^");
return LoseRef(rslt);
};
diff -uNr -X metakit-files-to-ignore-when-diffing
metakit-2.4.8/python/scxx/PWOSequence.h metakit-2.4.8+njr2/python/scxx/PWOSequence.h
--- metakit-2.4.8/python/scxx/PWOSequence.h Mon Dec 3 16:50:59 2001
+++ metakit-2.4.8+njr2/python/scxx/PWOSequence.h Tue Dec 10 17:10:17 2002
@@ -35,7 +35,7 @@
//PySequence_Concat
PWOSequence operator+(const PWOSequence& rhs) const {
PyObject* rslt = PySequence_Concat(_obj, rhs);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_TypeError, "Improper rhs for +");
return LoseRef(rslt);
};
@@ -82,7 +82,7 @@
//PySequence_Repeat
PWOSequence operator * (int count) const {
PyObject* rslt = PySequence_Repeat(_obj, count);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_RuntimeError, "sequence repeat failed");
return LoseRef(rslt);
};
@@ -159,7 +159,7 @@
};
static PWOString format(const PWOString& fmt, PWOTuple& args){
PyObject * rslt =PyString_Format(fmt, args);
- if (rslt==0)
+ if (rslt == NULL)
Fail(PyExc_RuntimeError, "string format failed");
return LoseRef(rslt);
};
diff -uNr -X metakit-files-to-ignore-when-diffing metakit-2.4.8/python/test/all.py
metakit-2.4.8+njr2/python/test/all.py
--- metakit-2.4.8/python/test/all.py Wed Dec 31 18:00:00 1969
+++ metakit-2.4.8+njr2/python/test/all.py Thu Dec 12 17:51:54 2002
@@ -0,0 +1,29 @@
+# all.py -- Run all tests for the MetaKit Python bindings
+# $Id$
+# This is part of MetaKit, see http://www.equi4.com/metakit/
+
+import sys
+import os
+import test.regrtest
+
+def canonicalPath(path):
+ """Do everything but resolve symbolic links to create an absolute path."""
+ return os.path.abspath(os.path.expanduser(os.path.expandvars(path)))
+
+# from Python 2.2's regrtest module
+def findtestdir():
+ if __name__ == '__main__':
+ file = sys.argv[0]
+ else:
+ file = __file__
+ testdir = os.path.dirname(file) or os.curdir
+ return testdir
+
+testdir = canonicalPath(findtestdir())
+
+# Don't run the standard Python tests, just run MetaKit tests
+test.regrtest.STDTESTS = []
+test.regrtest.NOTTESTS = []
+
+# Take a look at the
+test.regrtest.main(testdir=testdir)
diff -uNr -X metakit-files-to-ignore-when-diffing
metakit-2.4.8/python/test/test_inttypes.py
metakit-2.4.8+njr2/python/test/test_inttypes.py
--- metakit-2.4.8/python/test/test_inttypes.py Wed Dec 31 18:00:00 1969
+++ metakit-2.4.8+njr2/python/test/test_inttypes.py Fri Dec 13 09:57:14 2002
@@ -0,0 +1,178 @@
+# test_inttypes.py -- Test MetaKit Python bindings for integral types
+# $Id$
+# This is part of MetaKit, see http://www.equi4.com/metakit/
+
+from test.test_support import TestFailed, verbose
+import os
+import sys
+
+# Keep track of failures as they happen, but don't die on the first
+# one unless it's unrecoverable. If failure_count > 0 when script
+# finishes, raise TestFailed.
+failure_count = 0
+
+def fail(op, args, err=None, expected=None, actual=None):
+ global failure_count
+ print 'FAIL:', op, args
+ print ' ',
+ if err is not None: print err,
+ if actual is not None: print 'got', actual, actual.__class__,
+ if expected is not None: print 'expected', expected,
+ print
+ failure_count = failure_count + 1
+
+# for overflow testing
+MAXINT = sys.maxint
+MININT = -MAXINT - 1
+MAXLONGLONG = 2**63 - 1
+MINLONGLONG = -2**63
+MAXULONGLONG = 2**64
+
+# Make sure we're using modules from the builds directory, assuming
+# that's the current directory at the time we're run.
+sys.path.insert(0, os.getcwd())
+
+import metakit
+
+# Check that data types are as we expect (will break with Python 2.4
+# int/long integration?)
+try:
+ MAXLONGLONG = int(MAXLONGLONG)
+ raise TestFailed('not expecting 2^63 - 1 to be a valid Python integer')
+except OverflowError:
+ pass
+
+storage = metakit.storage()
+v = storage.getas('test[intf:I,longf:L]')
+
+# insert rows into view and Python array
+arr = []
+
+def checklen(**args):
+ alen = len(arr)
+ vlen = len(v)
+ if alen != vlen:
+ fail('append', args, 'view length mismatch', actual=vlen, expected=alen)
+ try:
+ print 'ARRAY CONTENTS:'
+ for arow in arr: print arow
+ metakit.dump(v, 'VIEW CONTENTS:')
+ except: pass
+ raise TestFailed('unexpected number of rows in view, aborting; run in verbose
+mode for details')
+
+def insert(**args):
+ try:
+ v.append(args)
+ arr.append(args)
+ except Exception, e:
+ fail('append', args, actual=e)
+ try:
+ checklen(**args)
+ except TestFailed:
+ raise
+ except Exception, e:
+ fail('append', args, 'spurious', actual=e)
+
+def reject(exception_class=Exception, **args):
+ try:
+ ix = v.append(args)
+ fail('append', args, 'succeeded', expected=exception_class)
+ v.delete(ix)
+ except Exception, e:
+ if isinstance(e, exception_class):
+ if verbose:
+ print 'PASS: rejected', args
+ print ' as expected <%s> %s' % (e.__class__, e)
+ else:
+ fail('append', args, expected=exception_class, actual=e)
+ try:
+ checklen(**args)
+ except TestFailed:
+ raise
+ except Exception, e:
+ fail('append', args, 'spurious', actual=e)
+
+# defaults
+insert(intf=0, longf=0)
+
+# int field
+insert(intf=1, longf=0)
+insert(intf=-5, longf=0)
+insert(intf=MAXINT, longf=0)
+insert(intf=MININT, longf=0)
+reject(TypeError, intf=MAXINT + 1, longf=0)
+reject(TypeError, intf=MININT - 1, longf=0)
+
+# long field
+insert(intf=0, longf=-1L)
+insert(intf=0, longf=5L)
+insert(intf=0, longf=MAXLONGLONG)
+insert(intf=0, longf=MINLONGLONG)
+reject(ValueError, intf=0, longf=MAXULONGLONG)
+reject(ValueError, intf=0, longf=MAXLONGLONG + 1)
+reject(ValueError, intf=0, longf=MAXULONGLONG)
+reject(ValueError, intf=0, longf=MINLONGLONG - 1)
+
+# mixed valid int/long
+insert(intf=1, longf=2)
+insert(intf=-5, longf=-2**30)
+
+# implicit conversion to int
+insert(intf=14L, longf=0)
+insert(intf=-30L, longf=0)
+insert(intf=45.0, longf=0)
+insert(intf=21.4, longf=0)
+reject(TypeError, intf=float(MAXINT + 1), longf=0)
+reject(TypeError, intf=float(MININT - 1), longf=0)
+reject(TypeError, intf='215', longf=0)
+reject(TypeError, intf='-318.19', longf=0)
+reject(TypeError, intf=str(MAXINT + 1), longf=0)
+
+# implicit conversion to long
+insert(intf=0, longf=278)
+insert(intf=0, longf=-213)
+insert(intf=0, longf=95.0)
+insert(intf=0, longf=27.3)
+reject(ValueError, intf=0, longf=float(2 * MAXLONGLONG))
+reject(ValueError, intf=0, longf=float(2 * MINLONGLONG))
+reject(TypeError, intf=0, longf=str(MAXLONGLONG))
+reject(TypeError, intf=0, longf=str(MINLONGLONG))
+reject(TypeError, intf=0, longf='-21.39')
+reject(TypeError, intf=0, longf=str(MAXULONGLONG))
+
+# XXX should repeat with assignment instead of appending
+# XXX test v.select()
+
+if verbose:
+ metakit.dump(v, 'VIEW CONTENTS:')
+
+# compare view with array
+for arow, vrow in zip(arr, v):
+ failed = False
+ for f in arow.keys():
+ try:
+ vf = getattr(vrow, f)
+ af = arow[f]
+ if af == vf:
+ continue
+ # Perform the same implicit coercion as Mk4py should
+ if type(af) != type(vf):
+ try:
+ af = type(vf)(af)
+ if af == vf:
+ continue
+ except:
+ pass
+ # If we get here, we got an exception or the values didn't match
+ # even with coercion
+ failed = True
+ fail('%s access' % f, arow, expected=af, actual=vf)
+ except Exception, e:
+ failed = True
+ fail('%s access' % f, arow, expected=arow[f], actual=e)
+ if not failed:
+ if verbose:
+ print 'PASS: retrieved', arow
+
+if failure_count > 0:
+ raise TestFailed('%d failures; run in verbose mode for details' % failure_count)
diff -uNr -X metakit-files-to-ignore-when-diffing metakit-2.4.8/unix/Makefile.in
metakit-2.4.8+njr2/unix/Makefile.in
--- metakit-2.4.8/unix/Makefile.in Sat Nov 2 16:29:13 2002
+++ metakit-2.4.8+njr2/unix/Makefile.in Fri Dec 13 10:30:01 2002
@@ -34,12 +34,16 @@
srcdir = @srcdir@
top_builddir = .
-pyincludedir = @includedir@/python2.2
-pylibdir = @libdir@/python2.2/site-packages
+python = python
+pyincludedir = @PY_INCLUDE_DIR@
+pylibdir = @PY_LIB_DIR@
tclsh = tclsh
tclincludedir = @TCL_INCLUDE_DIR@
-tcllibdir = @TCL_INCLUDE_DIR@/../lib
+tcllibdir = @TCL_LIB_DIR@
+
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
# Compiling without frame pointers can play tricks with exception handling
# (e.g. in Mk4py). This does not affect standard operation, *only* errors.
@@ -55,7 +59,8 @@
INSTALL_DATA = $L --mode=install @INSTALL_DATA@
INSTALL_PROGRAM = $L --mode=install @INSTALL_PROGRAM@
-LIBTOOL_FLAGS = @LIBTOOL_FLAGS@
+LIBTOOL_SHLIB_FLAGS = $(LDFLAGS) @LIBTOOL_SHLIB_FLAGS@
+LIBTOOL_MODULE_FLAGS = $(LDFLAGS) @LIBTOOL_MODULE_FLAGS@
STRIP_FLAGS = @STRIP_FLAGS@
@@ -63,20 +68,20 @@
#---------- Do not change, shorthand only
-CXX_SWITCHES = $(CXXFLAGS) \
+CXX_SWITCHES = $(CPPFLAGS) $(CXXFLAGS) \
-I$(srcdir)/../include \
-I$(srcdir)/../src -I.
-CXX_SWITCHES_TCL = $(CXXFLAGS) \
+CXX_SWITCHES_TCL = $(CPPFLAGS) $(CXXFLAGS) \
-I$(srcdir)/../include \
-I$(tclincludedir)/generic \
-I$(tclincludedir)
-CXX_SWITCHES_PY = $(CXXFLAGS) \
+CXX_SWITCHES_PY = $(CPPFLAGS) $(CXXFLAGS) \
-I$(srcdir)/../include \
-I$(srcdir)/../python/scxx \
-I$(pyincludedir)
-CXX_SWITCHES_LUA = $(CXXFLAGS) \
+CXX_SWITCHES_LUA = $(CPPFLAGS) $(CXXFLAGS) \
-I$(srcdir)/../include
-CXX_SWITCHES_TEST = $(CXXFLAGS) \
+CXX_SWITCHES_TEST = $(CPPFLAGS) $(CXXFLAGS) \
-I$(srcdir)/../include
#---------- The targets normally specified when calling "make"
@@ -87,7 +92,7 @@
tcl: Makefile Mk4tcl@SHLIB_SUFFIX@
-python: Makefile Mk4py@SHLIB_SUFFIX@
+python: Makefile Mk4py@MODULE_SUFFIX@
test: Makefile libmk4.la regress
test -d tests || mkdir tests
@@ -99,6 +104,9 @@
test-tcl: tcl
cd $(srcdir)/../tcl/test && $(tclsh) all.tcl
+test-python: python
+ $(python) $(srcdir)/../python/test/all.py
+
install: @MK_INSTALL@
install-mk: libmk4.la
@@ -114,9 +122,9 @@
$(INSTALL_PROGRAM) Mk4tcl@SHLIB_SUFFIX@ $(DESTDIR)$(tcllibdir)/Mk4tcl
echo 'package ifneeded Mk4tcl 2.4.8 [list load [file join $$dir
Mk4tcl@SHLIB_SUFFIX@] Mk4tcl]' >$(DESTDIR)$(tcllibdir)/Mk4tcl/pkgIndex.tcl
-install-python: Mk4py@SHLIB_SUFFIX@
- $(INSTALL_PROGRAM) Mk4py@SHLIB_SUFFIX@ $(DESTDIR)$(pylibdir)
- $(INSTALL_PROGRAM) $(srcdir)/../python/metakit.py $$(DESTDIR)(pylibdir)
+install-python: Mk4py@MODULE_SUFFIX@
+ $(INSTALL_PROGRAM) Mk4py@MODULE_SUFFIX@ $(DESTDIR)$(pylibdir)
+ $(INSTALL_PROGRAM) $(srcdir)/../python/metakit.py $(DESTDIR)$(pylibdir)
clean:
$L rm -f *.la *.o *.lo
@@ -138,7 +146,7 @@
cd $(srcdir) && autoconf
libmk4.la: $(LIBOBJS) $(LINK_SPECIAL_FILES)
- $L --mode=link $(CXX) -o $@ $(CXX_SWITCHES) $(LIBTOOL_FLAGS) -avoid-version \
+ $L --mode=link $(CXX) -o $@ $(CXX_SWITCHES) $(LIBTOOL_SHLIB_FLAGS)
+-avoid-version \
-rpath $(libdir) $(SHLOBJS) $(LINK_SPECIAL_FLAGS)
Mk4tcl@SHLIB_SUFFIX@: libmk4tcl.la
@@ -146,15 +154,15 @@
-strip $(STRIP_FLAGS) $@ 2>/dev/null
libmk4tcl.la: mk4tcl.o mk4too.o $(LIBOBJS) $(LINK_SPECIAL_FILES)
- $L --mode=link $(CXX) -o $@ $(CXX_SWITCHES) $(LIBTOOL_FLAGS) -avoid-version \
+ $L --mode=link $(CXX) -o $@ $(CXX_SWITCHES) $(LIBTOOL_SHLIB_FLAGS)
+-avoid-version \
-rpath $(libdir) mk4tcl.lo mk4too.lo $(SHLOBJS) $(LINK_SPECIAL_FLAGS)
-Mk4py@SHLIB_SUFFIX@: libmk4py.la
- cp .libs/libmk4py@SHLIB_SUFFIX@ $@
+Mk4py@MODULE_SUFFIX@: libmk4py.la
+ cp .libs/libmk4py@MODULE_SUFFIX@ $@
-strip $(STRIP_FLAGS) $@ 2>/dev/null
libmk4py.la: $(PYOBJS) $(LIBOBJS)
- $L --mode=link $(CXX) -o $@ $(CXX_SWITCHES) $(LIBTOOL_FLAGS) -avoid-version \
+ $L --mode=link $(CXX) -o $@ $(CXX_SWITCHES) $(LIBTOOL_MODULE_FLAGS)
+-avoid-version \
-rpath $(libdir) $(SPYOBJS) $(SHLOBJS)
Mk4lua@SHLIB_SUFFIX@: mk4lua.o libmk4.la
@@ -202,8 +210,16 @@
$L --mode=compile $(CXX) -c $(CXX_SWITCHES_PY) $?
PyView.o: $(srcdir)/../python/PyView.cpp
$L --mode=compile $(CXX) -c $(CXX_SWITCHES_PY) $?
-PWOImp.o: $(srcdir)/../python/scxx/PWOImp.cpp
- $L --mode=compile $(CXX) -c $(CXX_SWITCHES_PY) $?
+
+PWOImp.o: $(srcdir)/../python/scxx/PWOImp.cpp \
+ $(srcdir)/../python/scxx/PWOBase.h \
+ $(srcdir)/../python/scxx/PWOCallable.h \
+ $(srcdir)/../python/scxx/PWOMSequence.h \
+ $(srcdir)/../python/scxx/PWOMapping.h \
+ $(srcdir)/../python/scxx/PWONumber.h \
+ $(srcdir)/../python/scxx/PWOSequence.h
+ $L --mode=compile $(CXX) -c $(CXX_SWITCHES_PY) \
+ $(srcdir)/../python/scxx/PWOImp.cpp
column.o: $(srcdir)/../src/column.cpp
$L --mode=compile $(CXX) -c $(CXX_SWITCHES) $?
diff -uNr -X metakit-files-to-ignore-when-diffing metakit-2.4.8/unix/configure.in
metakit-2.4.8+njr2/unix/configure.in
--- metakit-2.4.8/unix/configure.in Fri Oct 4 15:54:02 2002
+++ metakit-2.4.8+njr2/unix/configure.in Fri Dec 13 10:28:41 2002
@@ -8,25 +8,75 @@
MK_TARGETS="core"
MK_INSTALL="install-mk"
-AC_ARG_ENABLE(python, [ --enable-python build the Mk4py extension for
Python], [python_ok=$enableval], [python_ok=no])
+AC_ARG_WITH(python,
+[ --with-python=PATH build the Mk4py extension for Python with headers in
+ `PATH/include/python2.2'; install the Mk4py modules in
+ `PATH/lib/python2.2/site-packages'. If PATH is of the
+ form `HEADER:LIB', search for header files in HEADER,
+ and install Mk4py in LIB. If you omit the `=PATH'
+ part completely, the configure script will use the
+ provided includedir and libdir.],
+ [with_python=${withval}], [with_python=no])
AC_MSG_CHECKING([for Python configuration])
-if test "$python_ok" = yes; then
- MK_TARGETS="$MK_TARGETS python"
- MK_INSTALL="$MK_INSTALL install-python"
- AC_MSG_RESULT(enabled)
+case "$with_python" in
+ "yes" )
+ PY_INCLUDE_DIR='${includedir}/python2.2'
+ PY_LIB_DIR='${libdir}/python2.2/site-packages'
+ ;;
+ "no" )
+ PY_INCLUDE_DIR=""
+ ;;
+ *":"* )
+ PY_INCLUDE_DIR="`echo $with_python | sed -e 's/:.*$//'`"
+ PY_LIB_DIR="`echo $with_python | sed -e 's/^.*://'`"
+ ;;
+ * )
+ PY_INCLUDE_DIR="$with_python/include/python2.2"
+ PY_LIB_DIR="$with_python/lib/python2.2/site-packages"
+ ;;
+esac
+
+if test x"${PY_INCLUDE_DIR}" != x; then
+ if test -f "${PY_INCLUDE_DIR}/Python.h" ; then
+ MK_TARGETS="$MK_TARGETS python"
+ MK_INSTALL="$MK_INSTALL install-python"
+ AC_MSG_RESULT($PY_INCLUDE_DIR and $PY_LIB_DIR)
+ else
+ AC_MSG_RESULT(can't find $(PY_INCLUDE_DIR)/Python.h)
+ fi
else
AC_MSG_RESULT(not enabled)
fi
-AC_ARG_WITH(tcl, [ --with-tcl=DIR location of tcl.h header file],
[TCL_INCLUDE_DIR=${withval}])
+AC_ARG_WITH(tcl,
+[ --with-tcl=PATH build the Mk4tcl extension for Tcl with tcl.h in
+ `PATH/include/tcl.h'; install the Mk4tcl package
+ in `PATH/lib'. If PATH is of the form `HEADER:LIB',
+ search for tcl.h in HEADER, and install Mk4tcl in
+ LIB.], [with_tcl=${withval}], [with_tcl=no])
AC_MSG_CHECKING([for Tcl headers])
+case "$with_tcl" in
+ "no" )
+ TCL_INCLUDE_DIR=""
+ ;;
+ *":"* )
+ TCL_INCLUDE_DIR="`echo $with_tcl | sed -e 's/:.*$//'`"
+ TCL_LIB_DIR="`echo $with_tcl | sed -e 's/^.*://'`"
+ ;;
+ * )
+ TCL_INCLUDE_DIR="$with_tcl/include"
+ TCL_LIB_DIR="$with_tcl/lib"
+ ;;
+esac
if test x"${TCL_INCLUDE_DIR}" != x ; then
if test -f "${TCL_INCLUDE_DIR}/tcl.h" ; then
AC_MSG_RESULT(found ${TCL_INCLUDE_DIR}/tcl.h)
MK_TARGETS="$MK_TARGETS tcl"
MK_INSTALL="$MK_INSTALL install-tcl"
+ AC_MSG_CHECKING(for Tcl package installation location)
+ AC_MSG_RESULT(${TCL_LIB_DIR})
else
AC_MSG_ERROR([${TCL_INCLUDE_DIR} directory doesn't contain tcl.h])
fi
@@ -59,24 +109,29 @@
# Deal with shared lib differences
SHLIB_SUFFIX=".so"
+MODULE_SUFFIX=".so"
STRIP_FLAGS=
-LIBTOOL_FLAGS=-module
+LIBTOOL_SHLIB_FLAGS=
+LIBTOOL_MODULE_FLAGS=-module
case $build_os in
darwin*)
SHLIB_SUFFIX=".dylib"
+ # MODULE_SUFFIX remains .so (Darwin doesn't care)
STRIP_FLAGS=-S
- LIBTOOL_FLAGS=
;;
hpux*)
SHLIB_SUFFIX=".sl"
+ MODULE_SUFFIX=".sl"
if test "X$build_cpu" = "Xia64" ; then
- # libtools insists on .so files for HPUX/Itanium :(
+ # libtool insists on .so files for HP-UX/Itanium :(
SHLIB_SUFFIX=".so"
+ MODULE_SUFFIX=".so"
fi
;;
cyg*)
SHLIB_SUFFIX=".dll"
+ MODULE_SUFFIX=".dll"
;;
esac
@@ -126,10 +181,17 @@
AC_SUBST(MK_TARGETS)
AC_SUBST(MK_INSTALL)
+AC_SUBST(PY_INCLUDE_DIR)
+AC_SUBST(PY_LIB_DIR)
AC_SUBST(TCL_INCLUDE_DIR)
+AC_SUBST(TCL_LIB_DIR)
AC_SUBST(EXEEXT)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
AC_SUBST(SHLIB_SUFFIX)
-AC_SUBST(LIBTOOL_FLAGS)
+AC_SUBST(MODULE_SUFFIX)
+AC_SUBST(LIBTOOL_SHLIB_FLAGS)
+AC_SUBST(LIBTOOL_MODULE_FLAGS)
AC_SUBST(STRIP_FLAGS)
AC_OUTPUT(Makefile)