Skip to content

Commit c8c4200

Browse files
vstinnerkoubaa
andauthored
bpo-42157: Convert unicodedata.UCD to heap type (GH-22991)
Convert the unicodedata extension module to the multiphase initialization API (PEP 489) and convert the unicodedata.UCD static type to a heap type. Co-Authored-By: Mohamed Koubaa <koubaa.m@gmail.com>
1 parent 920cb64 commit c8c4200

File tree

3 files changed

+56
-84
lines changed

3 files changed

+56
-84
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Convert the :mod:`unicodedata` extension module to the multiphase
2+
initialization API (:pep:`489`) and convert the ``unicodedata.UCD``
3+
static type to a heap type.
4+
Patch by Mohamed Koubaa and Victor Stinner.

Modules/_abc.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -891,14 +891,14 @@ static PyModuleDef_Slot _abcmodule_slots[] = {
891891

892892
static struct PyModuleDef _abcmodule = {
893893
PyModuleDef_HEAD_INIT,
894-
"_abc",
895-
_abc__doc__,
896-
sizeof(_abcmodule_state),
897-
_abcmodule_methods,
898-
_abcmodule_slots,
899-
_abcmodule_traverse,
900-
_abcmodule_clear,
901-
_abcmodule_free,
894+
.m_name = "_abc",
895+
.m_doc = _abc__doc__,
896+
.m_size = sizeof(_abcmodule_state),
897+
.m_methods = _abcmodule_methods,
898+
.m_slots = _abcmodule_slots,
899+
.m_traverse = _abcmodule_traverse,
900+
.m_clear = _abcmodule_clear,
901+
.m_free = _abcmodule_free,
902902
};
903903

904904
PyMODINIT_FUNC

Modules/unicodedata.c

+44-76
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ _Py_IDENTIFIER(NFKD);
2828

2929
/*[clinic input]
3030
module unicodedata
31-
class unicodedata.UCD 'PreviousDBVersion *' '&UCD_Type'
31+
class unicodedata.UCD 'PreviousDBVersion *' '<not used>'
3232
[clinic start generated code]*/
33-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6dac153082d150bc]*/
33+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e47113e05924be43]*/
3434

3535
/* character properties */
3636

@@ -90,9 +90,6 @@ static PyMemberDef DB_members[] = {
9090
{NULL}
9191
};
9292

93-
/* forward declaration */
94-
static PyTypeObject UCD_Type;
95-
9693
// Check if self is an unicodedata.UCD instance.
9794
// If self is NULL (when the PyCapsule C API is used), return 0.
9895
// PyModule_Check() is used to avoid having to retrieve the ucd_type.
@@ -1417,50 +1414,27 @@ static PyMethodDef unicodedata_functions[] = {
14171414
{NULL, NULL} /* sentinel */
14181415
};
14191416

1420-
static PyTypeObject UCD_Type = {
1421-
/* The ob_type field must be initialized in the module init function
1422-
* to be portable to Windows without using C++. */
1423-
PyVarObject_HEAD_INIT(NULL, 0)
1424-
"unicodedata.UCD", /*tp_name*/
1425-
sizeof(PreviousDBVersion), /*tp_basicsize*/
1426-
0, /*tp_itemsize*/
1427-
/* methods */
1428-
(destructor)PyObject_Del, /*tp_dealloc*/
1429-
0, /*tp_vectorcall_offset*/
1430-
0, /*tp_getattr*/
1431-
0, /*tp_setattr*/
1432-
0, /*tp_as_async*/
1433-
0, /*tp_repr*/
1434-
0, /*tp_as_number*/
1435-
0, /*tp_as_sequence*/
1436-
0, /*tp_as_mapping*/
1437-
0, /*tp_hash*/
1438-
0, /*tp_call*/
1439-
0, /*tp_str*/
1440-
PyObject_GenericGetAttr,/*tp_getattro*/
1441-
0, /*tp_setattro*/
1442-
0, /*tp_as_buffer*/
1443-
Py_TPFLAGS_DEFAULT, /*tp_flags*/
1444-
0, /*tp_doc*/
1445-
0, /*tp_traverse*/
1446-
0, /*tp_clear*/
1447-
0, /*tp_richcompare*/
1448-
0, /*tp_weaklistoffset*/
1449-
0, /*tp_iter*/
1450-
0, /*tp_iternext*/
1451-
unicodedata_functions, /*tp_methods*/
1452-
DB_members, /*tp_members*/
1453-
0, /*tp_getset*/
1454-
0, /*tp_base*/
1455-
0, /*tp_dict*/
1456-
0, /*tp_descr_get*/
1457-
0, /*tp_descr_set*/
1458-
0, /*tp_dictoffset*/
1459-
0, /*tp_init*/
1460-
0, /*tp_alloc*/
1461-
0, /*tp_new*/
1462-
0, /*tp_free*/
1463-
0, /*tp_is_gc*/
1417+
static void
1418+
ucd_dealloc(PreviousDBVersion *self)
1419+
{
1420+
PyTypeObject *tp = Py_TYPE(self);
1421+
PyObject_Del(self);
1422+
Py_DECREF(tp);
1423+
}
1424+
1425+
static PyType_Slot ucd_type_slots[] = {
1426+
{Py_tp_dealloc, ucd_dealloc},
1427+
{Py_tp_getattro, PyObject_GenericGetAttr},
1428+
{Py_tp_methods, unicodedata_functions},
1429+
{Py_tp_members, DB_members},
1430+
{0, 0}
1431+
};
1432+
1433+
static PyType_Spec ucd_type_spec = {
1434+
.name = "unicodedata.UCD",
1435+
.basicsize = sizeof(PreviousDBVersion),
1436+
.flags = Py_TPFLAGS_DEFAULT,
1437+
.slots = ucd_type_slots
14641438
};
14651439

14661440
PyDoc_STRVAR(unicodedata_docstring,
@@ -1472,37 +1446,28 @@ this database is based on the UnicodeData.txt file version\n\
14721446
The module uses the same names and symbols as defined by the\n\
14731447
UnicodeData File Format " UNIDATA_VERSION ".");
14741448

1475-
static struct PyModuleDef unicodedatamodule = {
1476-
PyModuleDef_HEAD_INIT,
1477-
"unicodedata",
1478-
unicodedata_docstring,
1479-
-1,
1480-
unicodedata_functions,
1481-
NULL,
1482-
NULL,
1483-
NULL,
1484-
NULL
1485-
};
1486-
1487-
14881449
static int
14891450
unicodedata_exec(PyObject *module)
14901451
{
1491-
Py_SET_TYPE(&UCD_Type, &PyType_Type);
1492-
PyTypeObject *ucd_type = &UCD_Type;
1493-
14941452
if (PyModule_AddStringConstant(module, "unidata_version", UNIDATA_VERSION) < 0) {
14951453
return -1;
14961454
}
14971455

1456+
PyTypeObject *ucd_type = (PyTypeObject *)PyType_FromSpec(&ucd_type_spec);
1457+
if (ucd_type == NULL) {
1458+
return -1;
1459+
}
1460+
14981461
if (PyModule_AddType(module, ucd_type) < 0) {
1462+
Py_DECREF(ucd_type);
14991463
return -1;
15001464
}
15011465

15021466
/* Previous versions */
15031467
PyObject *v;
15041468
v = new_previous_version(ucd_type, "3.2.0",
15051469
get_change_3_2_0, normalization_3_2_0);
1470+
Py_DECREF(ucd_type);
15061471
if (v == NULL) {
15071472
return -1;
15081473
}
@@ -1524,21 +1489,24 @@ unicodedata_exec(PyObject *module)
15241489
return 0;
15251490
}
15261491

1492+
static PyModuleDef_Slot unicodedata_slots[] = {
1493+
{Py_mod_exec, unicodedata_exec},
1494+
{0, NULL}
1495+
};
1496+
1497+
static struct PyModuleDef unicodedata_module = {
1498+
PyModuleDef_HEAD_INIT,
1499+
.m_name = "unicodedata",
1500+
.m_doc = unicodedata_docstring,
1501+
.m_size = 0,
1502+
.m_methods = unicodedata_functions,
1503+
.m_slots = unicodedata_slots,
1504+
};
15271505

15281506
PyMODINIT_FUNC
15291507
PyInit_unicodedata(void)
15301508
{
1531-
PyObject *module = PyModule_Create(&unicodedatamodule);
1532-
if (!module) {
1533-
return NULL;
1534-
}
1535-
1536-
if (unicodedata_exec(module) < 0) {
1537-
Py_DECREF(module);
1538-
return NULL;
1539-
}
1540-
1541-
return module;
1509+
return PyModuleDef_Init(&unicodedata_module);
15421510
}
15431511

15441512

0 commit comments

Comments
 (0)