Commit d9598ca5 authored by Dan O'Reilly's avatar Dan O'Reilly

Fix Python 3.4 cpp implementation

Fixes the ScalarMapContainer/MessageMapContainer implementations on
Python 3.4, by dynamically allocating their PyTypeObjects using
PyType_FromSpecWithBases, instead of statically allocating them. This is
necessary because Python 3.4+ disallows statically allocating a class
with a dynamically allocated parent.
Signed-off-by: 's avatarDan O'Reilly <oreilldf@gmail.com>
parent 0087da9d
...@@ -2863,6 +2863,14 @@ bool InitProto2MessageModule(PyObject *m) { ...@@ -2863,6 +2863,14 @@ bool InitProto2MessageModule(PyObject *m) {
} }
Py_INCREF(mutable_mapping); Py_INCREF(mutable_mapping);
#if PY_MAJOR_VERSION >= 3
PyObject* bases = PyTuple_New(1);
PyTuple_SET_ITEM(bases, 0, mutable_mapping.get());
ScalarMapContainer_Type =
PyType_FromSpecWithBases(&ScalarMapContainer_Type_spec, bases);
PyModule_AddObject(m, "ScalarMapContainer", ScalarMapContainer_Type);
#else
ScalarMapContainer_Type.tp_base = ScalarMapContainer_Type.tp_base =
reinterpret_cast<PyTypeObject*>(mutable_mapping.get()); reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
...@@ -2872,6 +2880,7 @@ bool InitProto2MessageModule(PyObject *m) { ...@@ -2872,6 +2880,7 @@ bool InitProto2MessageModule(PyObject *m) {
PyModule_AddObject(m, "ScalarMapContainer", PyModule_AddObject(m, "ScalarMapContainer",
reinterpret_cast<PyObject*>(&ScalarMapContainer_Type)); reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
#endif
if (PyType_Ready(&ScalarMapIterator_Type) < 0) { if (PyType_Ready(&ScalarMapIterator_Type) < 0) {
return false; return false;
...@@ -2880,6 +2889,12 @@ bool InitProto2MessageModule(PyObject *m) { ...@@ -2880,6 +2889,12 @@ bool InitProto2MessageModule(PyObject *m) {
PyModule_AddObject(m, "ScalarMapIterator", PyModule_AddObject(m, "ScalarMapIterator",
reinterpret_cast<PyObject*>(&ScalarMapIterator_Type)); reinterpret_cast<PyObject*>(&ScalarMapIterator_Type));
#if PY_MAJOR_VERSION >= 3
MessageMapContainer_Type =
PyType_FromSpecWithBases(&MessageMapContainer_Type_spec, bases);
PyModule_AddObject(m, "MessageMapContainer", MessageMapContainer_Type);
#else
Py_INCREF(mutable_mapping); Py_INCREF(mutable_mapping);
MessageMapContainer_Type.tp_base = MessageMapContainer_Type.tp_base =
reinterpret_cast<PyTypeObject*>(mutable_mapping.get()); reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
...@@ -2890,6 +2905,7 @@ bool InitProto2MessageModule(PyObject *m) { ...@@ -2890,6 +2905,7 @@ bool InitProto2MessageModule(PyObject *m) {
PyModule_AddObject(m, "MessageMapContainer", PyModule_AddObject(m, "MessageMapContainer",
reinterpret_cast<PyObject*>(&MessageMapContainer_Type)); reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
#endif
if (PyType_Ready(&MessageMapIterator_Type) < 0) { if (PyType_Ready(&MessageMapIterator_Type) < 0) {
return false; return false;
......
...@@ -84,7 +84,12 @@ PyObject* NewContainer(CMessage* parent, ...@@ -84,7 +84,12 @@ PyObject* NewContainer(CMessage* parent,
return NULL; return NULL;
} }
#if PY_MAJOR_VERSION >= 3
PyObject* obj = PyType_GenericAlloc(
reinterpret_cast<PyTypeObject *>(MessageMapContainer_Type), 0);
#else
PyObject* obj = PyType_GenericAlloc(&MessageMapContainer_Type, 0); PyObject* obj = PyType_GenericAlloc(&MessageMapContainer_Type, 0);
#endif
if (obj == NULL) { if (obj == NULL) {
return PyErr_Format(PyExc_RuntimeError, return PyErr_Format(PyExc_RuntimeError,
"Could not allocate new container."); "Could not allocate new container.");
...@@ -458,44 +463,67 @@ PyObject* IterNext(PyObject* _self) { ...@@ -458,44 +463,67 @@ PyObject* IterNext(PyObject* _self) {
} // namespace message_map_iterator } // namespace message_map_iterator
PyTypeObject MessageMapContainer_Type = { #if PY_MAJOR_VERSION >= 3
PyVarObject_HEAD_INIT(&PyType_Type, 0) static PyType_Slot MessageMapContainer_Type_slots[] = {
FULL_MODULE_NAME ".MessageMapContainer", // tp_name {Py_tp_dealloc, (void *)message_map_container::Dealloc},
sizeof(MessageMapContainer), // tp_basicsize {Py_mp_length, (void *)message_map_container::Length},
0, // tp_itemsize {Py_mp_subscript, (void *)message_map_container::GetItem},
message_map_container::Dealloc, // tp_dealloc {Py_mp_ass_subscript, (void *)message_map_container::SetItem},
0, // tp_print {Py_tp_methods, (void *)message_map_container::Methods},
0, // tp_getattr {Py_tp_iter, (void *)message_map_container::GetIterator},
0, // tp_setattr {0, 0}
0, // tp_compare };
0, // tp_repr
0, // tp_as_number PyType_Spec MessageMapContainer_Type_spec = {
0, // tp_as_sequence FULL_MODULE_NAME ".MessageMapContainer",
&message_map_container::MpMethods, // tp_as_mapping sizeof(MessageMapContainer),
0, // tp_hash 0,
0, // tp_call Py_TPFLAGS_DEFAULT,
0, // tp_str MessageMapContainer_Type_slots
0, // tp_getattro };
0, // tp_setattro
0, // tp_as_buffer PyObject *MessageMapContainer_Type;
Py_TPFLAGS_DEFAULT, // tp_flags
"A map container for message", // tp_doc #else
0, // tp_traverse PyTypeObject MessageMapContainer_Type = {
0, // tp_clear PyVarObject_HEAD_INIT(&PyType_Type, 0)
0, // tp_richcompare FULL_MODULE_NAME ".MessageMapContainer", // tp_name
0, // tp_weaklistoffset sizeof(MessageMapContainer), // tp_basicsize
message_map_container::GetIterator, // tp_iter 0, // tp_itemsize
0, // tp_iternext message_map_container::Dealloc, // tp_dealloc
message_map_container::Methods, // tp_methods 0, // tp_print
0, // tp_members 0, // tp_getattr
0, // tp_getset 0, // tp_setattr
0, // tp_base 0, // tp_compare
0, // tp_dict 0, // tp_repr
0, // tp_descr_get 0, // tp_as_number
0, // tp_descr_set 0, // tp_as_sequence
0, // tp_dictoffset &message_map_container::MpMethods, // tp_as_mapping
0, // tp_init 0, // tp_hash
}; 0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"A map container for message", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
message_map_container::GetIterator, // tp_iter
0, // tp_iternext
message_map_container::Methods, // tp_methods
0, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
};
#endif
PyTypeObject MessageMapIterator_Type = { PyTypeObject MessageMapIterator_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
......
...@@ -89,7 +89,12 @@ struct MessageMapContainer { ...@@ -89,7 +89,12 @@ struct MessageMapContainer {
uint64 version; uint64 version;
}; };
extern PyTypeObject MessageMapContainer_Type; #if PY_MAJOR_VERSION >= 3
extern PyObject *MessageMapContainer_Type;
extern PyType_Spec MessageMapContainer_Type_spec;
#else
extern PyTypeObject MessageMapContainer_Type;
#endif
extern PyTypeObject MessageMapIterator_Type; extern PyTypeObject MessageMapIterator_Type;
namespace message_map_container { namespace message_map_container {
......
...@@ -83,7 +83,12 @@ PyObject *NewContainer( ...@@ -83,7 +83,12 @@ PyObject *NewContainer(
return NULL; return NULL;
} }
#if PY_MAJOR_VERSION >= 3
ScopedPyObjectPtr obj(PyType_GenericAlloc(
reinterpret_cast<PyTypeObject *>(ScalarMapContainer_Type), 0));
#else
ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapContainer_Type, 0)); ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapContainer_Type, 0));
#endif
if (obj.get() == NULL) { if (obj.get() == NULL) {
return PyErr_Format(PyExc_RuntimeError, return PyErr_Format(PyExc_RuntimeError,
"Could not allocate new container."); "Could not allocate new container.");
...@@ -432,44 +437,66 @@ PyObject* IterNext(PyObject* _self) { ...@@ -432,44 +437,66 @@ PyObject* IterNext(PyObject* _self) {
} // namespace scalar_map_iterator } // namespace scalar_map_iterator
PyTypeObject ScalarMapContainer_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) #if PY_MAJOR_VERSION >= 3
FULL_MODULE_NAME ".ScalarMapContainer", // tp_name static PyType_Slot ScalarMapContainer_Type_slots[] = {
sizeof(ScalarMapContainer), // tp_basicsize {Py_tp_dealloc, (void *)scalar_map_container::Dealloc},
0, // tp_itemsize {Py_mp_length, (void *)scalar_map_container::Length},
scalar_map_container::Dealloc, // tp_dealloc {Py_mp_subscript, (void *)scalar_map_container::GetItem},
0, // tp_print {Py_mp_ass_subscript, (void *)scalar_map_container::SetItem},
0, // tp_getattr {Py_tp_methods, (void *)scalar_map_container::Methods},
0, // tp_setattr {Py_tp_iter, (void *)scalar_map_container::GetIterator},
0, // tp_compare {0, 0},
0, // tp_repr };
0, // tp_as_number
0, // tp_as_sequence PyType_Spec ScalarMapContainer_Type_spec = {
&scalar_map_container::MpMethods, // tp_as_mapping FULL_MODULE_NAME ".ScalarMapContainer",
0, // tp_hash sizeof(ScalarMapContainer),
0, // tp_call 0,
0, // tp_str Py_TPFLAGS_DEFAULT,
0, // tp_getattro ScalarMapContainer_Type_slots
0, // tp_setattro };
0, // tp_as_buffer PyObject *ScalarMapContainer_Type;
Py_TPFLAGS_DEFAULT, // tp_flags #else
"A scalar map container", // tp_doc PyTypeObject ScalarMapContainer_Type = {
0, // tp_traverse PyVarObject_HEAD_INIT(&PyType_Type, 0)
0, // tp_clear FULL_MODULE_NAME ".ScalarMapContainer", // tp_name
0, // tp_richcompare sizeof(ScalarMapContainer), // tp_basicsize
0, // tp_weaklistoffset 0, // tp_itemsize
scalar_map_container::GetIterator, // tp_iter scalar_map_container::Dealloc, // tp_dealloc
0, // tp_iternext 0, // tp_print
scalar_map_container::Methods, // tp_methods 0, // tp_getattr
0, // tp_members 0, // tp_setattr
0, // tp_getset 0, // tp_compare
0, // tp_base 0, // tp_repr
0, // tp_dict 0, // tp_as_number
0, // tp_descr_get 0, // tp_as_sequence
0, // tp_descr_set &scalar_map_container::MpMethods, // tp_as_mapping
0, // tp_dictoffset 0, // tp_hash
0, // tp_init 0, // tp_call
}; 0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
"A scalar map container", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
scalar_map_container::GetIterator, // tp_iter
0, // tp_iternext
scalar_map_container::Methods, // tp_methods
0, // tp_members
0, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
};
#endif
PyTypeObject ScalarMapIterator_Type = { PyTypeObject ScalarMapIterator_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
......
...@@ -83,7 +83,12 @@ struct ScalarMapContainer { ...@@ -83,7 +83,12 @@ struct ScalarMapContainer {
uint64 version; uint64 version;
}; };
extern PyTypeObject ScalarMapContainer_Type; #if PY_MAJOR_VERSION >= 3
extern PyObject *ScalarMapContainer_Type;
extern PyType_Spec ScalarMapContainer_Type_spec;
#else
extern PyTypeObject ScalarMapContainer_Type;
#endif
extern PyTypeObject ScalarMapIterator_Type; extern PyTypeObject ScalarMapIterator_Type;
namespace scalar_map_container { namespace scalar_map_container {
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
envlist = envlist =
# cpp implementation on py34 is currently broken due to # cpp implementation on py34 is currently broken due to
# changes introduced by http://bugs.python.org/issue22079. # changes introduced by http://bugs.python.org/issue22079.
#py{26,27,33,34}-{cpp,python} py{26,27,33,34}-{cpp,python}
py{26,27,33}-{cpp,python}, py34-{python}
[testenv] [testenv]
usedevelop=true usedevelop=true
......
...@@ -113,12 +113,14 @@ build_javanano_oracle7() { ...@@ -113,12 +113,14 @@ build_javanano_oracle7() {
internal_install_python_deps() { internal_install_python_deps() {
sudo pip install tox sudo pip install tox
# Only install Python2.6 on Linux. # Only install Python2.6/3.x on Linux.
if [ $(uname -s) == "Linux" ]; then if [ $(uname -s) == "Linux" ]; then
sudo apt-get install -y python-software-properties # for apt-add-repository sudo apt-get install -y python-software-properties # for apt-add-repository
sudo apt-add-repository -y ppa:fkrull/deadsnakes sudo apt-add-repository -y ppa:fkrull/deadsnakes
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -y python2.6 python2.6-dev sudo apt-get install -y python2.6 python2.6-dev
sudo apt-get install -y python3.3 python3.3-dev
sudo apt-get install -y python3.4 python3.4-dev
fi fi
} }
...@@ -127,9 +129,9 @@ build_python() { ...@@ -127,9 +129,9 @@ build_python() {
internal_build_cpp internal_build_cpp
internal_install_python_deps internal_install_python_deps
cd python cd python
# Only test Python 2.6 on Linux # Only test Python 2.6/3.x on Linux
if [ $(uname -s) == "Linux" ]; then if [ $(uname -s) == "Linux" ]; then
envlist=py26-python,py27-python envlist=py\{26,27,33,34\}-python
else else
envlist=py27-python envlist=py27-python
fi fi
...@@ -143,9 +145,9 @@ build_python_cpp() { ...@@ -143,9 +145,9 @@ build_python_cpp() {
export LD_LIBRARY_PATH=../src/.libs # for Linux export LD_LIBRARY_PATH=../src/.libs # for Linux
export DYLD_LIBRARY_PATH=../src/.libs # for OS X export DYLD_LIBRARY_PATH=../src/.libs # for OS X
cd python cd python
# Only test Python 2.6 on Linux # Only test Python 2.6/3.x on Linux
if [ $(uname -s) == "Linux" ]; then if [ $(uname -s) == "Linux" ]; then
envlist=py26-cpp,py27-cpp envlist=py\{26,27,33,34\}-cpp
else else
envlist=py27-cpp envlist=py27-cpp
fi fi
......
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