Issue 1519638: Now unmatched groups are replaced with empty strings in re.sub()
and re.subn().
This commit is contained in:
parent
365e28238f
commit
7438e4b56f
|
@ -701,6 +701,9 @@ form.
|
||||||
.. versionchanged:: 3.1
|
.. versionchanged:: 3.1
|
||||||
Added the optional flags argument.
|
Added the optional flags argument.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
Unmatched groups are replaced with an empty string.
|
||||||
|
|
||||||
|
|
||||||
.. function:: subn(pattern, repl, string, count=0, flags=0)
|
.. function:: subn(pattern, repl, string, count=0, flags=0)
|
||||||
|
|
||||||
|
@ -710,6 +713,9 @@ form.
|
||||||
.. versionchanged:: 3.1
|
.. versionchanged:: 3.1
|
||||||
Added the optional flags argument.
|
Added the optional flags argument.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
Unmatched groups are replaced with an empty string.
|
||||||
|
|
||||||
|
|
||||||
.. function:: escape(string)
|
.. function:: escape(string)
|
||||||
|
|
||||||
|
@ -885,6 +891,8 @@ Match objects support the following methods and attributes:
|
||||||
(``\g<1>``, ``\g<name>``) are replaced by the contents of the
|
(``\g<1>``, ``\g<name>``) are replaced by the contents of the
|
||||||
corresponding group.
|
corresponding group.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
Unmatched groups are replaced with an empty string.
|
||||||
|
|
||||||
.. method:: match.group([group1, ...])
|
.. method:: match.group([group1, ...])
|
||||||
|
|
||||||
|
|
|
@ -223,6 +223,9 @@ re
|
||||||
* Number of capturing groups in regular expression is no longer limited by 100.
|
* Number of capturing groups in regular expression is no longer limited by 100.
|
||||||
(Contributed by Serhiy Storchaka in :issue:`22437`.)
|
(Contributed by Serhiy Storchaka in :issue:`22437`.)
|
||||||
|
|
||||||
|
* Now unmatched groups are replaced with empty strings in :func:`re.sub`
|
||||||
|
and :func:`re.subn`. (Contributed by Serhiy Storchaka in :issue:`1519638`.)
|
||||||
|
|
||||||
shutil
|
shutil
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|
|
@ -880,14 +880,12 @@ def parse_template(source, pattern):
|
||||||
|
|
||||||
def expand_template(template, match):
|
def expand_template(template, match):
|
||||||
g = match.group
|
g = match.group
|
||||||
sep = match.string[:0]
|
empty = match.string[:0]
|
||||||
groups, literals = template
|
groups, literals = template
|
||||||
literals = literals[:]
|
literals = literals[:]
|
||||||
try:
|
try:
|
||||||
for index, group in groups:
|
for index, group in groups:
|
||||||
literals[index] = s = g(group)
|
literals[index] = g(group) or empty
|
||||||
if s is None:
|
|
||||||
raise error("unmatched group")
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise error("invalid group reference")
|
raise error("invalid group reference")
|
||||||
return sep.join(literals)
|
return empty.join(literals)
|
||||||
|
|
|
@ -225,9 +225,11 @@ class ReTests(unittest.TestCase):
|
||||||
self.assertRaises(re.error, re.sub, '(?P<a>x)', '\g<a a>', 'xx')
|
self.assertRaises(re.error, re.sub, '(?P<a>x)', '\g<a a>', 'xx')
|
||||||
self.assertRaises(re.error, re.sub, '(?P<a>x)', '\g<>', 'xx')
|
self.assertRaises(re.error, re.sub, '(?P<a>x)', '\g<>', 'xx')
|
||||||
self.assertRaises(re.error, re.sub, '(?P<a>x)', '\g<1a1>', 'xx')
|
self.assertRaises(re.error, re.sub, '(?P<a>x)', '\g<1a1>', 'xx')
|
||||||
|
self.assertRaises(re.error, re.sub, '(?P<a>x)', r'\g<2>', 'xx')
|
||||||
|
self.assertRaises(re.error, re.sub, '(?P<a>x)', r'\2', 'xx')
|
||||||
self.assertRaises(IndexError, re.sub, '(?P<a>x)', '\g<ab>', 'xx')
|
self.assertRaises(IndexError, re.sub, '(?P<a>x)', '\g<ab>', 'xx')
|
||||||
self.assertRaises(re.error, re.sub, '(?P<a>x)|(?P<b>y)', '\g<b>', 'xx')
|
self.assertEqual(re.sub('(?P<a>x)|(?P<b>y)', r'\g<b>', 'xx'), '')
|
||||||
self.assertRaises(re.error, re.sub, '(?P<a>x)|(?P<b>y)', '\\2', 'xx')
|
self.assertEqual(re.sub('(?P<a>x)|(?P<b>y)', r'\2', 'xx'), '')
|
||||||
self.assertRaises(re.error, re.sub, '(?P<a>x)', '\g<-1>', 'xx')
|
self.assertRaises(re.error, re.sub, '(?P<a>x)', '\g<-1>', 'xx')
|
||||||
# New valid/invalid identifiers in Python 3
|
# New valid/invalid identifiers in Python 3
|
||||||
self.assertEqual(re.sub('(?P<µ>x)', r'\g<µ>', 'xx'), 'xx')
|
self.assertEqual(re.sub('(?P<µ>x)', r'\g<µ>', 'xx'), 'xx')
|
||||||
|
@ -439,6 +441,10 @@ class ReTests(unittest.TestCase):
|
||||||
"first second")
|
"first second")
|
||||||
.expand(r"\2 \1 \g<second> \g<first>"),
|
.expand(r"\2 \1 \g<second> \g<first>"),
|
||||||
"second first second first")
|
"second first second first")
|
||||||
|
self.assertEqual(re.match("(?P<first>first)|(?P<second>second)",
|
||||||
|
"first")
|
||||||
|
.expand(r"\2 \g<second>"),
|
||||||
|
" ")
|
||||||
|
|
||||||
def test_repeat_minmax(self):
|
def test_repeat_minmax(self):
|
||||||
self.assertIsNone(re.match("^(\w){1}$", "abc"))
|
self.assertIsNone(re.match("^(\w){1}$", "abc"))
|
||||||
|
|
|
@ -166,7 +166,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
- Issue $18615: sndhdr.what/whathdr now return a namedtuple.
|
- Issue 1519638: Now unmatched groups are replaced with empty strings in re.sub()
|
||||||
|
and re.subn().
|
||||||
|
|
||||||
|
- Issue #18615: sndhdr.what/whathdr now return a namedtuple.
|
||||||
|
|
||||||
- Issue #22462: Fix pyexpat's creation of a dummy frame to make it
|
- Issue #22462: Fix pyexpat's creation of a dummy frame to make it
|
||||||
appear in exception tracebacks.
|
appear in exception tracebacks.
|
||||||
|
|
Loading…
Reference in New Issue