From ddc97f4392c9ac255671ac53a59852c541c954ec Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 29 Mar 2024 22:38:28 +0100 Subject: [PATCH 1/5] Fix error message for `ntpath.commonpath` --- Lib/ntpath.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index ecfc7d48dbb192..1e312b85020545 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -860,9 +860,6 @@ def commonpath(paths): drivesplits = [splitroot(p.replace(altsep, sep).lower()) for p in paths] split_paths = [p.split(sep) for d, r, p in drivesplits] - if len({r for d, r, p in drivesplits}) != 1: - raise ValueError("Can't mix absolute and relative paths") - # Check that all drive letters or UNC paths match. The check is made only # now otherwise type errors for mixing strings and bytes would not be # caught. @@ -870,6 +867,13 @@ def commonpath(paths): raise ValueError("Paths don't have the same drive") drive, root, path = splitroot(paths[0].replace(altsep, sep)) + if len({r for d, r, p in drivesplits}) != 1: + if drive: + raise ValueError("Can't mix absolute and relative paths") + else: + raise ValueError("Can't mix rooted relative paths and " + "not-rooted relative paths") + common = path.split(sep) common = [c for c in common if c and c != curdir] From f8aaf8139bb8ea6d355e0906596ecb9605439010 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:43:20 +0000 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2024-03-29-21-43-19.gh-issue-117381.fT0JFM.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-03-29-21-43-19.gh-issue-117381.fT0JFM.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-03-29-21-43-19.gh-issue-117381.fT0JFM.rst b/Misc/NEWS.d/next/Core and Builtins/2024-03-29-21-43-19.gh-issue-117381.fT0JFM.rst new file mode 100644 index 00000000000000..88b6c32e971e72 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-03-29-21-43-19.gh-issue-117381.fT0JFM.rst @@ -0,0 +1 @@ +Fix error message for :func:`ntpath.commonpath`. From 35de65f0dee661322756ea960691a8130e2c40df Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sat, 30 Mar 2024 22:42:05 +0100 Subject: [PATCH 3/5] Simplify error message --- Lib/ntpath.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py index 1e312b85020545..93d181a68f92f3 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -871,8 +871,7 @@ def commonpath(paths): if drive: raise ValueError("Can't mix absolute and relative paths") else: - raise ValueError("Can't mix rooted relative paths and " - "not-rooted relative paths") + raise ValueError("Can't mix rooted and not-rooted paths") common = path.split(sep) common = [c for c in common if c and c != curdir] From da28922617da089286feac854e320e6d265ade34 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Sun, 31 Mar 2024 20:28:33 +0200 Subject: [PATCH 4/5] Update unittests --- Lib/test/test_ntpath.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index c816f99e7e9f1b..f9b4b54eed6cf5 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -866,18 +866,25 @@ def test_commonpath(self): def check(paths, expected): tester(('ntpath.commonpath(%r)' % paths).replace('\\\\', '\\'), expected) - def check_error(exc, paths): - self.assertRaises(exc, ntpath.commonpath, paths) - self.assertRaises(exc, ntpath.commonpath, + def check_error(exc, exp, paths): + self.assertRaisesRegex(exc, exp, ntpath.commonpath, paths) + self.assertRaisesRegex(exc, exp, ntpath.commonpath, [os.fsencode(p) for p in paths]) self.assertRaises(TypeError, ntpath.commonpath, None) self.assertRaises(ValueError, ntpath.commonpath, []) self.assertRaises(ValueError, ntpath.commonpath, iter([])) - check_error(ValueError, ['C:\\Program Files', 'Program Files']) - check_error(ValueError, ['C:\\Program Files', 'C:Program Files']) - check_error(ValueError, ['\\Program Files', 'Program Files']) - check_error(ValueError, ['Program Files', 'C:\\Program Files']) + + # gh-117381: Logical error messages, feel free to change drive error + # to mix error + check_error(ValueError, "Paths don't have the same drive", ['C:\\Program Files', '\\Program Files']) + check_error(ValueError, "Paths don't have the same drive", ['C:\\Program Files', 'Program Files']) + check_error(ValueError, "Can't mix absolute and relative paths", ['C:\\Program Files', 'C:Program Files']) + check_error(ValueError, "Paths don't have the same drive", ['C:\\Program Files', 'D:Program Files']) + check_error(ValueError, "Paths don't have the same drive", ['C:Program Files', '\\Program Files']) + check_error(ValueError, "Paths don't have the same drive", ['C:Program Files', 'Program Files']) + check_error(ValueError, "Can't mix rooted and not-rooted paths", ['\\Program Files', 'Program Files']) + check_error(ValueError, "Paths don't have the same drive", ['Program Files', 'C:\\Program Files']) check(['C:\\Program Files'], 'C:\\Program Files') check(['C:\\Program Files', 'C:\\Program Files'], 'C:\\Program Files') @@ -905,7 +912,8 @@ def check_error(exc, paths): check(['c:/program files/bar', 'C:\\Program Files\\Foo'], 'c:\\program files') - check_error(ValueError, ['C:\\Program Files', 'D:\\Program Files']) + check_error(ValueError, "Paths don't have the same drive", ['C:\\Program Files', 'D:\\Program Files']) + check_error(ValueError, "Paths don't have the same drive", ['C:Program Files', 'D:Program Files']) check(['spam'], 'spam') check(['spam', 'spam'], 'spam') @@ -919,7 +927,7 @@ def check_error(exc, paths): check([''], '') check(['', 'spam\\alot'], '') - check_error(ValueError, ['', '\\spam\\alot']) + check_error(ValueError, "Can't mix rooted and not-rooted paths", ['', '\\spam\\alot']) self.assertRaises(TypeError, ntpath.commonpath, [b'C:\\Program Files', 'C:\\Program Files\\Foo']) From a819efb79e025f686c7515cf10f364270a00fb2e Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Tue, 2 Apr 2024 00:39:44 +0200 Subject: [PATCH 5/5] foo, bar, baz --- Lib/test/test_ntpath.py | 103 ++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index f9b4b54eed6cf5..31156130fcc747 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -866,54 +866,47 @@ def test_commonpath(self): def check(paths, expected): tester(('ntpath.commonpath(%r)' % paths).replace('\\\\', '\\'), expected) - def check_error(exc, exp, paths): - self.assertRaisesRegex(exc, exp, ntpath.commonpath, paths) - self.assertRaisesRegex(exc, exp, ntpath.commonpath, - [os.fsencode(p) for p in paths]) + def check_error(paths, expected): + self.assertRaisesRegex(ValueError, expected, ntpath.commonpath, paths) + self.assertRaisesRegex(ValueError, expected, ntpath.commonpath, paths[::-1]) + self.assertRaisesRegex(ValueError, expected, ntpath.commonpath, + [os.fsencode(p) for p in paths]) + self.assertRaisesRegex(ValueError, expected, ntpath.commonpath, + [os.fsencode(p) for p in paths[::-1]]) self.assertRaises(TypeError, ntpath.commonpath, None) self.assertRaises(ValueError, ntpath.commonpath, []) self.assertRaises(ValueError, ntpath.commonpath, iter([])) - # gh-117381: Logical error messages, feel free to change drive error - # to mix error - check_error(ValueError, "Paths don't have the same drive", ['C:\\Program Files', '\\Program Files']) - check_error(ValueError, "Paths don't have the same drive", ['C:\\Program Files', 'Program Files']) - check_error(ValueError, "Can't mix absolute and relative paths", ['C:\\Program Files', 'C:Program Files']) - check_error(ValueError, "Paths don't have the same drive", ['C:\\Program Files', 'D:Program Files']) - check_error(ValueError, "Paths don't have the same drive", ['C:Program Files', '\\Program Files']) - check_error(ValueError, "Paths don't have the same drive", ['C:Program Files', 'Program Files']) - check_error(ValueError, "Can't mix rooted and not-rooted paths", ['\\Program Files', 'Program Files']) - check_error(ValueError, "Paths don't have the same drive", ['Program Files', 'C:\\Program Files']) - - check(['C:\\Program Files'], 'C:\\Program Files') - check(['C:\\Program Files', 'C:\\Program Files'], 'C:\\Program Files') - check(['C:\\Program Files\\', 'C:\\Program Files'], - 'C:\\Program Files') - check(['C:\\Program Files\\', 'C:\\Program Files\\'], - 'C:\\Program Files') - check(['C:\\\\Program Files', 'C:\\Program Files\\\\'], - 'C:\\Program Files') - check(['C:\\.\\Program Files', 'C:\\Program Files\\.'], - 'C:\\Program Files') - check(['C:\\', 'C:\\bin'], 'C:\\') - check(['C:\\Program Files', 'C:\\bin'], 'C:\\') - check(['C:\\Program Files', 'C:\\Program Files\\Bar'], - 'C:\\Program Files') - check(['C:\\Program Files\\Foo', 'C:\\Program Files\\Bar'], - 'C:\\Program Files') - check(['C:\\Program Files', 'C:\\Projects'], 'C:\\') - check(['C:\\Program Files\\', 'C:\\Projects'], 'C:\\') - - check(['C:\\Program Files\\Foo', 'C:/Program Files/Bar'], - 'C:\\Program Files') - check(['C:\\Program Files\\Foo', 'c:/program files/bar'], - 'C:\\Program Files') - check(['c:/program files/bar', 'C:\\Program Files\\Foo'], - 'c:\\program files') - - check_error(ValueError, "Paths don't have the same drive", ['C:\\Program Files', 'D:\\Program Files']) - check_error(ValueError, "Paths don't have the same drive", ['C:Program Files', 'D:Program Files']) + # gh-117381: Logical error messages + check_error(['C:\\Foo', 'C:Foo'], "Can't mix absolute and relative paths") + check_error(['C:\\Foo', '\\Foo'], "Paths don't have the same drive") + check_error(['C:\\Foo', 'Foo'], "Paths don't have the same drive") + check_error(['C:Foo', '\\Foo'], "Paths don't have the same drive") + check_error(['C:Foo', 'Foo'], "Paths don't have the same drive") + check_error(['\\Foo', 'Foo'], "Can't mix rooted and not-rooted paths") + + check(['C:\\Foo'], 'C:\\Foo') + check(['C:\\Foo', 'C:\\Foo'], 'C:\\Foo') + check(['C:\\Foo\\', 'C:\\Foo'], 'C:\\Foo') + check(['C:\\Foo\\', 'C:\\Foo\\'], 'C:\\Foo') + check(['C:\\\\Foo', 'C:\\Foo\\\\'], 'C:\\Foo') + check(['C:\\.\\Foo', 'C:\\Foo\\.'], 'C:\\Foo') + check(['C:\\', 'C:\\baz'], 'C:\\') + check(['C:\\Bar', 'C:\\baz'], 'C:\\') + check(['C:\\Foo', 'C:\\Foo\\Baz'], 'C:\\Foo') + check(['C:\\Foo\\Bar', 'C:\\Foo\\Baz'], 'C:\\Foo') + check(['C:\\Bar', 'C:\\Baz'], 'C:\\') + check(['C:\\Bar\\', 'C:\\Baz'], 'C:\\') + + check(['C:\\Foo\\Bar', 'C:/Foo/Baz'], 'C:\\Foo') + check(['C:\\Foo\\Bar', 'c:/foo/baz'], 'C:\\Foo') + check(['c:/foo/bar', 'C:\\Foo\\Baz'], 'c:\\foo') + + # gh-117381: Logical error messages + check_error(['C:\\Foo', 'D:\\Foo'], "Paths don't have the same drive") + check_error(['C:\\Foo', 'D:Foo'], "Paths don't have the same drive") + check_error(['C:Foo', 'D:Foo'], "Paths don't have the same drive") check(['spam'], 'spam') check(['spam', 'spam'], 'spam') @@ -927,20 +920,16 @@ def check_error(exc, exp, paths): check([''], '') check(['', 'spam\\alot'], '') - check_error(ValueError, "Can't mix rooted and not-rooted paths", ['', '\\spam\\alot']) - - self.assertRaises(TypeError, ntpath.commonpath, - [b'C:\\Program Files', 'C:\\Program Files\\Foo']) - self.assertRaises(TypeError, ntpath.commonpath, - [b'C:\\Program Files', 'Program Files\\Foo']) - self.assertRaises(TypeError, ntpath.commonpath, - [b'Program Files', 'C:\\Program Files\\Foo']) - self.assertRaises(TypeError, ntpath.commonpath, - ['C:\\Program Files', b'C:\\Program Files\\Foo']) - self.assertRaises(TypeError, ntpath.commonpath, - ['C:\\Program Files', b'Program Files\\Foo']) - self.assertRaises(TypeError, ntpath.commonpath, - ['Program Files', b'C:\\Program Files\\Foo']) + + # gh-117381: Logical error messages + check_error(['', '\\spam\\alot'], "Can't mix rooted and not-rooted paths") + + self.assertRaises(TypeError, ntpath.commonpath, [b'C:\\Foo', 'C:\\Foo\\Baz']) + self.assertRaises(TypeError, ntpath.commonpath, [b'C:\\Foo', 'Foo\\Baz']) + self.assertRaises(TypeError, ntpath.commonpath, [b'Foo', 'C:\\Foo\\Baz']) + self.assertRaises(TypeError, ntpath.commonpath, ['C:\\Foo', b'C:\\Foo\\Baz']) + self.assertRaises(TypeError, ntpath.commonpath, ['C:\\Foo', b'Foo\\Baz']) + self.assertRaises(TypeError, ntpath.commonpath, ['Foo', b'C:\\Foo\\Baz']) @unittest.skipIf(is_emscripten, "Emscripten cannot fstat unnamed files.") def test_sameopenfile(self):