diff --git a/Lib/re/__init__.py b/Lib/re/__init__.py index c9b511422f1e59..f03cda38e9eb8f 100644 --- a/Lib/re/__init__.py +++ b/Lib/re/__init__.py @@ -122,6 +122,7 @@ """ import enum +from _sre import _set_RegexFlag_type from . import _compiler, _parser import functools @@ -152,6 +153,9 @@ class RegexFlag: __str__ = object.__str__ _numeric_repr_ = hex +# register the type of RegexFlag +_set_RegexFlag_type(RegexFlag) + # sre exception error = _compiler.error diff --git a/Modules/_sre/clinic/sre.c.h b/Modules/_sre/clinic/sre.c.h index 34cbe21f14071b..f6f84c0cca7d4a 100644 --- a/Modules/_sre/clinic/sre.c.h +++ b/Modules/_sre/clinic/sre.c.h @@ -461,17 +461,17 @@ PyDoc_STRVAR(_sre_SRE_Pattern_sub__doc__, static PyObject * _sre_SRE_Pattern_sub_impl(PatternObject *self, PyTypeObject *cls, - PyObject *repl, PyObject *string, Py_ssize_t count); + PyObject *repl, PyObject *string, PyObject *count); static PyObject * _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 = {"OO|n:sub", _keywords, 0}; + static _PyArg_Parser _parser = {"OO|O:sub", _keywords, 0}; PyObject *repl; PyObject *string; - Py_ssize_t count = 0; + PyObject *count = NULL; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, &repl, &string, &count)) { @@ -494,18 +494,17 @@ PyDoc_STRVAR(_sre_SRE_Pattern_subn__doc__, static PyObject * _sre_SRE_Pattern_subn_impl(PatternObject *self, PyTypeObject *cls, - PyObject *repl, PyObject *string, - Py_ssize_t count); + PyObject *repl, PyObject *string, PyObject *count); static PyObject * _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 = {"OO|n:subn", _keywords, 0}; + static _PyArg_Parser _parser = {"OO|O:subn", _keywords, 0}; PyObject *repl; PyObject *string; - Py_ssize_t count = 0; + PyObject *count = NULL; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, &repl, &string, &count)) { @@ -625,6 +624,37 @@ _sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject return return_value; } +PyDoc_STRVAR(_sre__set_RegexFlag_type__doc__, +"_set_RegexFlag_type($module, /, RegexFlag_Type)\n" +"--\n" +"\n"); + +#define _SRE__SET_REGEXFLAG_TYPE_METHODDEF \ + {"_set_RegexFlag_type", (PyCFunction)(void(*)(void))_sre__set_RegexFlag_type, METH_FASTCALL|METH_KEYWORDS, _sre__set_RegexFlag_type__doc__}, + +static PyObject * +_sre__set_RegexFlag_type_impl(PyObject *module, PyObject *RegexFlag_Type); + +static PyObject * +_sre__set_RegexFlag_type(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"RegexFlag_Type", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "_set_RegexFlag_type", 0}; + PyObject *argsbuf[1]; + PyObject *RegexFlag_Type; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + RegexFlag_Type = args[0]; + return_value = _sre__set_RegexFlag_type_impl(module, RegexFlag_Type); + +exit: + return return_value; +} + PyDoc_STRVAR(_sre_SRE_Match_expand__doc__, "expand($self, /, template)\n" "--\n" @@ -923,4 +953,4 @@ _sre_SRE_Scanner_search(ScannerObject *self, PyTypeObject *cls, PyObject *const exit: return return_value; } -/*[clinic end generated code: output=9d7510a57a157a38 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0cc8e966db112d6e input=a9049054013a1b77]*/ diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index bd9204da428af8..052f79f91aa91e 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -254,6 +254,7 @@ typedef struct { PyTypeObject *Pattern_Type; PyTypeObject *Match_Type; PyTypeObject *Scanner_Type; + PyTypeObject *RegexFlag_Type; } _sremodulestate; static _sremodulestate * @@ -1249,19 +1250,36 @@ _sre.SRE_Pattern.sub / repl: object string: object - count: Py_ssize_t = 0 + count: object(c_default="NULL") = 0 Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl. [clinic start generated code]*/ static PyObject * _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]*/ + PyObject *repl, PyObject *string, PyObject *count) +/*[clinic end generated code: output=9f7f5eca541878cb input=8b48c662991e844f]*/ { _sremodulestate *module_state = get_sre_module_state_by_class(cls); + Py_ssize_t count_value; - return pattern_subx(module_state, self, repl, string, count, 0); + /* Some users mistakenly pass flags to count parameter */ + if (count == NULL) { + count_value = 0; + } else if (Py_TYPE(count) == module_state->RegexFlag_Type) { + PyErr_SetString(PyExc_TypeError, + "count argument should not be RegexFlag."); + return NULL; + } else { + count_value = PyLong_AsSsize_t(count); + if (count_value == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_ValueError, + "count arguemnt wrong type."); + return NULL; + } + } + + return pattern_subx(module_state, self, repl, string, count_value, 0); } /*[clinic input] @@ -1271,20 +1289,36 @@ _sre.SRE_Pattern.subn / repl: object string: object - count: Py_ssize_t = 0 + count: object(c_default="NULL") = 0 Return the tuple (new_string, number_of_subs_made) found by replacing the leftmost non-overlapping occurrences of pattern with the replacement repl. [clinic start generated code]*/ static PyObject * _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]*/ + PyObject *repl, PyObject *string, PyObject *count) +/*[clinic end generated code: output=7d66d9c3696121e6 input=3c0642c0ba657dc1]*/ { _sremodulestate *module_state = get_sre_module_state_by_class(cls); + Py_ssize_t count_value; + + /* Some users mistakenly pass flags to count parameter */ + if (count == NULL) { + count_value = 0; + } else if (Py_TYPE(count) == module_state->RegexFlag_Type) { + PyErr_SetString(PyExc_TypeError, + "count argument should not be RegexFlag."); + return NULL; + } else { + count_value = PyLong_AsSsize_t(count); + if (count_value == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_ValueError, + "count arguemnt wrong type."); + return NULL; + } + } - return pattern_subx(module_state, self, repl, string, count, 1); + return pattern_subx(module_state, self, repl, string, count_value, 1); } /*[clinic input] @@ -2003,6 +2037,32 @@ _validate(PatternObject *self) return 1; } +/*[clinic input] +_sre._set_RegexFlag_type + + RegexFlag_Type: object + +[clinic start generated code]*/ + +static PyObject * +_sre__set_RegexFlag_type_impl(PyObject *module, PyObject *RegexFlag_Type) +/*[clinic end generated code: output=1276fbd158d1c5b2 input=fa4eabcd03dd9819]*/ +{ + _sremodulestate *module_state = get_sre_module_state(module); + + if (!PyType_Check(RegexFlag_Type)) { + PyErr_SetString(PyExc_ValueError, + "The argument should be RegexFlag type."); + return NULL; + } + + Py_INCREF(RegexFlag_Type); + module_state->RegexFlag_Type = (PyTypeObject*) RegexFlag_Type; + + Py_RETURN_NONE; +} + + /* -------------------------------------------------------------------- */ /* match methods */ @@ -2951,6 +3011,7 @@ static PyMethodDef _functions[] = { _SRE_UNICODE_ISCASED_METHODDEF _SRE_ASCII_TOLOWER_METHODDEF _SRE_UNICODE_TOLOWER_METHODDEF + _SRE__SET_REGEXFLAG_TYPE_METHODDEF {NULL, NULL} }; @@ -2962,6 +3023,7 @@ sre_traverse(PyObject *module, visitproc visit, void *arg) Py_VISIT(state->Pattern_Type); Py_VISIT(state->Match_Type); Py_VISIT(state->Scanner_Type); + Py_VISIT(state->RegexFlag_Type); return 0; } @@ -2974,6 +3036,7 @@ sre_clear(PyObject *module) Py_CLEAR(state->Pattern_Type); Py_CLEAR(state->Match_Type); Py_CLEAR(state->Scanner_Type); + Py_CLEAR(state->RegexFlag_Type); return 0; } @@ -3014,6 +3077,7 @@ sre_exec(PyObject *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); + state->RegexFlag_Type = NULL; if (PyModule_AddIntConstant(m, "MAGIC", SRE_MAGIC) < 0) { goto error;