|
13 | 13 | import aioshutil |
14 | 14 | import httpx |
15 | 15 | from anyio import Path as AsyncPath |
| 16 | +from packaging.requirements import Requirement |
16 | 17 | from packaging.specifiers import SpecifierSet, InvalidSpecifier |
17 | 18 | from packaging.version import Version, InvalidVersion |
18 | | -from pkg_resources import Requirement, working_set |
| 19 | +from importlib.metadata import distributions |
19 | 20 | from requests import Response |
20 | 21 |
|
21 | 22 | from app.core.cache import cached |
@@ -729,18 +730,26 @@ def install_dependencies(self, dependencies: List[str]) -> Tuple[bool, str]: |
729 | 730 | def __get_installed_packages(self) -> Dict[str, Version]: |
730 | 731 | """ |
731 | 732 | 获取已安装的包及其版本 |
732 | | - 使用 pkg_resources 获取当前环境中已安装的包,标准化包名并转换版本信息 |
| 733 | + 使用 importlib.metadata 获取当前环境中已安装的包,标准化包名并转换版本信息 |
733 | 734 | 对于无法解析的版本,记录警告日志并跳过 |
734 | 735 | :return: 已安装包的字典,格式为 {package_name: Version} |
735 | 736 | """ |
736 | 737 | installed_packages = {} |
737 | 738 | try: |
738 | | - for dist in working_set: |
739 | | - pkg_name = self.__standardize_pkg_name(dist.project_name) |
| 739 | + for dist in distributions(): |
| 740 | + name = dist.metadata.get("Name") |
| 741 | + if not name: |
| 742 | + continue |
| 743 | + pkg_name = self.__standardize_pkg_name(name) |
| 744 | + version_str = dist.metadata.get("Version") or getattr(dist, "version", None) |
| 745 | + if not version_str: |
| 746 | + continue |
740 | 747 | try: |
741 | | - installed_packages[pkg_name] = Version(dist.version) |
| 748 | + v = Version(version_str) |
| 749 | + if pkg_name not in installed_packages or v > installed_packages[pkg_name]: |
| 750 | + installed_packages[pkg_name] = v |
742 | 751 | except InvalidVersion: |
743 | | - logger.debug(f"无法解析已安装包 '{pkg_name}' 的版本:{dist.version}") |
| 752 | + logger.debug(f"无法解析已安装包 '{pkg_name}' 的版本:{version_str}") |
744 | 753 | continue |
745 | 754 | return installed_packages |
746 | 755 | except Exception as e: |
@@ -844,12 +853,14 @@ def __merge_dependencies(dependencies: Dict[str, Set[str]]) -> Dict[str, str]: |
844 | 853 | @staticmethod |
845 | 854 | def __standardize_pkg_name(name: str) -> str: |
846 | 855 | """ |
847 | | - 标准化包名,将包名转换为小写并将连字符替换为下划线 |
| 856 | + 标准化包名,将包名转换为小写,连字符与点替换为下划线(与 PEP 503 归一化风格一致) |
848 | 857 |
|
849 | 858 | :param name: 原始包名 |
850 | 859 | :return: 标准化后的包名 |
851 | 860 | """ |
852 | | - return name.lower().replace("-", "_") if name else name |
| 861 | + if not name: |
| 862 | + return name |
| 863 | + return name.lower().replace("-", "_").replace(".", "_") |
853 | 864 |
|
854 | 865 | async def async_get_plugin_package_version(self, pid: str, repo_url: str, |
855 | 866 | package_version: Optional[str] = None) -> Optional[str]: |
|
0 commit comments