https://github.com/python/cpython/commit/0fd00ee1bccde5161b96b2a3cf5a5f14afbe86c4
commit: 0fd00ee1bccde5161b96b2a3cf5a5f14afbe86c4
branch: main
author: Vasiliy Kiryanov <[email protected]>
committer: orsenthil <[email protected]>
date: 2026-11-01T15:04:21Z
summary:
gh-50720: Copy winerror to URLError on Windows (#161047)
files:
M Doc/library/urllib.error.rst
M Lib/test/test_urllib2.py
M Lib/urllib/error.py
M Misc/NEWS.d/next/Library/2026-10-29-20-52-57.gh-issue-50720.Kd1VMR.rst
diff --git a/Doc/library/urllib.error.rst b/Doc/library/urllib.error.rst
index 6a71d4a2ebb6845..0079699e06ca27d 100644
--- a/Doc/library/urllib.error.rst
+++ b/Doc/library/urllib.error.rst
@@ -29,7 +29,8 @@ The following exceptions are raised by :mod:`!urllib.error`
as appropriate:
.. versionchanged:: 3.16
The :attr:`~OSError.errno` and :attr:`~OSError.strerror` attributes are
- now set from :attr:`reason` when it is an :exc:`OSError`.
+ now set from :attr:`reason` when it is an :exc:`OSError`. On Windows,
+ :attr:`~OSError.winerror` is set as well.
.. exception:: HTTPError(url, code, msg, hdrs, fp)
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 1efc4f5a6280e43..52f77eaf85e589b 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -104,6 +104,16 @@ def request(self, *args, **kwargs):
self.assertEqual(err.errno, -2)
self.assertEqual(err.strerror, 'Name or service not known')
+ @unittest.skipUnless(sys.platform == "win32", "Windows-specific test")
+ def test_URLError_OSError_attributes_winerror(self):
+ # gh-50720: OSError(errno, strerror, filename, winerror):
+ # on Windows the constructor derives errno from winerror.
+ os_error = OSError(0, "The system cannot find the path specified",
None, 3)
+
+ err = urllib.error.URLError(os_error)
+ self.assertEqual(err.winerror, 3)
+ self.assertEqual(err.strerror, os_error.strerror)
+
class RequestHdrsTests(unittest.TestCase):
diff --git a/Lib/urllib/error.py b/Lib/urllib/error.py
index 5020a60f1ef9bd0..cc9a9254d760f7f 100644
--- a/Lib/urllib/error.py
+++ b/Lib/urllib/error.py
@@ -11,6 +11,7 @@
response.
"""
import io
+import sys
import urllib.response
__all__ = ['URLError', 'HTTPError', 'ContentTooShortError']
@@ -32,6 +33,8 @@ def __init__(self, reason, filename=None):
# it would have set from the wrapped error (gh-50720).
self.errno = reason.errno
self.strerror = reason.strerror
+ if sys.platform == 'win32':
+ self.winerror = reason.winerror
def __str__(self):
return '<urlopen error %s>' % self.reason
diff --git
a/Misc/NEWS.d/next/Library/2026-10-29-20-52-57.gh-issue-50720.Kd1VMR.rst
b/Misc/NEWS.d/next/Library/2026-10-29-20-52-57.gh-issue-50720.Kd1VMR.rst
index ddb4377c3c25987..263b7ac89585769 100644
--- a/Misc/NEWS.d/next/Library/2026-10-29-20-52-57.gh-issue-50720.Kd1VMR.rst
+++ b/Misc/NEWS.d/next/Library/2026-10-29-20-52-57.gh-issue-50720.Kd1VMR.rst
@@ -1,3 +1,4 @@
:exc:`urllib.error.URLError` now sets the :attr:`~OSError.errno` and
:attr:`~OSError.strerror` attributes from
-:attr:`~urllib.error.URLError.reason` when it is an :exc:`OSError`.
+:attr:`~urllib.error.URLError.reason` when it is an :exc:`OSError`. On
+Windows, :attr:`~OSError.winerror` is set as well.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]