pytest-jsonschema-snapshot 0.2.3__tar.gz → 0.2.5__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 (79) hide show
  1. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/PKG-INFO +2 -2
  2. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/pyproject.toml +1 -1
  3. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/pytest_jsonschema_snapshot/__init__.py +1 -1
  4. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/pytest_jsonschema_snapshot/core.py +27 -12
  5. pytest_jsonschema_snapshot-0.2.5/pytest_jsonschema_snapshot/stats.py +225 -0
  6. pytest_jsonschema_snapshot-0.2.5/pytest_jsonschema_snapshot/tools/__init__.py +3 -0
  7. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/requirements.txt +1 -1
  8. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/TestDataClass.get_data.first.schema.json +15 -15
  9. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/TestDataClass.get_data.schema.json +15 -15
  10. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/array_formats_test.schema.json +11 -11
  11. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/date_test.schema.json +6 -6
  12. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/datetime_test.schema.json +6 -6
  13. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/email_test.schema.json +8 -8
  14. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/get_data.first.schema.json +15 -15
  15. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/get_data.schema.json +15 -15
  16. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/ipv4_test.schema.json +8 -8
  17. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/mixed_formats_test.schema.json +20 -20
  18. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/regular_strings_test.schema.json +9 -9
  19. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/some_schema.schema.json +72 -103
  20. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/strict_email_validation_test.schema.json +5 -5
  21. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/uri_test.schema.json +8 -8
  22. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/uuid_test.schema.json +6 -6
  23. pytest_jsonschema_snapshot-0.2.5/tt.py +183 -0
  24. pytest_jsonschema_snapshot-0.2.5/yy.py +138 -0
  25. pytest_jsonschema_snapshot-0.2.3/pytest_jsonschema_snapshot/stats.py +0 -185
  26. pytest_jsonschema_snapshot-0.2.3/pytest_jsonschema_snapshot/tools/__init__.py +0 -4
  27. pytest_jsonschema_snapshot-0.2.3/pytest_jsonschema_snapshot/tools/genson_addon/__init__.py +0 -3
  28. pytest_jsonschema_snapshot-0.2.3/pytest_jsonschema_snapshot/tools/genson_addon/format_detector.py +0 -52
  29. pytest_jsonschema_snapshot-0.2.3/pytest_jsonschema_snapshot/tools/genson_addon/to_schema_converter.py +0 -100
  30. pytest_jsonschema_snapshot-0.2.3/tests/tools/genson_addon/test_format_safe.py +0 -82
  31. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.flake8 +0 -0
  32. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  33. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  34. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/ISSUE_TEMPLATE/documentation_issue.yml +0 -0
  35. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  36. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/PULL_REQUEST_TEMPLATE/general.md +0 -0
  37. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/actions/build-docs/action.yml +0 -0
  38. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/workflows/release.yml +0 -0
  39. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/workflows/reusable-test.yml +0 -0
  40. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.github/workflows/test.yml +0 -0
  41. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/.gitignore +0 -0
  42. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/LICENSE +0 -0
  43. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/Makefile +0 -0
  44. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/README.md +0 -0
  45. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/assets/logo.png +0 -0
  46. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/docs/source/_static/logo_day.png +0 -0
  47. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/docs/source/_static/logo_night.png +0 -0
  48. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/docs/source/basic/quick_start.rst +0 -0
  49. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/docs/source/conf.py +0 -0
  50. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/docs/source/index.rst +0 -0
  51. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/pytest_jsonschema_snapshot/plugin.py +0 -0
  52. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/pytest_jsonschema_snapshot/py.typed +0 -0
  53. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/pytest_jsonschema_snapshot/tools/name_maker.py +0 -0
  54. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/reinstall_plugin.sh +0 -0
  55. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/test_stats.py +0 -0
  56. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/tools/test_name_maker.py +0 -0
  57. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/TestDataClass.get_data.first.json +0 -0
  58. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/TestDataClass.get_data.json +0 -0
  59. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/array_formats_test.json +0 -0
  60. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/date_test.json +0 -0
  61. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/datetime_test.json +0 -0
  62. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/email_test.json +0 -0
  63. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/get_data.first.json +0 -0
  64. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/get_data.json +0 -0
  65. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/ipv4_test.json +0 -0
  66. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/mixed_formats_test.json +0 -0
  67. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/multi_schema_one.json +0 -0
  68. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/multi_schema_three.json +0 -0
  69. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/multi_schema_two.json +0 -0
  70. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/regular_strings_test.json +0 -0
  71. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/some_schema.json +0 -0
  72. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/strict_email_validation_test.json +0 -0
  73. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/uri_test.json +0 -0
  74. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/__snapshots__/uuid_test.json +0 -0
  75. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/test_base.py +0 -0
  76. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/test_base_name_callable.py +0 -0
  77. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/test_format_detection.py +0 -0
  78. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/test_format_validation.py +0 -0
  79. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.5}/tests/usage/test_multiple_schema_creation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-jsonschema-snapshot
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: Pytest plugin for automatic JSON Schema generation and validation from examples
5
5
  Project-URL: Homepage, https://miskler.github.io/pytest-jsonschema-snapshot/basic/quick_start.html
6
6
  Project-URL: Repository, https://github.com/Miskler/pytest-jsonschema-snapshot
@@ -22,7 +22,7 @@ Classifier: Programming Language :: Python :: 3.13
22
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
23
  Classifier: Topic :: Utilities
24
24
  Requires-Python: >=3.10
25
- Requires-Dist: genson
25
+ Requires-Dist: genschema
26
26
  Requires-Dist: jsonschema
27
27
  Requires-Dist: jsonschema-diff
28
28
  Requires-Dist: pathvalidate
@@ -27,7 +27,7 @@ classifiers = [
27
27
  "Topic :: Utilities"
28
28
  ]
29
29
  dependencies = [
30
- "genson",
30
+ "genschema",
31
31
  "pathvalidate",
32
32
  "jsonschema",
33
33
  "jsonschema-diff",
@@ -8,5 +8,5 @@ pytest-typed-schema-shot
8
8
 
9
9
  from .core import SchemaShot
10
10
 
11
- __version__ = "0.2.3"
11
+ __version__ = "0.2.5"
12
12
  __all__ = ["SchemaShot"]
@@ -13,10 +13,17 @@ if TYPE_CHECKING:
13
13
  from jsonschema_diff import JsonSchemaDiff
14
14
 
15
15
  import pytest
16
+ from genschema import Converter, PseudoArrayHandler
17
+ from genschema.comparators import (
18
+ DeleteElement,
19
+ FormatComparator,
20
+ RequiredComparator,
21
+ SchemaVersionComparator,
22
+ )
16
23
  from jsonschema import FormatChecker, ValidationError, validate
17
24
 
18
25
  from .stats import GLOBAL_STATS
19
- from .tools import JsonToSchemaConverter, NameMaker
26
+ from .tools import NameMaker
20
27
 
21
28
 
22
29
  class SchemaShot:
@@ -54,6 +61,17 @@ class SchemaShot:
54
61
  self.snapshot_dir: Path = root_dir / snapshot_dir_name
55
62
  self.used_schemas: Set[str] = set()
56
63
 
64
+ self.conv = Converter(
65
+ pseudo_handler=PseudoArrayHandler(),
66
+ base_of="anyOf",
67
+ )
68
+ self.conv.register(FormatComparator())
69
+ self.conv.register(RequiredComparator())
70
+ # self.conv.register(EmptyComparator())
71
+ self.conv.register(SchemaVersionComparator())
72
+ self.conv.register(DeleteElement())
73
+ self.conv.register(DeleteElement("isPseudoArray"))
74
+
57
75
  self.logger = logging.getLogger(__name__)
58
76
  # добавляем вывод в stderr
59
77
  handler = logging.StreamHandler()
@@ -144,11 +162,9 @@ class SchemaShot:
144
162
 
145
163
  real_name = self._process_name(name)
146
164
 
147
- builder = JsonToSchemaConverter(
148
- format_mode=self.format_mode # type: ignore[arg-type]
149
- ) # , examples=self.examples_limit)
150
- builder.add_object(data)
151
- current_schema = builder.to_schema()
165
+ self.conv.clear_data()
166
+ self.conv.add_schema(data)
167
+ current_schema = self.conv.run()
152
168
 
153
169
  real_name, status = self._base_match(data, current_schema, real_name)
154
170
 
@@ -234,12 +250,11 @@ class SchemaShot:
234
250
  schema_updated = False
235
251
 
236
252
  def merge_schemas(old: dict, new: dict) -> dict:
237
- builder = JsonToSchemaConverter(
238
- format_mode=self.format_mode # type: ignore[arg-type]
239
- ) # , examples=self.examples_limit)
240
- builder.add_schema(old)
241
- builder.add_schema(new)
242
- return builder.to_schema()
253
+ self.conv.clear_data()
254
+ self.conv.add_schema(old)
255
+ self.conv.add_schema(new)
256
+ result = self.conv.run()
257
+ return result
243
258
 
244
259
  if existing_schema != current_schema: # есть отличия
245
260
  if (self.update_mode or self.reset_mode) and self.update_actions.get("update"):
@@ -0,0 +1,225 @@
1
+ """
2
+ Module for collecting and displaying statistics about schemas.
3
+ """
4
+
5
+ from typing import Dict, Generator, List, Optional
6
+
7
+ import pytest
8
+
9
+
10
+ class SchemaStats:
11
+ """Class for collecting and displaying statistics about schemas"""
12
+
13
+ def __init__(self) -> None:
14
+ self.created: List[str] = []
15
+ self.updated: List[str] = []
16
+ self.updated_diffs: Dict[str, str] = {} # schema_name -> diff
17
+ self.uncommitted: List[str] = [] # New category for uncommitted changes
18
+ self.uncommitted_diffs: Dict[str, str] = {} # schema_name -> diff
19
+ self.deleted: List[str] = []
20
+ self.unused: List[str] = []
21
+
22
+ def add_created(self, schema_name: str) -> None:
23
+ """Adds created schema"""
24
+ self.created.append(schema_name)
25
+
26
+ def add_updated(self, schema_name: str, diff: Optional[str] = None) -> None:
27
+ """Adds updated schema"""
28
+ # Generate diff if both schemas are provided
29
+ if diff and diff.strip():
30
+ self.updated.append(schema_name)
31
+ self.updated_diffs[schema_name] = diff
32
+ else:
33
+ # If schemas are not provided, assume it was an update
34
+ self.updated.append(schema_name)
35
+
36
+ def add_uncommitted(self, schema_name: str, diff: Optional[str] = None) -> None:
37
+ """Adds schema with uncommitted changes"""
38
+ # Add only if there are real changes
39
+ if diff and diff.strip():
40
+ self.uncommitted.append(schema_name)
41
+ self.uncommitted_diffs[schema_name] = diff
42
+
43
+ def add_deleted(self, schema_name: str) -> None:
44
+ """Adds deleted schema"""
45
+ self.deleted.append(schema_name)
46
+
47
+ def add_unused(self, schema_name: str) -> None:
48
+ """Adds unused schema"""
49
+ self.unused.append(schema_name)
50
+
51
+ def has_changes(self) -> bool:
52
+ """Returns True if any schema has changes"""
53
+ return bool(self.created or self.updated or self.deleted)
54
+
55
+ def has_any_info(self) -> bool:
56
+ """Is there any information about schemas"""
57
+ return bool(self.created or self.updated or self.deleted or self.unused or self.uncommitted)
58
+
59
+ def __str__(self) -> str:
60
+ parts = []
61
+ if self.created:
62
+ parts.append(
63
+ f"Created schemas ({len(self.created)}): "
64
+ + ", ".join(f"`{s}`" for s in self.created)
65
+ )
66
+ if self.updated:
67
+ parts.append(
68
+ f"Updated schemas ({len(self.updated)}): "
69
+ + ", ".join(f"`{s}`" for s in self.updated)
70
+ )
71
+ if self.deleted:
72
+ parts.append(
73
+ f"Deleted schemas ({len(self.deleted)}): "
74
+ + ", ".join(f"`{s}`" for s in self.deleted)
75
+ )
76
+ if self.unused:
77
+ parts.append(
78
+ f"Unused schemas ({len(self.unused)}): " + ", ".join(f"`{s}`" for s in self.unused)
79
+ )
80
+
81
+ return "\n".join(parts)
82
+
83
+ def _iter_schemas(self, names: List[str]) -> Generator[tuple[str, Optional[str]], None, None]:
84
+ """
85
+ Iterates over schema displays: (display, schema_key)
86
+ - display: string to display (may have " + original")
87
+ - schema_key: file name of the schema (<name>.schema.json) to find diffs,
88
+ or None if it's not a schema.
89
+ Preserves the original list order: merging happens at .schema.json
90
+ position; skips .json if paired with schema.
91
+ """
92
+ names = list(names) # order matters
93
+ schema_sfx = ".schema.json"
94
+ json_sfx = ".json"
95
+
96
+ # sets of bases
97
+ # bases_with_schema = {n[: -len(schema_sfx)] for n in names if n.endswith(schema_sfx)}
98
+ bases_with_original = {
99
+ n[: -len(json_sfx)]
100
+ for n in names
101
+ if n.endswith(json_sfx) and not n.endswith(schema_sfx)
102
+ }
103
+
104
+ for n in names:
105
+ if n.endswith(schema_sfx):
106
+ base = n[: -len(schema_sfx)]
107
+ if base in bases_with_original:
108
+ yield f"{n} + original", n # display, schema_key
109
+ else:
110
+ yield n, n
111
+ # if .json, skip if paired
112
+ # if other, yield n, n (but assume all are .json or .schema.json)
113
+
114
+ def _iter_only_originals(self, names: List[str]) -> Generator[str, None, None]:
115
+ """
116
+ Iterates over only unpaired .json files, in the order they appear.
117
+ """
118
+ names = list(names) # order matters
119
+ schema_sfx = ".schema.json"
120
+ json_sfx = ".json"
121
+
122
+ bases_with_schema = {n[: -len(schema_sfx)] for n in names if n.endswith(schema_sfx)}
123
+
124
+ for n in names:
125
+ if n.endswith(json_sfx) and not n.endswith(schema_sfx):
126
+ base = n[: -len(json_sfx)]
127
+ if base not in bases_with_schema:
128
+ yield n
129
+
130
+ def print_summary(self, terminalreporter: pytest.TerminalReporter, update_mode: bool) -> None:
131
+ """
132
+ Prints schema summary to pytest terminal output.
133
+ Pairs of "<name>.schema.json" + "<name>.json" are merged into one line:
134
+ "<name>.schema.json + original" (if original is present).
135
+ Unpaired .json are shown in separate "only originals" sections.
136
+ """
137
+
138
+ if not self.has_any_info():
139
+ return
140
+
141
+ terminalreporter.write_sep("=", "Schema Summary")
142
+
143
+ # Created
144
+ if self.created:
145
+ schemas = list(self._iter_schemas(self.created))
146
+ only_originals = list(self._iter_only_originals(self.created))
147
+ if schemas:
148
+ terminalreporter.write_line(f"Created schemas ({len(schemas)}):", green=True)
149
+ for display, _key in schemas:
150
+ terminalreporter.write_line(f" - {display}", green=True)
151
+ if only_originals:
152
+ terminalreporter.write_line(
153
+ f"Created only originals ({len(only_originals)}):", green=True
154
+ )
155
+ for display in only_originals:
156
+ terminalreporter.write_line(f" - {display}", green=True)
157
+
158
+ # Updated
159
+ if self.updated:
160
+ schemas = list(self._iter_schemas(self.updated))
161
+ only_originals = list(self._iter_only_originals(self.updated))
162
+ if schemas:
163
+ terminalreporter.write_line(f"Updated schemas ({len(schemas)}):", yellow=True)
164
+ for display, key in schemas:
165
+ terminalreporter.write_line(f" - {display}", yellow=True)
166
+ # Show diff if available for schema
167
+ if key and key in self.updated_diffs:
168
+ diff = self.updated_diffs[key]
169
+ if diff.strip():
170
+ terminalreporter.write_line(" Changes:", yellow=True)
171
+ for line in diff.split("\n"):
172
+ if line.strip():
173
+ terminalreporter.write_line(f" {line}")
174
+ terminalreporter.write_line("") # separation
175
+ else:
176
+ terminalreporter.write_line(
177
+ " (Schema unchanged - no differences detected)", cyan=True
178
+ )
179
+ if only_originals:
180
+ terminalreporter.write_line(
181
+ f"Updated only originals ({len(only_originals)}):", yellow=True
182
+ )
183
+ for display in only_originals:
184
+ terminalreporter.write_line(f" - {display}", yellow=True)
185
+
186
+ # Uncommitted
187
+ if self.uncommitted:
188
+ terminalreporter.write_line(
189
+ f"Uncommitted minor updates ({len(self.uncommitted)}):", bold=True
190
+ )
191
+ for display, key in self._iter_schemas(self.uncommitted): # assuming mostly schemas
192
+ terminalreporter.write_line(f" - {display}", cyan=True)
193
+ # Show diff if available
194
+ if key and key in self.uncommitted_diffs:
195
+ terminalreporter.write_line(" Detected changes:", cyan=True)
196
+ for line in self.uncommitted_diffs[key].split("\n"):
197
+ if line.strip():
198
+ terminalreporter.write_line(f" {line}")
199
+ terminalreporter.write_line("") # separation
200
+ terminalreporter.write_line("Use --schema-update to commit these changes", cyan=True)
201
+
202
+ # Deleted
203
+ if self.deleted:
204
+ schemas = list(self._iter_schemas(self.deleted))
205
+ only_originals = list(self._iter_only_originals(self.deleted))
206
+ if schemas:
207
+ terminalreporter.write_line(f"Deleted schemas ({len(schemas)}):", red=True)
208
+ for display, _key in schemas:
209
+ terminalreporter.write_line(f" - {display}", red=True)
210
+ if only_originals:
211
+ terminalreporter.write_line(
212
+ f"Deleted only originals ({len(only_originals)}):", red=True
213
+ )
214
+ for display in only_originals:
215
+ terminalreporter.write_line(f" - {display}", red=True)
216
+
217
+ # Unused (only if not update_mode)
218
+ if self.unused and not update_mode:
219
+ terminalreporter.write_line(f"Unused schemas ({len(self.unused)}):")
220
+ for display, _key in self._iter_schemas(self.unused): # assuming schemas
221
+ terminalreporter.write_line(f" - {display}")
222
+ terminalreporter.write_line("Use --schema-update to delete unused schemas", yellow=True)
223
+
224
+
225
+ GLOBAL_STATS = SchemaStats()
@@ -0,0 +1,3 @@
1
+ from .name_maker import NameMaker
2
+
3
+ __all__ = ["NameMaker"]
@@ -1,4 +1,4 @@
1
- genson
1
+ genschema
2
2
  pathvalidate
3
3
  jsonschema
4
4
  jsonschema-diff
@@ -1,15 +1,24 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "необязательная",
5
+ "обязательная",
6
+ "словарь"
7
+ ],
8
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
9
  "properties": {
5
- "обязательная": {
6
- "type": "string"
7
- },
8
10
  "необязательная": {
9
11
  "type": "null"
10
12
  },
13
+ "обязательная": {
14
+ "type": "string"
15
+ },
11
16
  "словарь": {
12
17
  "type": "object",
18
+ "required": [
19
+ "ключ",
20
+ "число"
21
+ ],
13
22
  "properties": {
14
23
  "ключ": {
15
24
  "type": "string"
@@ -17,16 +26,7 @@
17
26
  "число": {
18
27
  "type": "integer"
19
28
  }
20
- },
21
- "required": [
22
- "ключ",
23
- "число"
24
- ]
29
+ }
25
30
  }
26
- },
27
- "required": [
28
- "необязательная",
29
- "обязательная",
30
- "словарь"
31
- ]
31
+ }
32
32
  }
@@ -1,15 +1,24 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "необязательная",
5
+ "обязательная",
6
+ "словарь"
7
+ ],
8
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
9
  "properties": {
5
- "обязательная": {
6
- "type": "string"
7
- },
8
10
  "необязательная": {
9
11
  "type": "null"
10
12
  },
13
+ "обязательная": {
14
+ "type": "string"
15
+ },
11
16
  "словарь": {
12
17
  "type": "object",
18
+ "required": [
19
+ "ключ",
20
+ "число"
21
+ ],
13
22
  "properties": {
14
23
  "ключ": {
15
24
  "type": "string"
@@ -17,16 +26,7 @@
17
26
  "число": {
18
27
  "type": "integer"
19
28
  }
20
- },
21
- "required": [
22
- "ключ",
23
- "число"
24
- ]
29
+ }
25
30
  }
26
- },
27
- "required": [
28
- "необязательная",
29
- "обязательная",
30
- "словарь"
31
- ]
31
+ }
32
32
  }
@@ -1,19 +1,24 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "dates",
5
+ "emails",
6
+ "uuids"
7
+ ],
8
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
9
  "properties": {
5
- "emails": {
10
+ "dates": {
6
11
  "type": "array",
7
12
  "items": {
8
13
  "type": "string",
9
- "format": "email"
14
+ "format": "date"
10
15
  }
11
16
  },
12
- "dates": {
17
+ "emails": {
13
18
  "type": "array",
14
19
  "items": {
15
20
  "type": "string",
16
- "format": "date"
21
+ "format": "email"
17
22
  }
18
23
  },
19
24
  "uuids": {
@@ -23,10 +28,5 @@
23
28
  "format": "uuid"
24
29
  }
25
30
  }
26
- },
27
- "required": [
28
- "dates",
29
- "emails",
30
- "uuids"
31
- ]
31
+ }
32
32
  }
@@ -1,6 +1,10 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "birth_date",
5
+ "registration_date"
6
+ ],
7
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
8
  "properties": {
5
9
  "birth_date": {
6
10
  "type": "string",
@@ -10,9 +14,5 @@
10
14
  "type": "string",
11
15
  "format": "date"
12
16
  }
13
- },
14
- "required": [
15
- "birth_date",
16
- "registration_date"
17
- ]
17
+ }
18
18
  }
@@ -1,6 +1,10 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "created_at",
5
+ "updated_at"
6
+ ],
7
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
8
  "properties": {
5
9
  "created_at": {
6
10
  "type": "string",
@@ -10,9 +14,5 @@
10
14
  "type": "string",
11
15
  "format": "date-time"
12
16
  }
13
- },
14
- "required": [
15
- "created_at",
16
- "updated_at"
17
- ]
17
+ }
18
18
  }
@@ -1,18 +1,18 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "admin_email",
5
+ "user_email"
6
+ ],
7
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
8
  "properties": {
5
- "user_email": {
9
+ "admin_email": {
6
10
  "type": "string",
7
11
  "format": "email"
8
12
  },
9
- "admin_email": {
13
+ "user_email": {
10
14
  "type": "string",
11
15
  "format": "email"
12
16
  }
13
- },
14
- "required": [
15
- "admin_email",
16
- "user_email"
17
- ]
17
+ }
18
18
  }
@@ -1,15 +1,24 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "необязательная",
5
+ "обязательная",
6
+ "словарь"
7
+ ],
8
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
9
  "properties": {
5
- "обязательная": {
6
- "type": "string"
7
- },
8
10
  "необязательная": {
9
11
  "type": "null"
10
12
  },
13
+ "обязательная": {
14
+ "type": "string"
15
+ },
11
16
  "словарь": {
12
17
  "type": "object",
18
+ "required": [
19
+ "ключ",
20
+ "число"
21
+ ],
13
22
  "properties": {
14
23
  "ключ": {
15
24
  "type": "string"
@@ -17,16 +26,7 @@
17
26
  "число": {
18
27
  "type": "integer"
19
28
  }
20
- },
21
- "required": [
22
- "ключ",
23
- "число"
24
- ]
29
+ }
25
30
  }
26
- },
27
- "required": [
28
- "необязательная",
29
- "обязательная",
30
- "словарь"
31
- ]
31
+ }
32
32
  }
@@ -1,15 +1,24 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "необязательная",
5
+ "обязательная",
6
+ "словарь"
7
+ ],
8
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
9
  "properties": {
5
- "обязательная": {
6
- "type": "string"
7
- },
8
10
  "необязательная": {
9
11
  "type": "null"
10
12
  },
13
+ "обязательная": {
14
+ "type": "string"
15
+ },
11
16
  "словарь": {
12
17
  "type": "object",
18
+ "required": [
19
+ "ключ",
20
+ "число"
21
+ ],
13
22
  "properties": {
14
23
  "ключ": {
15
24
  "type": "string"
@@ -17,16 +26,7 @@
17
26
  "число": {
18
27
  "type": "integer"
19
28
  }
20
- },
21
- "required": [
22
- "ключ",
23
- "число"
24
- ]
29
+ }
25
30
  }
26
- },
27
- "required": [
28
- "необязательная",
29
- "обязательная",
30
- "словарь"
31
- ]
31
+ }
32
32
  }
@@ -1,18 +1,18 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
2
  "type": "object",
3
+ "required": [
4
+ "gateway",
5
+ "server_ip"
6
+ ],
7
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
8
  "properties": {
5
- "server_ip": {
9
+ "gateway": {
6
10
  "type": "string",
7
11
  "format": "ipv4"
8
12
  },
9
- "gateway": {
13
+ "server_ip": {
10
14
  "type": "string",
11
15
  "format": "ipv4"
12
16
  }
13
- },
14
- "required": [
15
- "gateway",
16
- "server_ip"
17
- ]
17
+ }
18
18
  }