From 448231f9379f181350472a58e893265b02940eb0 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sat, 3 Dec 2022 19:50:13 +0900 Subject: [PATCH 1/3] gh-98778: Update HTTPError to initialize properly even if fp is None --- Lib/tempfile.py | 6 ++++-- Lib/test/test_urllib2.py | 4 ++++ Lib/urllib/error.py | 7 +------ .../Library/2022-12-03-20-06-16.gh-issue-98778.t5U9uc.rst | 2 ++ 4 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-12-03-20-06-16.gh-issue-98778.t5U9uc.rst diff --git a/Lib/tempfile.py b/Lib/tempfile.py index bb18d60db0d919..62eed9a7453ecb 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -433,7 +433,8 @@ def cleanup(self, windows=(_os.name == 'nt'), unlink=_os.unlink): try: if not self.close_called: self.close_called = True - self.file.close() + if self.file is not None: + self.file.close() finally: # Windows provides delete-on-close as a primitive, in which # case the file was deleted by self.file.close(). @@ -447,7 +448,8 @@ def close(self): if not self.close_called: self.close_called = True try: - self.file.close() + if self.file is not None: + self.file.close() finally: if self.delete and self.delete_on_close: self.cleanup() diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index 28f88412fdcaac..498c0382d2137b 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -1824,6 +1824,10 @@ def test_HTTPError_interface(self): expected_errmsg = '' % (err.code, err.msg) self.assertEqual(repr(err), expected_errmsg) + def test_gh_98778(self): + x = urllib.error.HTTPError("url", 405, "METHOD NOT ALLOWED", None, None) + self.assertEqual(getattr(x, "__notes__", ()), ()) + def test_parse_proxy(self): parse_proxy_test_cases = [ ('proxy.example.com', diff --git a/Lib/urllib/error.py b/Lib/urllib/error.py index 8cd901f13f8e49..1b5d2b1be295bc 100644 --- a/Lib/urllib/error.py +++ b/Lib/urllib/error.py @@ -42,12 +42,7 @@ def __init__(self, url, code, msg, hdrs, fp): self.hdrs = hdrs self.fp = fp self.filename = url - # The addinfourl classes depend on fp being a valid file - # object. In some cases, the HTTPError may not have a valid - # file object. If this happens, the simplest workaround is to - # not initialize the base classes. - if fp is not None: - self.__super_init(fp, hdrs, url, code) + self.__super_init(fp, hdrs, url, code) def __str__(self): return 'HTTP Error %s: %s' % (self.code, self.msg) diff --git a/Misc/NEWS.d/next/Library/2022-12-03-20-06-16.gh-issue-98778.t5U9uc.rst b/Misc/NEWS.d/next/Library/2022-12-03-20-06-16.gh-issue-98778.t5U9uc.rst new file mode 100644 index 00000000000000..b1c170dff3eabc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-12-03-20-06-16.gh-issue-98778.t5U9uc.rst @@ -0,0 +1,2 @@ +Update :exc:`~urllib.error.HTTPError` to be initialized properly, even if +the ``fp`` is ``None``. Patch by Dong-hee Na. From 91a6e6f906716fbd49d01a42b13d669360053314 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Wed, 7 Dec 2022 23:37:00 +0900 Subject: [PATCH 2/3] Address code review --- Lib/tempfile.py | 6 ++---- Lib/urllib/error.py | 7 +++++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 62eed9a7453ecb..bb18d60db0d919 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -433,8 +433,7 @@ def cleanup(self, windows=(_os.name == 'nt'), unlink=_os.unlink): try: if not self.close_called: self.close_called = True - if self.file is not None: - self.file.close() + self.file.close() finally: # Windows provides delete-on-close as a primitive, in which # case the file was deleted by self.file.close(). @@ -448,8 +447,7 @@ def close(self): if not self.close_called: self.close_called = True try: - if self.file is not None: - self.file.close() + self.file.close() finally: if self.delete and self.delete_on_close: self.cleanup() diff --git a/Lib/urllib/error.py b/Lib/urllib/error.py index 1b5d2b1be295bc..2f74cf2a3bdc89 100644 --- a/Lib/urllib/error.py +++ b/Lib/urllib/error.py @@ -10,7 +10,7 @@ an application may want to handle an exception like a regular response. """ - +import io import urllib.response __all__ = ['URLError', 'HTTPError', 'ContentTooShortError'] @@ -42,7 +42,10 @@ def __init__(self, url, code, msg, hdrs, fp): self.hdrs = hdrs self.fp = fp self.filename = url - self.__super_init(fp, hdrs, url, code) + if fp is not None: + self.__super_init(fp, hdrs, url, code) + else: + self.__super_init(io.StringIO(), hdrs, url, code) def __str__(self): return 'HTTP Error %s: %s' % (self.code, self.msg) From c3a75a14eb7ecf8832cc508b0259d0e52d54e50a Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Thu, 8 Dec 2022 10:37:25 +0900 Subject: [PATCH 3/3] Update Lib/urllib/error.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ɓukasz Langa --- Lib/urllib/error.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/urllib/error.py b/Lib/urllib/error.py index 2f74cf2a3bdc89..feec0e7f848e46 100644 --- a/Lib/urllib/error.py +++ b/Lib/urllib/error.py @@ -42,10 +42,9 @@ def __init__(self, url, code, msg, hdrs, fp): self.hdrs = hdrs self.fp = fp self.filename = url - if fp is not None: - self.__super_init(fp, hdrs, url, code) - else: - self.__super_init(io.StringIO(), hdrs, url, code) + if fp is None: + fp = io.StringIO() + self.__super_init(fp, hdrs, url, code) def __str__(self): return 'HTTP Error %s: %s' % (self.code, self.msg)