From 432ba06c7ae09c5cceb2596e7ee0b46d64b539e1 Mon Sep 17 00:00:00 2001 From: simbiot-harness Date: Mon, 19 Oct 2026 00:03:34 +0000 Subject: [PATCH] =?UTF-8?q?requirements.txt:=20=D1=80=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D1=8B=D0=BF=D0=B0=D0=BB=D0=B0=D1=81=D1=8C=20=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=BA=D0=B0=20watchdog=3D=3D6.0.0numpy>=3D2.0=20(=D0=BD?= =?UTF-8?q?=D0=B5=D1=82=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8)=20=E2=80=94=20pip=20in?= =?UTF-8?q?stall=20-r=20=D0=BF=D0=B0=D0=B4=D0=B0=D0=BB=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D1=81=D0=B2=D0=B5=D0=B6=D0=B8=D1=85=20=D1=83=D1=81=D1=82=D0=B0?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BA=D0=B0=D1=85=20install.sh;=20numpy=20?= =?UTF-8?q?=D0=B2=D1=8B=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=20=D0=BE=D1=82=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9=20=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BA=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements.txt | 3 +- tests/test_requirements_valid.py | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/test_requirements_valid.py diff --git a/requirements.txt b/requirements.txt index 9c5aa5d..b21729a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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): обучение учеников diff --git a/tests/test_requirements_valid.py b/tests/test_requirements_valid.py new file mode 100644 index 0000000..579293c --- /dev/null +++ b/tests/test_requirements_valid.py @@ -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 отдельными строками)")