Skip to content

Commit 4d77197

Browse files
authored
GH-84850: Remove urllib.request.URLopener and FancyURLopener (#125739)
1 parent a99dd23 commit 4d77197

File tree

7 files changed

+44
-987
lines changed

7 files changed

+44
-987
lines changed

Doc/deprecations/pending-removal-in-future.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,6 @@ although there is currently no date scheduled for their removal.
145145
* ``splitvalue()``
146146
* ``to_bytes()``
147147

148-
* :mod:`urllib.request`: :class:`~urllib.request.URLopener` and
149-
:class:`~urllib.request.FancyURLopener` style of invoking requests is
150-
deprecated. Use newer :func:`~urllib.request.urlopen` functions and methods.
151-
152148
* :mod:`wsgiref`: ``SimpleHandler.stdout.write()`` should not do partial
153149
writes.
154150

Doc/library/urllib.request.rst

Lines changed: 4 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ The :mod:`urllib.request` module defines the following functions:
6767
the response headers as it is specified in the documentation for
6868
:class:`~http.client.HTTPResponse`.
6969

70-
For FTP, file, and data URLs and requests explicitly handled by legacy
71-
:class:`URLopener` and :class:`FancyURLopener` classes, this function
70+
For FTP, file, and data URLs, this function
7271
returns a :class:`urllib.response.addinfourl` object.
7372

7473
Raises :exc:`~urllib.error.URLError` on protocol errors.
@@ -1339,15 +1338,15 @@ environment settings::
13391338

13401339
>>> import urllib.request
13411340
>>> proxies = {'http': 'http://proxy.example.com:8080/'}
1342-
>>> opener = urllib.request.FancyURLopener(proxies)
1341+
>>> opener = urllib.request.build_opener(urllib.request.ProxyHandler(proxies))
13431342
>>> with opener.open("http://www.python.org") as f:
13441343
... f.read().decode('utf-8')
13451344
...
13461345

13471346
The following example uses no proxies at all, overriding environment settings::
13481347

13491348
>>> import urllib.request
1350-
>>> opener = urllib.request.FancyURLopener({})
1349+
>>> opener = urllib.request.build_opener(urllib.request.ProxyHandler({}}))
13511350
>>> with opener.open("http://www.python.org/") as f:
13521351
... f.read().decode('utf-8')
13531352
...
@@ -1412,121 +1411,6 @@ some point in the future.
14121411
Cleans up temporary files that may have been left behind by previous
14131412
calls to :func:`urlretrieve`.
14141413

1415-
.. class:: URLopener(proxies=None, **x509)
1416-
1417-
.. deprecated:: 3.3
1418-
1419-
Base class for opening and reading URLs. Unless you need to support opening
1420-
objects using schemes other than :file:`http:`, :file:`ftp:`, or :file:`file:`,
1421-
you probably want to use :class:`FancyURLopener`.
1422-
1423-
By default, the :class:`URLopener` class sends a :mailheader:`User-Agent` header
1424-
of ``urllib/VVV``, where *VVV* is the :mod:`urllib` version number.
1425-
Applications can define their own :mailheader:`User-Agent` header by subclassing
1426-
:class:`URLopener` or :class:`FancyURLopener` and setting the class attribute
1427-
:attr:`version` to an appropriate string value in the subclass definition.
1428-
1429-
The optional *proxies* parameter should be a dictionary mapping scheme names to
1430-
proxy URLs, where an empty dictionary turns proxies off completely. Its default
1431-
value is ``None``, in which case environmental proxy settings will be used if
1432-
present, as discussed in the definition of :func:`urlopen`, above.
1433-
1434-
Additional keyword parameters, collected in *x509*, may be used for
1435-
authentication of the client when using the :file:`https:` scheme. The keywords
1436-
*key_file* and *cert_file* are supported to provide an SSL key and certificate;
1437-
both are needed to support client authentication.
1438-
1439-
:class:`URLopener` objects will raise an :exc:`OSError` exception if the server
1440-
returns an error code.
1441-
1442-
.. method:: open(fullurl, data=None)
1443-
1444-
Open *fullurl* using the appropriate protocol. This method sets up cache and
1445-
proxy information, then calls the appropriate open method with its input
1446-
arguments. If the scheme is not recognized, :meth:`open_unknown` is called.
1447-
The *data* argument has the same meaning as the *data* argument of
1448-
:func:`urlopen`.
1449-
1450-
This method always quotes *fullurl* using :func:`~urllib.parse.quote`.
1451-
1452-
.. method:: open_unknown(fullurl, data=None)
1453-
1454-
Overridable interface to open unknown URL types.
1455-
1456-
1457-
.. method:: retrieve(url, filename=None, reporthook=None, data=None)
1458-
1459-
Retrieves the contents of *url* and places it in *filename*. The return value
1460-
is a tuple consisting of a local filename and either an
1461-
:class:`email.message.Message` object containing the response headers (for remote
1462-
URLs) or ``None`` (for local URLs). The caller must then open and read the
1463-
contents of *filename*. If *filename* is not given and the URL refers to a
1464-
local file, the input filename is returned. If the URL is non-local and
1465-
*filename* is not given, the filename is the output of :func:`tempfile.mktemp`
1466-
with a suffix that matches the suffix of the last path component of the input
1467-
URL. If *reporthook* is given, it must be a function accepting three numeric
1468-
parameters: A chunk number, the maximum size chunks are read in and the total size of the download
1469-
(-1 if unknown). It will be called once at the start and after each chunk of data is read from the
1470-
network. *reporthook* is ignored for local URLs.
1471-
1472-
If the *url* uses the :file:`http:` scheme identifier, the optional *data*
1473-
argument may be given to specify a ``POST`` request (normally the request type
1474-
is ``GET``). The *data* argument must in standard
1475-
:mimetype:`application/x-www-form-urlencoded` format; see the
1476-
:func:`urllib.parse.urlencode` function.
1477-
1478-
1479-
.. attribute:: version
1480-
1481-
Variable that specifies the user agent of the opener object. To get
1482-
:mod:`urllib` to tell servers that it is a particular user agent, set this in a
1483-
subclass as a class variable or in the constructor before calling the base
1484-
constructor.
1485-
1486-
1487-
.. class:: FancyURLopener(...)
1488-
1489-
.. deprecated:: 3.3
1490-
1491-
:class:`FancyURLopener` subclasses :class:`URLopener` providing default handling
1492-
for the following HTTP response codes: 301, 302, 303, 307 and 401. For the 30x
1493-
response codes listed above, the :mailheader:`Location` header is used to fetch
1494-
the actual URL. For 401 response codes (authentication required), basic HTTP
1495-
authentication is performed. For the 30x response codes, recursion is bounded
1496-
by the value of the *maxtries* attribute, which defaults to 10.
1497-
1498-
For all other response codes, the method :meth:`~BaseHandler.http_error_default` is called
1499-
which you can override in subclasses to handle the error appropriately.
1500-
1501-
.. note::
1502-
1503-
According to the letter of :rfc:`2616`, 301 and 302 responses to POST requests
1504-
must not be automatically redirected without confirmation by the user. In
1505-
reality, browsers do allow automatic redirection of these responses, changing
1506-
the POST to a GET, and :mod:`urllib` reproduces this behaviour.
1507-
1508-
The parameters to the constructor are the same as those for :class:`URLopener`.
1509-
1510-
.. note::
1511-
1512-
When performing basic authentication, a :class:`FancyURLopener` instance calls
1513-
its :meth:`prompt_user_passwd` method. The default implementation asks the
1514-
users for the required information on the controlling terminal. A subclass may
1515-
override this method to support more appropriate behavior if needed.
1516-
1517-
The :class:`FancyURLopener` class offers one additional method that should be
1518-
overloaded to provide the appropriate behavior:
1519-
1520-
.. method:: prompt_user_passwd(host, realm)
1521-
1522-
Return information needed to authenticate the user at the given host in the
1523-
specified security realm. The return value should be a tuple, ``(user,
1524-
password)``, which can be used for basic authentication.
1525-
1526-
The implementation prompts for this information on the terminal; an application
1527-
should override this method to use an appropriate interaction model in the local
1528-
environment.
1529-
15301414

15311415
:mod:`urllib.request` Restrictions
15321416
----------------------------------
@@ -1578,8 +1462,7 @@ some point in the future.
15781462
you try to fetch a file whose read permissions make it inaccessible; the FTP
15791463
code will try to read it, fail with a 550 error, and then perform a directory
15801464
listing for the unreadable file. If fine-grained control is needed, consider
1581-
using the :mod:`ftplib` module, subclassing :class:`FancyURLopener`, or changing
1582-
*_urlopener* to meet your needs.
1465+
using the :mod:`ftplib` module.
15831466

15841467

15851468

Doc/whatsnew/3.14.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,10 @@ urllib
769769
* Remove deprecated :class:`!Quoter` class from :mod:`urllib.parse`.
770770
It had previously raised a :exc:`DeprecationWarning` since Python 3.11.
771771
(Contributed by Nikita Sobolev in :gh:`118827`.)
772+
* Remove deprecated :class:`!URLopener` and :class:`!FancyURLopener` classes
773+
from :mod:`urllib.request`. They had previously raised a
774+
:exc:`DeprecationWarning` since Python 3.3.
775+
(Contributed by Barney Gale in :gh:`84850`.)
772776

773777
Others
774778
------

0 commit comments

Comments
 (0)