Разделите один файл на модули
Программа работает, но весь код лежит в одном файле: строки, числа, даты и проверка данных вперемешку. Задача — разложить функции по модулям и папкам, не меняя их тел.
Что в архиве
Text Kit — набор небольших функций, которые пригождаются почти в любой программе: убрать лишние пробелы, сделать инициалы, посчитать среднее и медиану, проверить почту и телефон, прочитать дату из строки. Всего шестнадцать функций, и все они лежат в одном файле main.py.
Рядом лежит папка tests с четырьмя файлами проверок. Сейчас тесты не проходят: они написаны под структуру, которой ещё нет.
Сначала запустите программу как есть: python main.py. Запомните вывод — после разделения он должен остаться прежним. Полный текст задания лежит в архиве в файле ЗАДАНИЕ.md; его же можно скачать отдельно.
Куда какие функции
Где должна оказаться функция, написано в тестах. Первая строка каждого файла проверок — это импорт, а импорт повторяет путь к файлу.
from app.services.statistics import average, count_values, median, spreadСтрока означает: четыре функции расчётов лежат в файле app/services/statistics.py. Так же читаются остальные три файла тестов. Всего получается четыре модуля:
| Тема | Функции |
|---|---|
| строки | clean_spaces, shorten, initials, slug |
| даты | parse_date, format_date, is_weekend, days_between |
| расчёты по числам | average, median, spread, count_values |
| проверка данных | is_email, normalize_phone, is_phone, password_problems |
Строки и даты — мелкие функции, которые можно перенести в другой проект без изменений: они идут в app/utils/. Расчёты и проверка данных — правила именно этого проекта: они идут в app/services/. Это то же деление, что и в первой работе.
Порядок работы
- Где
- Новая папка
text-kit. - Действие
- Перенести функции из
main.pyв четыре модуля, оставив в точке запуска только запуск. - Результат
app/utils/,app/services/,app/main.pyи прежний вывод программы.- Проверка
- Девятнадцать тестов проходят, вывод программы не изменился.
- Создайте дерево. Папки
app,app/utils,app/servicesи пустой__init__.pyв каждой из них. Папкуtestsоставьте на месте. - Перенесите функции по темам. Тело каждой функции переносится как есть: менять код не нужно.
- Оставьте в каждом модуле только нужные импорты. Строка
from datetime import dateнужна только модулю дат. - Найдите связь между модулями. Одна функция проверки данных пользуется функцией из модуля строк. Допишите импорт в том модуле, который её вызывает.
- Соберите точку запуска.
main.pyпереезжает вapp/и оставляет себе константы с примерами данных, функциюmainи строкуif __name__ == "__main__":. Всё остальное он импортирует. - Запустите и проверьте. Обе команды выполняются из корня проекта.
- Напишите README. Назначение программы, дерево проекта, команды запуска, ожидаемый вывод и признак, по которому функции разделены на четыре модуля.
python -m app.main
python -m unittest discover -s tests -vВывод программы совпадает с выводом исходного main.py
Ran 19 tests ...
OKКак переносить функцию
Перенос одной функции состоит из трёх действий: вырезать её из main.py, вставить в нужный модуль, дописать импорт там, где она вызывается. Пока функция вызывается только из main, импорт нужен один.
from app.services.statistics import average, count_values, median, spread
from app.utils.text import clean_spaces, initials, shorten, slugПереносите функции по одной теме за раз и после каждой темы запускайте тесты этой темы:
python -m unittest tests.test_text -vТогда ошибка относится к одному модулю и находится сразу.
Если не работает
ImportError: cannot import name
Функция лежит не в том файле, которого ждёт тест, либо в имени функции есть опечатка. Сверьте имя в импорте и имя после def.
NameError: name 'clean_spaces' is not defined
Функция вызывается из другого модуля, а импорт не дописан. Модуль видит только то, что определено в нём самом или импортировано в него.
ModuleNotFoundError: No module named 'app'
Команда запускается не из корня проекта или в папке нет файла __init__.py.
Программа ничего не печатает
В app/main.py потерялась строка if __name__ == "__main__": с вызовом main(). Без неё функция определена, но не вызвана.
Тесты проходят, но остался старый main.py в корне
Исходный файл после переноса удаляется: иначе в проекте остаются две копии одного кода.
Сверка после собственной попытки
Показать готовое дерево
text-kit/
├ README.md
├ app/
│ ├ __init__.py
│ ├ main.py
│ ├ services/
│ │ ├ __init__.py
│ │ ├ statistics.py
│ │ └ validation.py
│ └ utils/
│ ├ __init__.py
│ ├ dates.py
│ └ text.py
└ tests/
Связь между модулями одна: validation.py импортирует clean_spaces из utils/text.py.
Что сдать
Папку text-kit в вашем репозитории дисциплины. В README.md — раздел о том, по какому признаку функции разделены на четыре модуля.
Баллы: раскладка функций по модулям — 3, запуск с прежним выводом — 3, тесты — 2, README — 2. Всего 10.