Skip to content

Commit

Permalink
Make most pyjtypes into heap types. (#395)
Browse files Browse the repository at this point in the history
This brings jep closer to the Python Stable ABI and ensures the
pyjtypes with c extensions behave the same as the dynamically
created types generated for other classes.

See: https://docs.python.org/3.10/c-api/typeobj.html#static-types
  • Loading branch information
bsteffensmeier authored May 10, 2022
1 parent 0b0e234 commit 31d5591
Show file tree
Hide file tree
Showing 16 changed files with 222 additions and 527 deletions.
5 changes: 1 addition & 4 deletions src/main/c/Include/pyjautocloseable.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@
#ifndef _Included_pyjautocloseable
#define _Included_pyjautocloseable

extern PyTypeObject PyJAutoCloseable_Type;

#define PyJAutoCloseable_Check(pyobj) \
PyObject_TypeCheck(pyobj, &PyJAutoCloseable_Type)
extern PyType_Spec PyJAutoCloseable_Spec;

#endif // ndef pyjautocloseable
5 changes: 1 addition & 4 deletions src/main/c/Include/pyjcollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@
#ifndef _Included_pyjcollection
#define _Included_pyjcollection

extern PyTypeObject PyJCollection_Type;

#define PyJCollection_Check(pyobj) \
PyObject_TypeCheck(pyobj, &PyJCollection_Type)
extern PyType_Spec PyJCollection_Spec;

#endif // ndef pyjcollection
5 changes: 1 addition & 4 deletions src/main/c/Include/pyjiterable.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@
#ifndef _Included_pyjiterable
#define _Included_pyjiterable

extern PyTypeObject PyJIterable_Type;

#define PyJIterable_Check(pyobj) \
PyObject_TypeCheck(pyobj, &PyJIterable_Type)
extern PyType_Spec PyJIterable_Spec;

#endif // ndef pyjiterable
6 changes: 1 addition & 5 deletions src/main/c/Include/pyjiterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@
#ifndef _Included_pyjiterator
#define _Included_pyjiterator

extern PyTypeObject PyJIterator_Type;

#define PyJIterator_Check(pyobj) \
PyObject_TypeCheck(pyobj, &PyJIterator_Type)

extern PyType_Spec PyJIterator_Spec;

#endif // ndef pyjiterator
5 changes: 1 addition & 4 deletions src/main/c/Include/pyjlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@
#ifndef _Included_pyjlist
#define _Included_pyjlist

extern PyTypeObject PyJList_Type;

#define PyJList_Check(pyobj) \
PyObject_TypeCheck(pyobj, &PyJList_Type)
extern PyType_Spec PyJList_Spec;

#endif // ndef pyjlist
6 changes: 1 addition & 5 deletions src/main/c/Include/pyjmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@
#ifndef _Included_pyjmap
#define _Included_pyjmap

extern PyTypeObject PyJMap_Type;

#define PyJMap_Check(pyobj) \
PyObject_TypeCheck(pyobj, &PyJMap_Type)

extern PyType_Spec PyJMap_Spec;

#endif // ndef pyjmap
6 changes: 1 addition & 5 deletions src/main/c/Include/pyjnumber.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@
#ifndef _Included_pyjnumber
#define _Included_pyjnumber

extern PyTypeObject PyJNumber_Type;

#define PyJNumber_Check(pyobj) \
PyObject_TypeCheck(pyobj, &PyJNumber_Type)

extern PyType_Spec PyJNumber_Spec;

#endif // ndef pyjnumber
45 changes: 0 additions & 45 deletions src/main/c/Jep/pyembed.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,14 +247,6 @@ void pyembed_preinit(JNIEnv *env,
* need to ensure that all the tp_base are set for the subtypes before we
* possibly use those subtypes.
*
* Furthermore, we need to ensure that the inheritance tree is built in the
* correct order, i.e. from the top down. For example, we need to set that
* PyJCollection's tp_base extends PyJIterable before we set that PyJList's
* tp_base extends PyJCollection. Interfaces that are not extending another
* interface should not set tp_base because interfaces are added to Python
* types using multiple inheritance and only one superclass can define a
* custom structure.
*
* See https://docs.python.org/3/extending/newtypes.html
*/
static int pyjtypes_ready(void)
Expand All @@ -269,50 +261,13 @@ static int pyjtypes_ready(void)
return -1;
}

if (!PyJNumber_Type.tp_base) {
PyJNumber_Type.tp_base = &PyJObject_Type;
}
if (PyType_Ready(&PyJNumber_Type) < 0) {
return -1;
}

if (PyType_Ready(&PyJIterable_Type) < 0) {
return -1;
}

if (PyType_Ready(&PyJIterator_Type) < 0) {
return -1;
}

if (!PyJCollection_Type.tp_base) {
PyJCollection_Type.tp_base = &PyJIterable_Type;
}
if (PyType_Ready(&PyJCollection_Type) < 0) {
return -1;
}

if (!PyJList_Type.tp_base) {
PyJList_Type.tp_base = &PyJCollection_Type;
}
if (PyType_Ready(&PyJList_Type) < 0) {
return -1;
}

if (PyType_Ready(&PyJMap_Type) < 0) {
return -1;
}

if (!PyJBuffer_Type.tp_base) {
PyJBuffer_Type.tp_base = &PyJObject_Type;
}
if (PyType_Ready(&PyJBuffer_Type) < 0) {
return -1;
}

if (PyType_Ready(&PyJAutoCloseable_Type) < 0) {
return -1;
}

return 0;
}

Expand Down
54 changes: 10 additions & 44 deletions src/main/c/Objects/pyjautocloseable.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,48 +71,14 @@ static PyMethodDef pyjautocloseable_methods[] = {
{ NULL, NULL }
};


/*
* Inherits from PyJObject_Type
*/
PyTypeObject PyJAutoCloseable_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"java.lang.AutoCloseable",
0,
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE, /* tp_flags */
"Jep java.lang.AutoCloseable", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
pyjautocloseable_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, // &PyJObject_Type /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
NULL, /* tp_new */
static PyType_Slot slots[] = {
{Py_tp_doc, "Jep java.lang.AutoCloseable"},
{Py_tp_methods, (void*) pyjautocloseable_methods},
{0, NULL}
};
PyType_Spec PyJAutoCloseable_Spec = {
.name = "java.lang.AutoCloseable",
.basicsize = 0,
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.slots = slots
};
69 changes: 12 additions & 57 deletions src/main/c/Objects/pyjcollection.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,62 +80,17 @@ static int pyjcollection_contains(PyObject *o, PyObject *v)
return result;
}


static PySequenceMethods pyjcollection_seq_methods = {
pyjcollection_len, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
pyjcollection_contains, /* sq_contains */
0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */
static PyType_Slot slots[] = {
// NOTE: Inherited `tp_iter` from PyJIterable
{Py_tp_doc, "Jep java.util.Collection"},
// sequence slots
{Py_sq_length, (void*) pyjcollection_len},
{Py_sq_contains, (void*) pyjcollection_contains},
{0, NULL},
};


/*
* Inherits from PyJIterable_Type
*/
PyTypeObject PyJCollection_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"java.util.Collection",
0,
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
&pyjcollection_seq_methods, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | /* tp_flags */
Py_TPFLAGS_BASETYPE,
"Jep java.util.Collection", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, // inherited /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, // &PyJIterable_Type /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
NULL, /* tp_new */
PyType_Spec PyJCollection_Spec = {
.name = "java.util.Collection",
.basicsize = 0,
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.slots = slots,
};
55 changes: 11 additions & 44 deletions src/main/c/Objects/pyjiterable.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,48 +56,15 @@ static PyObject* pyjiterable_getiter(PyObject* obj)
return result;
}


/*
* Inherits from PyJObject_Type
*/
PyTypeObject PyJIterable_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"java.lang.Iterable",
0,
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE, /* tp_flags */
"Jep java.lang.Iterable", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc) pyjiterable_getiter, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, // &PyJObject_Type /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
NULL, /* tp_new */
static PyType_Slot slots[] = {
{Py_tp_doc, "Jep java.lang.Iterable"},
{Py_tp_iter, (void*) pyjiterable_getiter},
{0, NULL}
};
PyType_Spec PyJIterable_Spec = {
.name = "java.lang.Iterable",
.basicsize = 0,
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.slots = slots
};

54 changes: 11 additions & 43 deletions src/main/c/Objects/pyjiterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,47 +60,15 @@ static PyObject* pyjiterator_next(PyObject* self)
return NULL;
}


/*
* Inherits from PyJObject_Type
*/
PyTypeObject PyJIterator_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"java.util.Iterator",
0,
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
"Jep java.util.Iterator", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc) pyjiterator_next, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, // &PyJObject_Type /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
NULL, /* tp_new */
static PyType_Slot slots[] = {
{Py_tp_doc, "Jep java.util.Iterator"},
{Py_tp_iter, (void*) PyObject_SelfIter},
{Py_tp_iternext, (void*) pyjiterator_next},
{0, NULL},
};
PyType_Spec PyJIterator_Spec = {
.name = "java.util.Iterator",
.basicsize = 0,
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.slots = slots,
};
Loading

0 comments on commit 31d5591

Please sign in to comment.