Issue #14260: The groupindex attribute of regular expression pattern object

now is non-modifiable mapping.
This commit is contained in:
Serhiy Storchaka 2015-03-30 01:01:48 +03:00
parent 1813c1701f
commit 07360df481
5 changed files with 31 additions and 5 deletions

View File

@ -231,20 +231,21 @@ class Sniffer:
quotes = {} quotes = {}
delims = {} delims = {}
spaces = 0 spaces = 0
groupindex = regexp.groupindex
for m in matches: for m in matches:
n = regexp.groupindex['quote'] - 1 n = groupindex['quote'] - 1
key = m[n] key = m[n]
if key: if key:
quotes[key] = quotes.get(key, 0) + 1 quotes[key] = quotes.get(key, 0) + 1
try: try:
n = regexp.groupindex['delim'] - 1 n = groupindex['delim'] - 1
key = m[n] key = m[n]
except KeyError: except KeyError:
continue continue
if key and (delimiters is None or key in delimiters): if key and (delimiters is None or key in delimiters):
delims[key] = delims.get(key, 0) + 1 delims[key] = delims.get(key, 0) + 1
try: try:
n = regexp.groupindex['space'] - 1 n = groupindex['space'] - 1
except KeyError: except KeyError:
continue continue
if m[n]: if m[n]:

View File

@ -855,6 +855,7 @@ def parse_template(source, pattern):
del literal[:] del literal[:]
groups.append((len(literals), index)) groups.append((len(literals), index))
literals.append(None) literals.append(None)
groupindex = pattern.groupindex
while True: while True:
this = sget() this = sget()
if this is None: if this is None:
@ -869,7 +870,7 @@ def parse_template(source, pattern):
name = s.getuntil(">") name = s.getuntil(">")
if name.isidentifier(): if name.isidentifier():
try: try:
index = pattern.groupindex[name] index = groupindex[name]
except KeyError: except KeyError:
raise IndexError("unknown group name %r" % name) raise IndexError("unknown group name %r" % name)
else: else:

View File

@ -577,6 +577,14 @@ class ReTests(unittest.TestCase):
self.assertEqual(re.match("(a)", "a").regs, ((0, 1), (0, 1))) self.assertEqual(re.match("(a)", "a").regs, ((0, 1), (0, 1)))
self.assertTrue(re.match("(a)", "a").re) self.assertTrue(re.match("(a)", "a").re)
# Issue 14260. groupindex should be non-modifiable mapping.
p = re.compile(r'(?i)(?P<first>a)(?P<other>b)')
self.assertEqual(sorted(p.groupindex), ['first', 'other'])
self.assertEqual(p.groupindex['other'], 2)
with self.assertRaises(TypeError):
p.groupindex['other'] = 0
self.assertEqual(p.groupindex['other'], 2)
def test_special_escapes(self): def test_special_escapes(self):
self.assertEqual(re.search(r"\b(b.)\b", self.assertEqual(re.search(r"\b(b.)\b",
"abcd abc bcd bx").group(1), "bx") "abcd abc bcd bx").group(1), "bx")

View File

@ -30,6 +30,9 @@ Core and Builtins
Library Library
------- -------
- Issue #14260: The groupindex attribute of regular expression pattern object
now is non-modifiable mapping.
- Issue #23792: Ignore KeyboardInterrupt when the pydoc pager is active. - Issue #23792: Ignore KeyboardInterrupt when the pydoc pager is active.
This mimics the behavior of the standard unix pagers, and prevents This mimics the behavior of the standard unix pagers, and prevents
pipepager from shutting down while the pager itself is still running. pipepager from shutting down while the pager itself is still running.

View File

@ -1384,12 +1384,24 @@ static PyMethodDef pattern_methods[] = {
{NULL, NULL} {NULL, NULL}
}; };
/* PatternObject's 'groupindex' method. */
static PyObject *
pattern_groupindex(PatternObject *self)
{
return PyDictProxy_New(self->groupindex);
}
static PyGetSetDef pattern_getset[] = {
{"groupindex", (getter)pattern_groupindex, (setter)NULL,
"A dictionary mapping group names to group numbers."},
{NULL} /* Sentinel */
};
#define PAT_OFF(x) offsetof(PatternObject, x) #define PAT_OFF(x) offsetof(PatternObject, x)
static PyMemberDef pattern_members[] = { static PyMemberDef pattern_members[] = {
{"pattern", T_OBJECT, PAT_OFF(pattern), READONLY}, {"pattern", T_OBJECT, PAT_OFF(pattern), READONLY},
{"flags", T_INT, PAT_OFF(flags), READONLY}, {"flags", T_INT, PAT_OFF(flags), READONLY},
{"groups", T_PYSSIZET, PAT_OFF(groups), READONLY}, {"groups", T_PYSSIZET, PAT_OFF(groups), READONLY},
{"groupindex", T_OBJECT, PAT_OFF(groupindex), READONLY},
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
@ -1422,6 +1434,7 @@ static PyTypeObject Pattern_Type = {
0, /* tp_iternext */ 0, /* tp_iternext */
pattern_methods, /* tp_methods */ pattern_methods, /* tp_methods */
pattern_members, /* tp_members */ pattern_members, /* tp_members */
pattern_getset, /* tp_getset */
}; };
static int _validate(PatternObject *self); /* Forward */ static int _validate(PatternObject *self); /* Forward */