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:
parent
dc004795f0
commit
bb2a3d7410
1
news/10825.removal.rst
Normal file
1
news/10825.removal.rst
Normal file
|
@ -0,0 +1 @@
|
|||
Remove the ``html5lib`` deprecated feature flag.
|
|
@ -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."),
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue