Skip to content

Commit 8b9e9d6

Browse files
codexByron
authored andcommitted
fix: restore Actor.name_email_regex (#2220)
GitPython 3.1.60 removed the Actor.name_email_regex class attribute while replacing internal actor parsing, which broke downstream consumers such as python-semantic-release. Restore the historical compiled pattern as a compatibility API while leaving Actor._from_string on its linear delimiter parser. The regression covers the public match behavior and verifies the parser remains independent of the regex, preserving the GHSA-g5vv-9gxw-82hx fix. Validation: - test/test_actor.py and actor-related test/test_util.py cases: 12 passed - ruff check and format checks passed
1 parent a9fb008 commit 8b9e9d6

2 files changed

Lines changed: 11 additions & 2 deletions

File tree

git/util.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,8 @@ class Actor:
858858
committers and authors or anything with a name and an email as mentioned in the git
859859
log entries."""
860860

861+
name_email_regex = re.compile(r"(.*) <(.*?)>")
862+
861863
# ENVIRONMENT VARIABLES
862864
# These are read when creating new commits.
863865
env_author_name = "GIT_AUTHOR_NAME"

test/test_actor.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# This module is part of GitPython and is released under the
44
# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/
55

6+
from unittest import mock
7+
68
from git import Actor
79

810
from test.lib import TestBase
@@ -29,10 +31,15 @@ def test_from_string_should_handle_just_name(self):
2931

3032
def test_from_string_handles_unterminated_email_without_regex_backtracking(self):
3133
value = "A" * 20_000 + " <unterminated"
32-
actor = Actor._from_string(value)
33-
self.assertNotIn("name_email_regex", vars(Actor))
34+
with mock.patch.object(Actor, "name_email_regex", None):
35+
actor = Actor._from_string(value)
3436
self.assertEqual(actor, Actor(value, None))
3537

38+
def test_name_email_regex_is_available(self):
39+
match = Actor.name_email_regex.match("Michael Trier <mtrier@example.com>")
40+
self.assertIsNotNone(match)
41+
self.assertEqual(match.groups(), ("Michael Trier", "mtrier@example.com"))
42+
3643
def test_from_string_does_not_parse_across_lines(self):
3744
self.assertEqual(Actor._from_string("x <a>\n y <b>"), Actor("x", "a"))
3845

0 commit comments

Comments
 (0)