Python builtin hashfunc closure fix

If the wrong return type in the hash function was used, an error:
  SystemError: error return without exception set
was raised

Add some tests for testing builtin slots
This commit is contained in:
William S Fulton 2016-08-16 19:39:51 +01:00
commit f778ee19df
4 changed files with 105 additions and 2 deletions

View file

@ -58,6 +58,7 @@ CPP_TEST_CASES += \
primitive_types \
python_abstractbase \
python_append \
python_builtin \
python_destructor_exception \
python_director \
python_docstring \

View file

@ -0,0 +1,26 @@
from python_builtin import *
if is_python_builtin():
# Test 1 for tp_hash
if hash(SimpleValue(222)) != 222:
raise RuntimeError("tp_hash not working")
# Test 2 for tp_hash
try:
# Was incorrectly raising: SystemError: error return without exception set
h = hash(BadHashFunctionReturnType())
raise RuntimeError("Missing TypeError")
except TypeError:
pass
# Test 3 for tp_hash
passed = False
try:
h = hash(ExceptionHashFunction())
except RuntimeError, e:
passed = str(e).find("oops") != -1
pass
if not passed:
raise RuntimeError("did not catch exception in hash()")

View file

@ -0,0 +1,74 @@
// Test customizing slots when using the -builtin option
%module python_builtin
%inline %{
#ifdef SWIGPYTHON_BUILTIN
bool is_python_builtin() { return true; }
#else
bool is_python_builtin() { return false; }
#endif
%}
// Test 1 for tp_hash
#if defined(SWIGPYTHON_BUILTIN)
%feature("python:tp_hash") SimpleValue "SimpleValueHashFunction"
#endif
%inline %{
struct SimpleValue {
int value;
SimpleValue(int value) : value(value) {}
static SimpleValue *inout(SimpleValue *sv) {
return sv;
}
};
%}
%{
#if PY_VERSION_HEX >= 0x03020000
Py_hash_t SimpleValueHashFunction(PyObject *v)
#else
long SimpleValueHashFunction(PyObject *v)
#endif
{
SwigPyObject *sobj = (SwigPyObject *) v;
SimpleValue *p = (SimpleValue *)sobj->ptr;
return p->value;
}
hashfunc test_hashfunc_cast() {
return SimpleValueHashFunction;
}
%}
// Test 2 for tp_hash
#if defined(SWIGPYTHON_BUILTIN)
%feature("python:slot", "tp_hash", functype="hashfunc") BadHashFunctionReturnType::bad_hash_function;
#endif
%inline %{
struct BadHashFunctionReturnType {
static const char * bad_hash_function() {
return "bad hash function";
}
};
%}
// Test 3 for tp_hash
#if defined(SWIGPYTHON_BUILTIN)
%feature("python:slot", "tp_hash", functype="hashfunc") ExceptionHashFunction::exception_hash_function;
#endif
%catches(const char *) exception_hash_function;
%inline %{
#if PY_VERSION_HEX < 0x03020000
#define Py_hash_t long
#endif
struct ExceptionHashFunction {
static Py_hash_t exception_hash_function() {
throw "oops";
}
};
%}

View file

@ -192,9 +192,11 @@ wrapper##_closure(PyObject *a) { \
PyObject *pyresult; \
long result; \
pyresult = wrapper(a, NULL); \
if (!pyresult || !PyLong_Check(pyresult)) \
return -1; \
if (!pyresult) \
return -1; \
result = PyLong_AsLong(pyresult); \
if (PyErr_Occurred()) \
result = -1; \
Py_DECREF(pyresult); \
return result; \
}