Files
vaiola/pythonapp/Decider/ABS.py
Bacruru Sakaguchi 9e5e214944 initial commit
2025-09-12 17:10:13 +07:00

79 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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