backport context argument of urlopen (#22366) for pep 476

This commit is contained in:
Senthil Kumaran 2014-09-19 15:23:30 +08:00
parent cc23154d02
commit 8b7e161ac3
4 changed files with 29 additions and 2 deletions

View File

@ -16,7 +16,7 @@ authentication, redirections, cookies and more.
The :mod:`urllib.request` module defines the following functions: The :mod:`urllib.request` module defines the following functions:
.. function:: urlopen(url, data=None[, timeout], *, cafile=None, capath=None, cadefault=False) .. function:: urlopen(url, data=None[, timeout], *, cafile=None, capath=None, cadefault=False, context=None)
Open the URL *url*, which can be either a string or a Open the URL *url*, which can be either a string or a
:class:`Request` object. :class:`Request` object.
@ -47,6 +47,10 @@ The :mod:`urllib.request` module defines the following functions:
the global default timeout setting will be used). This actually the global default timeout setting will be used). This actually
only works for HTTP, HTTPS and FTP connections. only works for HTTP, HTTPS and FTP connections.
If *context* is specified, it must be a :class:`ssl.SSLContext` instance
describing the various SSL options. See
:class:`~http.client.HTTPSConnection` for more details.
The optional *cafile* and *capath* parameters specify a set of trusted The optional *cafile* and *capath* parameters specify a set of trusted
CA certificates for HTTPS requests. *cafile* should point to a single CA certificates for HTTPS requests. *cafile* should point to a single
file containing a bundle of CA certificates, whereas *capath* should file containing a bundle of CA certificates, whereas *capath* should
@ -111,6 +115,9 @@ The :mod:`urllib.request` module defines the following functions:
.. versionchanged:: 3.3 .. versionchanged:: 3.3
*cadefault* was added. *cadefault* was added.
.. versionchanged:: 3.4.3
*context* was added.
.. function:: install_opener(opener) .. function:: install_opener(opener)
Install an :class:`OpenerDirector` instance as the default global opener. Install an :class:`OpenerDirector` instance as the default global opener.

View File

@ -10,6 +10,7 @@ import unittest
from unittest.mock import patch from unittest.mock import patch
from test import support from test import support
import os import os
import ssl
import sys import sys
import tempfile import tempfile
from nturl2path import url2pathname, pathname2url from nturl2path import url2pathname, pathname2url
@ -379,6 +380,13 @@ Content-Type: text/html; charset=iso-8859-1
with support.check_warnings(('',DeprecationWarning)): with support.check_warnings(('',DeprecationWarning)):
urllib.request.URLopener() urllib.request.URLopener()
def test_cafile_and_context(self):
context = ssl.create_default_context()
with self.assertRaises(ValueError):
urllib.request.urlopen(
"https://localhost", cafile="/nonexistent/path", context=context
)
class urlopen_DataTests(unittest.TestCase): class urlopen_DataTests(unittest.TestCase):
"""Test urlopen() opening a data URL.""" """Test urlopen() opening a data URL."""

View File

@ -136,9 +136,14 @@ __version__ = sys.version[:3]
_opener = None _opener = None
def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
*, cafile=None, capath=None, cadefault=False): *, cafile=None, capath=None, cadefault=False, context=None):
global _opener global _opener
if cafile or capath or cadefault: if cafile or capath or cadefault:
if context is not None:
raise ValueError(
"You can't pass both context and any of cafile, capath, and "
"cadefault"
)
if not _have_ssl: if not _have_ssl:
raise ValueError('SSL support not available') raise ValueError('SSL support not available')
context = ssl._create_stdlib_context(cert_reqs=ssl.CERT_REQUIRED, context = ssl._create_stdlib_context(cert_reqs=ssl.CERT_REQUIRED,
@ -146,6 +151,9 @@ def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
capath=capath) capath=capath)
https_handler = HTTPSHandler(context=context, check_hostname=True) https_handler = HTTPSHandler(context=context, check_hostname=True)
opener = build_opener(https_handler) opener = build_opener(https_handler)
elif context:
https_handler = HTTPSHandler(context=context)
opener = build_opener(https_handler)
elif _opener is None: elif _opener is None:
_opener = opener = build_opener() _opener = opener = build_opener()
else: else:

View File

@ -36,6 +36,10 @@ Core and Builtins
Library Library
------- -------
- Issue #22366: urllib.request.urlopen will accept a context object
(SSLContext) as an argument which will then used be for HTTPS connection.
Patch by Alex Gaynor.
- Issue #22776: Brought excluded code into the scope of a try block in - Issue #22776: Brought excluded code into the scope of a try block in
SysLogHandler.emit(). SysLogHandler.emit().