Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

Лабораторная работа №2.

Структура проекта:

    .
    ├── second_laba_python                     # Кодовая база моей лабораторной работы
    │   ├── src/                               # Исходный код
    │   ├── tests/                             # Unit тесты для проверки функциональности
    │   ├── .gitignore                         # файл, игнорируемый git
    │   ├── .pre-commit-config.yaml            # Конфигурация автоматической проверки кодстайла перед коммитом
    │   ├── README.md                          # Описание проекта, структуры и функционала
    │   ├── uv.lock                            # Lock-файл зафиксированных версий зависимостей

В папке src лежат файлы с реализацией задачи заданной в лабораторной работе:

    .
    ├── src
    │   ├── services/             # Папка с сервисами для работы с консолью
    │   ├── __init__.py
    │   ├── config.py             # Конфигурация логирования (настройка handlers, formatters, loggers)
    │   ├── container.py          # Контейнер зависимостей (Dependency Injection) для управления сервисами
    │   ├── enums.py              # Перечисления: режимы чтения файлов (string/bytes) и отображения (simple/detailed)
    │   ├── main.py               # Точка входа в приложение, CLI-команды (ls, cat, cd, cp, mv, rm, zip, unzip, tar, untar, grep)
    │   ├── errorss.py            # Пользовательские исключения (в настоящее время не используется)

В папке services лежат файлы с реализацией сервисов для работы с консолью:

    .
    ├── services                   # Папка с реализацией консольных команд
    │   ├── __init__.py
    │   ├── base.py                # Абстрактный базовый класс OSConsoleServiceBase с интерфейсом консольных команд
    │   ├── windows_console.py     # Реализация консольного сервиса (команды ls, cat, cd, cp, mv, rm, zip, unzip, tar, untar, grep)

Алгоритм работы программы

Общий алгоритм работы:

  1. Typer парсит аргументы командной строки
  2. Вызывается соответствующая команда из main.py
  3. Команда получает контейнер зависимостей из контекста и вызывает соответствующий метод сервиса
  4. Сервис WindowsConsoleService выполняет операцию с файловой системой
  5. Результаты выводятся в консоль или обрабатываются ошибки

Описание файлов и функций

1) enums.py - определяет перечисления для режимов работы программы:

  • FileReadMode: string (режим чтения файла как текст) / bytes (режим чтения файла как байтов) для команды cat
  • FileDisplayMode simple (простой режим) / detailed (подробный)

2) config.py - конфигурация системы логирования

3) container.py - контейнер зависимостей для управления сервисами (хранит все зависимости приложения и передается через контекст Typer в команды)

4) base.py - абстрактный базовый класс, определяющий интерфейс всех консольных команд

5) windows_console.py - тут у меня реализация всех команд, краткое описание функционала в данном файле:

  • init - делает так, чтобы логгер использовался во всех методах для записи действий/ошибок

  • format_detailed - форматирует подробную информации о файле для режима detailed/-l в ls:

    1. получает статистику файла через entry.stat()
    2. извлекает права доступа через oct(stat_module.S_IMODE(stat_info.st_mode))
    3. формирует строку: {тип}{права} {размер:>10} {дата} {имя}\n
    4. обрабатывает ошибки: при ошибке возвращается строка и логируется предупреждение
  • ls - отображает список файлов и каталогов:

    1. преобразовывает путь в объект Path
    2. проверяет существования и тип
    3. получает список элементов через path.iterdir()
    4. в зависимости от режима: добавляет названия (simple) или форматирует через format_detailed (detailed)
    • Ошибки: FileNotFoundError, NotADirectoryError с логированием
  • cd - совершает переход в указанный каталог:
    1. обрабатывает специальные пути: '' и '/' преобразовываются с помощью os.path.expanduser()
    2. преобразовывает относительный путь в абсолютный относительно текущей директории
    3. разрешает путь через path.resolve() для обработки '..'
    4. проверяет существование и тип
    5. совершает смену директории через os.chdir(path)
    • Ошибки: FileNotFoundError, NotADirectoryError
  • cat - выводит содержимое указанного файла в консоль:

    1. проверяет существования файла
    2. проверяет, что путь не является директорией
    3. выводит в зависимости от режима: path.read_text(encoding="utf-8") или path.read_bytes() (как текст или байты)
    • Ошибки: FileNotFoundError, IsADirectoryError, OSError с полным логированием
  • cp - копирует файл из источника в назначение:

    • если src_path.is_dir() (директория):
      1. проверяет наличия флага recursive`
      2. определяет конечный путь: если dst_path - существующая директория, то dst_path/src_path.name, иначе dst_path
      3. если конечный путь существует:
        • это директория: копирует содержимое через shutil.copytree() для каждой поддиректории и shutil.copy2() для файлов
        • это файл: ошибка FileExistsError
        • если не существует: shutil.copytree(src_path, final_dst)
        • иначе (файл):
          1. определяет конечный путь
          2. создает родительские директории через mkdir(parents=True, exist_ok=True)
          3. копирует через shutil.copy2()
    • Ошибки: FileNotFoundError, IsADirectoryError, PermissionError, OSError
  • mv - перемещает/переименовывает файл/каталог:

    1. определяет конечный путь: если dst_path - существующая директория, то dst_path/src_path.name
    2. создает родительские директории через mkdir(parents=True, exist_ok=True)
    3. перемещает через shutil.move()
    • Ошибки: FileNotFoundError, PermissionError, OSError
  • rm - удаляет указанный файл

    1. проверяет защищенные пути ('..', '/' запрещены)
    2. разрешает путь через resolve()
    3. проверяет, что путь не является корнем диска (Path(res.anchor))
    4. проверяет существование
    5. если директория: проверяет флага r, удаляет через shutil.rmtree() или ошибка
    6. если файл: удаляет через res.unlink()
    • Ошибки: PermissionError, FileNotFoundError, IsADirectoryErros, OSError
  • zip - создание архива формата zip из каталога::

    1. проверяет существование и тип (должен быть директорией)
    2. создает родительские директории архива
    3. открывает zip-архив в режиме записи с сжатием ZIP_DEFLATED
    4. совершает рекурсивный обход через src_dir.rglob("*") всех файлов
    5. добавляет каждый файл в архив с сохранением относительного пути через arcname = path.relative_to(src_dir)
    6. пропускает директорию (добавляются только файлы)
    • Ошибки: FileNotFoundError, NotADirectoryError, общие исключения с логированием
  • unzip - распаковывает архив zip в текущий каталог:

    1. определет папки назначения (текущая директория или res)
    2. проверяет существование архива
    3. создает директории назначения
    4. открывает zip-архив в режиме чтения
    5. распаковывает все файлы через zf.extractall(dst_dir)
    • Ошибки: FileNotFoundError, общие исключения с логированием
  • tar - создает архив формата tar.gz:

    1. проверяет существование и тип (должен быть директорией)
    2. создает родительские директории архива
    3. открывает tar.gz архива в режиме "w:gz" (запись с gzip сжатием)
    4. добавляет всю директорию через tf.add(src_dir, arcname=src_dir.name)
    • Ошибки: FileNotFoundError, NotADirectoryError, общие исключения
  • untar - распаковывает архив tar.gz:

    1. определяет папку назначения (текущая директория или res)
    2. проверяет существование архива
    3. создает директорию назначения
    4. открывает tar.gz архива в режиме "r:gz" (чтение с gzip распаковкой)
    5. распаковывает все файлы через tf.extractall(dst_dir)
    • Ошибки: FileNotFoundError, общие исключения
  • grep - ищет строки, соответствующие шаблону pattern в файлах:

    1. компилирует регулярное выражение с флагами (re.IGNORECASE если нужно)
    2. определяет список файлов:
      • если path - файл: добавляется в список
      • если директория: обход через rglob('') (рекурсивно) или glob('') (не рекурсивно)
    3. для каждого файла:
      • открывает в режиме текста с кодировкой UTF-8 и обработкой ошибок errors='ignore'
      • построчно читает и ищет совпадения через rgx.search(line)
      • добавляет в результат строки формата "{file_path}:{line_number}:{line.strip()}"
    4. обрабатывает ошибки чтения отдельных файлов (продолжается поиск в остальных)
    • Ошибки: re.error при некорректном регулярном выражении, ошибки чтения файлов логируются

Нюансы реализации

  1. Логирование:

    • Все операции подробно регистрируются на разных уровнях (DEBUG, INFO, ERROR)
    • Логи сохраняются в файле shell.log
    • Максимальный размер файла 5МБ, при переполнении он переименуется в shell.log.i и создастся новый shell.log
  2. Обработка путей:

    • Использование pathlib.Path обеспечивает универсальную работу с путями
    • Автоматическое разрешение относительных путей и обработка специальных символов ('~', '.', '..')
  3. Безопасность:

    • В rm() есть защита от удаления корня и '..', что предотвращает случайное удаление важных директорий
    • Команда rm запрашивает подтверждение при рекурсивном удалении директорий, что повышает безопасность

Вот такие пироги...

forest.jpeg

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages