From 77133f570dcad599e5b1199c39e999bfac959ae2 Mon Sep 17 00:00:00 2001 From: Jeremy Hylton <32469542+jeremyhylton@users.noreply.github.com> Date: Mon, 19 Aug 2024 20:35:05 -0400 Subject: gh-122909: Pass ftp error strings to URLError constructor (#122913) * pass the original string error message from the ftplib error to URLError() * Update request.py Change error string for ftp error to be consistent with other errors reported for ftp * Add NEWS entry for change to urllib.request for ftp errors. * Track the change in the ftp error message in the test. --- Lib/test/test_urllib2.py | 23 +++++++++++++++++++++- Lib/urllib/request.py | 2 +- .../2024-08-19-17-37-18.gh-issue-122909.kP12SK.rst | 3 +++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-08-19-17-37-18.gh-issue-122909.kP12SK.rst diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index eed0599..19179fd 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -8,6 +8,7 @@ from unittest import mock import os import io +import ftplib import socket import array import sys @@ -754,7 +755,6 @@ class HandlerTests(unittest.TestCase): self.ftpwrapper = MockFTPWrapper(self.data) return self.ftpwrapper - import ftplib data = "rheum rhaponicum" h = NullFTPHandler(data) h.parent = MockOpener() @@ -794,6 +794,27 @@ class HandlerTests(unittest.TestCase): self.assertEqual(headers.get("Content-type"), mimetype) self.assertEqual(int(headers["Content-length"]), len(data)) + def test_ftp_error(self): + class ErrorFTPHandler(urllib.request.FTPHandler): + def __init__(self, exception): + self._exception = exception + + def connect_ftp(self, user, passwd, host, port, dirs, + timeout=socket._GLOBAL_DEFAULT_TIMEOUT): + raise self._exception + + exception = ftplib.error_perm( + "500 OOPS: cannot change directory:/nonexistent") + h = ErrorFTPHandler(exception) + urlopen = urllib.request.build_opener(h).open + try: + urlopen("ftp://www.pythontest.net/") + except urllib.error.URLError as raised: + self.assertEqual(raised.reason, + f"ftp error: {exception.args[0]}") + else: + self.fail("Did not raise ftplib exception") + def test_file(self): import email.utils h = urllib.request.FileHandler() diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 58b0cb5..bc35d8a 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1555,7 +1555,7 @@ class FTPHandler(BaseHandler): headers = email.message_from_string(headers) return addinfourl(fp, headers, req.full_url) except ftplib.all_errors as exp: - raise URLError(exp) from exp + raise URLError(f"ftp error: {exp}") from exp def connect_ftp(self, user, passwd, host, port, dirs, timeout): return ftpwrapper(user, passwd, host, port, dirs, timeout, diff --git a/Misc/NEWS.d/next/Library/2024-08-19-17-37-18.gh-issue-122909.kP12SK.rst b/Misc/NEWS.d/next/Library/2024-08-19-17-37-18.gh-issue-122909.kP12SK.rst new file mode 100644 index 0000000..50eb4af --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-19-17-37-18.gh-issue-122909.kP12SK.rst @@ -0,0 +1,3 @@ +In urllib.request when URLError is raised opening an ftp URL, the exception +argument is now consistently a string. Earlier versions passed either a +string or an ftplib exception instance as the argument to URLError. -- cgit v0.12