Merge pull request #771 from swig/builtin-hashable
Make Python builtin types hashable by default
This commit is contained in:
commit
27254cde09
5 changed files with 53 additions and 16 deletions
|
|
@ -1,6 +1,17 @@
|
||||||
from python_builtin import *
|
from python_builtin import *
|
||||||
|
|
||||||
if is_python_builtin():
|
if is_python_builtin():
|
||||||
|
# Test 0 for default tp_hash
|
||||||
|
vs = ValueStruct(1234)
|
||||||
|
h = hash(vs)
|
||||||
|
d = dict()
|
||||||
|
d[h] = "hi"
|
||||||
|
if h not in d:
|
||||||
|
raise RuntimeError("h should be in d")
|
||||||
|
h2 = hash(ValueStruct.inout(vs))
|
||||||
|
if h != h2:
|
||||||
|
raise RuntimeError("default tp_hash not working")
|
||||||
|
|
||||||
# Test 1 for tp_hash
|
# Test 1 for tp_hash
|
||||||
if hash(SimpleValue(222)) != 222:
|
if hash(SimpleValue(222)) != 222:
|
||||||
raise RuntimeError("tp_hash not working")
|
raise RuntimeError("tp_hash not working")
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,17 @@ bool is_python_builtin() { return false; }
|
||||||
#endif
|
#endif
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
// Test 0 for default tp_hash
|
||||||
|
%inline %{
|
||||||
|
struct ValueStruct {
|
||||||
|
int value;
|
||||||
|
ValueStruct(int value) : value(value) {}
|
||||||
|
static ValueStruct *inout(ValueStruct *v) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
%}
|
||||||
|
|
||||||
// Test 1 for tp_hash
|
// Test 1 for tp_hash
|
||||||
#if defined(SWIGPYTHON_BUILTIN)
|
#if defined(SWIGPYTHON_BUILTIN)
|
||||||
%feature("python:tp_hash") SimpleValue "SimpleValueHashFunction"
|
%feature("python:tp_hash") SimpleValue "SimpleValueHashFunction"
|
||||||
|
|
@ -19,9 +30,6 @@ bool is_python_builtin() { return false; }
|
||||||
struct SimpleValue {
|
struct SimpleValue {
|
||||||
int value;
|
int value;
|
||||||
SimpleValue(int value) : value(value) {}
|
SimpleValue(int value) : value(value) {}
|
||||||
static SimpleValue *inout(SimpleValue *sv) {
|
|
||||||
return sv;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,19 +187,14 @@ wrapper##_closure(PyObject *a) { \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SWIGPY_HASHFUNC_CLOSURE(wrapper) \
|
#define SWIGPY_HASHFUNC_CLOSURE(wrapper) \
|
||||||
SWIGINTERN long \
|
SWIGINTERN Py_hash_t \
|
||||||
wrapper##_closure(PyObject *a) { \
|
wrapper##_closure(PyObject *a) { \
|
||||||
PyObject *pyresult; \
|
PyObject *pyresult; \
|
||||||
long result; \
|
Py_hash_t result; \
|
||||||
pyresult = wrapper(a, NULL); \
|
pyresult = wrapper(a, NULL); \
|
||||||
if (!pyresult) \
|
if (!pyresult) \
|
||||||
return -1; \
|
return -1; \
|
||||||
if (!PyLong_Check(pyresult)) \
|
result = SWIG_PyNumber_AsPyHash(pyresult); \
|
||||||
PyErr_Format(PyExc_TypeError, "Wrong type for hash function");\
|
|
||||||
else \
|
|
||||||
result = PyLong_AsLong(pyresult); \
|
|
||||||
if (PyErr_Occurred()) \
|
|
||||||
result = -1; \
|
|
||||||
Py_DECREF(pyresult); \
|
Py_DECREF(pyresult); \
|
||||||
return result; \
|
return result; \
|
||||||
}
|
}
|
||||||
|
|
@ -227,14 +222,35 @@ SwigPyBuiltin_BadInit(PyObject *self, PyObject *SWIGUNUSEDPARM(args), PyObject *
|
||||||
}
|
}
|
||||||
|
|
||||||
SWIGINTERN void
|
SWIGINTERN void
|
||||||
SwigPyBuiltin_BadDealloc(PyObject *pyobj) {
|
SwigPyBuiltin_BadDealloc(PyObject *obj) {
|
||||||
SwigPyObject *sobj;
|
SwigPyObject *sobj = (SwigPyObject *)obj;
|
||||||
sobj = (SwigPyObject *)pyobj;
|
|
||||||
if (sobj->own) {
|
if (sobj->own) {
|
||||||
PyErr_Format(PyExc_TypeError, "Swig detected a memory leak in type '%.300s': no callable destructor found.", pyobj->ob_type->tp_name);
|
PyErr_Format(PyExc_TypeError, "Swig detected a memory leak in type '%.300s': no callable destructor found.", obj->ob_type->tp_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWIGINTERN Py_hash_t
|
||||||
|
SwigPyObject_hash(PyObject *obj) {
|
||||||
|
SwigPyObject *sobj = (SwigPyObject *)obj;
|
||||||
|
void *ptr = sobj->ptr;
|
||||||
|
return (Py_hash_t)ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWIGINTERN Py_hash_t
|
||||||
|
SWIG_PyNumber_AsPyHash(PyObject *obj) {
|
||||||
|
Py_hash_t result = -1;
|
||||||
|
#if PY_VERSION_HEX < 0x03020000
|
||||||
|
if (PyLong_Check(obj))
|
||||||
|
result = PyLong_AsLong(obj);
|
||||||
|
#else
|
||||||
|
if (PyNumber_Check(obj))
|
||||||
|
result = PyNumber_AsSsize_t(obj, NULL);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
PyErr_Format(PyExc_TypeError, "Wrong type for hash function");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyCFunction get;
|
PyCFunction get;
|
||||||
PyCFunction set;
|
PyCFunction set;
|
||||||
|
|
|
||||||
|
|
@ -211,4 +211,5 @@ typedef destructor freefunc;
|
||||||
#if PY_VERSION_HEX < 0x03020000
|
#if PY_VERSION_HEX < 0x03020000
|
||||||
#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
|
#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
|
||||||
#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
|
#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
|
||||||
|
#define Py_hash_t long
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -4057,6 +4057,7 @@ public:
|
||||||
static String *tp_basicsize = NewStringf("sizeof(SwigPyObject)");
|
static String *tp_basicsize = NewStringf("sizeof(SwigPyObject)");
|
||||||
static String *tp_dictoffset_default = NewString("offsetof(SwigPyObject, dict)");
|
static String *tp_dictoffset_default = NewString("offsetof(SwigPyObject, dict)");
|
||||||
static String *tp_new = NewString("PyType_GenericNew");
|
static String *tp_new = NewString("PyType_GenericNew");
|
||||||
|
static String *tp_hash = NewString("SwigPyObject_hash");
|
||||||
String *tp_as_number = NewStringf("&%s_type.as_number", templ);
|
String *tp_as_number = NewStringf("&%s_type.as_number", templ);
|
||||||
String *tp_as_sequence = NewStringf("&%s_type.as_sequence", templ);
|
String *tp_as_sequence = NewStringf("&%s_type.as_sequence", templ);
|
||||||
String *tp_as_mapping = NewStringf("&%s_type.as_mapping", templ);
|
String *tp_as_mapping = NewStringf("&%s_type.as_mapping", templ);
|
||||||
|
|
@ -4088,7 +4089,7 @@ public:
|
||||||
printSlot(f, getSlot(n, "feature:python:tp_as_number", tp_as_number), "tp_as_number");
|
printSlot(f, getSlot(n, "feature:python:tp_as_number", tp_as_number), "tp_as_number");
|
||||||
printSlot(f, getSlot(n, "feature:python:tp_as_sequence", tp_as_sequence), "tp_as_sequence");
|
printSlot(f, getSlot(n, "feature:python:tp_as_sequence", tp_as_sequence), "tp_as_sequence");
|
||||||
printSlot(f, getSlot(n, "feature:python:tp_as_mapping", tp_as_mapping), "tp_as_mapping");
|
printSlot(f, getSlot(n, "feature:python:tp_as_mapping", tp_as_mapping), "tp_as_mapping");
|
||||||
printSlot(f, getSlot(n, "feature:python:tp_hash"), "tp_hash", "hashfunc");
|
printSlot(f, getSlot(n, "feature:python:tp_hash", tp_hash), "tp_hash", "hashfunc");
|
||||||
printSlot(f, getSlot(n, "feature:python:tp_call"), "tp_call", "ternaryfunc");
|
printSlot(f, getSlot(n, "feature:python:tp_call"), "tp_call", "ternaryfunc");
|
||||||
printSlot(f, getSlot(n, "feature:python:tp_str"), "tp_str", "reprfunc");
|
printSlot(f, getSlot(n, "feature:python:tp_str"), "tp_str", "reprfunc");
|
||||||
printSlot(f, getSlot(n, "feature:python:tp_getattro"), "tp_getattro", "getattrofunc");
|
printSlot(f, getSlot(n, "feature:python:tp_getattro"), "tp_getattro", "getattrofunc");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue