Coverage for genschema / comparators / empty.py: 94%
31 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-14 22:23 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-14 22:23 +0000
1from .template import Comparator, ComparatorResult, ProcessingContext, Resource
4class EmptyComparator(Comparator):
5 """
6 Добавляет maxItems=0 или maxProperties=0 для полностью пустых массивов/объектов,
7 а так же minItems=0 или minProperties=0 для полностью НЕ пустых массивов/объектов,
8 если на данном уровне нет кандидатов из непустых схем или JSON.
9 """
11 name = "empty"
13 def __init__(self, flag_empty: bool = True, flag_non_empty: bool = True):
14 self.flag_empty = flag_empty
15 self.flag_non_empty = flag_non_empty
17 def can_process(self, ctx: ProcessingContext, env: str, node: dict) -> bool:
18 t = node.get("type")
19 return t == "object" or t == "array"
21 def process(self, ctx: ProcessingContext, env: str, node: dict) -> ComparatorResult:
23 # Проверяем есть ли непустые кандидаты на этом уровне
24 def is_nonempty(r: Resource) -> bool:
25 c = r.content
26 if isinstance(c, dict):
27 return bool(c) # не пустой словарь
28 if isinstance(c, list):
29 return bool(c) # не пустой список
30 return True # скаляры считаем непустыми
32 candidates = [is_nonempty(r) for r in ctx.schemas + ctx.jsons]
34 if self.flag_empty and not any(candidates):
35 t = node.get("type")
36 if t == "object":
37 return {"maxProperties": 0}, None
38 elif t == "array":
39 return {"maxItems": 0}, None
40 elif self.flag_non_empty and all(candidates):
41 t = node.get("type")
42 if t == "object":
43 return {"minProperties": 1}, None
44 elif t == "array":
45 return {"minItems": 1}, None
47 return None, None