structurize 3.7.3__tar.gz → 3.7.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.
- {structurize-3.7.3/structurize.egg-info → structurize-3.7.4}/PKG-INFO +1 -1
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/_version.py +3 -3
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jsonstostructure.py +169 -12
- {structurize-3.7.3 → structurize-3.7.4/structurize.egg-info}/PKG-INFO +1 -1
- {structurize-3.7.3 → structurize-3.7.4}/.gitignore +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/LICENSE +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/MANIFEST.in +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/README.md +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/__init__.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/__main__.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/asn1toavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotize.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotocapnproto.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotocpp.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotocsharp.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotocsv.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotocue.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotodatapackage.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotodb.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotoflatbuffers.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotogo.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotographql.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotoiceberg.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotojava.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotojs.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotojsons.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotojstruct.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotojtd.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotokusto.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotomd.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotools.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotoparquet.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotoproto.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotopython.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotoraml.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotorust.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotosmithy.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotosurreal.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotothrift.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotots.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrototsml.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrotoxsd.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/avrovalidator.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/capnprototoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/cddltostructure.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/choice_inference.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/commands.json +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/common.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/constants.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/csvtoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/cuetoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/cuetostructure.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/datapackagetoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/dependencies/cpp/vcpkg/vcpkg.json +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/dependencies/typescript/node22/package.json +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/dependency_resolver.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/dependency_version.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/flatbufferstoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/flatbufferstojstruct.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jsonstoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jsontoschema.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jstructtoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jstructtoflatbuffers.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jstructtoraml.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jstructtosmithy.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jtdtoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/jtdtostructure.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/kstructtoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/kustotoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/kustotojstruct.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/mcp_server.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/openapitostructure.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/parquettoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/proto2parser.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/proto3parser.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/prototoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/ramltoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/ramltojstruct.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/schema_inference.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/smithytoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/smithytojstruct.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/sqltoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretocddl.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretocpp.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretocsharp.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretocsv.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretocue.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretodatapackage.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretodb.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretogo.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretographql.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretoiceberg.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretojava.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretojs.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretojsons.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretojtd.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretokusto.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretomd.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretoparquet.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretoproto.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretopython.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretorust.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretots.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretotsml.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/structuretoxsd.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/surrealtoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/thriftstructure.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/thrifttoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/tmslvalidate.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/validate.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/xmltoschema.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/avrotize/xsdtoavro.py +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/build.ps1 +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/build.sh +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/pyproject.toml +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/setup.cfg +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/structurize.egg-info/SOURCES.txt +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/structurize.egg-info/dependency_links.txt +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/structurize.egg-info/entry_points.txt +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/structurize.egg-info/requires.txt +0 -0
- {structurize-3.7.3 → structurize-3.7.4}/structurize.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: structurize
|
|
3
|
-
Version: 3.7.
|
|
3
|
+
Version: 3.7.4
|
|
4
4
|
Summary: Tools to convert from and to JSON Structure from various other schema languages.
|
|
5
5
|
Author-email: Clemens Vasters <clemensv@microsoft.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '3.7.
|
|
22
|
-
__version_tuple__ = version_tuple = (3, 7,
|
|
21
|
+
__version__ = version = '3.7.4'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 7, 4)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gd6893c97b'
|
|
@@ -331,6 +331,69 @@ class JsonToStructureConverter:
|
|
|
331
331
|
|
|
332
332
|
return None
|
|
333
333
|
|
|
334
|
+
_STRING_FAMILY = {'string', 'uuid', 'date', 'time', 'datetime', 'duration', 'bytes'}
|
|
335
|
+
_NUMBER_FAMILY = {'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32',
|
|
336
|
+
'uint64', 'int128', 'uint128', 'float', 'double', 'decimal',
|
|
337
|
+
'number', 'integer'}
|
|
338
|
+
|
|
339
|
+
def _json_value_category(self, value: Any) -> Optional[str]:
|
|
340
|
+
"""Classify a Python-decoded JSON value into a JSON Structure type family."""
|
|
341
|
+
if value is None:
|
|
342
|
+
return 'null'
|
|
343
|
+
if isinstance(value, bool):
|
|
344
|
+
return 'boolean'
|
|
345
|
+
if isinstance(value, (int, float)):
|
|
346
|
+
return 'number'
|
|
347
|
+
if isinstance(value, str):
|
|
348
|
+
return 'string'
|
|
349
|
+
return None
|
|
350
|
+
|
|
351
|
+
def _type_category(self, structure_type: str) -> Optional[str]:
|
|
352
|
+
"""Map a scalar JSON Structure type name to its value family."""
|
|
353
|
+
if structure_type in self._STRING_FAMILY:
|
|
354
|
+
return 'string'
|
|
355
|
+
if structure_type in self._NUMBER_FAMILY:
|
|
356
|
+
return 'number'
|
|
357
|
+
if structure_type in ('boolean', 'null'):
|
|
358
|
+
return structure_type
|
|
359
|
+
return None
|
|
360
|
+
|
|
361
|
+
def _enum_type_for(self, structure_type: Any, enum_values: list) -> Any:
|
|
362
|
+
"""Return the JSON Structure ``type`` that admits every enum value.
|
|
363
|
+
|
|
364
|
+
JSON Schema permits heterogeneous ``enum`` lists (e.g. a ``null`` or
|
|
365
|
+
boolean member alongside strings). JSON Structure requires the declared
|
|
366
|
+
type to admit each enum value, so widen a single scalar type to a
|
|
367
|
+
type-union covering the JSON families actually present. The declared type
|
|
368
|
+
is always preserved as a union member so string-family refinements such as
|
|
369
|
+
``uuid`` are never lost, and ``null`` is floated to the front by
|
|
370
|
+
convention. If a value's family already matches the declared type (or the
|
|
371
|
+
declared type is not a recognised scalar), no widening occurs.
|
|
372
|
+
"""
|
|
373
|
+
if not isinstance(structure_type, str):
|
|
374
|
+
return structure_type
|
|
375
|
+
base_cat = self._type_category(structure_type)
|
|
376
|
+
if base_cat is None:
|
|
377
|
+
return structure_type
|
|
378
|
+
canonical = {'null': 'null', 'boolean': 'boolean', 'string': 'string', 'number': 'int64'}
|
|
379
|
+
extras: list = []
|
|
380
|
+
for value in enum_values:
|
|
381
|
+
cat = self._json_value_category(value)
|
|
382
|
+
if cat is None or cat == base_cat:
|
|
383
|
+
continue
|
|
384
|
+
member = canonical[cat]
|
|
385
|
+
if member not in extras:
|
|
386
|
+
extras.append(member)
|
|
387
|
+
if not extras:
|
|
388
|
+
return structure_type
|
|
389
|
+
ordered: list = []
|
|
390
|
+
if 'null' in extras:
|
|
391
|
+
ordered.append('null')
|
|
392
|
+
extras = [e for e in extras if e != 'null']
|
|
393
|
+
ordered.append(structure_type)
|
|
394
|
+
ordered.extend(extras)
|
|
395
|
+
return ordered
|
|
396
|
+
|
|
334
397
|
def json_schema_primitive_to_structure_type(self, json_primitive: Optional[str | list], format: Optional[str], enum: Optional[list], record_name: str, field_name: str, namespace: str, dependencies: list, schema: dict) -> str | dict[str, Any] | list:
|
|
335
398
|
"""
|
|
336
399
|
Convert a JSON Schema primitive type to JSON Structure primitive type.
|
|
@@ -348,10 +411,11 @@ class JsonToStructureConverter:
|
|
|
348
411
|
|
|
349
412
|
if isinstance(json_primitive, list):
|
|
350
413
|
if enum:
|
|
351
|
-
#
|
|
414
|
+
# Heterogeneous enum: widen the type to admit every value's family.
|
|
415
|
+
enum_values = list(enum)
|
|
352
416
|
return {
|
|
353
|
-
'type': 'string',
|
|
354
|
-
'enum':
|
|
417
|
+
'type': self._enum_type_for('string', enum_values),
|
|
418
|
+
'enum': enum_values
|
|
355
419
|
}
|
|
356
420
|
else:
|
|
357
421
|
# Handle union types
|
|
@@ -419,7 +483,10 @@ class JsonToStructureConverter:
|
|
|
419
483
|
|
|
420
484
|
# Handle enums
|
|
421
485
|
if enum is not None:
|
|
422
|
-
|
|
486
|
+
enum_values = list(enum)
|
|
487
|
+
# Widen the declared type so every enum value's family is admitted.
|
|
488
|
+
result['type'] = self._enum_type_for(structure_type, enum_values)
|
|
489
|
+
result['enum'] = enum_values
|
|
423
490
|
|
|
424
491
|
# Add constraints for string types
|
|
425
492
|
if structure_type == 'string' and isinstance(schema, dict):
|
|
@@ -578,6 +645,28 @@ class JsonToStructureConverter:
|
|
|
578
645
|
# propertyNames and keyNames and adds JSONStructureValidation to $uses
|
|
579
646
|
pass
|
|
580
647
|
|
|
648
|
+
def _reconcile_required(self, required: list, emitted_properties: dict) -> list:
|
|
649
|
+
"""Reconcile a JSON Schema ``required`` list with the emitted JSON Structure
|
|
650
|
+
property keys.
|
|
651
|
+
|
|
652
|
+
Property names that are not valid identifiers are normalised (the original
|
|
653
|
+
wire name is preserved via ``altnames``); the corresponding ``required``
|
|
654
|
+
entries must reference the same normalised identifier. Entries that do not
|
|
655
|
+
correspond to any emitted property - e.g. a source schema that lists a
|
|
656
|
+
required property it never defines under ``properties`` - are dropped so the
|
|
657
|
+
result validates against the JSON Structure Core metaschema.
|
|
658
|
+
"""
|
|
659
|
+
if not required:
|
|
660
|
+
return []
|
|
661
|
+
reconciled: list = []
|
|
662
|
+
seen: set = set()
|
|
663
|
+
for name in required:
|
|
664
|
+
key = name if self.is_valid_identifier(name) else self.normalize_identifier(name)
|
|
665
|
+
if key in emitted_properties and key not in seen:
|
|
666
|
+
reconciled.append(key)
|
|
667
|
+
seen.add(key)
|
|
668
|
+
return reconciled
|
|
669
|
+
|
|
581
670
|
def create_structure_object(self, properties: dict, required: list, record_name: str, namespace: str, dependencies: list, json_schema: dict, base_uri: str, structure_schema: dict, record_stack: list, recursion_depth: int = 1, original_schema: dict | None = None) -> dict:
|
|
582
671
|
"""
|
|
583
672
|
Create a JSON Structure object type from properties.
|
|
@@ -601,9 +690,8 @@ class JsonToStructureConverter:
|
|
|
601
690
|
'type': 'object'
|
|
602
691
|
}
|
|
603
692
|
|
|
604
|
-
#
|
|
605
|
-
|
|
606
|
-
structure_obj['required'] = required
|
|
693
|
+
# 'required' is reconciled against the emitted property keys after the
|
|
694
|
+
# property loop below (names may be normalised; dangling entries dropped).
|
|
607
695
|
|
|
608
696
|
# Add name if provided
|
|
609
697
|
if record_name:
|
|
@@ -633,7 +721,14 @@ class JsonToStructureConverter:
|
|
|
633
721
|
new_entry['altnames'] = {'json': prop_name}
|
|
634
722
|
structure_obj['properties'][normalized_name] = new_entry
|
|
635
723
|
else:
|
|
636
|
-
structure_obj['properties'][prop_name] = self._ensure_schema_object(prop_type, structure_schema, prop_name)
|
|
724
|
+
structure_obj['properties'][prop_name] = self._ensure_schema_object(prop_type, structure_schema, prop_name)
|
|
725
|
+
|
|
726
|
+
# Reconcile required names against the (possibly normalised) property keys.
|
|
727
|
+
reconciled_required = self._reconcile_required(required, structure_obj.get('properties', {}))
|
|
728
|
+
if reconciled_required:
|
|
729
|
+
structure_obj['required'] = reconciled_required
|
|
730
|
+
|
|
731
|
+
# Handle patternProperties and additionalProperties
|
|
637
732
|
has_additional_schema = False
|
|
638
733
|
if original_schema:
|
|
639
734
|
# Check for patternProperties that coexist with properties/additionalProperties
|
|
@@ -804,7 +899,7 @@ class JsonToStructureConverter:
|
|
|
804
899
|
choice_key = ref[14:] # Remove '#/definitions/' prefix
|
|
805
900
|
else:
|
|
806
901
|
choice_key = f"option_{i}"
|
|
807
|
-
choice_obj['choices'][choice_key] = {'$ref': ref}
|
|
902
|
+
choice_obj['choices'][choice_key] = self._ensure_schema_object({'$ref': ref}, structure_schema, choice_key)
|
|
808
903
|
else:
|
|
809
904
|
# Convert option to structure type
|
|
810
905
|
choice_key = f"option_{i}"
|
|
@@ -837,7 +932,8 @@ class JsonToStructureConverter:
|
|
|
837
932
|
values_schema, record_name, 'value', namespace, dependencies,
|
|
838
933
|
json_schema, base_uri, structure_schema, record_stack, recursion_depth + 1
|
|
839
934
|
)
|
|
840
|
-
# Always wrap as schema object
|
|
935
|
+
# Always wrap as schema object
|
|
936
|
+
values_type = self._ensure_schema_object(values_type, structure_schema, 'value')
|
|
841
937
|
return {
|
|
842
938
|
'type': 'map',
|
|
843
939
|
'values': values_type
|
|
@@ -992,8 +1088,12 @@ class JsonToStructureConverter:
|
|
|
992
1088
|
}
|
|
993
1089
|
|
|
994
1090
|
if required:
|
|
995
|
-
|
|
996
|
-
|
|
1091
|
+
# Reconcile: drop required entries that reference no emitted property
|
|
1092
|
+
# so the result validates against the JSON Structure Core metaschema.
|
|
1093
|
+
reconciled = [n for n in required if n in structure_properties]
|
|
1094
|
+
if reconciled:
|
|
1095
|
+
result['required'] = reconciled
|
|
1096
|
+
|
|
997
1097
|
return result
|
|
998
1098
|
|
|
999
1099
|
def add_alternate_names(self, structure: dict, original_name: str) -> dict:
|
|
@@ -1915,6 +2015,48 @@ class JsonToStructureConverter:
|
|
|
1915
2015
|
'discriminator' in def_schema):
|
|
1916
2016
|
def_schema['abstract'] = True
|
|
1917
2017
|
|
|
2018
|
+
def _ensure_root_type(self, structure_schema: dict, json_schema: Any = None) -> None:
|
|
2019
|
+
"""Ensure a definitions-only document nominates a root type.
|
|
2020
|
+
|
|
2021
|
+
A document whose only meaningful content is a library of reusable named
|
|
2022
|
+
types (e.g. an OpenAPI ``components/schemas`` bundle) has no single root
|
|
2023
|
+
instance type, yet the JSON Structure Core metaschema still requires the
|
|
2024
|
+
root to carry ``type``, ``$root`` or composition keywords. Following the
|
|
2025
|
+
spec's ``$root`` idiom (and the "Prohibition of Top-Level Unions" rule),
|
|
2026
|
+
point ``$root`` at:
|
|
2027
|
+
* the referenced type when the source root is a bare ``$ref``; else
|
|
2028
|
+
* the single definition when there is exactly one; else
|
|
2029
|
+
* a synthetic type-union over every top-level definition, so that no
|
|
2030
|
+
type is arbitrarily privileged.
|
|
2031
|
+
"""
|
|
2032
|
+
if not isinstance(structure_schema, dict):
|
|
2033
|
+
return
|
|
2034
|
+
if 'type' in structure_schema or '$root' in structure_schema:
|
|
2035
|
+
return
|
|
2036
|
+
definitions = structure_schema.get('definitions')
|
|
2037
|
+
if not isinstance(definitions, dict) or not definitions:
|
|
2038
|
+
return
|
|
2039
|
+
# Prefer an explicit root $ref (the source root is a reference to one type).
|
|
2040
|
+
if (isinstance(json_schema, dict) and isinstance(json_schema.get('$ref'), str)
|
|
2041
|
+
and json_schema['$ref'].startswith('#/')):
|
|
2042
|
+
target = avro_name(json_schema['$ref'].split('/')[-1])
|
|
2043
|
+
if target in definitions:
|
|
2044
|
+
structure_schema['$root'] = f"#/definitions/{target}"
|
|
2045
|
+
return
|
|
2046
|
+
def_names = list(definitions.keys())
|
|
2047
|
+
if len(def_names) == 1:
|
|
2048
|
+
structure_schema['$root'] = f"#/definitions/{def_names[0]}"
|
|
2049
|
+
return
|
|
2050
|
+
# Synthesize a type-union root over all top-level definitions.
|
|
2051
|
+
root_name = avro_name(self.root_class_name)
|
|
2052
|
+
while root_name in definitions:
|
|
2053
|
+
root_name = f"{root_name}_root"
|
|
2054
|
+
definitions[root_name] = {
|
|
2055
|
+
'name': root_name,
|
|
2056
|
+
'type': [{'$ref': f"#/definitions/{name}"} for name in def_names]
|
|
2057
|
+
}
|
|
2058
|
+
structure_schema['$root'] = f"#/definitions/{root_name}"
|
|
2059
|
+
|
|
1918
2060
|
def jsons_to_structure(self, json_schema: Union[dict, list], namespace: str, base_uri: str) -> dict:
|
|
1919
2061
|
"""
|
|
1920
2062
|
Convert a JSON Schema to JSON Structure format.
|
|
@@ -2045,6 +2187,9 @@ class JsonToStructureConverter:
|
|
|
2045
2187
|
# Generate default $id for non-dict schemas
|
|
2046
2188
|
structure_schema['$id'] = f"https://example.com/{namespace.replace('.', '/')}.schema.json"
|
|
2047
2189
|
|
|
2190
|
+
# Nominate a root type for definitions-only documents (type libraries).
|
|
2191
|
+
self._ensure_root_type(structure_schema, json_schema)
|
|
2192
|
+
|
|
2048
2193
|
# Mark abstract types
|
|
2049
2194
|
self._mark_abstract_types(structure_schema)
|
|
2050
2195
|
|
|
@@ -2201,6 +2346,18 @@ class JsonToStructureConverter:
|
|
|
2201
2346
|
# Handle additionalProperties
|
|
2202
2347
|
if 'additionalProperties' in structure_type and isinstance(structure_type['additionalProperties'], dict):
|
|
2203
2348
|
structure_type['additionalProperties'] = self._validate_and_fix_json_structure_type(structure_type['additionalProperties'])
|
|
2349
|
+
|
|
2350
|
+
# Ensure choice branches are schema objects with wrapped refs
|
|
2351
|
+
if structure_type.get('type') == 'choice' and isinstance(structure_type.get('choices'), dict):
|
|
2352
|
+
fixed_choices = {}
|
|
2353
|
+
for choice_key, choice_val in structure_type['choices'].items():
|
|
2354
|
+
if isinstance(choice_val, dict) and '$ref' in choice_val and 'type' not in choice_val:
|
|
2355
|
+
choice_val = {'type': {'$ref': choice_val['$ref']}}
|
|
2356
|
+
fixed_choices[choice_key] = (
|
|
2357
|
+
self._validate_and_fix_json_structure_type(choice_val)
|
|
2358
|
+
if isinstance(choice_val, dict) else choice_val
|
|
2359
|
+
)
|
|
2360
|
+
structure_type['choices'] = fixed_choices
|
|
2204
2361
|
|
|
2205
2362
|
# Handle definitions
|
|
2206
2363
|
if 'definitions' in structure_type and isinstance(structure_type['definitions'], dict):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: structurize
|
|
3
|
-
Version: 3.7.
|
|
3
|
+
Version: 3.7.4
|
|
4
4
|
Summary: Tools to convert from and to JSON Structure from various other schema languages.
|
|
5
5
|
Author-email: Clemens Vasters <clemensv@microsoft.com>
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{structurize-3.7.3 → structurize-3.7.4}/avrotize/dependencies/typescript/node22/package.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|