добавила цветной вывод (ANSI-коды)

This commit is contained in:
2026-04-28 09:14:02 +03:00
parent 6f66a98f31
commit e905a19a4a
3 changed files with 64 additions and 46 deletions

View File

@@ -1,22 +1,15 @@
# mypkg/cli/main.py # mypkg/cli/main.py
#!/usr/bin/env python3
import argparse import argparse
import sys import sys
from ..core.package_manager import PackageManager from ..core.package_manager import PackageManager
from ..utils.colors import print_info, print_package
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="My Package Manager - простой менеджер пакетов для Linux", description="My Package Manager - менеджер пакетов для Linux"
epilog="""
Примеры:
mypkg install nano Установить пакет nano
mypkg list Показать установленные пакеты
mypkg --sandbox /tmp/test install nano Установить в песочницу
"""
) )
# Глобальный аргумент --sandbox (может быть указан в любом месте)
parser.add_argument('--sandbox', type=str, default=None, parser.add_argument('--sandbox', type=str, default=None,
help='Режим песочницы: установка в изолированную директорию') help='Режим песочницы: установка в изолированную директорию')
parser.add_argument('--repo', default='repo', parser.add_argument('--repo', default='repo',
@@ -24,11 +17,9 @@ def main():
subparsers = parser.add_subparsers(dest='command', help='Команды') subparsers = parser.add_subparsers(dest='command', help='Команды')
# команда install
install_parser = subparsers.add_parser('install', help='Установить пакет') install_parser = subparsers.add_parser('install', help='Установить пакет')
install_parser.add_argument('package', help='Имя пакета') install_parser.add_argument('package', help='Имя пакета')
# команда list
list_parser = subparsers.add_parser('list', help='Список установленных пакетов') list_parser = subparsers.add_parser('list', help='Список установленных пакетов')
args = parser.parse_args() args = parser.parse_args()
@@ -37,21 +28,16 @@ def main():
parser.print_help() parser.print_help()
sys.exit(1) sys.exit(1)
# Создаем менеджер пакетов с учетом песочницы pm = PackageManager(repo_path=args.repo, sandbox=args.sandbox)
pm = PackageManager(
repo_path=args.repo,
sandbox=args.sandbox
)
if args.command == 'install': if args.command == 'install':
pm.install(args.package) pm.install(args.package)
elif args.command == 'list': elif args.command == 'list':
packages = pm.list_installed() packages = pm.list_installed()
if not packages: if not packages:
print("Нет установленных пакетов") print_info("Нет установленных пакетов")
else: else:
print("Установленные пакеты:") print_package(f"Установленные пакеты ({len(packages)}):")
for pkg in packages: for pkg in packages:
print(f" {pkg.name} ({pkg.version})") print(f" {pkg.name} ({pkg.version})")
sys.exit(0) sys.exit(0)

View File

@@ -2,27 +2,23 @@
import json import json
import os import os
import shutil import shutil
from typing import List, Optional from typing import List
from ..models.package import Package from ..models.package import Package
from ..database.db_manager import DatabaseManager from ..database.db_manager import DatabaseManager
from ..utils.colors import (
print_success, print_error, print_warning,
print_info, print_package, print_step, print_sandbox_mode
)
class PackageManager: class PackageManager:
"""Главный класс менеджера пакетов"""
def __init__(self, repo_path: str = "repo", sandbox: str = None): def __init__(self, repo_path: str = "repo", sandbox: str = None):
"""
Args:
repo_path: путь к репозиторию (папка с пакетами)
sandbox: путь к песочнице (если указан, все установки идут туда)
"""
self.repo_path = repo_path self.repo_path = repo_path
# Если указана песочница, используем её как корень
if sandbox: if sandbox:
self.root = sandbox self.root = sandbox
self.sandbox_mode = True self.sandbox_mode = True
print(f"🏖️ РЕЖИМ ПЕСОЧНИЦЫ: {sandbox}") print_sandbox_mode(self.root)
else: else:
self.root = "/" self.root = "/"
self.sandbox_mode = False self.sandbox_mode = False
@@ -30,14 +26,12 @@ class PackageManager:
self.db = DatabaseManager(self.root) self.db = DatabaseManager(self.root)
def install(self, package_name: str) -> bool: def install(self, package_name: str) -> bool:
"""Устанавливает пакет""" print_step(f"Поиск пакета {package_name}...")
print(f"🔧 Поиск пакета {package_name}...")
# Ищем meta.json пакета
meta_path = os.path.join(self.repo_path, "packages", package_name, "meta.json") meta_path = os.path.join(self.repo_path, "packages", package_name, "meta.json")
if not os.path.exists(meta_path): if not os.path.exists(meta_path):
print(f"Пакет {package_name} не найден в репозитории") print_error(f"Пакет {package_name} не найден")
return False return False
with open(meta_path, 'r') as f: with open(meta_path, 'r') as f:
@@ -45,40 +39,31 @@ class PackageManager:
pkg = Package(**pkg_data) pkg = Package(**pkg_data)
# Проверяем, не установлен ли уже
if self.db.is_installed(package_name): if self.db.is_installed(package_name):
print(f" Пакет {package_name} уже установлен") print_warning(f"Пакет {package_name} уже установлен")
return True return True
print(f"📦 Установка {pkg.full_name()}...") print_package(f"Установка {pkg.full_name()}...")
# Копируем файлы
source_dir = os.path.join(self.repo_path, "packages", package_name, "files") source_dir = os.path.join(self.repo_path, "packages", package_name, "files")
for file_info in pkg.files: for file_info in pkg.files:
src = os.path.join(source_dir, file_info["source"]) src = os.path.join(source_dir, file_info["source"])
dst = os.path.join(self.root, file_info["destination"].lstrip("/")) dst = os.path.join(self.root, file_info["destination"].lstrip("/"))
# Создаем папку назначения, если ее нет
os.makedirs(os.path.dirname(dst), exist_ok=True) os.makedirs(os.path.dirname(dst), exist_ok=True)
# Копируем файл
shutil.copy2(src, dst) shutil.copy2(src, dst)
# Устанавливаем права доступа, если указаны
if "permissions" in file_info: if "permissions" in file_info:
os.chmod(dst, file_info["permissions"]) os.chmod(dst, file_info["permissions"])
# Сохраняем в базу
self.db.add_package(pkg) self.db.add_package(pkg)
print_success(f"Пакет {package_name} установлен")
print(f"✅ Пакет {package_name} успешно установлен")
if self.sandbox_mode: if self.sandbox_mode:
print(f"📁 Файлы установлены в: {self.root}") print_info(f"Файлы в: {self.root}")
return True return True
def list_installed(self) -> List[Package]: def list_installed(self) -> List[Package]:
"""Возвращает список установленных пакетов"""
return list(self.db.installed.values()) return list(self.db.installed.values())

47
mypkg/utils/colors.py Normal file
View File

@@ -0,0 +1,47 @@
# mypkg/utils/colors.py
class Colors:
"""ANSI-коды для цветов в терминале"""
GREEN = '\033[92m'
RED = '\033[91m'
YELLOW = '\033[93m'
BLUE = '\033[94m'
CYAN = '\033[96m'
MAGENTA = '\033[95m'
BOLD = '\033[1m'
DIM = '\033[2m'
RESET = '\033[0m'
class Emoji:
"""Эмодзи для разных ситуаций"""
SUCCESS = ""
ERROR = ""
WARNING = "⚠️"
INFO = ""
PACKAGE = "📦"
INSTALL = "🔧"
DELETE = "🗑️"
SEARCH = "🔍"
SANDBOX = "🏖️"
def print_success(msg: str):
print(f"{Colors.GREEN}{Emoji.SUCCESS} {msg}{Colors.RESET}")
def print_error(msg: str):
print(f"{Colors.RED}{Emoji.ERROR} {msg}{Colors.RESET}")
def print_warning(msg: str):
print(f"{Colors.YELLOW}{Emoji.WARNING} {msg}{Colors.RESET}")
def print_info(msg: str):
print(f"{Colors.BLUE}{Emoji.INFO} {msg}{Colors.RESET}")
def print_package(msg: str):
print(f"{Colors.CYAN}{Emoji.PACKAGE} {msg}{Colors.RESET}")
def print_step(msg: str):
print(f"{Colors.BOLD}{Emoji.INSTALL} {msg}{Colors.RESET}")
def print_sandbox_mode(root: str):
print(f"{Colors.YELLOW}{Emoji.SANDBOX} РЕЖИМ ПЕСОЧНИЦЫ: {root}{Colors.RESET}")