Skip to content
Closed
Prev Previous commit
Next Next commit
PyModule_AddNew* helpers
Add helpers to create new type/exception and add it to the module dict
in one call.

Signed-off-by: Christian Heimes <christian@python.org>
  • Loading branch information
tiran committed Apr 17, 2021
commit a1c824032ef245c0d5d8590b27305d210995cbcf
6 changes: 5 additions & 1 deletion Include/modsupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ PyAPI_FUNC(int) PyModule_AddType(PyObject *module, PyTypeObject *type);

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000
/* New in 3.9 */
PyAPI_FUNC(int) PyModule_AddTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases, PyTypeObject **rtype);
PyAPI_FUNC(PyTypeObject *) PyModule_AddNewTypeFromSpec(
PyObject *module, PyType_Spec *spec, PyObject *base);
PyAPI_FUNC(PyObject *) PyModule_AddNewException(
PyObject *module, const char *name, const char *doc,
PyObject *base, PyObject *dict);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you start by adding these two functions in a separated PR, to make this PR shorter?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really think that's necessary; the PR is not that big.

#endif

#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000
Expand Down
23 changes: 13 additions & 10 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2023,8 +2023,11 @@ hashlib_free(void *m)
static int
hashlib_init_evptype(PyObject *module)
{
return PyModule_AddTypeFromSpec(
module, &EVPtype_spec, NULL, &(get_hashlib_state(module)->EVPtype));
_hashlibstate *state = get_hashlib_state(module);

state->EVPtype = PyModule_AddNewTypeFromSpec(
module, &EVPtype_spec, NULL);
return state->EVPtype == NULL ? -1 : 0;
}

static int
Expand All @@ -2036,21 +2039,21 @@ hashlib_init_evpxoftype(PyObject *module)
if (state->EVPtype == NULL) {
return -1;
}
bases = PyTuple_Pack(1, state->EVPtype);
if (bases == NULL) {
return -1;
}
return PyModule_AddTypeFromSpec(
module, &EVPXOFtype_spec, state->EVPtype, &(state->EVPXOFtype));
state->EVPXOFtype = PyModule_AddNewTypeFromSpec(
module, &EVPXOFtype_spec, (PyObject *)state->EVPtype);
return state->EVPXOFtype == NULL ? -1 : 0;
#endif
return 0;
}

static int
hashlib_init_hmactype(PyObject *module)
{
return PyModule_AddTypeFromSpec(
module, &HMACtype_spec, NULL, &(get_hashlib_state(module)->HMACtype));
_hashlibstate *state = get_hashlib_state(module);

state->HMACtype = PyModule_AddNewTypeFromSpec(
module, &HMACtype_spec, NULL);
return state->HMACtype == NULL ? -1 : 0;
}

static int
Expand Down
52 changes: 44 additions & 8 deletions Python/modsupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,22 +713,58 @@ PyModule_AddType(PyObject *module, PyTypeObject *type)
return PyModule_AddObjectRef(module, name, (PyObject *)type);
}

int
PyModule_AddTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases, PyTypeObject **rtype)
PyTypeObject *
PyModule_AddNewTypeFromSpec(PyObject *module, PyType_Spec *spec,
PyObject *base)
{
PyTypeObject *type;
PyObject *bases;

/* Support single, optional type like PyErr_NewException() */
if (base == NULL) {
bases = NULL;
}
else if (PyTuple_Check(base)) {
bases = base;
Py_INCREF(bases);
} else {
bases = PyTuple_Pack(1, base);
if (bases == NULL)
return NULL;
}

type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, bases);
/* steal ref to bases */
Py_XDECREF(bases);
if (type == NULL) {
return -1;
return NULL;
}

if (PyModule_AddType(module, type) < 0) {
return -1;
Py_DECREF(type);
return NULL;
}
if (rtype != NULL) {
*rtype = type;
return type;
}

PyObject *
PyModule_AddNewException(PyObject *module, const char *name, const char *doc,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two functions need tests.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I see these return borrowed references (held by the module object). That saves a DECREF if you don't need the new object, but it'll be problematic for HPy.

PyObject *base, PyObject *dict)
{
PyObject *exc = PyErr_NewExceptionWithDoc(name, doc, base, dict);
if (exc == NULL) {
return NULL;
}
return 0;

const char *shortname = strrchr(name, '.');
if (shortname == NULL) {
shortname = name;
}
else {
shortname++;
}
if (PyModule_AddObjectRef(module, shortname, exc) < 0) {
Py_DECREF(exc);
return NULL;
}
return exc;
}