diff options
author | Pieter Eendebak <pieter.eendebak@gmail.com> | 2024-06-10 11:06:18 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-10 11:06:18 (GMT) |
commit | c3b6dbff2c8886de1edade737febe85dd47ff4d0 (patch) | |
tree | 17d7a14f7e1c9bf239f1a38ccf7eb24d303c6745 | |
parent | b90bd3e5bbc136f53b24ee791824acd6b17e0d42 (diff) | |
download | cpython-c3b6dbff2c8886de1edade737febe85dd47ff4d0.zip cpython-c3b6dbff2c8886de1edade737febe85dd47ff4d0.tar.gz cpython-c3b6dbff2c8886de1edade737febe85dd47ff4d0.tar.bz2 |
gh-115801: Only allow sequence of strings as input for difflib.unified_diff (GH-118333)
-rw-r--r-- | Lib/difflib.py | 6 | ||||
-rw-r--r-- | Lib/test/test_difflib.py | 30 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2024-04-27-18-36-46.gh-issue-115801.SVeHSy.rst | 1 |
3 files changed, 31 insertions, 6 deletions
diff --git a/Lib/difflib.py b/Lib/difflib.py index 0443963..7f595b6 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1264,6 +1264,12 @@ def _check_types(a, b, *args): if b and not isinstance(b[0], str): raise TypeError('lines to compare must be str, not %s (%r)' % (type(b[0]).__name__, b[0])) + if isinstance(a, str): + raise TypeError('input must be a sequence of strings, not %s' % + type(a).__name__) + if isinstance(b, str): + raise TypeError('input must be a sequence of strings, not %s' % + type(b).__name__) for arg in args: if not isinstance(arg, str): raise TypeError('all arguments must be str, not: %r' % (arg,)) diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py index bf6e5b1..9e21724 100644 --- a/Lib/test/test_difflib.py +++ b/Lib/test/test_difflib.py @@ -295,7 +295,7 @@ class TestDiffer(unittest.TestCase): class TestOutputFormat(unittest.TestCase): def test_tab_delimiter(self): - args = ['one', 'two', 'Original', 'Current', + args = [['one'], ['two'], 'Original', 'Current', '2005-01-26 23:30:50', '2010-04-02 10:20:52'] ud = difflib.unified_diff(*args, lineterm='') self.assertEqual(list(ud)[0:2], [ @@ -307,7 +307,7 @@ class TestOutputFormat(unittest.TestCase): "--- Current\t2010-04-02 10:20:52"]) def test_no_trailing_tab_on_empty_filedate(self): - args = ['one', 'two', 'Original', 'Current'] + args = [['one'], ['two'], 'Original', 'Current'] ud = difflib.unified_diff(*args, lineterm='') self.assertEqual(list(ud)[0:2], ["--- Original", "+++ Current"]) @@ -447,6 +447,28 @@ class TestBytes(unittest.TestCase): lineterm=b'') assertDiff(expect, actual) + +class TestInputTypes(unittest.TestCase): + def _assert_type_error(self, msg, generator, *args): + with self.assertRaises(TypeError) as ctx: + list(generator(*args)) + self.assertEqual(msg, str(ctx.exception)) + + def test_input_type_checks(self): + unified = difflib.unified_diff + context = difflib.context_diff + + expect = "input must be a sequence of strings, not str" + self._assert_type_error(expect, unified, 'a', ['b']) + self._assert_type_error(expect, context, 'a', ['b']) + + self._assert_type_error(expect, unified, ['a'], 'b') + self._assert_type_error(expect, context, ['a'], 'b') + + expect = "lines to compare must be str, not NoneType (None)" + self._assert_type_error(expect, unified, ['a'], [None]) + self._assert_type_error(expect, context, ['a'], [None]) + def test_mixed_types_content(self): # type of input content must be consistent: all str or all bytes a = [b'hello'] @@ -495,10 +517,6 @@ class TestBytes(unittest.TestCase): b = ['bar\n'] list(difflib.unified_diff(a, b, 'a', 'b', datea, dateb)) - def _assert_type_error(self, msg, generator, *args): - with self.assertRaises(TypeError) as ctx: - list(generator(*args)) - self.assertEqual(msg, str(ctx.exception)) class TestJunkAPIs(unittest.TestCase): def test_is_line_junk_true(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-27-18-36-46.gh-issue-115801.SVeHSy.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-27-18-36-46.gh-issue-115801.SVeHSy.rst new file mode 100644 index 0000000..93b176d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-27-18-36-46.gh-issue-115801.SVeHSy.rst @@ -0,0 +1 @@ +Raise ``TypeError`` when passing a string to :func:`difflib.unified_diff` and :func:`difflib.context_diff`. |