genschema 0.1.0__tar.gz → 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. {genschema-0.1.0 → genschema-0.1.1}/PKG-INFO +1 -1
  2. {genschema-0.1.0 → genschema-0.1.1}/genschema/__init__.py +1 -1
  3. {genschema-0.1.0 → genschema-0.1.1}/genschema/cli.py +8 -0
  4. {genschema-0.1.0 → genschema-0.1.1}/genschema/comparators/__init__.py +2 -0
  5. genschema-0.1.1/genschema/comparators/required.py +57 -0
  6. genschema-0.1.1/genschema/comparators/schema_version.py +18 -0
  7. {genschema-0.1.0 → genschema-0.1.1}/genschema/pipeline.py +5 -0
  8. {genschema-0.1.0 → genschema-0.1.1}/genschema.egg-info/PKG-INFO +1 -1
  9. {genschema-0.1.0 → genschema-0.1.1}/genschema.egg-info/SOURCES.txt +1 -0
  10. genschema-0.1.0/genschema/comparators/required.py +0 -38
  11. {genschema-0.1.0 → genschema-0.1.1}/LICENSE +0 -0
  12. {genschema-0.1.0 → genschema-0.1.1}/README.md +0 -0
  13. {genschema-0.1.0 → genschema-0.1.1}/genschema/comparators/delete_element.py +0 -0
  14. {genschema-0.1.0 → genschema-0.1.1}/genschema/comparators/empty.py +0 -0
  15. {genschema-0.1.0 → genschema-0.1.1}/genschema/comparators/flag.py +0 -0
  16. {genschema-0.1.0 → genschema-0.1.1}/genschema/comparators/format.py +0 -0
  17. {genschema-0.1.0 → genschema-0.1.1}/genschema/comparators/no_additional_prop.py +0 -0
  18. {genschema-0.1.0 → genschema-0.1.1}/genschema/comparators/template.py +0 -0
  19. {genschema-0.1.0 → genschema-0.1.1}/genschema/comparators/type.py +0 -0
  20. {genschema-0.1.0 → genschema-0.1.1}/genschema/node.py +0 -0
  21. {genschema-0.1.0 → genschema-0.1.1}/genschema/pseudo_arrays.py +0 -0
  22. {genschema-0.1.0 → genschema-0.1.1}/genschema/py.typed +0 -0
  23. {genschema-0.1.0 → genschema-0.1.1}/genschema.egg-info/dependency_links.txt +0 -0
  24. {genschema-0.1.0 → genschema-0.1.1}/genschema.egg-info/entry_points.txt +0 -0
  25. {genschema-0.1.0 → genschema-0.1.1}/genschema.egg-info/requires.txt +0 -0
  26. {genschema-0.1.0 → genschema-0.1.1}/genschema.egg-info/top_level.txt +0 -0
  27. {genschema-0.1.0 → genschema-0.1.1}/pyproject.toml +0 -0
  28. {genschema-0.1.0 → genschema-0.1.1}/setup.cfg +0 -0
  29. {genschema-0.1.0 → genschema-0.1.1}/tests/test_check_datasets.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genschema
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: A library for comparing JSON and schemas and generate new
5
5
  Author-email: Miskler <mail@miskler.ru>
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -2,4 +2,4 @@ from .pipeline import Converter
2
2
  from .pseudo_arrays import PseudoArrayHandler, PseudoArrayHandlerBase
3
3
 
4
4
  __all__ = ["Converter", "PseudoArrayHandler", "PseudoArrayHandlerBase"]
5
- __version__ = "0.1.0"
5
+ __version__ = "0.1.1"
@@ -11,6 +11,7 @@ from .comparators import (
11
11
  EmptyComparator,
12
12
  FormatComparator,
13
13
  RequiredComparator,
14
+ SchemaVersionComparator,
14
15
  )
15
16
 
16
17
  console = Console()
@@ -52,6 +53,11 @@ Examples:
52
53
  parser.add_argument("--no-format", action="store_true", help="Disable FormatComparator.")
53
54
  parser.add_argument("--no-required", action="store_true", help="Disable RequiredComparator.")
54
55
  parser.add_argument("--no-empty", action="store_true", help="Disable EmptyComparator.")
56
+ parser.add_argument(
57
+ "--no-schema-version",
58
+ action="store_true",
59
+ help="Disable SchemaVersionComparator.",
60
+ )
55
61
  parser.add_argument(
56
62
  "--no-delete-element", action="store_true", help="Disable DeleteElement comparators."
57
63
  )
@@ -108,6 +114,8 @@ Examples:
108
114
  # Register comparators conditionally
109
115
  if not args.no_format:
110
116
  conv.register(FormatComparator())
117
+ if not args.no_schema_version:
118
+ conv.register(SchemaVersionComparator())
111
119
  if not args.no_required:
112
120
  conv.register(RequiredComparator())
113
121
  if not args.no_empty:
@@ -4,6 +4,7 @@ from .flag import FlagMaker
4
4
  from .format import FormatComparator
5
5
  from .no_additional_prop import NoAdditionalProperties
6
6
  from .required import RequiredComparator
7
+ from .schema_version import SchemaVersionComparator
7
8
  from .type import TypeComparator
8
9
 
9
10
  __all__ = [
@@ -14,4 +15,5 @@ __all__ = [
14
15
  "EmptyComparator",
15
16
  "NoAdditionalProperties",
16
17
  "DeleteElement",
18
+ "SchemaVersionComparator",
17
19
  ]
@@ -0,0 +1,57 @@
1
+ import logging
2
+
3
+ from .template import Comparator, ComparatorResult, ProcessingContext
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ class RequiredComparator(Comparator):
9
+ """
10
+ Компаратор для определения обязательных полей.
11
+ Устанавливает "required" на основе наличия ключей в JSON на текущем уровне.
12
+ """
13
+
14
+ def can_process(self, ctx: ProcessingContext, env: str, node: dict) -> bool:
15
+ # обрабатываем только объекты
16
+ return (
17
+ (node.get("type") == "object" and not node.get("isPseudoArray", False))
18
+ or node.get("type") is None
19
+ or not ctx.jsons
20
+ )
21
+
22
+ def process(self, ctx: ProcessingContext, env: str, node: dict) -> ComparatorResult:
23
+ required_sets: list[set[str]] = []
24
+
25
+ # Если есть хотя бы один JSON, который не является объектом,
26
+ # мы не можем корректно определить обязательные ключи.
27
+ if ctx.jsons and any(not isinstance(j.content, dict) for j in ctx.jsons):
28
+ return None, None
29
+
30
+ # ---------- из json ----------
31
+ objects = [j.content for j in ctx.jsons if isinstance(j.content, dict)]
32
+ if objects:
33
+ keys: set[str] = set()
34
+ for obj in objects:
35
+ keys.update(obj.keys())
36
+
37
+ required_from_json = {k for k in keys if all(k in obj for obj in objects)}
38
+ required_sets.append(required_from_json)
39
+
40
+ # ---------- из схем ----------
41
+ for schema in ctx.schemas:
42
+ content = schema.content
43
+ if not isinstance(content, dict):
44
+ continue
45
+ req = content.get("required")
46
+ if isinstance(req, list):
47
+ required_sets.append(set(req))
48
+
49
+ if not required_sets:
50
+ return None, None
51
+
52
+ # ---------- минимальное пересечение ----------
53
+ required = sorted(set.intersection(*required_sets))
54
+
55
+ if required:
56
+ return {"required": required}, None
57
+ return None, None
@@ -0,0 +1,18 @@
1
+ from .template import Comparator, ComparatorResult, ProcessingContext
2
+
3
+
4
+ class SchemaVersionComparator(Comparator):
5
+ """
6
+ Компаратор для установки версии JSON Schema на верхнем уровне.
7
+ """
8
+
9
+ name = "schema_version"
10
+
11
+ def __init__(self, version: str = "https://json-schema.org/draft/2020-12/schema"):
12
+ self._version = version
13
+
14
+ def can_process(self, ctx: ProcessingContext, env: str, prev_result: dict) -> bool:
15
+ return env == "/" and "$schema" not in prev_result
16
+
17
+ def process(self, ctx: ProcessingContext, env: str, prev_result: dict) -> ComparatorResult:
18
+ return {"$schema": self._version}, None
@@ -57,6 +57,11 @@ class Converter:
57
57
  self._jsons.append(Resource(str(self._id), "json", j))
58
58
  self._id += 1
59
59
 
60
+ def clear_data(self) -> None:
61
+ self._id = 0
62
+ self._jsons = []
63
+ self._schemas = []
64
+
60
65
  def register(self, c: Comparator) -> None:
61
66
  if isinstance(c, TypeComparator):
62
67
  raise UserWarning(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: genschema
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: A library for comparing JSON and schemas and generate new
5
5
  Author-email: Miskler <mail@miskler.ru>
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -20,6 +20,7 @@ genschema/comparators/flag.py
20
20
  genschema/comparators/format.py
21
21
  genschema/comparators/no_additional_prop.py
22
22
  genschema/comparators/required.py
23
+ genschema/comparators/schema_version.py
23
24
  genschema/comparators/template.py
24
25
  genschema/comparators/type.py
25
26
  tests/test_check_datasets.py
@@ -1,38 +0,0 @@
1
- import logging
2
-
3
- from .template import Comparator, ComparatorResult, ProcessingContext
4
-
5
- logger = logging.getLogger(__name__)
6
-
7
-
8
- class RequiredComparator(Comparator):
9
- """
10
- Компаратор для определения обязательных полей.
11
- Устанавливает "required" на основе наличия ключей в JSON на текущем уровне.
12
- """
13
-
14
- def can_process(self, ctx: ProcessingContext, env: str, node: dict) -> bool:
15
- # обрабатываем только объекты
16
- return (
17
- (node.get("type") == "object" and not node.get("isPseudoArray", False))
18
- or node.get("type") is None
19
- or not ctx.jsons
20
- )
21
-
22
- def process(self, ctx: ProcessingContext, env: str, node: dict) -> ComparatorResult:
23
- # собираем все ключи в JSON на этом уровне
24
- keys: set[str] = set()
25
- for j in ctx.jsons:
26
- if isinstance(j.content, dict):
27
- keys.update(j.content.keys())
28
-
29
- # определяем обязательные: ключи, которые есть во всех JSON
30
- required = [
31
- k
32
- for k in sorted(keys)
33
- if all(isinstance(j.content, dict) and k in j.content for j in ctx.jsons)
34
- ]
35
-
36
- if required:
37
- return {"required": required}, None
38
- return None, None
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes