summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPieter Eendebak <pieter.eendebak@gmail.com>2024-06-10 11:06:18 (GMT)
committerGitHub <noreply@github.com>2024-06-10 11:06:18 (GMT)
commitc3b6dbff2c8886de1edade737febe85dd47ff4d0 (patch)
tree17d7a14f7e1c9bf239f1a38ccf7eb24d303c6745
parentb90bd3e5bbc136f53b24ee791824acd6b17e0d42 (diff)
downloadcpython-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.py6
-rw-r--r--Lib/test/test_difflib.py30
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-04-27-18-36-46.gh-issue-115801.SVeHSy.rst1
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`.