import enum from dataclasses import dataclass from typing import Optional, Set, Dict from pythonapp.Instance.ABS import Instance from pythonapp.Libs.pip_api import pip_api from pythonapp.Decider.Loader import Loader from .misc import * class ConflictSeverity(enum.Enum): FATAL = "Fatal" ERROR = "Error" WARNING = "Warning" @dataclass class ConflictError: """Класс для хранения информации о конфликте зависимостей.""" conflicting_packages: Set[str] sources: Dict[str, str] # package -> source (installed/requested) severity: ConflictSeverity error_message: str resolution_action: str = "" def __post_init__(self): # Автоматически определяем источники, если не предоставлены if not self.sources: self.sources = {pkg: "unknown" for pkg in self.conflicting_packages} class DeciderState(enum.Enum): SUCCESS = 0 WARN = 30 ERROR = 50 FATAL = 100 class Decider: @classmethod def decide(cls, instance: Instance, packages: list[RequirementInfo] | Path, pip_path: str, index_url: Optional[str] = None, extra_index_urls: Optional[list[str]] = None ) -> tuple[list[RequirementInfo], list[ConflictError], DeciderState]: raise NotImplemented @classmethod def load(cls, instance: Instance, packages: list[RequirementInfo] | Path, manual=False): if isinstance(packages, Path): opt, req = requirements_separator(packages) packages = requirements_converter(opt, req) p = instance.path c = instance.config installed = Loader.load_existent_requirements( str(p / c.manual_requirements_path), str(p / c.requirements_dir), str(p / c.pinned_packages_path), str(p / c.excluded_packages_path)) if not manual: packages = Loader.filter_reqs(packages, str(p / c.pinned_packages_path), str(p / c.excluded_packages_path)) installed.extend(packages) return installed, packages class SimpleDecider(Decider): @classmethod def decide(cls, instance: Instance, packages: list[RequirementInfo] | Path, pip_path: str, index_url: Optional[str] = None, extra_index_urls: Optional[list[str]] = None, manual=False) -> tuple[list[RequirementInfo] | None, list[ConflictError], DeciderState]: all_packages, packages = cls.load(instance, packages, manual) result = pip_api.run_pip_install(pip_path, [p.requirement_str for p in all_packages], index_url, extra_index_urls, dry_run=True) if result.exit_code != 0: return None, [], DeciderState.FATAL return packages, [], DeciderState.SUCCESS