pytest-jsonschema-snapshot 0.2.3__py3-none-any.whl → 0.2.5__py3-none-any.whl

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.
@@ -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"):
@@ -80,51 +80,61 @@ class SchemaStats:
80
80
 
81
81
  return "\n".join(parts)
82
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
+
83
130
  def print_summary(self, terminalreporter: pytest.TerminalReporter, update_mode: bool) -> None:
84
131
  """
85
132
  Prints schema summary to pytest terminal output.
86
133
  Pairs of "<name>.schema.json" + "<name>.json" are merged into one line:
87
134
  "<name>.schema.json + original" (if original is present).
135
+ Unpaired .json are shown in separate "only originals" sections.
88
136
  """
89
137
 
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
138
  if not self.has_any_info():
129
139
  return
130
140
 
@@ -132,52 +142,82 @@ class SchemaStats:
132
142
 
133
143
  # Created
134
144
  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)
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)
138
157
 
139
158
  # Updated
140
159
  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
- )
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)
155
185
 
156
186
  # Uncommitted
157
187
  if self.uncommitted:
158
188
  terminalreporter.write_line(
159
189
  f"Uncommitted minor updates ({len(self.uncommitted)}):", bold=True
160
190
  )
161
- for display, key in _iter_merged(self.uncommitted):
191
+ for display, key in self._iter_schemas(self.uncommitted): # assuming mostly schemas
162
192
  terminalreporter.write_line(f" - {display}", cyan=True)
193
+ # Show diff if available
163
194
  if key and key in self.uncommitted_diffs:
164
195
  terminalreporter.write_line(" Detected changes:", cyan=True)
165
196
  for line in self.uncommitted_diffs[key].split("\n"):
166
197
  if line.strip():
167
198
  terminalreporter.write_line(f" {line}")
168
- terminalreporter.write_line("") # разделение
199
+ terminalreporter.write_line("") # separation
169
200
  terminalreporter.write_line("Use --schema-update to commit these changes", cyan=True)
170
201
 
171
202
  # Deleted
172
203
  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)
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)
178
218
  if self.unused and not update_mode:
179
219
  terminalreporter.write_line(f"Unused schemas ({len(self.unused)}):")
180
- for display, _key in _iter_merged(self.unused):
220
+ for display, _key in self._iter_schemas(self.unused): # assuming schemas
181
221
  terminalreporter.write_line(f" - {display}")
182
222
  terminalreporter.write_line("Use --schema-update to delete unused schemas", yellow=True)
183
223
 
@@ -1,4 +1,3 @@
1
- from .genson_addon import JsonToSchemaConverter
2
1
  from .name_maker import NameMaker
3
2
 
4
- __all__ = ["JsonToSchemaConverter", "NameMaker"]
3
+ __all__ = ["NameMaker"]
@@ -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
@@ -0,0 +1,12 @@
1
+ pytest_jsonschema_snapshot/__init__.py,sha256=o7yiVh_nbK13tO4NpaE25XW3J9V2YD7fkicByUdS-iM,385
2
+ pytest_jsonschema_snapshot/core.py,sha256=fM8r8wD83litob2sheHb1jh8x8Nam4g8AnjGzk8TZ2o,12347
3
+ pytest_jsonschema_snapshot/plugin.py,sha256=nvAfxtLSX_B5FzaWu7DfsiWRxFjxDvnQNNOhkRrRnbw,8677
4
+ pytest_jsonschema_snapshot/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ pytest_jsonschema_snapshot/stats.py,sha256=BfhfMoSkRq6Q8BwhVfrpcFl5TP9OzpgpLwnKf1Kslkw,9593
6
+ pytest_jsonschema_snapshot/tools/__init__.py,sha256=WeD2EVrQpKIoFW1s43QAqsJmartqZ3Irwckt814P1bs,59
7
+ pytest_jsonschema_snapshot/tools/name_maker.py,sha256=tqss8NCGSo2aQX_-RkCJzy3NJx_TDA-xrn8qsblecf0,5799
8
+ pytest_jsonschema_snapshot-0.2.5.dist-info/METADATA,sha256=QR0VvtvzFi6fDHtGUv_sNgSSUBSTw7ZJET_Ajd09IEE,7798
9
+ pytest_jsonschema_snapshot-0.2.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
10
+ pytest_jsonschema_snapshot-0.2.5.dist-info/entry_points.txt,sha256=eJ1x4TMmhcc8YtM7IoCsUJO4-rLeTrGy8tPgkrojjKs,58
11
+ pytest_jsonschema_snapshot-0.2.5.dist-info/licenses/LICENSE,sha256=1HRFdSzlJ4BtHv6U7tZun3iCArjbCnm5NUowE9hZpNs,1071
12
+ pytest_jsonschema_snapshot-0.2.5.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,3 +0,0 @@
1
- from .to_schema_converter import JsonToSchemaConverter
2
-
3
- __all__ = ["JsonToSchemaConverter"]
@@ -1,52 +0,0 @@
1
- import re
2
- from typing import Optional
3
-
4
-
5
- class FormatDetector:
6
- """Class for detecting string formats"""
7
-
8
- # Regular expressions for various formats
9
- EMAIL_PATTERN = re.compile(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")
10
- UUID_PATTERN = re.compile(
11
- r"^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
12
- re.I,
13
- )
14
- DATE_PATTERN = re.compile(r"^\d{4}-\d{2}-\d{2}$")
15
- DATETIME_PATTERN = re.compile(
16
- r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$"
17
- )
18
- URI_PATTERN = re.compile(r"^https?://[^\s/$.?#].[^\s]*$", re.I)
19
- IPV4_PATTERN = re.compile(
20
- r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}"
21
- r"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
22
- )
23
-
24
- @classmethod
25
- def detect_format(cls, value: str) -> Optional[str]:
26
- """
27
- Detects the format of a string.
28
-
29
- Args:
30
- value: The string to analyze
31
-
32
- Returns:
33
- The name of the format or None if the format is not defined
34
- """
35
- if not isinstance(value, str) or not value:
36
- return None
37
-
38
- # Check formats from more specific to less specific
39
- if cls.EMAIL_PATTERN.match(value):
40
- return "email"
41
- elif cls.UUID_PATTERN.match(value):
42
- return "uuid"
43
- elif cls.DATETIME_PATTERN.match(value):
44
- return "date-time"
45
- elif cls.DATE_PATTERN.match(value):
46
- return "date"
47
- elif cls.URI_PATTERN.match(value):
48
- return "uri"
49
- elif cls.IPV4_PATTERN.match(value):
50
- return "ipv4"
51
-
52
- return None
@@ -1,100 +0,0 @@
1
- """Json → Schema with optional format handling.
2
-
3
- `format_mode` options
4
- ---------------------
5
- * ``"on"`` – detect formats and let validators assert them (default).
6
- * ``"off"`` – ignore formats entirely.
7
- * ``"safe"`` – keep the annotations but embed a ``$vocabulary`` block that
8
- **disables** the draft‑2020‑12 *format‑assertion* vocabulary.
9
- This makes every ``format`` purely informational, regardless
10
- of validator settings.
11
- """
12
-
13
- from typing import Any, Dict, Literal
14
-
15
- from genson import SchemaBuilder # type: ignore[import-untyped]
16
-
17
- from .format_detector import FormatDetector
18
-
19
- _FormatMode = Literal["on", "off", "safe"]
20
-
21
-
22
- class JsonToSchemaConverter(SchemaBuilder):
23
- """A thin wrapper around :class:`genson.SchemaBuilder`."""
24
-
25
- # ------------------------------------------------------------------
26
- # Construction
27
- # ------------------------------------------------------------------
28
- def __init__(
29
- self,
30
- schema_uri: str = "https://json-schema.org/draft/2020-12/schema",
31
- *,
32
- format_mode: _FormatMode = "on",
33
- ):
34
- super().__init__(schema_uri) if schema_uri else super().__init__()
35
- if format_mode not in {"on", "off", "safe"}:
36
- raise ValueError("format_mode must be 'on', 'off', or 'safe'.")
37
- self._format_mode: _FormatMode = format_mode
38
- self._format_cache: Dict[str, set[str]] = {}
39
-
40
- # ------------------------------------------------------------------
41
- # Public API (overrides)
42
- # ------------------------------------------------------------------
43
- def add_object(self, obj: Any, path: str = "root") -> None:
44
- super().add_object(obj)
45
- if self._format_mode != "off":
46
- self._collect_formats(obj, path)
47
-
48
- def to_schema(self) -> Dict[str, Any]:
49
- schema = dict(super().to_schema()) # shallow‑copy
50
-
51
- if self._format_mode != "off":
52
- self._inject_formats(schema, "root")
53
-
54
- if self._format_mode == "safe":
55
- schema.setdefault(
56
- "$vocabulary",
57
- {
58
- "https://json-schema.org/draft/2020-12/vocab/core": True,
59
- "https://json-schema.org/draft/2020-12/vocab/applicator": True,
60
- "https://json-schema.org/draft/2020-12/vocab/format-annotation": True,
61
- "https://json-schema.org/draft/2020-12/vocab/format-assertion": False,
62
- },
63
- )
64
-
65
- return schema
66
-
67
- # ------------------------------------------------------------------
68
- # Internals
69
- # ------------------------------------------------------------------
70
- def _collect_formats(self, obj: Any, path: str) -> None:
71
- if isinstance(obj, str):
72
- fmt = FormatDetector.detect_format(obj)
73
- if fmt:
74
- self._format_cache.setdefault(path, set()).add(fmt)
75
- elif isinstance(obj, dict):
76
- for k, v in obj.items():
77
- self._collect_formats(v, f"{path}.{k}")
78
- elif isinstance(obj, (list, tuple)):
79
- for i, item in enumerate(obj):
80
- self._collect_formats(item, f"{path}[{i}]")
81
-
82
- def _inject_formats(self, schema: Dict[str, Any], path: str) -> None:
83
- t = schema.get("type")
84
- if t == "string":
85
- fmts = self._format_cache.get(path)
86
- if fmts and len(fmts) == 1:
87
- schema["format"] = next(iter(fmts))
88
- elif t == "object" and "properties" in schema:
89
- for name, subschema in schema["properties"].items():
90
- self._inject_formats(subschema, f"{path}.{name}")
91
- elif t == "array" and "items" in schema:
92
- items_schema = schema["items"]
93
- if isinstance(items_schema, dict):
94
- self._inject_formats(items_schema, f"{path}[0]")
95
- else:
96
- for idx, subschema in enumerate(items_schema):
97
- self._inject_formats(subschema, f"{path}[{idx}]")
98
- elif "anyOf" in schema:
99
- for subschema in schema["anyOf"]:
100
- self._inject_formats(subschema, path)
@@ -1,15 +0,0 @@
1
- pytest_jsonschema_snapshot/__init__.py,sha256=v-YeeYwLr0JgBV0W2iNt8SEfBDFnP0TivliTh8btZYc,385
2
- pytest_jsonschema_snapshot/core.py,sha256=CoL_W-u6o3N7XDwv-MbePJiZaGX0LtGS6BLbj9MHROU,11995
3
- pytest_jsonschema_snapshot/plugin.py,sha256=nvAfxtLSX_B5FzaWu7DfsiWRxFjxDvnQNNOhkRrRnbw,8677
4
- pytest_jsonschema_snapshot/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- pytest_jsonschema_snapshot/stats.py,sha256=XGGzHY0ytMFOkFpnqNAK1DpV9iI0_fZPWrVvHFNFL3g,7943
6
- pytest_jsonschema_snapshot/tools/__init__.py,sha256=WMS6PdgMABBfTRhPGuoUOXB-R2PcqcadwH8pG1C6MFU,132
7
- pytest_jsonschema_snapshot/tools/name_maker.py,sha256=tqss8NCGSo2aQX_-RkCJzy3NJx_TDA-xrn8qsblecf0,5799
8
- pytest_jsonschema_snapshot/tools/genson_addon/__init__.py,sha256=nANkqHTaWTZPwBDztsnQvObHUZLSeHenJS--oWfep8c,92
9
- pytest_jsonschema_snapshot/tools/genson_addon/format_detector.py,sha256=Wc5pB_xstyr4OtjwJ2qqmV62xET63cN7Nb0gxkrYyW0,1636
10
- pytest_jsonschema_snapshot/tools/genson_addon/to_schema_converter.py,sha256=UdQIkZhMrTJNHwI1B1dv3aEwx41B1B_lLyr4KWiUpNY,4168
11
- pytest_jsonschema_snapshot-0.2.3.dist-info/METADATA,sha256=cMTeW3ydl2gg8dQHUqmsiLSa9l9ndSoQP5yUlzktOn4,7795
12
- pytest_jsonschema_snapshot-0.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
- pytest_jsonschema_snapshot-0.2.3.dist-info/entry_points.txt,sha256=eJ1x4TMmhcc8YtM7IoCsUJO4-rLeTrGy8tPgkrojjKs,58
14
- pytest_jsonschema_snapshot-0.2.3.dist-info/licenses/LICENSE,sha256=1HRFdSzlJ4BtHv6U7tZun3iCArjbCnm5NUowE9hZpNs,1071
15
- pytest_jsonschema_snapshot-0.2.3.dist-info/RECORD,,