1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Remove the html5lib deprecated feature flag.

This commit is contained in:
Stéphane Bidoul 2022-07-14 18:15:07 +02:00
parent dc004795f0
commit bb2a3d7410
No known key found for this signature in database
GPG key ID: BCAB2555446B5B92
14 changed files with 21 additions and 151 deletions

1
news/10825.removal.rst Normal file
View file

@ -0,0 +1 @@
Remove the ``html5lib`` deprecated feature flag.

View file

@ -1013,7 +1013,6 @@ use_deprecated_feature: Callable[..., Option] = partial(
default=[],
choices=[
"legacy-resolver",
"html5lib",
],
help=("Enable deprecated functionality, that will be removed in the future."),
)

View file

@ -499,5 +499,4 @@ class RequirementCommand(IndexGroupCommand):
link_collector=link_collector,
selection_prefs=selection_prefs,
target_python=target_python,
use_deprecated_html5lib="html5lib" in options.deprecated_features_enabled,
)

View file

@ -97,7 +97,6 @@ class IndexCommand(IndexGroupCommand):
link_collector=link_collector,
selection_prefs=selection_prefs,
target_python=target_python,
use_deprecated_html5lib="html5lib" in options.deprecated_features_enabled,
)
def get_available_package_versions(self, options: Values, args: List[Any]) -> None:

View file

@ -149,7 +149,6 @@ class ListCommand(IndexGroupCommand):
return PackageFinder.create(
link_collector=link_collector,
selection_prefs=selection_prefs,
use_deprecated_html5lib="html5lib" in options.deprecated_features_enabled,
)
def run(self, options: Values, args: List[str]) -> int:

View file

@ -29,7 +29,7 @@ from typing import (
Union,
)
from pip._vendor import html5lib, requests
from pip._vendor import requests
from pip._vendor.requests import Response
from pip._vendor.requests.exceptions import RetryError, SSLError
@ -191,27 +191,6 @@ def _get_encoding_from_headers(headers: ResponseHeaders) -> Optional[str]:
return None
def _determine_base_url(document: HTMLElement, page_url: str) -> str:
"""Determine the HTML document's base URL.
This looks for a ``<base>`` tag in the HTML document. If present, its href
attribute denotes the base URL of anchor tags in the document. If there is
no such tag (or if it does not have a valid href attribute), the HTML
file's URL is used as the base URL.
:param document: An HTML document representation. The current
implementation expects the result of ``html5lib.parse()``.
:param page_url: The URL of the HTML document.
TODO: Remove when `html5lib` is dropped.
"""
for base in document.findall(".//base"):
href = base.get("href")
if href is not None:
return href
return page_url
def _clean_url_path_part(part: str) -> str:
"""
Clean a "part" of a URL path (i.e. after splitting on "@" characters).
@ -313,9 +292,7 @@ class CacheablePageContent:
class ParseLinks(Protocol):
def __call__(
self, page: "IndexContent", use_deprecated_html5lib: bool
) -> Iterable[Link]:
def __call__(self, page: "IndexContent") -> Iterable[Link]:
...
@ -327,49 +304,20 @@ def with_cached_index_content(fn: ParseLinks) -> ParseLinks:
"""
@functools.lru_cache(maxsize=None)
def wrapper(
cacheable_page: CacheablePageContent, use_deprecated_html5lib: bool
) -> List[Link]:
return list(fn(cacheable_page.page, use_deprecated_html5lib))
def wrapper(cacheable_page: CacheablePageContent) -> List[Link]:
return list(fn(cacheable_page.page))
@functools.wraps(fn)
def wrapper_wrapper(
page: "IndexContent", use_deprecated_html5lib: bool
) -> List[Link]:
def wrapper_wrapper(page: "IndexContent") -> List[Link]:
if page.cache_link_parsing:
return wrapper(CacheablePageContent(page), use_deprecated_html5lib)
return list(fn(page, use_deprecated_html5lib))
return wrapper(CacheablePageContent(page))
return list(fn(page))
return wrapper_wrapper
def _parse_links_html5lib(page: "IndexContent") -> Iterable[Link]:
"""
Parse an HTML document, and yield its anchor elements as Link objects.
TODO: Remove when `html5lib` is dropped.
"""
document = html5lib.parse(
page.content,
transport_encoding=page.encoding,
namespaceHTMLElements=False,
)
url = page.url
base_url = _determine_base_url(document, url)
for anchor in document.findall(".//a"):
link = _create_link_from_element(
anchor.attrib,
page_url=url,
base_url=base_url,
)
if link is None:
continue
yield link
@with_cached_index_content
def parse_links(page: "IndexContent", use_deprecated_html5lib: bool) -> Iterable[Link]:
def parse_links(page: "IndexContent") -> Iterable[Link]:
"""
Parse a Simple API's Index Content, and yield its anchor elements as Link objects.
"""
@ -398,10 +346,6 @@ def parse_links(page: "IndexContent", use_deprecated_html5lib: bool) -> Iterable
hashes=file.get("hashes", {}),
)
if use_deprecated_html5lib:
yield from _parse_links_html5lib(page)
return
parser = HTMLLinkParser(page.url)
encoding = page.encoding or "utf-8"
parser.feed(page.content.decode(encoding))

View file

@ -598,7 +598,6 @@ class PackageFinder:
link_collector: LinkCollector,
target_python: TargetPython,
allow_yanked: bool,
use_deprecated_html5lib: bool,
format_control: Optional[FormatControl] = None,
candidate_prefs: Optional[CandidatePreferences] = None,
ignore_requires_python: Optional[bool] = None,
@ -623,7 +622,6 @@ class PackageFinder:
self._ignore_requires_python = ignore_requires_python
self._link_collector = link_collector
self._target_python = target_python
self._use_deprecated_html5lib = use_deprecated_html5lib
self.format_control = format_control
@ -640,8 +638,6 @@ class PackageFinder:
link_collector: LinkCollector,
selection_prefs: SelectionPreferences,
target_python: Optional[TargetPython] = None,
*,
use_deprecated_html5lib: bool,
) -> "PackageFinder":
"""Create a PackageFinder.
@ -666,7 +662,6 @@ class PackageFinder:
allow_yanked=selection_prefs.allow_yanked,
format_control=selection_prefs.format_control,
ignore_requires_python=selection_prefs.ignore_requires_python,
use_deprecated_html5lib=use_deprecated_html5lib,
)
@property
@ -796,7 +791,7 @@ class PackageFinder:
if index_response is None:
return []
page_links = list(parse_links(index_response, self._use_deprecated_html5lib))
page_links = list(parse_links(index_response))
with indent_log():
package_links = self.evaluate_links(

View file

@ -173,7 +173,6 @@ def _get_current_remote_pip_version(
finder = PackageFinder.create(
link_collector=link_collector,
selection_prefs=selection_prefs,
use_deprecated_html5lib=("html5lib" in options.deprecated_features_enabled),
)
best_candidate = finder.find_best_candidate("pip").best_candidate
if best_candidate is None:

View file

@ -49,7 +49,6 @@ def run_with_build_env(
finder = PackageFinder.create(
link_collector=link_collector,
selection_prefs=selection_prefs,
use_deprecated_html5lib=False,
)
with global_tempdir_manager():

View file

@ -115,7 +115,6 @@ def make_test_finder(
allow_all_prereleases: bool = False,
session: Optional[PipSession] = None,
target_python: Optional[TargetPython] = None,
use_deprecated_html5lib: bool = False,
) -> PackageFinder:
"""
Create a PackageFinder for testing purposes.
@ -134,7 +133,6 @@ def make_test_finder(
link_collector=link_collector,
selection_prefs=selection_prefs,
target_python=target_python,
use_deprecated_html5lib=use_deprecated_html5lib,
)

View file

@ -26,7 +26,7 @@ def finder(data: TestData) -> Iterator[PackageFinder]:
scope = SearchScope([str(data.packages)], [])
collector = LinkCollector(session, scope)
prefs = SelectionPreferences(allow_yanked=False)
finder = PackageFinder.create(collector, prefs, use_deprecated_html5lib=False)
finder = PackageFinder.create(collector, prefs)
yield finder

View file

@ -10,7 +10,7 @@ from typing import List, Optional, Tuple
from unittest import mock
import pytest
from pip._vendor import html5lib, requests
from pip._vendor import requests
from pip._internal.exceptions import NetworkConnectionError
from pip._internal.index.collector import (
@ -18,7 +18,6 @@ from pip._internal.index.collector import (
LinkCollector,
_clean_link,
_clean_url_path,
_determine_base_url,
_get_index_content,
_get_simple_response,
_make_index_content,
@ -249,33 +248,6 @@ def test_get_simple_response_dont_log_clear_text_password(
]
@pytest.mark.parametrize(
("html", "url", "expected"),
[
(b"<html></html>", "https://example.com/", "https://example.com/"),
(
b'<html><head><base href="https://foo.example.com/"></head></html>',
"https://example.com/",
"https://foo.example.com/",
),
(
b"<html><head>"
b'<base><base href="https://foo.example.com/">'
b"</head></html>",
"https://example.com/",
"https://foo.example.com/",
),
],
)
def test_determine_base_url(html: bytes, url: str, expected: str) -> None:
document = html5lib.parse(
html,
transport_encoding=None,
namespaceHTMLElements=False,
)
assert _determine_base_url(document, url) == expected
@pytest.mark.parametrize(
("path", "expected"),
[
@ -451,7 +423,7 @@ def _test_parse_links_data_attribute(
# the page content isn't cached.
url=f"https://example.com/simple-{uuid.uuid4()}/",
)
links = list(parse_links(page, use_deprecated_html5lib=False))
links = list(parse_links(page))
(link,) = links
actual = getattr(link, attr)
assert actual == expected
@ -513,7 +485,7 @@ def test_parse_links_json() -> None:
# the page content isn't cached.
url=f"https://example.com/simple-{uuid.uuid4()}/",
)
links = list(parse_links(page, use_deprecated_html5lib=False))
links = list(parse_links(page))
assert links == [
Link(
@ -597,33 +569,19 @@ def test_parse_links_caches_same_page_by_url() -> None:
cache_link_parsing=False,
)
parsed_links_1 = list(parse_links(page_1, use_deprecated_html5lib=False))
parsed_links_1 = list(parse_links(page_1))
assert len(parsed_links_1) == 1
assert "pkg1" in parsed_links_1[0].url
parsed_links_2 = list(parse_links(page_2, use_deprecated_html5lib=False))
parsed_links_2 = list(parse_links(page_2))
assert parsed_links_2 == parsed_links_1
parsed_links_3 = list(parse_links(page_3, use_deprecated_html5lib=False))
parsed_links_3 = list(parse_links(page_3))
assert len(parsed_links_3) == 1
assert parsed_links_3 != parsed_links_1
assert "pkg2" in parsed_links_3[0].url
def test_parse_link_handles_deprecated_usage_properly() -> None:
html = b'<a href="/pkg1-1.0.tar.gz"></a><a href="/pkg1-2.0.tar.gz"></a>'
url = "https://example.com/simple/"
page = IndexContent(
html, "text/html", encoding=None, url=url, cache_link_parsing=False
)
parsed_links = list(parse_links(page, use_deprecated_html5lib=True))
assert len(parsed_links) == 2
assert "pkg1-1.0" in parsed_links[0].url
assert "pkg1-2.0" in parsed_links[1].url
@mock.patch("pip._internal.index.collector.raise_for_status")
def test_request_http_error(
mock_raise_for_status: mock.Mock, caplog: pytest.LogCaptureFixture

View file

@ -80,10 +80,7 @@ def test_incorrect_case_file_index(data: TestData) -> None:
@pytest.mark.network
@pytest.mark.parametrize("use_deprecated_html5lib", [False, True])
def test_finder_detects_latest_already_satisfied_find_links(
data: TestData, use_deprecated_html5lib: bool
) -> None:
def test_finder_detects_latest_already_satisfied_find_links(data: TestData) -> None:
"""Test PackageFinder detects latest already satisfied using find-links"""
req = install_req_from_line("simple", None)
# the latest simple in local pkgs is 3.0
@ -93,19 +90,14 @@ def test_finder_detects_latest_already_satisfied_find_links(
version=parse_version(latest_version),
)
req.satisfied_by = satisfied_by
finder = make_test_finder(
find_links=[data.find_links], use_deprecated_html5lib=use_deprecated_html5lib
)
finder = make_test_finder(find_links=[data.find_links])
with pytest.raises(BestVersionAlreadyInstalled):
finder.find_requirement(req, True)
@pytest.mark.network
@pytest.mark.parametrize("use_deprecated_html5lib", [False, True])
def test_finder_detects_latest_already_satisfied_pypi_links(
use_deprecated_html5lib: bool,
) -> None:
def test_finder_detects_latest_already_satisfied_pypi_links() -> None:
"""Test PackageFinder detects latest already satisfied using pypi links"""
req = install_req_from_line("initools", None)
# the latest initools on PyPI is 0.3.1
@ -115,10 +107,7 @@ def test_finder_detects_latest_already_satisfied_pypi_links(
version=parse_version(latest_version),
)
req.satisfied_by = satisfied_by
finder = make_test_finder(
index_urls=["http://pypi.org/simple/"],
use_deprecated_html5lib=use_deprecated_html5lib,
)
finder = make_test_finder(index_urls=["http://pypi.org/simple/"])
with pytest.raises(BestVersionAlreadyInstalled):
finder.find_requirement(req, True)

View file

@ -603,7 +603,6 @@ class TestPackageFinder:
finder = PackageFinder.create(
link_collector=link_collector,
selection_prefs=selection_prefs,
use_deprecated_html5lib=False,
)
candidate_prefs = finder._candidate_prefs
assert candidate_prefs.allow_all_prereleases == allow_all_prereleases
@ -620,7 +619,6 @@ class TestPackageFinder:
finder = PackageFinder.create(
link_collector=link_collector,
selection_prefs=SelectionPreferences(allow_yanked=True),
use_deprecated_html5lib=False,
)
assert finder._link_collector is link_collector
@ -638,7 +636,6 @@ class TestPackageFinder:
link_collector=link_collector,
selection_prefs=SelectionPreferences(allow_yanked=True),
target_python=target_python,
use_deprecated_html5lib=False,
)
actual_target_python = finder._target_python
# The target_python attribute should be set as is.
@ -658,7 +655,6 @@ class TestPackageFinder:
link_collector=link_collector,
selection_prefs=SelectionPreferences(allow_yanked=True),
target_python=None,
use_deprecated_html5lib=False,
)
# Spot-check the default TargetPython object.
actual_target_python = finder._target_python
@ -678,7 +674,6 @@ class TestPackageFinder:
finder = PackageFinder.create(
link_collector=link_collector,
selection_prefs=selection_prefs,
use_deprecated_html5lib=False,
)
assert finder._allow_yanked == allow_yanked
@ -698,7 +693,6 @@ class TestPackageFinder:
finder = PackageFinder.create(
link_collector=link_collector,
selection_prefs=selection_prefs,
use_deprecated_html5lib=False,
)
assert finder._ignore_requires_python == ignore_requires_python
@ -718,7 +712,6 @@ class TestPackageFinder:
finder = PackageFinder.create(
link_collector=link_collector,
selection_prefs=selection_prefs,
use_deprecated_html5lib=False,
)
actual_format_control = finder.format_control
assert actual_format_control is format_control
@ -759,7 +752,6 @@ class TestPackageFinder:
allow_yanked=allow_yanked,
format_control=format_control,
ignore_requires_python=ignore_requires_python,
use_deprecated_html5lib=False,
)
# Pass a project_name that will be different from canonical_name.
@ -808,7 +800,6 @@ class TestPackageFinder:
target_python=target_python,
allow_yanked=True,
candidate_prefs=candidate_prefs,
use_deprecated_html5lib=False,
)
specifier = SpecifierSet()