Files
hlamingo/tests/guard.py
T
alexandClaude Opus 5 17b7d49d2f hlamingo — помощник «где что лежит»
Веб-помощник для домашнего склада: помнит, в какой коробке и в каком месте
лежит вещь, и находит её по названию, тегам и маркировке. Открывается
с телефона, интеллект — локальная Ollama.

Основное:
- структурный ввод «место → ёмкость → предмет» и кнопки
  Положить / Забрать / Переместить / Удалить;
- иерархия мест (Гараж → Стеллаж А → Полка 2), ёмкости с кодом «буква+цифра»,
  состояние «на руках» для взятых вещей;
- поиск по словам с учётом русских окончаний, теги от модели расширяют
  словарь предмета, смысловой поиск — вспомогательный (замеры в search.py);
- фото к вещам и коробкам: съёмка и выбор из галереи;
- правка и удаление всех сущностей, удаление коробки не теряет её содержимое;
- работает и без Ollama: отключаются только разбор фраз, теги и поиск
  по смыслу.

Данные (data/, static/photos/) и локальный конфиг (.env) в репозиторий
не попадают. Тесты работают только в песочнице: путь к данным берётся
из окружения, tests/guard.py отказывается запускаться на живых данных.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 14:27:20 +03:00

60 lines
2.4 KiB
Python

# -*- coding: utf-8 -*-
"""Защита живых данных. Импортировать ПЕРВЫМ в любом тесте.
История: тест начинался со `shutil.rmtree(DATA_DIR)`, DATA_DIR указывал на
рабочую папку, и один прогон уничтожил реальную базу с вещами. Восстановить
её не удалось. Поэтому теперь тест обязан работать в песочнице, а проверка
этого — не пожелание, а условие запуска.
"""
import os
import sys
import atexit
import shutil
import tempfile
from pathlib import Path
def sandbox():
"""Переводит приложение на временную папку и возвращает её.
Вызывать ДО импорта hlamingo.* — переменная окружения читается в config
на этапе импорта. Если живые данные всё же оказались подключены, тест
падает, а не удаляет их.
"""
root = Path(tempfile.mkdtemp(prefix="hlamingo-test-"))
os.environ["HLAMINGO_DATA_DIR"] = str(root)
for name in list(sys.modules):
if name == "hlamingo" or name.startswith("hlamingo."):
del sys.modules[name] # чтобы config перечитал окружение
from hlamingo import config
if config.IS_LIVE_DATA:
raise SystemExit("ОТКАЗ: приложение смотрит на живые данные. Тест не запускается.")
if root not in config.DATA_DIR.parents and config.DATA_DIR != root / "data":
raise SystemExit("ОТКАЗ: база вне песочницы (%s)." % config.DATA_DIR)
atexit.register(lambda: shutil.rmtree(str(root), ignore_errors=True))
return root
class Report(object):
"""Счётчик проверок с человеческим выводом."""
def __init__(self):
self.ok = 0
self.fail = 0
def check(self, label, cond, extra=""):
if cond:
self.ok += 1
print(" OK %s" % label)
else:
self.fail += 1
print(" FAIL %s %s" % (label, extra))
def finish(self):
print("\n%s успешно: %d, провалено: %d\n" % ("=" * 40, self.ok, self.fail))
return 1 if self.fail else 0