diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 1b05458280d..7e79871bbd6 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -26,7 +26,7 @@ authentication, redirections, cookies and more. The :mod:`urllib.request` module defines the following functions: -.. function:: urlopen(url, data=None[, timeout], *, cafile=None, capath=None, cadefault=False, context=None) +.. function:: urlopen(url, data=None[, timeout], *, context=None) Open *url*, which can be either a string containing a valid, properly encoded URL, or a :class:`Request` object. @@ -47,14 +47,6 @@ The :mod:`urllib.request` module defines the following functions: describing the various SSL options. See :class:`~http.client.HTTPSConnection` for more details. - The optional *cafile* and *capath* parameters specify a set of trusted - CA certificates for HTTPS requests. *cafile* should point to a single - file containing a bundle of CA certificates, whereas *capath* should - point to a directory of hashed certificate files. More information can - be found in :meth:`ssl.SSLContext.load_verify_locations`. - - The *cadefault* parameter is ignored. - This function always returns an object which can work as a :term:`context manager` and has the properties *url*, *headers*, and *status*. See :class:`urllib.response.addinfourl` for more detail on these properties. @@ -115,12 +107,9 @@ The :mod:`urllib.request` module defines the following functions: ``http/1.1`` when no *context* is given. Custom *context* should set ALPN protocols with :meth:`~ssl.SSLContext.set_alpn_protocol`. - .. deprecated:: 3.6 - - *cafile*, *capath* and *cadefault* are deprecated in favor of *context*. - Please use :meth:`ssl.SSLContext.load_cert_chain` instead, or let - :func:`ssl.create_default_context` select the system's trusted CA - certificates for you. + .. versionchanged:: 3.13 + Remove *cafile*, *capath* and *cadefault* parameters: use the *context* + parameter instead. .. function:: install_opener(opener) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 1eb859f3a5a..502cafdaf5e 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -316,6 +316,14 @@ Removed method instead. (Contributed by Victor Stinner in :gh:`105376`.) +* Remove *cafile*, *capath* and *cadefault* parameters of the + :func:`urllib.request.urlopen` function, deprecated in Python 3.6: use the + *context* parameter instead. Please use + :meth:`ssl.SSLContext.load_cert_chain` instead, or let + :func:`ssl.create_default_context` select the system's trusted CA + certificates for you. + (Contributed by Victor Stinner in :gh:`105382`.) + Porting to Python 3.13 ====================== diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py index 2df74f5e6f9..6bb0fb303fa 100644 --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -597,15 +597,6 @@ Connection: close with warnings_helper.check_warnings(('',DeprecationWarning)): urllib.request.URLopener() - @unittest.skipUnless(ssl, "ssl module required") - def test_cafile_and_context(self): - context = ssl.create_default_context() - with warnings_helper.check_warnings(('', DeprecationWarning)): - with self.assertRaises(ValueError): - urllib.request.urlopen( - "https://localhost", cafile="/nonexistent/path", context=context - ) - class urlopen_DataTests(unittest.TestCase): """Test urlopen() opening a data URL.""" diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py index f4729358557..1c5b027931c 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -568,31 +568,6 @@ class TestUrlopen(unittest.TestCase): data = self.urlopen("https://localhost:%s/bizarre" % handler.port, context=context) self.assertEqual(data, b"we care a bit") - def test_https_with_cafile(self): - handler = self.start_https_server(certfile=CERT_localhost) - with warnings_helper.check_warnings(('', DeprecationWarning)): - # Good cert - data = self.urlopen("https://localhost:%s/bizarre" % handler.port, - cafile=CERT_localhost) - self.assertEqual(data, b"we care a bit") - # Bad cert - with self.assertRaises(urllib.error.URLError) as cm: - self.urlopen("https://localhost:%s/bizarre" % handler.port, - cafile=CERT_fakehostname) - # Good cert, but mismatching hostname - handler = self.start_https_server(certfile=CERT_fakehostname) - with self.assertRaises(urllib.error.URLError) as cm: - self.urlopen("https://localhost:%s/bizarre" % handler.port, - cafile=CERT_fakehostname) - - def test_https_with_cadefault(self): - handler = self.start_https_server(certfile=CERT_localhost) - # Self-signed cert should fail verification with system certificate store - with warnings_helper.check_warnings(('', DeprecationWarning)): - with self.assertRaises(urllib.error.URLError) as cm: - self.urlopen("https://localhost:%s/bizarre" % handler.port, - cadefault=True) - def test_https_sni(self): if ssl is None: self.skipTest("ssl module required") diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 5314b3f2602..1d03259b918 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -136,7 +136,7 @@ __version__ = '%d.%d' % sys.version_info[:2] _opener = None def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, - *, cafile=None, capath=None, cadefault=False, context=None): + *, context=None): '''Open the URL url, which can be either a string or a Request object. *data* must be an object specifying additional data to be sent to @@ -154,14 +154,6 @@ def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, If *context* is specified, it must be a ssl.SSLContext instance describing the various SSL options. See HTTPSConnection for more details. - The optional *cafile* and *capath* parameters specify a set of trusted CA - certificates for HTTPS requests. cafile should point to a single file - containing a bundle of CA certificates, whereas capath should point to a - directory of hashed certificate files. More information can be found in - ssl.SSLContext.load_verify_locations(). - - The *cadefault* parameter is ignored. - This function always returns an object which can work as a context manager and has the properties url, headers, and status. @@ -187,25 +179,7 @@ def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, ''' global _opener - if cafile or capath or cadefault: - import warnings - warnings.warn("cafile, capath and cadefault are deprecated, use a " - "custom context instead.", DeprecationWarning, 2) - if context is not None: - raise ValueError( - "You can't pass both context and any of cafile, capath, and " - "cadefault" - ) - if not _have_ssl: - raise ValueError('SSL support not available') - context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, - cafile=cafile, - capath=capath) - # send ALPN extension to indicate HTTP/1.1 protocol - context.set_alpn_protocols(['http/1.1']) - https_handler = HTTPSHandler(context=context) - opener = build_opener(https_handler) - elif context: + if context: https_handler = HTTPSHandler(context=context) opener = build_opener(https_handler) elif _opener is None: diff --git a/Misc/NEWS.d/next/Library/2023-06-06-16-00-03.gh-issue-105382.A1LgzA.rst b/Misc/NEWS.d/next/Library/2023-06-06-16-00-03.gh-issue-105382.A1LgzA.rst new file mode 100644 index 00000000000..4e6d72745ff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-06-06-16-00-03.gh-issue-105382.A1LgzA.rst @@ -0,0 +1,3 @@ +Remove *cafile*, *capath* and *cadefault* parameters of the +:func:`urllib.request.urlopen` function, deprecated in Python 3.6. Patch by +Victor Stinner.