- Зачем: - Пример базовой загрузки CSV перенесен в отдельный репозиторий `airflow-manual` для разделения учебных треков. - Что: - удалены DAG-файлы `csv_to_greenplum` и вспомогательные скрипты `helpers/greenplum.py`, `orders_ddl.sql`. - из `docker-compose.yml` и `.env.example` удалены переменные и тома (`airflow_data`), необходимые для CSV. - очищена документация (`README.md`, `TESTING.md`, `educational-tasks.md`) и тесты (`test_dags_smoke.py`, `conftest.py`). - отмечен выполненным 'Этап 1' в `TODO.md`. - Проверка: - `make test` проходит успешно (smoke-тесты оставшихся DAG-ов не затронуты).
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib
|
|
import sys
|
|
from pathlib import Path
|
|
from types import ModuleType
|
|
from typing import Type
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
if str(PROJECT_ROOT) not in sys.path:
|
|
sys.path.append(str(PROJECT_ROOT))
|
|
|
|
if "airflow" not in sys.modules:
|
|
airflow_module = ModuleType("airflow")
|
|
airflow_module.__path__ = [str(PROJECT_ROOT / "airflow")]
|
|
sys.modules["airflow"] = airflow_module
|
|
|
|
providers_module = ModuleType("airflow.providers")
|
|
providers_module.__path__ = []
|
|
sys.modules["airflow.providers"] = providers_module
|
|
airflow_module.providers = providers_module
|
|
|
|
postgres_module = ModuleType("airflow.providers.postgres")
|
|
postgres_module.__path__ = []
|
|
sys.modules["airflow.providers.postgres"] = postgres_module
|
|
providers_module.postgres = postgres_module
|
|
|
|
hooks_module = ModuleType("airflow.providers.postgres.hooks")
|
|
hooks_module.__path__ = []
|
|
sys.modules["airflow.providers.postgres.hooks"] = hooks_module
|
|
postgres_module.hooks = hooks_module
|
|
|
|
if "psycopg2" not in sys.modules:
|
|
psycopg2_stub = ModuleType("psycopg2")
|
|
psycopg2_stub.connect = lambda **_: None # type: ignore[assignment]
|
|
sys.modules["psycopg2"] = psycopg2_stub
|
|
|
|
|
|
def _ensure_stub_module(full_name: str) -> ModuleType:
|
|
"""
|
|
Ensure that module placeholders exist for a dotted path and return leaf module.
|
|
"""
|
|
parts = full_name.split(".")
|
|
module: ModuleType | None = None
|
|
path = ""
|
|
for part in parts:
|
|
path = f"{path}.{part}" if path else part
|
|
if path not in sys.modules:
|
|
new_module = ModuleType(path)
|
|
if module is not None:
|
|
setattr(module, part, new_module)
|
|
sys.modules[path] = new_module
|
|
module = new_module
|
|
else:
|
|
module = sys.modules[path]
|
|
assert isinstance(module, ModuleType)
|
|
return module
|