This is an automated email from the ASF dual-hosted git repository.
tvalentyn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push:
new fbc9db6bae6 [Python] Return every group from Regex.all_matches (#40563)
fbc9db6bae6 is described below
commit fbc9db6bae64f7a7ed846d323a2716e755c96988
Author: raams95 <[email protected]>
AuthorDate: Wed Oct 14 17:56:45 2026 -0500
[Python] Return every group from Regex.all_matches (#40563)
Regex.all_matches built its output from range(m.lastindex + 1), but
lastindex is the index of the last group that matched (or the outermost
group that closed last), not the number of groups. A regex without
groups failed with a TypeError, and nested groups or an unmatched
trailing optional group were dropped from the output. Use the entire
match followed by m.groups(), which has one entry per group, with None
for a group that did not participate, as Java's AllMatches does with
null.
Fixes #40562
Co-authored-by: JanakiRamChittineni
<[email protected]>
---
CHANGES.md | 1 +
sdks/python/apache_beam/transforms/util.py | 6 ++++--
sdks/python/apache_beam/transforms/util_test.py | 16 ++++++++++++++++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 1848d909db9..f98790bc2e1 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -83,6 +83,7 @@
`valueMapper`, `topicNameMapper`, or providing a `ConnectionFactory` must
update imports from `javax.jms.*` to
`jakarta.jms.*`. The module now requires Java 17 at runtime
([#38729](https://github.com/apache/beam/issues/38729)).
* (Python) `Regex.find_all` with `group=Regex.ALL` now returns every group, as
`(match, group1, group2, ...)`, instead of only group 1, and with
`outputEmpty=False` it drops a match only when the whole match is empty,
matching the `group=0` behavior
([#40399](https://github.com/apache/beam/pull/40399)).
+* (Python) `Regex.all_matches` now returns every group of the regex, instead
of failing with a `TypeError` when the regex has no groups and dropping nested
or unmatched trailing groups
([#40562](https://github.com/apache/beam/issues/40562)).
## Deprecations
diff --git a/sdks/python/apache_beam/transforms/util.py
b/sdks/python/apache_beam/transforms/util.py
index b7885544dbf..c8c7cc86d71 100644
--- a/sdks/python/apache_beam/transforms/util.py
+++ b/sdks/python/apache_beam/transforms/util.py
@@ -2156,7 +2156,9 @@ class Regex(object):
def all_matches(pcoll, regex):
"""
Returns all matches (groups) if zero or more characters at the beginning
- of string match the regular expression.
+ of string match the regular expression. Each output is a list of the
+ entire match followed by every group of the regex, with None for a group
+ that did not participate in the match.
Args:
regex: the regular expression string or (re.compile) pattern.
@@ -2166,7 +2168,7 @@ class Regex(object):
def _process(element):
m = regex.match(element)
if m:
- yield [m.group(ix) for ix in range(m.lastindex + 1)]
+ yield [m.group(), *m.groups()]
return pcoll | FlatMap(_process)
diff --git a/sdks/python/apache_beam/transforms/util_test.py
b/sdks/python/apache_beam/transforms/util_test.py
index bba09245a0f..1e3db695e07 100644
--- a/sdks/python/apache_beam/transforms/util_test.py
+++ b/sdks/python/apache_beam/transforms/util_test.py
@@ -2854,6 +2854,22 @@ class RegexTest(unittest.TestCase):
["z z", "z", "z"]]
assert_that(result, equal_to(expected_result))
+ def test_all_matched_returns_every_group(self):
+ with TestPipeline() as p:
+ pcol = (p | beam.Create(["ab"]))
+ assert_that(
+ pcol | 'nested groups' >> util.Regex.all_matches("((a)(b))"),
+ equal_to([["ab", "ab", "a", "b"]]),
+ label='CheckNestedGroups')
+ assert_that(
+ pcol | 'optional group' >> util.Regex.all_matches("(a)(c)?"),
+ equal_to([["a", "a", None]]),
+ label='CheckOptionalGroup')
+ assert_that(
+ pcol | 'no groups' >> util.Regex.all_matches("a+"),
+ equal_to([["a"]]),
+ label='CheckNoGroups')
+
def test_match_group_kv(self):
with TestPipeline() as p:
result = (