Files
redmine-reporter/tests/test_import_side_effects.py
Кокос Артем Николаевич 1df1194f58 refactor: remove import-time side effects
Импорт модулей больше не мутирует процесс:

- config.py: module-level load_dotenv(override=False) мутировал os.environ
  при любом импорте. Вызов перенесён в Config.load_yaml() — точку явной
  загрузки конфигурации, семантика override=False и путь по умолчанию
  сохранены. --config PATH (load_dotenv(path, override=True)) не затронут.
- mailer.py: глобальная регистрация email.charset.add_charset('utf-8', ...)
  меняла кодировку для всего процесса. Заменена на точечное применение
  8bit UTF-8 к телу письма в _utf8_text_part() — payload в UTF-8
  (surrogateescape) + Content-Transfer-Encoding: 8bit на конкретной части.
  Проверено: сериализация в байты (BytesGenerator, как в send_message)
  побайтово совпадает со старым поведением.

Тест test_env_var_takes_priority_over_dotenv адаптирован к новой точке
вызова load_dotenv; test_body_substitution переведён с as_string() на
декодированный payload (str-сериализация не-ASCII части без глобальной
мутации реестра теперь даёт base64; wire-формат 8bit сохранён и
зафиксирован test_wire_format_is_8bit_utf8).

Closes #64
2026-07-17 13:35:02 +07:00

51 lines
1.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""#64: импорт модулей не должен давать side effects в процессе."""
import os
import subprocess
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
def _run_in_subprocess(code: str, cwd: Path) -> str:
"""Выполняет code в чистом интерпретаторе с доступом к пакету."""
env = {**os.environ, "PYTHONPATH": str(REPO_ROOT)}
result = subprocess.run(
[sys.executable, "-c", code],
cwd=cwd,
env=env,
capture_output=True,
text=True,
check=True,
)
return result.stdout.strip()
def test_config_import_does_not_mutate_os_environ(tmp_path):
"""import redmine_reporter.config не подгружает .env из текущей директории."""
(tmp_path / ".env").write_text("RR_IMPORT_PROBE=1\n")
output = _run_in_subprocess(
"import os\n"
"import redmine_reporter.config\n"
"print('RR_IMPORT_PROBE' in os.environ)\n",
cwd=tmp_path,
)
assert output == "False"
def test_mailer_import_does_not_mutate_global_charset_registry(tmp_path):
"""import redmine_reporter.mailer не меняет email.charset для всего процесса."""
output = _run_in_subprocess(
"from email.charset import BASE64, Charset\n"
"before = Charset('utf-8').body_encoding\n"
"import redmine_reporter.mailer\n"
"after = Charset('utf-8').body_encoding\n"
"print(before == BASE64, after == BASE64)\n",
cwd=tmp_path,
)
assert output == "True True"