Source code for package_maximizer.parsers

"""Parsers module - Модуль парсеров пакетов."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .apt_parser import APTParser
    from .brew_parser import BrewParser
    from .dnf_parser import DNFParser
    from .extra_parsers import (
        ApkParser,
        CargoParser,
        ChocoParser,
        ComposerParser,
        CondaParser,
        FlatpakParser,
        GemParser,
        NpmParser,
        NuGetParser,
        PipParser,
        PortageParser,
        ScoopParser,
        SnapParser,
        VcpkgParser,
        WingetParser,
        YarnParser,
        YumParser,
        ZypperParser,
    )
    from .pacman_parser import PacmanParser

# Available parsers (names re-exported for typing convenience)
__all__ = [
    "APTParser",
    "PacmanParser",
    "DNFParser",
    "BrewParser",
    "SnapParser",
    "FlatpakParser",
    "CargoParser",
    "NpmParser",
    "CondaParser",
    "PortageParser",
    "ApkParser",
    "ZypperParser",
    "YumParser",
    "PipParser",
    "GemParser",
    "YarnParser",
    "ComposerParser",
    "VcpkgParser",
    "NuGetParser",
    "WingetParser",
    "ScoopParser",
    "ChocoParser",
    "get_parser",
    "PARSER_REGISTRY",
]

# Lazy registry: name -> (module_path, class_name, required_dependency).
_PARSER_SPECS = {
    "apt": (".apt_parser", "APTParser", None),
    "pacman": (".pacman_parser", "PacmanParser", None),
    "dnf": (".dnf_parser", "DNFParser", None),
    "brew": (".brew_parser", "BrewParser", None),
    "snap": (".extra_parsers", "SnapParser", None),
    "flatpak": (".extra_parsers", "FlatpakParser", None),
    "cargo": (".extra_parsers", "CargoParser", None),
    "npm": (".extra_parsers", "NpmParser", None),
    "conda": (".extra_parsers", "CondaParser", None),
    "portage": (".extra_parsers", "PortageParser", None),
    "apk": (".extra_parsers", "ApkParser", None),
    "zypper": (".extra_parsers", "ZypperParser", None),
    "yum": (".extra_parsers", "YumParser", None),
    "pip": (".extra_parsers", "PipParser", None),
    "gem": (".extra_parsers", "GemParser", None),
    "yarn": (".extra_parsers", "YarnParser", None),
    "composer": (".extra_parsers", "ComposerParser", None),
    "vcpkg": (".extra_parsers", "VcpkgParser", None),
    "nuget": (".extra_parsers", "NuGetParser", None),
    "winget": (".extra_parsers", "WingetParser", None),
    "scoop": (".extra_parsers", "ScoopParser", None),
    "choco": (".extra_parsers", "ChocoParser", None),
}

# Public class names importable directly (resolved lazily).
_PUBLIC_PARSER_NAMES = {
    "APTParser": (".apt_parser", "APTParser"),
    "PacmanParser": (".pacman_parser", "PacmanParser"),
    "DNFParser": (".dnf_parser", "DNFParser"),
    "BrewParser": (".brew_parser", "BrewParser"),
    "SnapParser": (".extra_parsers", "SnapParser"),
    "FlatpakParser": (".extra_parsers", "FlatpakParser"),
    "CargoParser": (".extra_parsers", "CargoParser"),
    "NpmParser": (".extra_parsers", "NpmParser"),
    "CondaParser": (".extra_parsers", "CondaParser"),
    "PortageParser": (".extra_parsers", "PortageParser"),
    "ApkParser": (".extra_parsers", "ApkParser"),
    "ZypperParser": (".extra_parsers", "ZypperParser"),
    "YumParser": (".extra_parsers", "YumParser"),
    "PipParser": (".extra_parsers", "PipParser"),
    "GemParser": (".extra_parsers", "GemParser"),
    "YarnParser": (".extra_parsers", "YarnParser"),
    "ComposerParser": (".extra_parsers", "ComposerParser"),
    "VcpkgParser": (".extra_parsers", "VcpkgParser"),
    "NuGetParser": (".extra_parsers", "NuGetParser"),
    "WingetParser": (".extra_parsers", "WingetParser"),
    "ScoopParser": (".extra_parsers", "ScoopParser"),
    "ChocoParser": (".extra_parsers", "ChocoParser"),
}


class _LazyParserRegistry(dict):
    """Dict-like view over ``_PARSER_SPECS`` (lazy import on access)."""

    def __init__(self) -> None:  # type: ignore[no-untyped-def]
        super().__init__({name: None for name in _PARSER_SPECS})

    def __getitem__(self, name: str):  # type: ignore[override]
        if name not in _PARSER_SPECS:
            raise KeyError(name)
        cached = super().__getitem__(name)
        if cached is not None:
            return cached
        module_path, class_name, _ = _PARSER_SPECS[name]
        import importlib

        module = importlib.import_module(module_path, __name__)
        cls = getattr(module, class_name)
        super().__setitem__(name, cls)
        return cls

    def get(self, name: str, default=None):  # type: ignore[override]
        try:
            return self[name]
        except KeyError:
            return default

    def __contains__(self, name: object) -> bool:  # type: ignore[override]
        return name in _PARSER_SPECS

    def keys(self):  # type: ignore[override]
        return _PARSER_SPECS.keys()

    def items(self):  # type: ignore[override]
        return ((name, self[name]) for name in _PARSER_SPECS)

    def values(self):  # type: ignore[override]
        return (self[name] for name in _PARSER_SPECS)

    def __iter__(self):  # type: ignore[override]
        return iter(_PARSER_SPECS)


PARSER_REGISTRY = _LazyParserRegistry()


[docs] def get_parser(parser_name: str): """ Получение экземпляра парсера по имени. Args: parser_name: Имя парсера (регистронезависимое) Returns: Экземпляр парсера Raises: ValueError: Если парсер не найден """ parser_name = parser_name.lower() if parser_name not in PARSER_REGISTRY: available = ", ".join(PARSER_REGISTRY.keys()) raise ValueError(f"Parser '{parser_name}' not found. Available: {available}") return PARSER_REGISTRY[parser_name]()
def __getattr__(name: str): # module-level lazy attribute resolution spec = _PUBLIC_PARSER_NAMES.get(name) if spec is None: raise AttributeError(f"module {__name__!r} has no attribute {name!r}") module_path, class_name = spec import importlib module = importlib.import_module(module_path, __name__) return getattr(module, class_name)