Реорганизация ISSUES.md: открытые задачи сверху, завершенные снизу, убраны дубли
This commit is contained in:
parent
311cfa7513
commit
089a77ce17
132
ISSUES.md
132
ISSUES.md
@ -1,90 +1,13 @@
|
|||||||
# ISSUES — Задачи и баг-трекер
|
# ISSUES — Задачи и баг-трекер
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Исправлено
|
|
||||||
|
|
||||||
- [x] ~~Эмодзи в embed-сообщениях~~ — удалены `🌅`, `✅`, `❌` из `utils/morning_runner.py`
|
|
||||||
- [x] ~~f-string в logger~~ — замена на `%`-формат в `bot.py`
|
|
||||||
- [x] ~~`import time` внутри `__init__`~~ — перенесён на уровень модуля в `bot.py`
|
|
||||||
- [x] ~~Проверка наличия `.env`~~ — `.env` в `.gitignore`, есть `.env.example`
|
|
||||||
- [x] ~~Команда `!msg` в BotRunner~~ — удалена из проекта
|
|
||||||
- [x] ~~Отсутствует `.gitignore`~~ — файл существует
|
|
||||||
- [x] ~~Отсутствует Dockerfile~~ — файл существует
|
|
||||||
- [x] ~~Отсутствует `.env.example`~~ — файл существует
|
|
||||||
- [x] **Type hints в production-коде** — добавлены аннотации ко всем 20 функциям
|
|
||||||
- [x] **`asyncio.iscoroutinefunction` deprecated** — monkey-patch в `bot.py` + `conftest.py`
|
|
||||||
- [x] **Утечка корутины Scheduler в тестах** — mock `_start_scheduler` вместо `asyncio.create_task`
|
|
||||||
- [x] **Graceful shutdown (SIGTERM)** — реализован через `on_shutdown` listener + `async with self.bot`
|
|
||||||
- [x] **Пустой `__init__` в Morning** — удалён
|
|
||||||
- [x] **Global RateLimiter на модульном уровне** — добавлены factory-функции `make_*_limiter()`
|
|
||||||
- [x] **Type hints в тестах** — добавлены `-> None` ко всем 140 test-функциям
|
|
||||||
- [x] **`import` внутри функций в тестах** — вынесены наверх модулей (35 вхождений)
|
|
||||||
- [x] **Добавить pre-commit хуки** — `.pre-commit-config.yaml` (ruff + ruff-format), `requirements-dev.txt`
|
|
||||||
- [x] **Интеграционные тесты** — 9 тестов загрузок когов, команд и утилит
|
|
||||||
- [x] **`format_weather_for_embed` отсутствует в коде** — заменено на `format_weather_for_message` в README.md (`README.md`)
|
|
||||||
- [x] **`_WEATHER_MAPPING` не отсортирован по убыванию длины ключей** — отсортирован список по убыванию `len(key)`, добавлен комментарий (`utils/pogoda.py`)
|
|
||||||
- [x] **Глобальные `requests.Session` не закрываются** — добавлена `close_all_sessions()` в `utils/__init__.py`, вызов из `_on_shutdown` в `bot.py`
|
|
||||||
- [x] **`run_morning` fallback может отправить дайджест в несколько каналов** — fallback перебирает каналы целевого сервера вместо `bot.get_all_channels()` (`utils/morning_runner.py`)
|
|
||||||
- [x] **`!nw`: последовательные вызовы API вместо параллельных** — заменено на `asyncio.gather()` (`commands/news.py`)
|
|
||||||
- [x] **`format_weather_data_for_console` выводит `None` в текст** — добавлена явная проверка `is None` для всех полей (`utils/pogoda.py`), обновлён тест (`tests/test_commands_pg.py`)
|
|
||||||
- [x] **`_parse_date` хрупкий fallback** — валидация формата через regex, ISO даты конвертируются в DD.MM.YYYY (`utils/news.py`)
|
|
||||||
- [x] **`wmo_to_russian` создаёт dict на каждый вызов** — вынесен в константу `_WMO_MAPPING` (`utils/pogoda.py`)
|
|
||||||
- [x] **`TextHelpCommand` пропускает команды без cog** — standalone-команды показываются если не hidden (`bot.py`)
|
|
||||||
- [x] **`translate_weather(" ")` возвращает пробелы** — добавлен `.strip()` перед проверкой (`utils/pogoda.py`)
|
|
||||||
- [x] **`pressure_to_mmhg(mb: Any)`** — заменён на `float | int | str | None` (`utils/pogoda.py`)
|
|
||||||
- [x] **`conftest.py` и `bot.py` дублируют monkey-patch** — вынесен в `utils/compat.py`, оба файла импортируют оттуда
|
|
||||||
- [x] **`RateLimiter` тесты зависят от реального времени** — добавлен `_time_func` параметр, все тесты используют контролируемую функцию времени
|
|
||||||
- [x] ~~**`Dockerfile` не копирует `conftest.py`**~~ — `conftest.py` убран из Dockerfile (тестовый файл не нужен в production)
|
|
||||||
- [x] **`requirements.txt` без пиннинга версий** — `>=` заменён на `~=` (compatible release)
|
|
||||||
- [x] **Закомментированный тест `pressure_to_mmhg(0)`** — удалена устаревшая закомментированная строка
|
|
||||||
- [x] **`format_articles(None)` бросает `TypeError`** — добавлена валидация `None`, graceful fallback с сообщением
|
|
||||||
- [x] **`setup_logging()` создаёт дублирующиеся handlers** — добавлен `root.handlers.clear()` (`utils/logger.py`)
|
|
||||||
- [x] **Первый `logger.info()` теряется** — `setup_logging()` вызывается до первого лога (`bot.py`)
|
|
||||||
- [x] **`translate_weather()` уязвим к ложным substring-совпадениям** — точное совпадение приоритизируется (`utils/pogoda.py`)
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Открытые задачи
|
## Открытые задачи
|
||||||
|
|
||||||
### Критические
|
|
||||||
|
|
||||||
- [x] ~~**`setup_logging()` создаёт дублирующиеся handlers**~~ — добавлен `root.handlers.clear()` перед добавлением новых хендлеров (`utils/logger.py`)
|
|
||||||
- [x] ~~**Первый `logger.info()` теряется**~~ — `setup_logging()` перемещён до первого `logger.info()` (`bot.py`)
|
|
||||||
- [x] ~~**`translate_weather()` уязвим к ложным substring-совпадениям**~~ — добавлена проверка точного совпадения (case-insensitive) перед substring-matching (`utils/pogoda.py`)
|
|
||||||
|
|
||||||
### Средние
|
|
||||||
|
|
||||||
- [x] ~~**`fromstring` импортирован внутри функции `fetch_rss`**~~ — вынесен на уровень модуля (`utils/news.py`)
|
|
||||||
- [x] ~~**`Scheduler._start_scheduler()` создаёт task синхронно**~~ — `__init__` больше не создаёт task; `start()` стал async-методом (`utils/morning_runner.py`, `bot.py`)
|
|
||||||
- [x] ~~**`Pg.__init__` хранит `self.api_url` как инстанс-переменную**~~ — удалён `__init__`, используется `API_URL_WEATHER` напрямую (`commands/pg.py`)
|
|
||||||
- [x] ~~**`fetch_cat()` не передаёт `x-api-key`**~~ — добавлена поддержка `CAT_API_KEY` из окружения, заголовок `x-api-key` передаётся при наличии ключа (`utils/cat.py`)
|
|
||||||
|
|
||||||
### Низкие
|
|
||||||
|
|
||||||
- [x] ~~**Глобальные экземпляры RateLimiter + factory-функции**~~ — дизайн подтверждён: глобальные синглтоны для production, factory-функции для тестов. Добавлен поясняющий комментарий (`utils/rate_limiter.py`)
|
|
||||||
- [x] ~~**`@pytest.mark.asyncio` избыточен**~~ — удалены 5 декораторов из `tests/test_integration.py` (`pytest.ini` имеет `asyncio_mode = auto`)
|
|
||||||
- [x] ~~**`Dockerfile` не копирует `tests/`**~~ — отклонено: Docker — production-окружение, тесты туда не нужны
|
|
||||||
- [x] ~~**Приватные атрибуты на объекте бота**~~ — `START_TIME` вынесен на уровень модуля `bot.py`, `self.bot._scheduler` удалён (не использовался). Обновлены `commands/status.py` и тесты
|
|
||||||
- [x] ~~Избыточная проверка `ctx` в `on_command_error`~~ — удалены проверки `ctx and`, так как `ctx` гарантированно передан discord.py (`bot.py`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Открытые задачи
|
|
||||||
|
|
||||||
### Высокий приоритет
|
|
||||||
|
|
||||||
- [x] ~~**`ruff format --check` падает на 5 файлах**~~ — применён `ruff format` к 7 файлам (`bot.py`, `tests/test_commands_news.py`, `tests/test_commands_pg.py`, `tests/test_fetch_weather.py`, `tests/test_help_command.py`, `tests/test_morning_runner.py`, `utils/pogoda.py`)
|
|
||||||
|
|
||||||
### Средний приоритет
|
### Средний приоритет
|
||||||
|
|
||||||
- [ ] **Отсутствует `pyproject.toml`** — проект использует `requirements.txt` + `requirements-dev.txt` без единого файла конфигурации. Рекомендуется `pyproject.toml` с `[project]`, настройками ruff и pytest
|
- [ ] **Отсутствует `pyproject.toml`** — проект использует `requirements.txt` + `requirements-dev.txt` без единого файла конфигурации. Рекомендуется `pyproject.toml` с `[project]`, настройками ruff и pytest
|
||||||
|
|
||||||
- [x] ~~**`commands/news.py` — дублирование кода для статей и постов**~~ — вынесено в `_format_feed_section()` (`commands/news.py`)
|
|
||||||
|
|
||||||
- [x] ~~**Город захардкожен в `API_URL_WEATHER`**~~ — вынесен в `WEATHER_CITY` env-переменную, шаблон `"Погода: {city}:"` (`utils/pogoda.py`, `.env.example`)
|
|
||||||
|
|
||||||
- [ ] **`Scheduler._task` без `add_done_callback`** — если `_scheduler_loop` завершится unexpectedly (не через `CancelledError`), это не будет залогировано. Добавить callback для логирования нештатного завершения task
|
- [ ] **`Scheduler._task` без `add_done_callback`** — если `_scheduler_loop` завершится unexpectedly (не через `CancelledError`), это не будет залогировано. Добавить callback для логирования нештатного завершения task
|
||||||
|
|
||||||
- [ ] **Тест `test_fetch_weather_http_error_no_fallback` — raises bare `Exception` вместо `requests.HTTPError`** — в реальности `raise_for_status()` бросает `requests.HTTPError`, который ловится `except requests.RequestException` и корректно переходит на fallback. Тест проверяет несуществующий сценарий
|
- [ ] **Тест `test_fetch_weather_http_error_no_fallback` — raises bare `Exception` вместо `requests.HTTPError`** — в реальности `raise_for_status()` бросает `requests.HTTPError`, который ловится `except requests.RequestException` и корректно переходит на fallback. Тест проверяет несуществующий сценарий
|
||||||
@ -98,3 +21,58 @@
|
|||||||
- [ ] **`commands/morning.py` не ловит исключения `run_morning`** — если `run_morning` выбросит, лог `!morning завершен` не запишется, а ошибка уйдёт в `on_command_error`. Добавить `try/except` для локальной обработки и логирования
|
- [ ] **`commands/morning.py` не ловит исключения `run_morning`** — если `run_morning` выбросит, лог `!morning завершен` не запишется, а ошибка уйдёт в `on_command_error`. Добавить `try/except` для локальной обработки и логирования
|
||||||
|
|
||||||
- [ ] **Файл `nul` в корне проекта** — артефакт Windows (29 байт). Удалить из рабочей директории
|
- [ ] **Файл `nul` в корне проекта** — артефакт Windows (29 байт). Удалить из рабочей директории
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Завершено
|
||||||
|
|
||||||
|
- [x] ~~Эмодзи в embed-сообщениях~~ — удалены `🌅`, `✅`, `❌` из `utils/morning_runner.py`
|
||||||
|
- [x] ~~f-string в logger~~ — замена на `%`-формат в `bot.py`
|
||||||
|
- [x] ~~`import time` внутри `__init__`~~ — перенесён на уровень модуля в `bot.py`
|
||||||
|
- [x] ~~Проверка наличия `.env`~~ — `.env` в `.gitignore`, есть `.env.example`
|
||||||
|
- [x] ~~Команда `!msg` в BotRunner~~ — удалена из проекта
|
||||||
|
- [x] ~~Отсутствует `.gitignore`~~ — файл существует
|
||||||
|
- [x] ~~Отсутствует Dockerfile~~ — файл существует
|
||||||
|
- [x] ~~Отсутствует `.env.example`~~ — файл существует
|
||||||
|
- [x] ~~**Type hints в production-коде**~~ — добавлены аннотации ко всем 20 функциям
|
||||||
|
- [x] ~~**`asyncio.iscoroutinefunction` deprecated**~~ — monkey-patch в `bot.py` + `conftest.py`
|
||||||
|
- [x] ~~**Утечка корутины Scheduler в тестах**~~ — mock `_start_scheduler` вместо `asyncio.create_task`
|
||||||
|
- [x] ~~**Graceful shutdown (SIGTERM)**~~ — реализован через `on_shutdown` listener + `async with self.bot`
|
||||||
|
- [x] ~~**Пустой `__init__` в Morning**~~ — удалён
|
||||||
|
- [x] ~~**Global RateLimiter на модульном уровне**~~ — добавлены factory-функции `make_*_limiter()`
|
||||||
|
- [x] ~~**Type hints в тестах**~~ — добавлены `-> None` ко всем 140 test-функциям
|
||||||
|
- [x] ~~**`import` внутри функций в тестах**~~ — вынесены наверх модулей (35 вхождений)
|
||||||
|
- [x] ~~**Добавить pre-commit хуки**~~ — `.pre-commit-config.yaml` (ruff + ruff-format), `requirements-dev.txt`
|
||||||
|
- [x] ~~**Интеграционные тесты**~~ — 9 тестов загрузок когов, команд и утилит
|
||||||
|
- [x] ~~**`format_weather_for_embed` отсутствует в коде**~~ — заменено на `format_weather_for_message` в README.md
|
||||||
|
- [x] ~~**`_WEATHER_MAPPING` не отсортирован по убыванию длины ключей**~~ — отсортирован список по убыванию `len(key)`, добавлен комментарий (`utils/pogoda.py`)
|
||||||
|
- [x] ~~**Глобальные `requests.Session` не закрываются**~~ — добавлена `close_all_sessions()` в `utils/__init__.py`, вызов из `_on_shutdown` в `bot.py`
|
||||||
|
- [x] ~~**`run_morning` fallback может отправить дайджест в несколько каналов**~~ — fallback перебирает каналы целевого сервера вместо `bot.get_all_channels()` (`utils/morning_runner.py`)
|
||||||
|
- [x] ~~**`!nw`: последовательные вызовы API вместо параллельных**~~ — заменено на `asyncio.gather()` (`commands/news.py`)
|
||||||
|
- [x] ~~**`format_weather_data_for_console` выводит `None` в текст**~~ — добавлена явная проверка `is None` для всех полей (`utils/pogoda.py`), обновлён тест (`tests/test_commands_pg.py`)
|
||||||
|
- [x] ~~**`_parse_date` хрупкий fallback**~~ — валидация формата через regex, ISO даты конвертируются в DD.MM.YYYY (`utils/news.py`)
|
||||||
|
- [x] ~~**`wmo_to_russian` создаёт dict на каждый вызов**~~ — вынесен в константу `_WMO_MAPPING` (`utils/pogoda.py`)
|
||||||
|
- [x] ~~**`TextHelpCommand` пропускает команды без cog**~~ — standalone-команды показываются если не hidden (`bot.py`)
|
||||||
|
- [x] ~~**`translate_weather(" ")` возвращает пробелы**~~ — добавлен `.strip()` перед проверкой (`utils/pogoda.py`)
|
||||||
|
- [x] ~~**`pressure_to_mmhg(mb: Any)`**~~ — заменён на `float | int | str | None` (`utils/pogoda.py`)
|
||||||
|
- [x] ~~**`conftest.py` и `bot.py` дублируют monkey-patch**~~ — вынесен в `utils/compat.py`, оба файла импортируют оттуда
|
||||||
|
- [x] ~~**`RateLimiter` тесты зависят от реального времени**~~ — добавлен `_time_func` параметр, все тесты используют контролируемую функцию времени
|
||||||
|
- [x] ~~**`Dockerfile` не копирует `conftest.py`**~~ — `conftest.py` убран из Dockerfile (тестовый файл не нужен в production)
|
||||||
|
- [x] ~~**`requirements.txt` без пиннинга версий**~~ — `>=` заменён на `~=` (compatible release)
|
||||||
|
- [x] ~~**Закомментированный тест `pressure_to_mmhg(0)`**~~ — удалена устаревшая закомментированная строка
|
||||||
|
- [x] ~~**`format_articles(None)` бросает `TypeError`**~~ — добавлена валидация `None`, graceful fallback с сообщением
|
||||||
|
- [x] ~~**`setup_logging()` создаёт дублирующиеся handlers**~~ — добавлен `root.handlers.clear()` (`utils/logger.py`)
|
||||||
|
- [x] ~~**Первый `logger.info()` теряется**~~ — `setup_logging()` вызывается до первого лога (`bot.py`)
|
||||||
|
- [x] ~~**`translate_weather()` уязвим к ложным substring-совпадениям**~~ — точное совпадение приоритизируется (`utils/pogoda.py`)
|
||||||
|
- [x] ~~**`fromstring` импортирован внутри функции `fetch_rss`**~~ — вынесен на уровень модуля (`utils/news.py`)
|
||||||
|
- [x] ~~**`Scheduler._start_scheduler()` создаёт task синхронно**~~ — `__init__` больше не создаёт task; `start()` стал async-методом (`utils/morning_runner.py`, `bot.py`)
|
||||||
|
- [x] ~~**`Pg.__init__` хранит `self.api_url` как инстанс-переменную**~~ — удалён `__init__`, используется `API_URL_WEATHER` напрямую (`commands/pg.py`)
|
||||||
|
- [x] ~~**`fetch_cat()` не передаёт `x-api-key`**~~ — добавлена поддержка `CAT_API_KEY` из окружения, заголовок `x-api-key` передаётся при наличии ключа (`utils/cat.py`)
|
||||||
|
- [x] ~~**Глобальные экземпляры RateLimiter + factory-функции**~~ — дизайн подтверждён: глобальные синглтоны для production, factory-функции для тестов. Добавлен поясняющий комментарий (`utils/rate_limiter.py`)
|
||||||
|
- [x] ~~**`@pytest.mark.asyncio` избыточен**~~ — удалены 5 декораторов из `tests/test_integration.py` (`pytest.ini` имеет `asyncio_mode = auto`)
|
||||||
|
- [x] ~~**`Dockerfile` не копирует `tests/`**~~ — отклонено: Docker — production-окружение, тесты туда не нужны
|
||||||
|
- [x] ~~**Приватные атрибуты на объекте бота**~~ — `START_TIME` вынесен на уровень модуля `bot.py`, `self.bot._scheduler` удалён (не использовался). Обновлены `commands/status.py` и тесты
|
||||||
|
- [x] ~~**Избыточная проверка `ctx` в `on_command_error`**~~ — удалены проверки `ctx and`, так как `ctx` гарантированно передан discord.py (`bot.py`)
|
||||||
|
- [x] ~~**`ruff format --check` падает на 5 файлах**~~ — применён `ruff format` к 7 файлам
|
||||||
|
- [x] ~~**`commands/news.py` — дублирование кода для статей и постов**~~ — вынесено в `_format_feed_section()` (`commands/news.py`)
|
||||||
|
- [x] ~~**Город захардкожен в `API_URL_WEATHER`**~~ — вынесен в `WEATHER_CITY` env-переменную, шаблон `"Погода: {city}:"` (`utils/pogoda.py`, `.env.example`)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user