pytest-jsonschema-snapshot 0.2.3__tar.gz → 0.2.4__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 (76) hide show
  1. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/PKG-INFO +1 -1
  2. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/__init__.py +1 -1
  3. pytest_jsonschema_snapshot-0.2.4/pytest_jsonschema_snapshot/stats.py +225 -0
  4. pytest_jsonschema_snapshot-0.2.3/pytest_jsonschema_snapshot/stats.py +0 -185
  5. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.flake8 +0 -0
  6. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  7. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  8. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/ISSUE_TEMPLATE/documentation_issue.yml +0 -0
  9. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  10. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/PULL_REQUEST_TEMPLATE/general.md +0 -0
  11. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/actions/build-docs/action.yml +0 -0
  12. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/workflows/release.yml +0 -0
  13. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/workflows/reusable-test.yml +0 -0
  14. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.github/workflows/test.yml +0 -0
  15. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/.gitignore +0 -0
  16. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/LICENSE +0 -0
  17. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/Makefile +0 -0
  18. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/README.md +0 -0
  19. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/assets/logo.png +0 -0
  20. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/docs/source/_static/logo_day.png +0 -0
  21. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/docs/source/_static/logo_night.png +0 -0
  22. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/docs/source/basic/quick_start.rst +0 -0
  23. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/docs/source/conf.py +0 -0
  24. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/docs/source/index.rst +0 -0
  25. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pyproject.toml +0 -0
  26. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/core.py +0 -0
  27. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/plugin.py +0 -0
  28. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/py.typed +0 -0
  29. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/tools/__init__.py +0 -0
  30. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/tools/genson_addon/__init__.py +0 -0
  31. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/tools/genson_addon/format_detector.py +0 -0
  32. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/tools/genson_addon/to_schema_converter.py +0 -0
  33. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/pytest_jsonschema_snapshot/tools/name_maker.py +0 -0
  34. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/reinstall_plugin.sh +0 -0
  35. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/requirements.txt +0 -0
  36. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/test_stats.py +0 -0
  37. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/tools/genson_addon/test_format_safe.py +0 -0
  38. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/tools/test_name_maker.py +0 -0
  39. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/TestDataClass.get_data.first.json +0 -0
  40. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/TestDataClass.get_data.first.schema.json +0 -0
  41. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/TestDataClass.get_data.json +0 -0
  42. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/TestDataClass.get_data.schema.json +0 -0
  43. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/array_formats_test.json +0 -0
  44. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/array_formats_test.schema.json +0 -0
  45. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/date_test.json +0 -0
  46. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/date_test.schema.json +0 -0
  47. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/datetime_test.json +0 -0
  48. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/datetime_test.schema.json +0 -0
  49. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/email_test.json +0 -0
  50. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/email_test.schema.json +0 -0
  51. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/get_data.first.json +0 -0
  52. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/get_data.first.schema.json +0 -0
  53. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/get_data.json +0 -0
  54. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/get_data.schema.json +0 -0
  55. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/ipv4_test.json +0 -0
  56. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/ipv4_test.schema.json +0 -0
  57. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/mixed_formats_test.json +0 -0
  58. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/mixed_formats_test.schema.json +0 -0
  59. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/multi_schema_one.json +0 -0
  60. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/multi_schema_three.json +0 -0
  61. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/multi_schema_two.json +0 -0
  62. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/regular_strings_test.json +0 -0
  63. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/regular_strings_test.schema.json +0 -0
  64. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/some_schema.json +0 -0
  65. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/some_schema.schema.json +0 -0
  66. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/strict_email_validation_test.json +0 -0
  67. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/strict_email_validation_test.schema.json +0 -0
  68. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/uri_test.json +0 -0
  69. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/uri_test.schema.json +0 -0
  70. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/uuid_test.json +0 -0
  71. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/__snapshots__/uuid_test.schema.json +0 -0
  72. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/test_base.py +0 -0
  73. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/test_base_name_callable.py +0 -0
  74. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/test_format_detection.py +0 -0
  75. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/tests/usage/test_format_validation.py +0 -0
  76. {pytest_jsonschema_snapshot-0.2.3 → pytest_jsonschema_snapshot-0.2.4}/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.4
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
@@ -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.4"
12
12
  __all__ = ["SchemaShot"]
@@ -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()
@@ -1,185 +0,0 @@
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 print_summary(self, terminalreporter: pytest.TerminalReporter, update_mode: bool) -> None:
84
- """
85
- Prints schema summary to pytest terminal output.
86
- Pairs of "<name>.schema.json" + "<name>.json" are merged into one line:
87
- "<name>.schema.json + original" (if original is present).
88
- """
89
-
90
- def _iter_merged(names: List[str]) -> Generator[tuple[str, Optional[str]], None, None]:
91
- """
92
- Iterates over (display, schema_key):
93
- - display: string to display (may have " + original")
94
- - schema_key: file name of the schema (<name>.schema.json) to find diffs,
95
- or None if it's not a schema.
96
- Preserves the original list order: merging happens at .schema.json
97
- position; single .json outputs are left as is.
98
- """
99
- names = list(names) # порядок важен
100
- schema_sfx = ".schema.json"
101
- json_sfx = ".json"
102
-
103
- # множество баз, где имеются схемы/оригиналы
104
- bases_with_schema = {n[: -len(schema_sfx)] for n in names if n.endswith(schema_sfx)}
105
- bases_with_original = {
106
- n[: -len(json_sfx)]
107
- for n in names
108
- if n.endswith(json_sfx) and not n.endswith(schema_sfx)
109
- }
110
-
111
- for n in names:
112
- if n.endswith(schema_sfx):
113
- base = n[: -len(schema_sfx)]
114
- if base in bases_with_original:
115
- yield f"{n} + original", n # display, schema_key
116
- else:
117
- yield n, n
118
- elif n.endswith(json_sfx) and not n.endswith(schema_sfx):
119
- base = n[: -len(json_sfx)]
120
- # если есть парная схема — .json не выводим отдельно
121
- if base in bases_with_schema:
122
- continue
123
- yield n, None
124
- else:
125
- # на всякий случай — прочие имена
126
- yield n, n
127
-
128
- if not self.has_any_info():
129
- return
130
-
131
- terminalreporter.write_sep("=", "Schema Summary")
132
-
133
- # Created
134
- if self.created:
135
- terminalreporter.write_line(f"Created schemas ({len(self.created)}):", green=True)
136
- for display, _key in _iter_merged(self.created):
137
- terminalreporter.write_line(f" - {display}", green=True)
138
-
139
- # Updated
140
- if self.updated:
141
- terminalreporter.write_line(f"Updated schemas ({len(self.updated)}):", yellow=True)
142
- for display, key in _iter_merged(self.updated):
143
- terminalreporter.write_line(f" - {display}", yellow=True)
144
- # Показываем diff, если он есть под ключом схемы (.schema.json)
145
- if key and key in self.updated_diffs:
146
- terminalreporter.write_line(" Changes:", yellow=True)
147
- for line in self.updated_diffs[key].split("\n"):
148
- if line.strip():
149
- terminalreporter.write_line(f" {line}")
150
- terminalreporter.write_line("") # разделение
151
- elif key:
152
- terminalreporter.write_line(
153
- " (Schema unchanged - no differences detected)", cyan=True
154
- )
155
-
156
- # Uncommitted
157
- if self.uncommitted:
158
- terminalreporter.write_line(
159
- f"Uncommitted minor updates ({len(self.uncommitted)}):", bold=True
160
- )
161
- for display, key in _iter_merged(self.uncommitted):
162
- terminalreporter.write_line(f" - {display}", cyan=True)
163
- if key and key in self.uncommitted_diffs:
164
- terminalreporter.write_line(" Detected changes:", cyan=True)
165
- for line in self.uncommitted_diffs[key].split("\n"):
166
- if line.strip():
167
- terminalreporter.write_line(f" {line}")
168
- terminalreporter.write_line("") # разделение
169
- terminalreporter.write_line("Use --schema-update to commit these changes", cyan=True)
170
-
171
- # Deleted
172
- if self.deleted:
173
- terminalreporter.write_line(f"Deleted schemas ({len(self.deleted)}):", red=True)
174
- for display, _key in _iter_merged(self.deleted):
175
- terminalreporter.write_line(f" - {display}", red=True)
176
-
177
- # Unused (только если не update_mode)
178
- if self.unused and not update_mode:
179
- terminalreporter.write_line(f"Unused schemas ({len(self.unused)}):")
180
- for display, _key in _iter_merged(self.unused):
181
- terminalreporter.write_line(f" - {display}")
182
- terminalreporter.write_line("Use --schema-update to delete unused schemas", yellow=True)
183
-
184
-
185
- GLOBAL_STATS = SchemaStats()