Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-84850: Remove urllib.request.URLopener and FancyURLopener #125739

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Doc/deprecations/pending-removal-in-future.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,6 @@ although there is currently no date scheduled for their removal.
* ``splitvalue()``
* ``to_bytes()``

* :mod:`urllib.request`: :class:`~urllib.request.URLopener` and
:class:`~urllib.request.FancyURLopener` style of invoking requests is
deprecated. Use newer :func:`~urllib.request.urlopen` functions and methods.

* :mod:`wsgiref`: ``SimpleHandler.stdout.write()`` should not do partial
writes.

Expand Down
125 changes: 4 additions & 121 deletions Doc/library/urllib.request.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ The :mod:`urllib.request` module defines the following functions:
the response headers as it is specified in the documentation for
:class:`~http.client.HTTPResponse`.

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

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

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

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

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

.. class:: URLopener(proxies=None, **x509)

.. deprecated:: 3.3

Base class for opening and reading URLs. Unless you need to support opening
objects using schemes other than :file:`http:`, :file:`ftp:`, or :file:`file:`,
you probably want to use :class:`FancyURLopener`.

By default, the :class:`URLopener` class sends a :mailheader:`User-Agent` header
of ``urllib/VVV``, where *VVV* is the :mod:`urllib` version number.
Applications can define their own :mailheader:`User-Agent` header by subclassing
:class:`URLopener` or :class:`FancyURLopener` and setting the class attribute
:attr:`version` to an appropriate string value in the subclass definition.

The optional *proxies* parameter should be a dictionary mapping scheme names to
proxy URLs, where an empty dictionary turns proxies off completely. Its default
value is ``None``, in which case environmental proxy settings will be used if
present, as discussed in the definition of :func:`urlopen`, above.

Additional keyword parameters, collected in *x509*, may be used for
authentication of the client when using the :file:`https:` scheme. The keywords
*key_file* and *cert_file* are supported to provide an SSL key and certificate;
both are needed to support client authentication.

:class:`URLopener` objects will raise an :exc:`OSError` exception if the server
returns an error code.

.. method:: open(fullurl, data=None)

Open *fullurl* using the appropriate protocol. This method sets up cache and
proxy information, then calls the appropriate open method with its input
arguments. If the scheme is not recognized, :meth:`open_unknown` is called.
The *data* argument has the same meaning as the *data* argument of
:func:`urlopen`.

This method always quotes *fullurl* using :func:`~urllib.parse.quote`.

.. method:: open_unknown(fullurl, data=None)

Overridable interface to open unknown URL types.


.. method:: retrieve(url, filename=None, reporthook=None, data=None)

Retrieves the contents of *url* and places it in *filename*. The return value
is a tuple consisting of a local filename and either an
:class:`email.message.Message` object containing the response headers (for remote
URLs) or ``None`` (for local URLs). The caller must then open and read the
contents of *filename*. If *filename* is not given and the URL refers to a
local file, the input filename is returned. If the URL is non-local and
*filename* is not given, the filename is the output of :func:`tempfile.mktemp`
with a suffix that matches the suffix of the last path component of the input
URL. If *reporthook* is given, it must be a function accepting three numeric
parameters: A chunk number, the maximum size chunks are read in and the total size of the download
(-1 if unknown). It will be called once at the start and after each chunk of data is read from the
network. *reporthook* is ignored for local URLs.

If the *url* uses the :file:`http:` scheme identifier, the optional *data*
argument may be given to specify a ``POST`` request (normally the request type
is ``GET``). The *data* argument must in standard
:mimetype:`application/x-www-form-urlencoded` format; see the
:func:`urllib.parse.urlencode` function.


.. attribute:: version

Variable that specifies the user agent of the opener object. To get
:mod:`urllib` to tell servers that it is a particular user agent, set this in a
subclass as a class variable or in the constructor before calling the base
constructor.


.. class:: FancyURLopener(...)

.. deprecated:: 3.3

:class:`FancyURLopener` subclasses :class:`URLopener` providing default handling
for the following HTTP response codes: 301, 302, 303, 307 and 401. For the 30x
response codes listed above, the :mailheader:`Location` header is used to fetch
the actual URL. For 401 response codes (authentication required), basic HTTP
authentication is performed. For the 30x response codes, recursion is bounded
by the value of the *maxtries* attribute, which defaults to 10.

For all other response codes, the method :meth:`~BaseHandler.http_error_default` is called
which you can override in subclasses to handle the error appropriately.

.. note::

According to the letter of :rfc:`2616`, 301 and 302 responses to POST requests
must not be automatically redirected without confirmation by the user. In
reality, browsers do allow automatic redirection of these responses, changing
the POST to a GET, and :mod:`urllib` reproduces this behaviour.

The parameters to the constructor are the same as those for :class:`URLopener`.

.. note::

When performing basic authentication, a :class:`FancyURLopener` instance calls
its :meth:`prompt_user_passwd` method. The default implementation asks the
users for the required information on the controlling terminal. A subclass may
override this method to support more appropriate behavior if needed.

The :class:`FancyURLopener` class offers one additional method that should be
overloaded to provide the appropriate behavior:

.. method:: prompt_user_passwd(host, realm)

Return information needed to authenticate the user at the given host in the
specified security realm. The return value should be a tuple, ``(user,
password)``, which can be used for basic authentication.

The implementation prompts for this information on the terminal; an application
should override this method to use an appropriate interaction model in the local
environment.


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



Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,10 @@ urllib
* Remove deprecated :class:`!Quoter` class from :mod:`urllib.parse`.
It had previously raised a :exc:`DeprecationWarning` since Python 3.11.
(Contributed by Nikita Sobolev in :gh:`118827`.)
* Remove deprecated :class:`!URLopener` and :class:`!FancyURLopener` classes
from :mod:`urllib.request`. They had previously raised a
:exc:`DeprecationWarning` since Python 3.3.
(Contributed by Barney Gale in :gh:`84850`.)

Others
------
Expand Down
Loading
Loading