From 78b9d53ee794d20607ff306aa4421ff231b8c2b6 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 10:46:08 +0100 Subject: [PATCH 01/14] Add convenience macro --- Modules/_sre.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Modules/_sre.c b/Modules/_sre.c index fbabeb7c9f3054..c346666e53518d 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -2773,6 +2773,14 @@ static struct PyModuleDef sremodule = { NULL }; +#define CREATE_TYPE(m, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(m, spec, NULL); \ + if (type == NULL) { \ + goto error; \ + } \ +} while (0) + PyMODINIT_FUNC PyInit__sre(void) { PyObject* m; @@ -2819,6 +2827,10 @@ PyMODINIT_FUNC PyInit__sre(void) Py_DECREF(x); } return m; + +error: + Py_XDECREF(m); + return NULL; } /* vim:ts=4:sw=4:et From ce746b3fe81f83216f514f19a6a31bee131349a1 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 10:33:25 +0100 Subject: [PATCH 02/14] Convert _sre pattern type to heap type --- Modules/_sre.c | 79 ++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index c346666e53518d..59a10976871eca 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -255,13 +255,13 @@ static PyObject *pattern_scanner(PatternObject *, PyObject *, Py_ssize_t, Py_ssi /*[clinic input] module _sre -class _sre.SRE_Pattern "PatternObject *" "&Pattern_Type" +class _sre.SRE_Pattern "PatternObject *" "Pattern_Type" class _sre.SRE_Match "MatchObject *" "&Match_Type" class _sre.SRE_Scanner "ScannerObject *" "&Scanner_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0230ec19a0deac8]*/ -static PyTypeObject Pattern_Type; +static PyTypeObject *Pattern_Type = NULL; static PyTypeObject Match_Type; static PyTypeObject Scanner_Type; @@ -550,12 +550,15 @@ pattern_error(Py_ssize_t status) static void pattern_dealloc(PatternObject* self) { + PyTypeObject *tp = Py_TYPE(self); + if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); Py_XDECREF(self->pattern); Py_XDECREF(self->groupindex); Py_XDECREF(self->indexgroup); PyObject_DEL(self); + Py_DECREF(tp); } LOCAL(Py_ssize_t) @@ -1343,7 +1346,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, n = PyList_GET_SIZE(code); /* coverity[ampersand_in_size] */ - self = PyObject_NewVar(PatternObject, &Pattern_Type, n); + self = PyObject_NewVar(PatternObject, Pattern_Type, n); if (!self) return NULL; self->weakreflist = NULL; @@ -2523,7 +2526,7 @@ pattern_richcompare(PyObject *lefto, PyObject *righto, int op) Py_RETURN_NOTIMPLEMENTED; } - if (!Py_IS_TYPE(lefto, &Pattern_Type) || !Py_IS_TYPE(righto, &Pattern_Type)) { + if (!Py_IS_TYPE(lefto, Pattern_Type) || !Py_IS_TYPE(righto, Pattern_Type)) { Py_RETURN_NOTIMPLEMENTED; } @@ -2592,39 +2595,28 @@ static PyMemberDef pattern_members[] = { "The regex matching flags."}, {"groups", T_PYSSIZET, PAT_OFF(groups), READONLY, "The number of capturing groups in the pattern."}, + {"__weaklistoffset__", T_PYSSIZET, offsetof(PatternObject, weakreflist), READONLY}, {NULL} /* Sentinel */ }; -static PyTypeObject Pattern_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "re.Pattern", - sizeof(PatternObject), sizeof(SRE_CODE), - (destructor)pattern_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)pattern_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)pattern_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - pattern_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - pattern_richcompare, /* tp_richcompare */ - offsetof(PatternObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - pattern_methods, /* tp_methods */ - pattern_members, /* tp_members */ - pattern_getset, /* tp_getset */ +static PyType_Slot pattern_slots[] = { + {Py_tp_dealloc, (destructor)pattern_dealloc}, + {Py_tp_repr, (reprfunc)pattern_repr}, + {Py_tp_hash, (hashfunc)pattern_hash}, + {Py_tp_doc, (void *)pattern_doc}, + {Py_tp_richcompare, pattern_richcompare}, + {Py_tp_methods, pattern_methods}, + {Py_tp_members, pattern_members}, + {Py_tp_getset, pattern_getset}, + {0, NULL}, +}; + +static PyType_Spec pattern_spec = { + .name = "re.Pattern", + .basicsize = sizeof(PatternObject), + .itemsize = sizeof(SRE_CODE), + .flags = Py_TPFLAGS_DEFAULT, + .slots = pattern_slots, }; /* Match objects do not support length or assignment, but do support @@ -2762,15 +2754,10 @@ static PyMethodDef _functions[] = { }; static struct PyModuleDef sremodule = { - PyModuleDef_HEAD_INIT, - "_" SRE_MODULE, - NULL, - -1, - _functions, - NULL, - NULL, - NULL, - NULL + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_" SRE_MODULE, + .m_size = -1, + .m_methods = _functions, }; #define CREATE_TYPE(m, type, spec) \ @@ -2788,13 +2775,17 @@ PyMODINIT_FUNC PyInit__sre(void) PyObject* x; /* Patch object types */ - if (PyType_Ready(&Pattern_Type) || PyType_Ready(&Match_Type) || + if (PyType_Ready(&Match_Type) || PyType_Ready(&Scanner_Type)) return NULL; m = PyModule_Create(&sremodule); if (m == NULL) return NULL; + + /* Create heap types */ + CREATE_TYPE(m, Pattern_Type, &pattern_spec); + d = PyModule_GetDict(m); x = PyLong_FromLong(SRE_MAGIC); From 529142d06f657a89c5a28191446363c90a6c1ca7 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 11:01:10 +0100 Subject: [PATCH 03/14] Convert _sre match type to heap type --- Modules/_sre.c | 74 +++++++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index 59a10976871eca..b70bec975db944 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -256,13 +256,13 @@ static PyObject *pattern_scanner(PatternObject *, PyObject *, Py_ssize_t, Py_ssi /*[clinic input] module _sre class _sre.SRE_Pattern "PatternObject *" "Pattern_Type" -class _sre.SRE_Match "MatchObject *" "&Match_Type" +class _sre.SRE_Match "MatchObject *" "Match_Type" class _sre.SRE_Scanner "ScannerObject *" "&Scanner_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0230ec19a0deac8]*/ static PyTypeObject *Pattern_Type = NULL; -static PyTypeObject Match_Type; +static PyTypeObject *Match_Type = NULL; static PyTypeObject Scanner_Type; /*[clinic input] @@ -1890,10 +1890,13 @@ _validate(PatternObject *self) static void match_dealloc(MatchObject* self) { + PyTypeObject *tp = Py_TYPE(self); + Py_XDECREF(self->regs); Py_XDECREF(self->string); Py_DECREF(self->pattern); PyObject_DEL(self); + Py_DECREF(tp); } static PyObject* @@ -2335,7 +2338,7 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) /* create match object (with room for extra group marks) */ /* coverity[ampersand_in_size] */ - match = PyObject_NewVar(MatchObject, &Match_Type, + match = PyObject_NewVar(MatchObject, Match_Type, 2*(pattern->groups+1)); if (!match) return NULL; @@ -2619,14 +2622,6 @@ static PyType_Spec pattern_spec = { .slots = pattern_slots, }; -/* Match objects do not support length or assignment, but do support - __getitem__. */ -static PyMappingMethods match_as_mapping = { - NULL, - (binaryfunc)match_getitem, - NULL -}; - static PyMethodDef match_methods[] = { {"group", (PyCFunction) match_group, METH_VARARGS, match_group_doc}, _SRE_SRE_MATCH_START_METHODDEF @@ -2666,37 +2661,30 @@ static PyMemberDef match_members[] = { /* FIXME: implement setattr("string", None) as a special case (to detach the associated string, if any */ +static PyType_Slot match_slots[] = { + {Py_tp_dealloc, match_dealloc}, + {Py_tp_repr, match_repr}, + {Py_tp_doc, (void *)match_doc}, + {Py_tp_methods, match_methods}, + {Py_tp_members, match_members}, + {Py_tp_getset, match_getset}, + + /* As mapping. + * + * Match objects do not support length or assignment, but do support + * __getitem__. + */ + {Py_mp_subscript, match_getitem}, -static PyTypeObject Match_Type = { - PyVarObject_HEAD_INIT(NULL,0) - "re.Match", - sizeof(MatchObject), sizeof(Py_ssize_t), - (destructor)match_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)match_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - &match_as_mapping, /* 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 */ - match_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - match_methods, /* tp_methods */ - match_members, /* tp_members */ - match_getset, /* tp_getset */ + {0, NULL}, +}; + +static PyType_Spec match_spec = { + .name = "re.Match", + .basicsize = sizeof(MatchObject), + .itemsize = sizeof(Py_ssize_t), + .flags = Py_TPFLAGS_DEFAULT, + .slots = match_slots, }; static PyMethodDef scanner_methods[] = { @@ -2775,8 +2763,7 @@ PyMODINIT_FUNC PyInit__sre(void) PyObject* x; /* Patch object types */ - if (PyType_Ready(&Match_Type) || - PyType_Ready(&Scanner_Type)) + if (PyType_Ready(&Scanner_Type)) return NULL; m = PyModule_Create(&sremodule); @@ -2785,6 +2772,7 @@ PyMODINIT_FUNC PyInit__sre(void) /* Create heap types */ CREATE_TYPE(m, Pattern_Type, &pattern_spec); + CREATE_TYPE(m, Match_Type, &match_spec); d = PyModule_GetDict(m); From 7583104c401e6c2329961151c69827b523134c6a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 11:10:05 +0100 Subject: [PATCH 04/14] Convert _sre scanner type to heap type --- Modules/_sre.c | 56 +++++++++++++++++--------------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index b70bec975db944..e991c9514118f3 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -257,13 +257,13 @@ static PyObject *pattern_scanner(PatternObject *, PyObject *, Py_ssize_t, Py_ssi module _sre class _sre.SRE_Pattern "PatternObject *" "Pattern_Type" class _sre.SRE_Match "MatchObject *" "Match_Type" -class _sre.SRE_Scanner "ScannerObject *" "&Scanner_Type" +class _sre.SRE_Scanner "ScannerObject *" "Scanner_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0230ec19a0deac8]*/ static PyTypeObject *Pattern_Type = NULL; static PyTypeObject *Match_Type = NULL; -static PyTypeObject Scanner_Type; +static PyTypeObject *Scanner_Type = NULL; /*[clinic input] _sre.getcodesize -> int @@ -2393,9 +2393,12 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) static void scanner_dealloc(ScannerObject* self) { + PyTypeObject *tp = Py_TYPE(self); + state_fini(&self->state); Py_XDECREF(self->pattern); PyObject_DEL(self); + Py_DECREF(tp); } /*[clinic input] @@ -2479,7 +2482,7 @@ pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_ ScannerObject* scanner; /* create scanner object */ - scanner = PyObject_New(ScannerObject, &Scanner_Type); + scanner = PyObject_New(ScannerObject, Scanner_Type); if (!scanner) return NULL; scanner->pattern = NULL; @@ -2699,36 +2702,18 @@ static PyMemberDef scanner_members[] = { {NULL} /* Sentinel */ }; -static PyTypeObject Scanner_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_" SRE_MODULE ".SRE_Scanner", - sizeof(ScannerObject), 0, - (destructor)scanner_dealloc,/* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 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, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - scanner_methods, /* tp_methods */ - scanner_members, /* tp_members */ - 0, /* tp_getset */ +static PyType_Slot scanner_slots[] = { + {Py_tp_dealloc, scanner_dealloc}, + {Py_tp_methods, scanner_methods}, + {Py_tp_members, scanner_members}, + {0, NULL}, +}; + +static PyType_Spec scanner_spec = { + .name = "_" SRE_MODULE ".SRE_Scanner", + .basicsize = sizeof(ScannerObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = scanner_slots, }; static PyMethodDef _functions[] = { @@ -2762,10 +2747,6 @@ PyMODINIT_FUNC PyInit__sre(void) PyObject* d; PyObject* x; - /* Patch object types */ - if (PyType_Ready(&Scanner_Type)) - return NULL; - m = PyModule_Create(&sremodule); if (m == NULL) return NULL; @@ -2773,6 +2754,7 @@ PyMODINIT_FUNC PyInit__sre(void) /* Create heap types */ CREATE_TYPE(m, Pattern_Type, &pattern_spec); CREATE_TYPE(m, Match_Type, &match_spec); + CREATE_TYPE(m, Scanner_Type, &scanner_spec); d = PyModule_GetDict(m); From 575fccf664ee40e12b8eb4500c272cea443a5af7 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 11:26:55 +0100 Subject: [PATCH 05/14] Establish global module state and add types to it --- Modules/_sre.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index e991c9514118f3..3884cc2300cc81 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -253,18 +253,28 @@ static PyObject*pattern_new_match(PatternObject*, SRE_STATE*, Py_ssize_t); static PyObject *pattern_scanner(PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); +typedef struct { + PyTypeObject *Pattern_Type; + PyTypeObject *Match_Type; + PyTypeObject *Scanner_Type; +} sre_module_state; + +sre_module_state sre_global_state; + +static sre_module_state * +get_sre_module_state() +{ + return &sre_global_state; +} + /*[clinic input] module _sre -class _sre.SRE_Pattern "PatternObject *" "Pattern_Type" -class _sre.SRE_Match "MatchObject *" "Match_Type" -class _sre.SRE_Scanner "ScannerObject *" "Scanner_Type" +class _sre.SRE_Pattern "PatternObject *" "get_sre_module_state()->Pattern_Type" +class _sre.SRE_Match "MatchObject *" "get_sre_module_state()->Match_Type" +class _sre.SRE_Scanner "ScannerObject *" "get_sre_module_state()->Scanner_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0230ec19a0deac8]*/ -static PyTypeObject *Pattern_Type = NULL; -static PyTypeObject *Match_Type = NULL; -static PyTypeObject *Scanner_Type = NULL; - /*[clinic input] _sre.getcodesize -> int [clinic start generated code]*/ @@ -1346,7 +1356,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, n = PyList_GET_SIZE(code); /* coverity[ampersand_in_size] */ - self = PyObject_NewVar(PatternObject, Pattern_Type, n); + self = PyObject_NewVar(PatternObject, get_sre_module_state()->Pattern_Type, n); if (!self) return NULL; self->weakreflist = NULL; @@ -2338,7 +2348,7 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) /* create match object (with room for extra group marks) */ /* coverity[ampersand_in_size] */ - match = PyObject_NewVar(MatchObject, Match_Type, + match = PyObject_NewVar(MatchObject, get_sre_module_state()->Match_Type, 2*(pattern->groups+1)); if (!match) return NULL; @@ -2482,7 +2492,7 @@ pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_ ScannerObject* scanner; /* create scanner object */ - scanner = PyObject_New(ScannerObject, Scanner_Type); + scanner = PyObject_New(ScannerObject, get_sre_module_state()->Scanner_Type); if (!scanner) return NULL; scanner->pattern = NULL; @@ -2525,6 +2535,7 @@ pattern_hash(PatternObject *self) static PyObject* pattern_richcompare(PyObject *lefto, PyObject *righto, int op) { + sre_module_state *state = get_sre_module_state(); PatternObject *left, *right; int cmp; @@ -2532,7 +2543,9 @@ pattern_richcompare(PyObject *lefto, PyObject *righto, int op) Py_RETURN_NOTIMPLEMENTED; } - if (!Py_IS_TYPE(lefto, Pattern_Type) || !Py_IS_TYPE(righto, Pattern_Type)) { + if (!Py_IS_TYPE(lefto, state->Pattern_Type) || + !Py_IS_TYPE(righto, state->Pattern_Type)) + { Py_RETURN_NOTIMPLEMENTED; } @@ -2743,6 +2756,7 @@ do { \ PyMODINIT_FUNC PyInit__sre(void) { + sre_module_state *state = get_sre_module_state(); PyObject* m; PyObject* d; PyObject* x; @@ -2752,9 +2766,9 @@ PyMODINIT_FUNC PyInit__sre(void) return NULL; /* Create heap types */ - CREATE_TYPE(m, Pattern_Type, &pattern_spec); - CREATE_TYPE(m, Match_Type, &match_spec); - CREATE_TYPE(m, Scanner_Type, &scanner_spec); + CREATE_TYPE(m, state->Pattern_Type, &pattern_spec); + CREATE_TYPE(m, state->Match_Type, &match_spec); + CREATE_TYPE(m, state->Scanner_Type, &scanner_spec); d = PyModule_GetDict(m); From f82463cc06cc0cf626431c5c30160475f75a6d06 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 12:01:11 +0100 Subject: [PATCH 06/14] Convert global state to module state --- Modules/_sre.c | 182 ++++++++++++------- Modules/clinic/_sre.c.h | 378 ++++++++++------------------------------ 2 files changed, 213 insertions(+), 347 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index 3884cc2300cc81..4f3e7038ad44aa 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -248,32 +248,38 @@ data_stack_grow(SRE_STATE* state, Py_ssize_t size) /* -------------------------------------------------------------------- */ /* factories and destructors */ -/* see sre.h for object declarations */ -static PyObject*pattern_new_match(PatternObject*, SRE_STATE*, Py_ssize_t); -static PyObject *pattern_scanner(PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); - - +/* module state */ typedef struct { PyTypeObject *Pattern_Type; PyTypeObject *Match_Type; PyTypeObject *Scanner_Type; } sre_module_state; -sre_module_state sre_global_state; - static sre_module_state * -get_sre_module_state() +get_sre_module_state(PyObject *m) { - return &sre_global_state; + sre_module_state *state = (sre_module_state *)PyModule_GetState(m); + assert(state); + return state; } +static struct PyModuleDef sremodule; +#define get_sre_module_state_by_type(tp) \ + (get_sre_module_state(_PyType_GetModuleByDef(tp, &sremodule))) +#define get_sre_module_state_by_class(cls) \ + (get_sre_module_state(PyType_GetModule(cls))) + +/* see sre.h for object declarations */ +static PyObject*pattern_new_match(sre_module_state *, PatternObject*, SRE_STATE*, Py_ssize_t); +static PyObject *pattern_scanner(sre_module_state *, PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); + /*[clinic input] module _sre -class _sre.SRE_Pattern "PatternObject *" "get_sre_module_state()->Pattern_Type" -class _sre.SRE_Match "MatchObject *" "get_sre_module_state()->Match_Type" -class _sre.SRE_Scanner "ScannerObject *" "get_sre_module_state()->Scanner_Type" +class _sre.SRE_Pattern "PatternObject *" "get_sre_module_state_by_type(tp)->Pattern_Type" +class _sre.SRE_Match "MatchObject *" "get_sre_module_state_by_type(tp)->Match_Type" +class _sre.SRE_Scanner "ScannerObject *" "get_sre_module_state_by_type(tp)->Scanner_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0230ec19a0deac8]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9f2e869a208f635c]*/ /*[clinic input] _sre.getcodesize -> int @@ -596,6 +602,8 @@ sre_search(SRE_STATE* state, SRE_CODE* pattern) /*[clinic input] _sre.SRE_Pattern.match + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -604,10 +612,12 @@ Matches zero or more characters at the beginning of the string. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=ea2d838888510661 input=a2ba191647abebe5]*/ +_sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=ec6208ea58a0cca0 input=4bdb9c3e564d13ac]*/ { + sre_module_state *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -627,7 +637,7 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -635,6 +645,8 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.fullmatch + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -643,10 +655,12 @@ Matches against all of the string. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=5833c47782a35f4a input=d9fb03a7625b5828]*/ +_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=625b75b027ef94da input=50981172ab0fcfdd]*/ { + sre_module_state *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -667,7 +681,7 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -675,6 +689,8 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.search + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -685,10 +701,12 @@ Return None if no position in the string matches. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=25f302a644e951e8 input=4ae5cb7dc38fed1b]*/ +_sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=bd7f2d9d583e1463 input=afa9afb66a74a4b3]*/ { + sre_module_state *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -707,7 +725,7 @@ _sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -839,6 +857,8 @@ _sre_SRE_Pattern_findall_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.finditer + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -849,15 +869,17 @@ For each match, the iterator returns a match object. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=0bbb1a0aeb38bb14 input=612aab69e9fe08e4]*/ +_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=1791dbf3618ade56 input=812e332a4848cbaf]*/ { + sre_module_state *module_state = get_sre_module_state_by_class(cls); PyObject* scanner; PyObject* search; PyObject* iterator; - scanner = pattern_scanner(self, string, pos, endpos); + scanner = pattern_scanner(module_state, self, string, pos, endpos); if (!scanner) return NULL; @@ -875,6 +897,8 @@ _sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.scanner + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -882,11 +906,14 @@ _sre.SRE_Pattern.scanner [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=54ea548aed33890b input=3aacdbde77a3a637]*/ +_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=f70cd506112f1bd9 input=2e487e5151bcee4c]*/ { - return pattern_scanner(self, string, pos, endpos); + sre_module_state *module_state = get_sre_module_state_by_class(cls); + + return pattern_scanner(module_state, self, string, pos, endpos); } /*[clinic input] @@ -993,8 +1020,12 @@ _sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string, } static PyObject* -pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, - Py_ssize_t count, Py_ssize_t subn) +pattern_subx(sre_module_state* module_state, + PatternObject* self, + PyObject* ptemplate, + PyObject* string, + Py_ssize_t count, + Py_ssize_t subn) { SRE_STATE state; PyObject* list; @@ -1096,7 +1127,7 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, if (filter_is_callable) { /* pass match object through filter */ - match = pattern_new_match(self, &state, 1); + match = pattern_new_match(module_state, self, &state, 1); if (!match) goto error; item = PyObject_CallOneArg(filter, match); @@ -1176,6 +1207,8 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, /*[clinic input] _sre.SRE_Pattern.sub + cls: defining_class + / repl: object string: object count: Py_ssize_t = 0 @@ -1184,16 +1217,20 @@ Return the string obtained by replacing the leftmost non-overlapping occurrences [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_sub_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count) -/*[clinic end generated code: output=1dbf2ec3479cba00 input=c53d70be0b3caf86]*/ +_sre_SRE_Pattern_sub_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, Py_ssize_t count) +/*[clinic end generated code: output=4be141ab04bca60d input=d8d1d4ac2311a07c]*/ { - return pattern_subx(self, repl, string, count, 0); + sre_module_state *module_state = get_sre_module_state_by_class(cls); + + return pattern_subx(module_state, self, repl, string, count, 0); } /*[clinic input] _sre.SRE_Pattern.subn + cls: defining_class + / repl: object string: object count: Py_ssize_t = 0 @@ -1202,11 +1239,14 @@ Return the tuple (new_string, number_of_subs_made) found by replacing the leftmo [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_subn_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count) -/*[clinic end generated code: output=0d9522cd529e9728 input=e7342d7ce6083577]*/ +_sre_SRE_Pattern_subn_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, + Py_ssize_t count) +/*[clinic end generated code: output=da02fd85258b1e1f input=8b78a65b8302e58d]*/ { - return pattern_subx(self, repl, string, count, 1); + sre_module_state *module_state = get_sre_module_state_by_class(cls); + + return pattern_subx(module_state, self, repl, string, count, 1); } /*[clinic input] @@ -1351,12 +1391,13 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, { /* "compile" pattern descriptor to pattern object */ + sre_module_state *module_state = get_sre_module_state(module); PatternObject* self; Py_ssize_t i, n; n = PyList_GET_SIZE(code); /* coverity[ampersand_in_size] */ - self = PyObject_NewVar(PatternObject, get_sre_module_state()->Pattern_Type, n); + self = PyObject_NewVar(PatternObject, module_state->Pattern_Type, n); if (!self) return NULL; self->weakreflist = NULL; @@ -2335,7 +2376,10 @@ match_repr(MatchObject *self) static PyObject* -pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) +pattern_new_match(sre_module_state* module_state, + PatternObject* pattern, + SRE_STATE* state, + Py_ssize_t status) { /* create match object (from state object) */ @@ -2348,7 +2392,8 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) /* create match object (with room for extra group marks) */ /* coverity[ampersand_in_size] */ - match = PyObject_NewVar(MatchObject, get_sre_module_state()->Match_Type, + match = PyObject_NewVar(MatchObject, + module_state->Match_Type, 2*(pattern->groups+1)); if (!match) return NULL; @@ -2414,12 +2459,16 @@ scanner_dealloc(ScannerObject* self) /*[clinic input] _sre.SRE_Scanner.match + cls: defining_class + / + [clinic start generated code]*/ static PyObject * -_sre_SRE_Scanner_match_impl(ScannerObject *self) -/*[clinic end generated code: output=936b30c63d4b81eb input=881a0154f8c13d9a]*/ +_sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=6e22c149dc0f0325 input=b5146e1f30278cb7]*/ { + sre_module_state *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; PyObject* match; Py_ssize_t status; @@ -2435,8 +2484,8 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self) if (PyErr_Occurred()) return NULL; - match = pattern_new_match((PatternObject*) self->pattern, - state, status); + match = pattern_new_match(module_state, (PatternObject*) self->pattern, + state, status); if (status == 0) state->start = NULL; @@ -2452,12 +2501,16 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self) /*[clinic input] _sre.SRE_Scanner.search + cls: defining_class + / + [clinic start generated code]*/ static PyObject * -_sre_SRE_Scanner_search_impl(ScannerObject *self) -/*[clinic end generated code: output=7dc211986088f025 input=161223ee92ef9270]*/ +_sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=23e8fc78013f9161 input=056c2d37171d0bf2]*/ { + sre_module_state *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; PyObject* match; Py_ssize_t status; @@ -2473,8 +2526,8 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self) if (PyErr_Occurred()) return NULL; - match = pattern_new_match((PatternObject*) self->pattern, - state, status); + match = pattern_new_match(module_state, (PatternObject*) self->pattern, + state, status); if (status == 0) state->start = NULL; @@ -2487,12 +2540,16 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self) } static PyObject * -pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_t endpos) +pattern_scanner(sre_module_state *module_state, + PatternObject *self, + PyObject *string, + Py_ssize_t pos, + Py_ssize_t endpos) { ScannerObject* scanner; /* create scanner object */ - scanner = PyObject_New(ScannerObject, get_sre_module_state()->Scanner_Type); + scanner = PyObject_New(ScannerObject, module_state->Scanner_Type); if (!scanner) return NULL; scanner->pattern = NULL; @@ -2535,7 +2592,8 @@ pattern_hash(PatternObject *self) static PyObject* pattern_richcompare(PyObject *lefto, PyObject *righto, int op) { - sre_module_state *state = get_sre_module_state(); + PyTypeObject *tp = Py_TYPE(lefto); + sre_module_state *module_state = get_sre_module_state_by_type(tp); PatternObject *left, *right; int cmp; @@ -2543,8 +2601,7 @@ pattern_richcompare(PyObject *lefto, PyObject *righto, int op) Py_RETURN_NOTIMPLEMENTED; } - if (!Py_IS_TYPE(lefto, state->Pattern_Type) || - !Py_IS_TYPE(righto, state->Pattern_Type)) + if (!Py_IS_TYPE(righto, module_state->Pattern_Type)) { Py_RETURN_NOTIMPLEMENTED; } @@ -2742,7 +2799,7 @@ static PyMethodDef _functions[] = { static struct PyModuleDef sremodule = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "_" SRE_MODULE, - .m_size = -1, + .m_size = sizeof(sre_module_state), .m_methods = _functions, }; @@ -2756,7 +2813,7 @@ do { \ PyMODINIT_FUNC PyInit__sre(void) { - sre_module_state *state = get_sre_module_state(); + sre_module_state *state; PyObject* m; PyObject* d; PyObject* x; @@ -2766,6 +2823,7 @@ PyMODINIT_FUNC PyInit__sre(void) return NULL; /* Create heap types */ + state = get_sre_module_state(m); CREATE_TYPE(m, state->Pattern_Type, &pattern_spec); CREATE_TYPE(m, state->Match_Type, &match_spec); CREATE_TYPE(m, state->Scanner_Type, &scanner_spec); diff --git a/Modules/clinic/_sre.c.h b/Modules/clinic/_sre.c.h index 2314114a1bc805..72d772c289ae8b 100644 --- a/Modules/clinic/_sre.c.h +++ b/Modules/clinic/_sre.c.h @@ -164,63 +164,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_match__doc__, "Matches zero or more characters at the beginning of the string."); #define _SRE_SRE_PATTERN_MATCH_METHODDEF \ - {"match", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_match, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_match__doc__}, + {"match", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_match, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_match__doc__}, static PyObject * -_sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_match(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_match(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "match", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:match", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_match_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_match_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -233,63 +198,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_fullmatch__doc__, "Matches against all of the string."); #define _SRE_SRE_PATTERN_FULLMATCH_METHODDEF \ - {"fullmatch", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_fullmatch, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_fullmatch__doc__}, + {"fullmatch", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_fullmatch, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_fullmatch__doc__}, static PyObject * -_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_fullmatch(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_fullmatch(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "fullmatch", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:fullmatch", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_fullmatch_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_fullmatch_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -304,63 +234,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_search__doc__, "Return None if no position in the string matches."); #define _SRE_SRE_PATTERN_SEARCH_METHODDEF \ - {"search", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_search, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_search__doc__}, + {"search", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_search, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_search__doc__}, static PyObject * -_sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_search(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_search(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "search", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:search", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_search_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_search_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -444,63 +339,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_finditer__doc__, "For each match, the iterator returns a match object."); #define _SRE_SRE_PATTERN_FINDITER_METHODDEF \ - {"finditer", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_finditer, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_finditer__doc__}, + {"finditer", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_finditer, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_finditer__doc__}, static PyObject * -_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_finditer(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_finditer(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "finditer", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:finditer", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_finditer_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_finditer_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -512,63 +372,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_scanner__doc__, "\n"); #define _SRE_SRE_PATTERN_SCANNER_METHODDEF \ - {"scanner", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_scanner, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_scanner__doc__}, + {"scanner", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_scanner, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_scanner__doc__}, static PyObject * -_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_scanner(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_scanner(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "scanner", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:scanner", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_scanner_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_scanner_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -632,47 +457,27 @@ PyDoc_STRVAR(_sre_SRE_Pattern_sub__doc__, "Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl."); #define _SRE_SRE_PATTERN_SUB_METHODDEF \ - {"sub", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_sub, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_sub__doc__}, + {"sub", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_sub, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_sub__doc__}, static PyObject * -_sre_SRE_Pattern_sub_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count); +_sre_SRE_Pattern_sub_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, Py_ssize_t count); static PyObject * -_sre_SRE_Pattern_sub(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_sub(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"repl", "string", "count", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "sub", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + static _PyArg_Parser _parser = {"OO|n:sub", _keywords, 0}; PyObject *repl; PyObject *string; Py_ssize_t count = 0; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &repl, &string, &count)) { goto exit; } - repl = args[0]; - string = args[1]; - if (!noptargs) { - goto skip_optional_pos; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_sub_impl(self, repl, string, count); + return_value = _sre_SRE_Pattern_sub_impl(self, cls, repl, string, count); exit: return return_value; @@ -685,47 +490,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_subn__doc__, "Return the tuple (new_string, number_of_subs_made) found by replacing the leftmost non-overlapping occurrences of pattern with the replacement repl."); #define _SRE_SRE_PATTERN_SUBN_METHODDEF \ - {"subn", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_subn, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_subn__doc__}, + {"subn", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_subn, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_subn__doc__}, static PyObject * -_sre_SRE_Pattern_subn_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count); +_sre_SRE_Pattern_subn_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, + Py_ssize_t count); static PyObject * -_sre_SRE_Pattern_subn(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_subn(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"repl", "string", "count", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "subn", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + static _PyArg_Parser _parser = {"OO|n:subn", _keywords, 0}; PyObject *repl; PyObject *string; Py_ssize_t count = 0; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &repl, &string, &count)) { goto exit; } - repl = args[0]; - string = args[1]; - if (!noptargs) { - goto skip_optional_pos; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = _PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_subn_impl(self, repl, string, count); + return_value = _sre_SRE_Pattern_subn_impl(self, cls, repl, string, count); exit: return return_value; @@ -1075,15 +861,26 @@ PyDoc_STRVAR(_sre_SRE_Scanner_match__doc__, "\n"); #define _SRE_SRE_SCANNER_MATCH_METHODDEF \ - {"match", (PyCFunction)_sre_SRE_Scanner_match, METH_NOARGS, _sre_SRE_Scanner_match__doc__}, + {"match", (PyCFunction)(void(*)(void))_sre_SRE_Scanner_match, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Scanner_match__doc__}, static PyObject * -_sre_SRE_Scanner_match_impl(ScannerObject *self); +_sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls); static PyObject * -_sre_SRE_Scanner_match(ScannerObject *self, PyObject *Py_UNUSED(ignored)) +_sre_SRE_Scanner_match(ScannerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _sre_SRE_Scanner_match_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":match", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _sre_SRE_Scanner_match_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_sre_SRE_Scanner_search__doc__, @@ -1092,14 +889,25 @@ PyDoc_STRVAR(_sre_SRE_Scanner_search__doc__, "\n"); #define _SRE_SRE_SCANNER_SEARCH_METHODDEF \ - {"search", (PyCFunction)_sre_SRE_Scanner_search, METH_NOARGS, _sre_SRE_Scanner_search__doc__}, + {"search", (PyCFunction)(void(*)(void))_sre_SRE_Scanner_search, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Scanner_search__doc__}, static PyObject * -_sre_SRE_Scanner_search_impl(ScannerObject *self); +_sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls); static PyObject * -_sre_SRE_Scanner_search(ScannerObject *self, PyObject *Py_UNUSED(ignored)) +_sre_SRE_Scanner_search(ScannerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _sre_SRE_Scanner_search_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":search", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _sre_SRE_Scanner_search_impl(self, cls); + +exit: + return return_value; } -/*[clinic end generated code: output=0e27915b1eb7c0e4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=518f7bb775c1184f input=a9049054013a1b77]*/ From 63ad0f103b41bb36360d19e110cf53b25aa11c10 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 3 Nov 2020 12:28:08 +0100 Subject: [PATCH 07/14] Convert _sre to multi-phase initialisation --- Modules/_sre.c | 70 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index 4f3e7038ad44aa..c0359d8172082e 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -2796,12 +2796,35 @@ static PyMethodDef _functions[] = { {NULL, NULL} }; -static struct PyModuleDef sremodule = { - .m_base = PyModuleDef_HEAD_INIT, - .m_name = "_" SRE_MODULE, - .m_size = sizeof(sre_module_state), - .m_methods = _functions, -}; +static int +sre_traverse(PyObject *module, visitproc visit, void *arg) +{ + sre_module_state *state = get_sre_module_state(module); + + Py_VISIT(state->Pattern_Type); + Py_VISIT(state->Match_Type); + Py_VISIT(state->Scanner_Type); + + return 0; +} + +static int +sre_clear(PyObject *module) +{ + sre_module_state *state = get_sre_module_state(module); + + Py_CLEAR(state->Pattern_Type); + Py_CLEAR(state->Match_Type); + Py_CLEAR(state->Scanner_Type); + + return 0; +} + +static void +sre_free(void *module) +{ + sre_clear((PyObject *)module); +} #define CREATE_TYPE(m, type, spec) \ do { \ @@ -2811,17 +2834,13 @@ do { \ } \ } while (0) -PyMODINIT_FUNC PyInit__sre(void) +static int +sre_exec(PyObject *m) { sre_module_state *state; - PyObject* m; PyObject* d; PyObject* x; - m = PyModule_Create(&sremodule); - if (m == NULL) - return NULL; - /* Create heap types */ state = get_sre_module_state(m); CREATE_TYPE(m, state->Pattern_Type, &pattern_spec); @@ -2859,11 +2878,32 @@ PyMODINIT_FUNC PyInit__sre(void) PyDict_SetItemString(d, "copyright", x); Py_DECREF(x); } - return m; + return 0; error: - Py_XDECREF(m); - return NULL; + return -1; +} + +static PyModuleDef_Slot sre_slots[] = { + {Py_mod_exec, sre_exec}, + {0, NULL}, +}; + +static struct PyModuleDef sremodule = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_" SRE_MODULE, + .m_size = sizeof(sre_module_state), + .m_methods = _functions, + .m_slots = sre_slots, + .m_traverse = sre_traverse, + .m_free = sre_free, + .m_clear = sre_clear, +}; + +PyMODINIT_FUNC +PyInit__sre(void) +{ + return PyModuleDef_Init(&sremodule); } /* vim:ts=4:sw=4:et From 27134f086f27926c2f159ae2551905744fe8dc20 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 19 Nov 2020 09:59:15 +0100 Subject: [PATCH 08/14] Add NEWS --- .../next/Library/2020-11-19-09-59-07.bpo-1635741.7cMypH.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2020-11-19-09-59-07.bpo-1635741.7cMypH.rst diff --git a/Misc/NEWS.d/next/Library/2020-11-19-09-59-07.bpo-1635741.7cMypH.rst b/Misc/NEWS.d/next/Library/2020-11-19-09-59-07.bpo-1635741.7cMypH.rst new file mode 100644 index 00000000000000..1e7d412680a1b2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-11-19-09-59-07.bpo-1635741.7cMypH.rst @@ -0,0 +1,2 @@ +Convert _sre module types to heap types (PEP 384). Patch by Erlend E. +Aasland. From 1c925b9c2c355f8c822527cf051c788aa54ec965 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 19 Nov 2020 10:19:46 +0100 Subject: [PATCH 09/14] Address Heimes' review: improve module state naming --- Modules/_sre.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index c0359d8172082e..f960d8e676dc5b 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -253,12 +253,12 @@ typedef struct { PyTypeObject *Pattern_Type; PyTypeObject *Match_Type; PyTypeObject *Scanner_Type; -} sre_module_state; +} _sremodulestate; -static sre_module_state * +static _sremodulestate * get_sre_module_state(PyObject *m) { - sre_module_state *state = (sre_module_state *)PyModule_GetState(m); + _sremodulestate *state = (_sremodulestate *)PyModule_GetState(m); assert(state); return state; } @@ -270,8 +270,8 @@ static struct PyModuleDef sremodule; (get_sre_module_state(PyType_GetModule(cls))) /* see sre.h for object declarations */ -static PyObject*pattern_new_match(sre_module_state *, PatternObject*, SRE_STATE*, Py_ssize_t); -static PyObject *pattern_scanner(sre_module_state *, PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); +static PyObject*pattern_new_match(_sremodulestate *, PatternObject*, SRE_STATE*, Py_ssize_t); +static PyObject *pattern_scanner(_sremodulestate *, PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); /*[clinic input] module _sre @@ -617,7 +617,7 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, Py_ssize_t endpos) /*[clinic end generated code: output=ec6208ea58a0cca0 input=4bdb9c3e564d13ac]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -660,7 +660,7 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyTypeObject *cls, Py_ssize_t endpos) /*[clinic end generated code: output=625b75b027ef94da input=50981172ab0fcfdd]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -706,7 +706,7 @@ _sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls, Py_ssize_t endpos) /*[clinic end generated code: output=bd7f2d9d583e1463 input=afa9afb66a74a4b3]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -874,7 +874,7 @@ _sre_SRE_Pattern_finditer_impl(PatternObject *self, PyTypeObject *cls, Py_ssize_t endpos) /*[clinic end generated code: output=1791dbf3618ade56 input=812e332a4848cbaf]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); PyObject* scanner; PyObject* search; PyObject* iterator; @@ -911,7 +911,7 @@ _sre_SRE_Pattern_scanner_impl(PatternObject *self, PyTypeObject *cls, Py_ssize_t endpos) /*[clinic end generated code: output=f70cd506112f1bd9 input=2e487e5151bcee4c]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); return pattern_scanner(module_state, self, string, pos, endpos); } @@ -1020,7 +1020,7 @@ _sre_SRE_Pattern_split_impl(PatternObject *self, PyObject *string, } static PyObject* -pattern_subx(sre_module_state* module_state, +pattern_subx(_sremodulestate* module_state, PatternObject* self, PyObject* ptemplate, PyObject* string, @@ -1221,7 +1221,7 @@ _sre_SRE_Pattern_sub_impl(PatternObject *self, PyTypeObject *cls, PyObject *repl, PyObject *string, Py_ssize_t count) /*[clinic end generated code: output=4be141ab04bca60d input=d8d1d4ac2311a07c]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); return pattern_subx(module_state, self, repl, string, count, 0); } @@ -1244,7 +1244,7 @@ _sre_SRE_Pattern_subn_impl(PatternObject *self, PyTypeObject *cls, Py_ssize_t count) /*[clinic end generated code: output=da02fd85258b1e1f input=8b78a65b8302e58d]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); return pattern_subx(module_state, self, repl, string, count, 1); } @@ -1391,7 +1391,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, { /* "compile" pattern descriptor to pattern object */ - sre_module_state *module_state = get_sre_module_state(module); + _sremodulestate *module_state = get_sre_module_state(module); PatternObject* self; Py_ssize_t i, n; @@ -2376,7 +2376,7 @@ match_repr(MatchObject *self) static PyObject* -pattern_new_match(sre_module_state* module_state, +pattern_new_match(_sremodulestate* module_state, PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) @@ -2468,7 +2468,7 @@ static PyObject * _sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls) /*[clinic end generated code: output=6e22c149dc0f0325 input=b5146e1f30278cb7]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; PyObject* match; Py_ssize_t status; @@ -2510,7 +2510,7 @@ static PyObject * _sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls) /*[clinic end generated code: output=23e8fc78013f9161 input=056c2d37171d0bf2]*/ { - sre_module_state *module_state = get_sre_module_state_by_class(cls); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; PyObject* match; Py_ssize_t status; @@ -2540,7 +2540,7 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls) } static PyObject * -pattern_scanner(sre_module_state *module_state, +pattern_scanner(_sremodulestate *module_state, PatternObject *self, PyObject *string, Py_ssize_t pos, @@ -2593,7 +2593,7 @@ static PyObject* pattern_richcompare(PyObject *lefto, PyObject *righto, int op) { PyTypeObject *tp = Py_TYPE(lefto); - sre_module_state *module_state = get_sre_module_state_by_type(tp); + _sremodulestate *module_state = get_sre_module_state_by_type(tp); PatternObject *left, *right; int cmp; @@ -2799,7 +2799,7 @@ static PyMethodDef _functions[] = { static int sre_traverse(PyObject *module, visitproc visit, void *arg) { - sre_module_state *state = get_sre_module_state(module); + _sremodulestate *state = get_sre_module_state(module); Py_VISIT(state->Pattern_Type); Py_VISIT(state->Match_Type); @@ -2811,7 +2811,7 @@ sre_traverse(PyObject *module, visitproc visit, void *arg) static int sre_clear(PyObject *module) { - sre_module_state *state = get_sre_module_state(module); + _sremodulestate *state = get_sre_module_state(module); Py_CLEAR(state->Pattern_Type); Py_CLEAR(state->Match_Type); @@ -2837,7 +2837,7 @@ do { \ static int sre_exec(PyObject *m) { - sre_module_state *state; + _sremodulestate *state; PyObject* d; PyObject* x; @@ -2892,7 +2892,7 @@ static PyModuleDef_Slot sre_slots[] = { static struct PyModuleDef sremodule = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "_" SRE_MODULE, - .m_size = sizeof(sre_module_state), + .m_size = sizeof(_sremodulestate), .m_methods = _functions, .m_slots = sre_slots, .m_traverse = sre_traverse, From 12bf771c5d931a67e6360e49c265ad189d06a00e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 19 Nov 2020 10:28:17 +0100 Subject: [PATCH 10/14] Merge GH-23101 --- Lib/test/test_re.py | 4 ++++ Modules/_sre.c | 44 ++++++++++++++++++++------------------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 1bfbcb853c4ed1..c1d02cfaf0dcb6 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2197,6 +2197,10 @@ def test_overlap_table(self): self.assertEqual(f("ababba"), [0, 0, 1, 2, 0, 1]) self.assertEqual(f("abcabdac"), [0, 0, 0, 1, 2, 0, 1, 0]) + def test_signedness(self): + self.assertGreaterEqual(sre_compile.MAXREPEAT, 0) + self.assertGreaterEqual(sre_compile.MAXGROUPS, 0) + class ExternalTests(unittest.TestCase): diff --git a/Modules/_sre.c b/Modules/_sre.c index f960d8e676dc5b..e9ee9492877d38 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -2834,6 +2834,18 @@ do { \ } \ } while (0) +#define ADD_ULONG_CONSTANT(module, name, value) \ + do { \ + PyObject *o = PyLong_FromUnsignedLong(value); \ + if (!o) \ + goto error; \ + int res = PyModule_AddObjectRef(module, name, o); \ + Py_DECREF(o); \ + if (res <) { \ + goto error; \ + } \ +} while (0) + static int sre_exec(PyObject *m) { @@ -2847,37 +2859,21 @@ sre_exec(PyObject *m) CREATE_TYPE(m, state->Match_Type, &match_spec); CREATE_TYPE(m, state->Scanner_Type, &scanner_spec); - d = PyModule_GetDict(m); - - x = PyLong_FromLong(SRE_MAGIC); - if (x) { - PyDict_SetItemString(d, "MAGIC", x); - Py_DECREF(x); + if (PyModule_AddIntConstant(m, "MAGIC", SRE_MAGIC) < 0) { + goto error; } - x = PyLong_FromLong(sizeof(SRE_CODE)); - if (x) { - PyDict_SetItemString(d, "CODESIZE", x); - Py_DECREF(x); + if (PyModule_AddIntConstant(m, "CODESIZE", sizeof(SRE_CODE)) < 0) { + goto error; } - x = PyLong_FromUnsignedLong(SRE_MAXREPEAT); - if (x) { - PyDict_SetItemString(d, "MAXREPEAT", x); - Py_DECREF(x); - } + ADD_ULONG_CONSTANT(m, "MAXREPEAT", SRE_MAXREPEAT); + ADD_ULONG_CONSTANT(m, "MAXGROUPS", SRE_MAXGROUPS); - x = PyLong_FromUnsignedLong(SRE_MAXGROUPS); - if (x) { - PyDict_SetItemString(d, "MAXGROUPS", x); - Py_DECREF(x); + if (PyModule_AddStringConstant(m, "copyright", copyright) < 0) { + goto error; } - x = PyUnicode_FromString(copyright); - if (x) { - PyDict_SetItemString(d, "copyright", x); - Py_DECREF(x); - } return 0; error: From 0f10f7dc855338440df7c0d096d07c7408f79a1d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 19 Nov 2020 10:34:47 +0100 Subject: [PATCH 11/14] Update clinic --- Modules/_sre.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index e9ee9492877d38..432f6a34db5e8e 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -279,7 +279,7 @@ class _sre.SRE_Pattern "PatternObject *" "get_sre_module_state_by_type(tp)->Patt class _sre.SRE_Match "MatchObject *" "get_sre_module_state_by_type(tp)->Match_Type" class _sre.SRE_Scanner "ScannerObject *" "get_sre_module_state_by_type(tp)->Scanner_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9f2e869a208f635c]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8b48770d8db721b4]*/ /*[clinic input] _sre.getcodesize -> int @@ -2841,7 +2841,7 @@ do { \ goto error; \ int res = PyModule_AddObjectRef(module, name, o); \ Py_DECREF(o); \ - if (res <) { \ + if (res < 0) { \ goto error; \ } \ } while (0) @@ -2850,8 +2850,6 @@ static int sre_exec(PyObject *m) { _sremodulestate *state; - PyObject* d; - PyObject* x; /* Create heap types */ state = get_sre_module_state(m); From bdd133884d3d2be0b99a08db57ca6c6e21cfea74 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 19 Nov 2020 11:16:26 +0100 Subject: [PATCH 12/14] Address Heimes' review: Drop using _PyType_GetModuleByDef --- Modules/_sre.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Modules/_sre.c b/Modules/_sre.c index 432f6a34db5e8e..0a5ca60097af36 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -264,8 +264,6 @@ get_sre_module_state(PyObject *m) } static struct PyModuleDef sremodule; -#define get_sre_module_state_by_type(tp) \ - (get_sre_module_state(_PyType_GetModuleByDef(tp, &sremodule))) #define get_sre_module_state_by_class(cls) \ (get_sre_module_state(PyType_GetModule(cls))) @@ -275,11 +273,11 @@ static PyObject *pattern_scanner(_sremodulestate *, PatternObject *, PyObject *, /*[clinic input] module _sre -class _sre.SRE_Pattern "PatternObject *" "get_sre_module_state_by_type(tp)->Pattern_Type" -class _sre.SRE_Match "MatchObject *" "get_sre_module_state_by_type(tp)->Match_Type" -class _sre.SRE_Scanner "ScannerObject *" "get_sre_module_state_by_type(tp)->Scanner_Type" +class _sre.SRE_Pattern "PatternObject *" "get_sre_module_state_by_class(tp)->Pattern_Type" +class _sre.SRE_Match "MatchObject *" "get_sre_module_state_by_class(tp)->Match_Type" +class _sre.SRE_Scanner "ScannerObject *" "get_sre_module_state_by_class(tp)->Scanner_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8b48770d8db721b4]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fe2966e32b66a231]*/ /*[clinic input] _sre.getcodesize -> int @@ -2593,7 +2591,7 @@ static PyObject* pattern_richcompare(PyObject *lefto, PyObject *righto, int op) { PyTypeObject *tp = Py_TYPE(lefto); - _sremodulestate *module_state = get_sre_module_state_by_type(tp); + _sremodulestate *module_state = get_sre_module_state_by_class(tp); PatternObject *left, *right; int cmp; From a6bc4810d6eb4551d192db90b6779f96a1cf47ab Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 19 Nov 2020 12:18:06 +0100 Subject: [PATCH 13/14] Adjust idlelib tiptest from Lib/idlelib/idle_test/test_calltip.py: The tests of builtins may break if inspect or the docstrings change, but a red buildbot is better than a user crash (as has happened). For a simple mismatch, change the expected output to the actual. --- Lib/idlelib/idle_test/test_calltip.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Lib/idlelib/idle_test/test_calltip.py b/Lib/idlelib/idle_test/test_calltip.py index 489b6899baf424..9a5fb30fbbd457 100644 --- a/Lib/idlelib/idle_test/test_calltip.py +++ b/Lib/idlelib/idle_test/test_calltip.py @@ -88,10 +88,7 @@ class SB: __call__ = None replacement repl. repl can be either a string or a callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the Match object and must return''') - tiptest(p.sub, '''\ -(repl, string, count=0) -Return the string obtained by replacing the leftmost \ -non-overlapping occurrences o...''') + tiptest(p.sub, '(repl, string, count=0)') def test_signature_wrap(self): if textwrap.TextWrapper.__doc__ is not None: From 2fd3bd188a94bc123d9244711b04f6636d592699 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 19 Nov 2020 19:38:38 +0100 Subject: [PATCH 14/14] Revert "Adjust idlelib tiptest" This reverts commit a6bc4810d6eb4551d192db90b6779f96a1cf47ab. --- Lib/idlelib/idle_test/test_calltip.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/idle_test/test_calltip.py b/Lib/idlelib/idle_test/test_calltip.py index 9a5fb30fbbd457..489b6899baf424 100644 --- a/Lib/idlelib/idle_test/test_calltip.py +++ b/Lib/idlelib/idle_test/test_calltip.py @@ -88,7 +88,10 @@ class SB: __call__ = None replacement repl. repl can be either a string or a callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the Match object and must return''') - tiptest(p.sub, '(repl, string, count=0)') + tiptest(p.sub, '''\ +(repl, string, count=0) +Return the string obtained by replacing the leftmost \ +non-overlapping occurrences o...''') def test_signature_wrap(self): if textwrap.TextWrapper.__doc__ is not None: