diff --git a/homeassistant/requirements.py b/homeassistant/requirements.py index 30c5d0a2448..954de3bf5a6 100644 --- a/homeassistant/requirements.py +++ b/homeassistant/requirements.py @@ -7,7 +7,7 @@ import logging import os from typing import Any, cast -import pkg_resources +from packaging.requirements import Requirement from .core import HomeAssistant, callback from .exceptions import HomeAssistantError @@ -232,8 +232,7 @@ class RequirementsManager: skipped_requirements = [ req for req in requirements - if pkg_resources.Requirement.parse(req).project_name - in self.hass.config.skip_pip_packages + if Requirement(req).name in self.hass.config.skip_pip_packages ] for req in skipped_requirements: diff --git a/homeassistant/util/package.py b/homeassistant/util/package.py index 45ceb471fd8..7de75c1e24f 100644 --- a/homeassistant/util/package.py +++ b/homeassistant/util/package.py @@ -3,7 +3,7 @@ from __future__ import annotations import asyncio from functools import cache -from importlib.metadata import PackageNotFoundError, version +from importlib.metadata import PackageNotFoundError, distribution, version import logging import os from pathlib import Path @@ -11,7 +11,7 @@ from subprocess import PIPE, Popen import sys from urllib.parse import urlparse -import pkg_resources +from packaging.requirements import InvalidRequirement, Requirement _LOGGER = logging.getLogger(__name__) @@ -37,26 +37,27 @@ def is_installed(package: str) -> bool: Returns False when the package is not installed or doesn't meet req. """ try: - pkg_resources.get_distribution(package) + distribution(package) return True - except (IndexError, pkg_resources.ResolutionError, pkg_resources.ExtractionError): - req = pkg_resources.Requirement.parse(package) - except ValueError: - # This is a zip file. We no longer use this in Home Assistant, - # leaving it in for custom components. - req = pkg_resources.Requirement.parse(urlparse(package).fragment) + except (IndexError, PackageNotFoundError): + try: + req = Requirement(package) + except InvalidRequirement: + # This is a zip file. We no longer use this in Home Assistant, + # leaving it in for custom components. + req = Requirement(urlparse(package).fragment) try: - installed_version = version(req.project_name) + installed_version = version(req.name) # This will happen when an install failed or # was aborted while in progress see # https://github.com/home-assistant/core/issues/47699 if installed_version is None: _LOGGER.error( # type: ignore[unreachable] - "Installed version for %s resolved to None", req.project_name + "Installed version for %s resolved to None", req.name ) return False - return installed_version in req + return req.specifier.contains(installed_version, prereleases=True) except PackageNotFoundError: return False diff --git a/tests/util/test_package.py b/tests/util/test_package.py index 2a190d2aea5..ff26cba0dd4 100644 --- a/tests/util/test_package.py +++ b/tests/util/test_package.py @@ -1,12 +1,12 @@ """Test Home Assistant package util methods.""" import asyncio +from importlib.metadata import PackageNotFoundError, metadata import logging import os from subprocess import PIPE import sys from unittest.mock import MagicMock, call, patch -import pkg_resources import pytest import homeassistant.util.package as package @@ -246,9 +246,9 @@ async def test_async_get_user_site(mock_env_copy) -> None: def test_check_package_global() -> None: """Test for an installed package.""" - first_package = list(pkg_resources.working_set)[0] - installed_package = first_package.project_name - installed_version = first_package.version + pkg = metadata("homeassistant") + installed_package = pkg["name"] + installed_version = pkg["version"] assert package.is_installed(installed_package) assert package.is_installed(f"{installed_package}=={installed_version}") @@ -264,13 +264,13 @@ def test_check_package_zip() -> None: def test_get_distribution_falls_back_to_version() -> None: """Test for get_distribution failing and fallback to version.""" - first_package = list(pkg_resources.working_set)[0] - installed_package = first_package.project_name - installed_version = first_package.version + pkg = metadata("homeassistant") + installed_package = pkg["name"] + installed_version = pkg["version"] with patch( - "homeassistant.util.package.pkg_resources.get_distribution", - side_effect=pkg_resources.ExtractionError, + "homeassistant.util.package.distribution", + side_effect=PackageNotFoundError, ): assert package.is_installed(installed_package) assert package.is_installed(f"{installed_package}=={installed_version}") @@ -281,13 +281,13 @@ def test_get_distribution_falls_back_to_version() -> None: def test_check_package_previous_failed_install() -> None: """Test for when a previously install package failed and left cruft behind.""" - first_package = list(pkg_resources.working_set)[0] - installed_package = first_package.project_name - installed_version = first_package.version + pkg = metadata("homeassistant") + installed_package = pkg["name"] + installed_version = pkg["version"] with patch( - "homeassistant.util.package.pkg_resources.get_distribution", - side_effect=pkg_resources.ExtractionError, + "homeassistant.util.package.distribution", + side_effect=PackageNotFoundError, ), patch("homeassistant.util.package.version", return_value=None): assert not package.is_installed(installed_package) assert not package.is_installed(f"{installed_package}=={installed_version}")