This commit is contained in:
commit
f970031c36
3 changed files with 77 additions and 4 deletions
|
|
@ -20,4 +20,5 @@ uvicorn==0.54.0
|
|||
sse-starlette==3.5.0
|
||||
python-multipart==0.0.32
|
||||
py-spy==0.4.2
|
||||
watchdog==6.0.0numpy>=2.0 # ядро Коди (harness/kodi_core.py): обучение учеников
|
||||
watchdog==6.0.0
|
||||
numpy>=2.0 # ядро Коди (harness/kodi_core.py): обучение учеников
|
||||
|
|
|
|||
|
|
@ -166,9 +166,18 @@ os.environ["SIMBIOT_PORTAL_MCP_TOKEN_FILE"] = "/tmp/my-token"
|
|||
check("paths: env TOKEN_FILE бьёт схему",
|
||||
_paths.portal_mcp_token_path() == "/tmp/my-token")
|
||||
del os.environ["SIMBIOT_PORTAL_MCP_TOKEN_FILE"]
|
||||
# герметичность: поведение изолята не зависит от того, на каком инстансе
|
||||
# запущен тест (legacy-хост без SIMBIOT_HOME иначе даёт ложный FAIL) —
|
||||
# патчим _HOME/IS_ISOLATED как это делают остальные тесты схемы путей
|
||||
_saved = (_paths._HOME, _paths.IS_ISOLATED)
|
||||
_paths._HOME = "/tmp/simbiot-test-home"
|
||||
_paths.IS_ISOLATED = True
|
||||
try:
|
||||
check("paths: изолят → secrets/portal-mcp-token",
|
||||
_paths.portal_mcp_token_path().endswith("secrets/portal-mcp-token"),
|
||||
_paths.portal_mcp_token_path())
|
||||
finally:
|
||||
_paths._HOME, _paths.IS_ISOLATED = _saved
|
||||
|
||||
print()
|
||||
print("FAILURES:", fails if fails else "нет — все проверки пройдены")
|
||||
|
|
|
|||
63
tests/test_requirements_valid.py
Normal file
63
tests/test_requirements_valid.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""requirements.txt валиден для pip (t-261019001038-0eb7d7) — hermetic.
|
||||
|
||||
Запуск: ./venv/bin/python tests/test_requirements_valid.py
|
||||
|
||||
Регрессия: на origin/master строка watchdog==6.0.0numpy>=2.0 была склеена
|
||||
без перевода строки — pip install -r requirements.txt падал на СВЕЖИХ
|
||||
установках install.sh (curl install.sh | bash) с InvalidRequirement,
|
||||
ломая канал дистрибуции харнеса. Проверяем через packaging.Requirement
|
||||
(тот же парсер, что у pip): каждая строка файла — ровно одно валидное
|
||||
требование, watchdog и numpy распознаны отдельными пакетами.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, "/root/simbiot-harness")
|
||||
|
||||
from packaging.requirements import Requirement
|
||||
|
||||
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
REQ = os.path.join(REPO, "requirements.txt")
|
||||
|
||||
fails = []
|
||||
|
||||
|
||||
def check(name, cond, extra=""):
|
||||
print(("PASS" if cond else "FAIL"), name, ("| " + str(extra)) if not cond else "")
|
||||
if not cond:
|
||||
fails.append(name)
|
||||
|
||||
|
||||
# все строки-требования парсятся packaging (тот же парсер, что у pip):
|
||||
# склейка watchdog==6.0.0numpy>=2.0 дала бы InvalidRequirement
|
||||
req_names = []
|
||||
for i, line in enumerate(open(REQ, encoding="utf-8"), 1):
|
||||
s = line.split("#", 1)[0].strip()
|
||||
if not s:
|
||||
continue
|
||||
try:
|
||||
r = Requirement(s)
|
||||
except Exception as e:
|
||||
check("строка %d валидна (InvalidRequirement)" % i, False, repr(e))
|
||||
continue
|
||||
req_names.append(r.name.lower())
|
||||
check("все строки requirements.txt валидны для pip", True)
|
||||
|
||||
# ключевые пакеты распознаны как отдельные требования
|
||||
for name in ("watchdog", "numpy"):
|
||||
check("зависимость %r отдельной строкой" % name, name in req_names)
|
||||
|
||||
# битая склейка действительно ловится парсером (self-check теста)
|
||||
try:
|
||||
Requirement("watchdog==6.0.0numpy>=2.0")
|
||||
glued_raises = False
|
||||
except Exception:
|
||||
glued_raises = True
|
||||
check("парсер отклоняет склейку watchdog==6.0.0numpy>=2.0", glued_raises)
|
||||
|
||||
print()
|
||||
if fails:
|
||||
print("FAILED:", len(fails))
|
||||
sys.exit(1)
|
||||
print("OK: requirements.txt валиден (watchdog и numpy отдельными строками)")
|
||||
Loading…
Reference in a new issue