From b8977c8b0a840ff9158d53e3dac56475e94e9331 Mon Sep 17 00:00:00 2001 From: Kesara Rathnayake Date: Wed, 2 Sep 2026 23:24:41 +1200 Subject: [PATCH 1/4] Promote _mdiff to a standard method --- Lib/difflib.py | 4 ++-- Lib/test/test_difflib.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/difflib.py b/Lib/difflib.py index 95ba8fd782c6c3c..a0282255ff5bc5d 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1358,7 +1358,7 @@ def ndiff(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK): """ return Differ(linejunk, charjunk).compare(a, b) -def _mdiff(fromlines, tolines, context=None, linejunk=None, +def mdiff(fromlines, tolines, context=None, linejunk=None, charjunk=IS_CHARACTER_JUNK): r"""Returns generator yielding marked up from/to side by side differences. @@ -2025,7 +2025,7 @@ def make_table(self,fromlines,tolines,fromdesc='',todesc='',context=False, context_lines = numlines else: context_lines = None - diffs = _mdiff(fromlines,tolines,context_lines,linejunk=self._linejunk, + diffs = mdiff(fromlines,tolines,context_lines,linejunk=self._linejunk, charjunk=self._charjunk) # set up iterator to wrap lines that exceed desired width diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py index 4f99b7c91c654e4..80f6711b6f4b673 100644 --- a/Lib/test/test_difflib.py +++ b/Lib/test/test_difflib.py @@ -114,7 +114,7 @@ def test_hint_indented_properly_with_tabs(self): def test_mdiff_catch_stop_iteration(self): # Issue #33224 self.assertEqual( - list(difflib._mdiff(["2"], ["3"], 1)), + list(difflib.mdiff(["2"], ["3"], 1)), [((1, '\x00-2\x01'), (1, '\x00+3\x01'), True)], ) From 78c98fa751386f9470ca79a4d8937b464234da1f Mon Sep 17 00:00:00 2001 From: Kesara Rathnayake Date: Wed, 2 Sep 2026 23:42:53 +1200 Subject: [PATCH 2/4] Add NEWS entry --- .../next/Library/2026-09-02-23-38-40.gh-issue-129922.Klr4dt.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-09-02-23-38-40.gh-issue-129922.Klr4dt.rst diff --git a/Misc/NEWS.d/next/Library/2026-09-02-23-38-40.gh-issue-129922.Klr4dt.rst b/Misc/NEWS.d/next/Library/2026-09-02-23-38-40.gh-issue-129922.Klr4dt.rst new file mode 100644 index 000000000000000..bfc8e282ad0645b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-09-02-23-38-40.gh-issue-129922.Klr4dt.rst @@ -0,0 +1 @@ +Promote ``difflib._mdiff()`` to a public function named :func:`difflib.mdiff`. From 1b66519ec8de723e150b3d1bedf6e3b717762e60 Mon Sep 17 00:00:00 2001 From: Kesara Rathnayake Date: Thu, 3 Sep 2026 01:20:24 +1200 Subject: [PATCH 3/4] Update documentation --- Doc/library/difflib.rst | 17 +++++++++++++++++ Lib/difflib.py | 5 ++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index 5339186b72f6bc7..dd9b9a2b88fad60 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -338,6 +338,23 @@ Diff generation + tree + emu +.. function:: mdiff(fromlines, tolines, context=None, linejunk=None, charjunk=IS_CHARACTER_JUNK) + + Return a generator yielding marked up *fromlines* and *tolines* side by side differences. + + Optional keyword parameters *context* is number of lines to display on each side the difference, if ``None``, all from/to text lines will be generated; *linejunk* and *charjunk* are filtering functions. + + from/to line tuple -- (line num, line text) + line num -- integer or None (to indicate a context separation) + line text -- original line text with following markers inserted: + + '\0+' -- marks start of added text + '\0-' -- marks start of deleted text + '\0^' -- marks start of changed text + '\1' -- marks end of added/deleted/changed text + + boolean flag -- None indicates context separation, True indicates + either "from" or "to" line contains a change, otherwise False. .. function:: restore(sequence, which) diff --git a/Lib/difflib.py b/Lib/difflib.py index a0282255ff5bc5d..0d70861e4529c1c 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -10,6 +10,9 @@ Function ndiff(a, b): Return a delta: the difference between `a` and `b` (lists of strings). +Function mdiff(fromlines, tolines): + Return a generator yielding marked up from/to side by side differences. + Function restore(delta, which): Return one of the two sequences that generated an ndiff delta. @@ -26,7 +29,7 @@ For producing HTML side by side comparison with change highlights. """ -__all__ = ['get_close_matches', 'ndiff', 'restore', 'SequenceMatcher', +__all__ = ['get_close_matches', 'ndiff', 'mdiff', 'restore', 'SequenceMatcher', 'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff', 'unified_diff', 'diff_bytes', 'HtmlDiff', 'Match'] From 517e44086bd5f00798ffb8203d71c747425f37d3 Mon Sep 17 00:00:00 2001 From: Kesara Rathnayake Date: Thu, 3 Sep 2026 01:48:59 +1200 Subject: [PATCH 4/4] Improve doc formatting --- Doc/library/difflib.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index dd9b9a2b88fad60..e86e72f7578dead 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -348,10 +348,13 @@ Diff generation line num -- integer or None (to indicate a context separation) line text -- original line text with following markers inserted: - '\0+' -- marks start of added text - '\0-' -- marks start of deleted text - '\0^' -- marks start of changed text - '\1' -- marks end of added/deleted/changed text + ``'\0+'`` -- marks start of added text + + ``'\0-'`` -- marks start of deleted text + + ``'\0^'`` -- marks start of changed text + + ``'\1'`` -- marks end of added/deleted/changed text boolean flag -- None indicates context separation, True indicates either "from" or "to" line contains a change, otherwise False.