doc: аудит Fable 5 + моё мнение (Opus vs Fable)
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# План: Decouple polygon v0.2.1
|
||||
|
||||
Цель: разнести монолитный `app.py` (400 строк, 17 роутов) на отдельные blueprint-файлы
|
||||
по шаблону app-autotest. Никакого инлайн-CSS/HTML — всё в `static/` и `templates/`.
|
||||
|
||||
## Текущее → Целевое
|
||||
|
||||
```
|
||||
polygon/site/
|
||||
├── app.py (400 строк, всё в одном)
|
||||
├── mock_state.py
|
||||
├── state_machine.py
|
||||
├── config_loader.py
|
||||
└── from_stands.py
|
||||
|
||||
↓
|
||||
|
||||
polygon/site/
|
||||
├── app.py # ТОЛЬКО: Flask(), register_blueprint, /health, app.run()
|
||||
├── routes/
|
||||
│ ├── root.py # GET / (render_template + style.css)
|
||||
│ ├── services_routes.py # GET /api/v1/svc/services, GET /services/<id>
|
||||
│ ├── instances_routes.py # GET/POST /api/v1/svc/instances, GET /instances/<uid>
|
||||
│ ├── operations_routes.py # POST /instanceOperations, GET default, GET status, POST params, GET validate
|
||||
│ ├── run.py # POST /instanceOperations/<uid>/run
|
||||
│ └── mock_routes.py # POST /_mock/reset, GET /_mock/state, GET /_mock/services, POST /_mock/delay
|
||||
├── state/
|
||||
│ ├── mock_state.py # MockState (без изменений)
|
||||
│ └── state_machine.py # apply_effect (без изменений)
|
||||
├── config/
|
||||
│ └── loader.py # load_services() (бывший config_loader.py)
|
||||
├── converter/
|
||||
│ └── from_stands.py # конвертер (без изменений)
|
||||
├── utils/
|
||||
│ ├── pluralize.py # _pluralize() — одна функция
|
||||
│ └── now.py # _now() — одна функция
|
||||
├── static/
|
||||
│ └── style.css # CSS из index() — тёмная тема
|
||||
├── templates/
|
||||
│ └── index.html # HTML из index() — Jinja2 с {{ VERSION }}
|
||||
└── services/
|
||||
└── ...yaml # без изменений
|
||||
```
|
||||
|
||||
## Пошагово
|
||||
|
||||
### Шаг 1. Утилиты
|
||||
|
||||
- `utils/now.py` — `_now()` из app.py (одна функция)
|
||||
- `utils/pluralize.py` — `_pluralize()` из state_machine.py (одна функция)
|
||||
|
||||
### Шаг 2. CSS и HTML
|
||||
|
||||
- `static/style.css` — вынести инлайн-CSS из f-строки `index()`
|
||||
- `templates/index.html` — вынести HTML из f-строки, использовать Jinja2 `{{ version }}`, `<link rel="stylesheet">`
|
||||
|
||||
### Шаг 3. Маршруты — 6 blueprint-файлов
|
||||
|
||||
Каждый blueprint импортирует нужные модули из `state/`, `config/`, `utils/`.
|
||||
|
||||
- `routes/root.py` — `bp = Blueprint("root", __name__)`, роут `/` с `render_template`
|
||||
- `routes/services_routes.py` — `bp = Blueprint("services", __name__)`, 2 роута
|
||||
- `routes/instances_routes.py` — `bp = Blueprint("instances", __name__)`, 3 роута
|
||||
- `routes/operations_routes.py` — `bp = Blueprint("operations", __name__)`, 5 роутов
|
||||
- `routes/run.py` — `bp = Blueprint("run", __name__)`, 1 роут
|
||||
- `routes/mock_routes.py` — `bp = Blueprint("mock", __name__)`, 4 роута
|
||||
|
||||
### Шаг 4. app.py — только скелет
|
||||
|
||||
```python
|
||||
import os
|
||||
from flask import Flask
|
||||
from routes.root import bp as root_bp
|
||||
from routes.services_routes import bp as services_bp
|
||||
# ... все 6 blueprint'ов
|
||||
from config.loader import load_services
|
||||
|
||||
os.environ.setdefault("WEB_CONCURRENCY", "1")
|
||||
VERSION = "0.2.1"
|
||||
MOCK_OP_DELAY = float(os.getenv("MOCK_OP_DELAY", "0.1"))
|
||||
|
||||
app = Flask(__name__, template_folder="templates", static_folder="static")
|
||||
|
||||
app.register_blueprint(root_bp)
|
||||
app.register_blueprint(services_bp)
|
||||
# ... все 6
|
||||
|
||||
@app.route("/health")
|
||||
def health():
|
||||
return "OK"
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True, host="0.0.0.0", port=5000)
|
||||
```
|
||||
|
||||
### Шаг 5. Импорты в state_machine и from_stands
|
||||
|
||||
- `state_machine.py`: `from utils.pluralize import pluralize` (вместо `_pluralize()` внутри)
|
||||
- `from_stands.py`: импортирует `pluralize` из `utils/`
|
||||
|
||||
## Что НЕ меняется
|
||||
|
||||
- `state/mock_state.py` — как есть
|
||||
- `state/state_machine.py` — только импорт `pluralize`
|
||||
- `converter/from_stands.py` — только импорт `pluralize`
|
||||
- `services/*.yaml` — данные
|
||||
- `tests/` — только поправить пути импорта (site → site.state и т.д.)
|
||||
|
||||
## Верификация
|
||||
|
||||
1. `python -m py_compile` на ВСЕХ .py файлах
|
||||
2. `python -c "from app import app; [print(r.rule) for r in app.url_map.iter_rules()]"` → те же 17 роутов
|
||||
3. `pytest tests/ -v` → 19/19 PASS
|
||||
4. Запустить `python app.py` → curl /health, /services, /instances → работает
|
||||
Reference in New Issue
Block a user