structurize 3.2.1__tar.gz → 3.2.2__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 (88) hide show
  1. {structurize-3.2.1/structurize.egg-info → structurize-3.2.2}/PKG-INFO +1 -1
  2. {structurize-3.2.1 → structurize-3.2.2}/avrotize/_version.py +3 -3
  3. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretocsharp.py +59 -19
  4. {structurize-3.2.1 → structurize-3.2.2/structurize.egg-info}/PKG-INFO +1 -1
  5. {structurize-3.2.1 → structurize-3.2.2}/.gitignore +0 -0
  6. {structurize-3.2.1 → structurize-3.2.2}/LICENSE +0 -0
  7. {structurize-3.2.1 → structurize-3.2.2}/MANIFEST.in +0 -0
  8. {structurize-3.2.1 → structurize-3.2.2}/README.md +0 -0
  9. {structurize-3.2.1 → structurize-3.2.2}/avrotize/__init__.py +0 -0
  10. {structurize-3.2.1 → structurize-3.2.2}/avrotize/__main__.py +0 -0
  11. {structurize-3.2.1 → structurize-3.2.2}/avrotize/asn1toavro.py +0 -0
  12. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotize.py +0 -0
  13. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotocpp.py +0 -0
  14. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotocsharp.py +0 -0
  15. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotocsv.py +0 -0
  16. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotodatapackage.py +0 -0
  17. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotodb.py +0 -0
  18. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotogo.py +0 -0
  19. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotographql.py +0 -0
  20. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotoiceberg.py +0 -0
  21. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotojava.py +0 -0
  22. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotojs.py +0 -0
  23. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotojsons.py +0 -0
  24. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotojstruct.py +0 -0
  25. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotokusto.py +0 -0
  26. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotomd.py +0 -0
  27. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotools.py +0 -0
  28. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotoparquet.py +0 -0
  29. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotoproto.py +0 -0
  30. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotopython.py +0 -0
  31. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotorust.py +0 -0
  32. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotots.py +0 -0
  33. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrotoxsd.py +0 -0
  34. {structurize-3.2.1 → structurize-3.2.2}/avrotize/avrovalidator.py +0 -0
  35. {structurize-3.2.1 → structurize-3.2.2}/avrotize/cddltostructure.py +0 -0
  36. {structurize-3.2.1 → structurize-3.2.2}/avrotize/choice_inference.py +0 -0
  37. {structurize-3.2.1 → structurize-3.2.2}/avrotize/commands.json +0 -0
  38. {structurize-3.2.1 → structurize-3.2.2}/avrotize/common.py +0 -0
  39. {structurize-3.2.1 → structurize-3.2.2}/avrotize/constants.py +0 -0
  40. {structurize-3.2.1 → structurize-3.2.2}/avrotize/csvtoavro.py +0 -0
  41. {structurize-3.2.1 → structurize-3.2.2}/avrotize/datapackagetoavro.py +0 -0
  42. {structurize-3.2.1 → structurize-3.2.2}/avrotize/dependencies/cpp/vcpkg/vcpkg.json +0 -0
  43. {structurize-3.2.1 → structurize-3.2.2}/avrotize/dependencies/typescript/node22/package.json +0 -0
  44. {structurize-3.2.1 → structurize-3.2.2}/avrotize/dependency_resolver.py +0 -0
  45. {structurize-3.2.1 → structurize-3.2.2}/avrotize/dependency_version.py +0 -0
  46. {structurize-3.2.1 → structurize-3.2.2}/avrotize/jsonstoavro.py +0 -0
  47. {structurize-3.2.1 → structurize-3.2.2}/avrotize/jsonstostructure.py +0 -0
  48. {structurize-3.2.1 → structurize-3.2.2}/avrotize/jsontoschema.py +0 -0
  49. {structurize-3.2.1 → structurize-3.2.2}/avrotize/jstructtoavro.py +0 -0
  50. {structurize-3.2.1 → structurize-3.2.2}/avrotize/kstructtoavro.py +0 -0
  51. {structurize-3.2.1 → structurize-3.2.2}/avrotize/kustotoavro.py +0 -0
  52. {structurize-3.2.1 → structurize-3.2.2}/avrotize/openapitostructure.py +0 -0
  53. {structurize-3.2.1 → structurize-3.2.2}/avrotize/parquettoavro.py +0 -0
  54. {structurize-3.2.1 → structurize-3.2.2}/avrotize/proto2parser.py +0 -0
  55. {structurize-3.2.1 → structurize-3.2.2}/avrotize/proto3parser.py +0 -0
  56. {structurize-3.2.1 → structurize-3.2.2}/avrotize/prototoavro.py +0 -0
  57. {structurize-3.2.1 → structurize-3.2.2}/avrotize/schema_inference.py +0 -0
  58. {structurize-3.2.1 → structurize-3.2.2}/avrotize/sqltoavro.py +0 -0
  59. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretocddl.py +0 -0
  60. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretocpp.py +0 -0
  61. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretocsv.py +0 -0
  62. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretodatapackage.py +0 -0
  63. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretodb.py +0 -0
  64. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretogo.py +0 -0
  65. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretographql.py +0 -0
  66. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretoiceberg.py +0 -0
  67. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretojava.py +0 -0
  68. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretojs.py +0 -0
  69. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretojsons.py +0 -0
  70. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretokusto.py +0 -0
  71. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretomd.py +0 -0
  72. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretoproto.py +0 -0
  73. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretopython.py +0 -0
  74. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretorust.py +0 -0
  75. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretots.py +0 -0
  76. {structurize-3.2.1 → structurize-3.2.2}/avrotize/structuretoxsd.py +0 -0
  77. {structurize-3.2.1 → structurize-3.2.2}/avrotize/validate.py +0 -0
  78. {structurize-3.2.1 → structurize-3.2.2}/avrotize/xmltoschema.py +0 -0
  79. {structurize-3.2.1 → structurize-3.2.2}/avrotize/xsdtoavro.py +0 -0
  80. {structurize-3.2.1 → structurize-3.2.2}/build.ps1 +0 -0
  81. {structurize-3.2.1 → structurize-3.2.2}/build.sh +0 -0
  82. {structurize-3.2.1 → structurize-3.2.2}/pyproject.toml +0 -0
  83. {structurize-3.2.1 → structurize-3.2.2}/setup.cfg +0 -0
  84. {structurize-3.2.1 → structurize-3.2.2}/structurize.egg-info/SOURCES.txt +0 -0
  85. {structurize-3.2.1 → structurize-3.2.2}/structurize.egg-info/dependency_links.txt +0 -0
  86. {structurize-3.2.1 → structurize-3.2.2}/structurize.egg-info/entry_points.txt +0 -0
  87. {structurize-3.2.1 → structurize-3.2.2}/structurize.egg-info/requires.txt +0 -0
  88. {structurize-3.2.1 → structurize-3.2.2}/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.2.1
3
+ Version: 3.2.2
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
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '3.2.1'
32
- __version_tuple__ = version_tuple = (3, 2, 1)
31
+ __version__ = version = '3.2.2'
32
+ __version_tuple__ = version_tuple = (3, 2, 2)
33
33
 
34
- __commit_id__ = commit_id = 'gfc8429a20'
34
+ __commit_id__ = commit_id = 'g4fc2eb920'
@@ -47,6 +47,7 @@ class StructureToCSharp:
47
47
  self.schema_registry: Dict[str, Dict] = {} # Maps $id URIs to schemas
48
48
  self.offers: Dict[str, Any] = {} # Maps add-in names to property definitions from $offers
49
49
  self.needs_json_structure_converters = False # Track if any types need JSON Structure converters
50
+ self.discriminator_properties: Dict[str, str] = {} # Maps type ref -> discriminator property name (for inline unions)
50
51
 
51
52
  def get_qualified_name(self, namespace: str, name: str) -> str:
52
53
  """ Concatenates namespace and name with a dot separator """
@@ -390,9 +391,13 @@ class StructureToCSharp:
390
391
  # Check additionalProperties setting (Section 3.7.8)
391
392
  additional_props = structure_schema.get('additionalProperties', True if is_abstract else None)
392
393
 
394
+ # Check if any property in this class is a discriminator for an inline union
395
+ discriminator_prop = self.discriminator_properties.get(ref, None)
396
+
393
397
  fields_str = []
394
398
  for prop_name, prop_schema in properties.items():
395
- field_def = self.generate_property(prop_name, prop_schema, class_name, schema_namespace, required_props)
399
+ is_discriminator = (prop_name == discriminator_prop)
400
+ field_def = self.generate_property(prop_name, prop_schema, class_name, schema_namespace, required_props, is_discriminator=is_discriminator)
396
401
  fields_str.append(field_def)
397
402
 
398
403
  # Add dictionary for additional properties if needed
@@ -460,7 +465,7 @@ class StructureToCSharp:
460
465
  self.generated_structure_types[ref] = structure_schema
461
466
  return ref
462
467
 
463
- def generate_property(self, prop_name: str, prop_schema: Dict, class_name: str, parent_namespace: str, required_props: List) -> str:
468
+ def generate_property(self, prop_name: str, prop_schema: Dict, class_name: str, parent_namespace: str, required_props: List, is_discriminator: bool = False) -> str:
464
469
  """ Generates a property for a class """
465
470
  property_definition = ''
466
471
 
@@ -521,9 +526,13 @@ class StructureToCSharp:
521
526
  doc = prop_schema.get('description', prop_schema.get('doc', field_name_cs))
522
527
  property_definition += f"{INDENT}/// <summary>\n{INDENT}/// {doc}\n{INDENT}/// </summary>\n"
523
528
 
529
+ # If this property is used as a discriminator in an inline union, add JsonIgnore
530
+ # because JsonPolymorphic handles it as metadata
531
+ if is_discriminator and self.system_text_json_annotation:
532
+ property_definition += f'{INDENT}[System.Text.Json.Serialization.JsonIgnore]\n'
524
533
  # Add JSON property name annotation when property name differs from schema name
525
534
  # This is needed for proper JSON serialization/deserialization, especially with pascal_properties
526
- if needs_json_annotation:
535
+ elif needs_json_annotation:
527
536
  property_definition += f'{INDENT}[System.Text.Json.Serialization.JsonPropertyName("{prop_name}")]\n'
528
537
  if self.newtonsoft_json_annotation and needs_json_annotation:
529
538
  property_definition += f'{INDENT}[Newtonsoft.Json.JsonProperty("{prop_name}")]\n'
@@ -1027,18 +1036,30 @@ class StructureToCSharp:
1027
1036
  # Fallback to tagged union if no base
1028
1037
  return self.generate_tagged_union(structure_schema, parent_namespace, write_file, explicit_name)
1029
1038
 
1030
- # First, ensure base class is generated (if it's abstract, it won't be referenced directly)
1039
+ choices = structure_schema.get('choices', {})
1040
+ selector = structure_schema.get('selector', 'type')
1041
+
1042
+ # Mark the selector property as a discriminator BEFORE generating the base class
1043
+ # This allows generate_class to add [JsonIgnore] to the property
1031
1044
  base_schema_copy = base_schema.copy()
1032
1045
  if 'name' not in base_schema_copy:
1033
1046
  # Extract name from $extends ref
1034
1047
  base_name = extends_ref.split('/')[-1]
1035
1048
  base_schema_copy['name'] = base_name
1049
+
1050
+ # Calculate what the base class ref will be
1051
+ base_namespace_for_ref = pascal(self.concat_namespace(self.base_namespace, base_schema_copy.get('namespace', schema_namespace)))
1052
+ base_class_name_for_ref = pascal(base_schema_copy['name'])
1053
+ pending_base_ref = 'global::'+self.get_qualified_name(base_namespace_for_ref, base_class_name_for_ref)
1054
+
1055
+ # Record that this base type's selector property is a discriminator
1056
+ if self.system_text_json_annotation and selector in base_schema.get('properties', {}):
1057
+ self.discriminator_properties[pending_base_ref] = selector
1058
+
1059
+ # Now generate the base class (it will check discriminator_properties)
1036
1060
  base_class_ref = self.generate_class(base_schema_copy, schema_namespace, write_file)
1037
1061
  base_class_name = base_class_ref.split('::')[-1].split('.')[-1]
1038
1062
 
1039
- choices = structure_schema.get('choices', {})
1040
- selector = structure_schema.get('selector', 'type')
1041
-
1042
1063
  # Generate abstract base class with selector property
1043
1064
  class_definition = f"/// <summary>\n/// {structure_schema.get('description', class_name + ' (inline union base)')}\n/// </summary>\n"
1044
1065
 
@@ -1056,16 +1077,15 @@ class StructureToCSharp:
1056
1077
 
1057
1078
  class_definition += "\n{\n"
1058
1079
 
1059
- # Add selector property (not required since derived classes set it in constructor)
1060
- class_definition += f"{INDENT}/// <summary>\n{INDENT}/// Type discriminator\n{INDENT}/// </summary>\n"
1061
- if self.system_text_json_annotation:
1062
- class_definition += f'{INDENT}[System.Text.Json.Serialization.JsonPropertyName("{selector}")]\n'
1063
-
1064
1080
  # Check if selector is already in base properties
1065
1081
  base_has_selector = selector in base_schema.get('properties', {})
1066
- if base_has_selector:
1067
- class_definition += f"{INDENT}public new string {pascal(selector)} {{ get; set; }} = \"\";\n"
1068
- else:
1082
+
1083
+ # Only add selector property if base class doesn't already have it
1084
+ # If base has the selector, JsonPolymorphic will use it directly
1085
+ if not base_has_selector:
1086
+ class_definition += f"{INDENT}/// <summary>\n{INDENT}/// Type discriminator\n{INDENT}/// </summary>\n"
1087
+ if self.system_text_json_annotation:
1088
+ class_definition += f'{INDENT}[System.Text.Json.Serialization.JsonPropertyName("{selector}")]\n'
1069
1089
  class_definition += f"{INDENT}public string {pascal(selector)} {{ get; set; }} = \"\";\n"
1070
1090
 
1071
1091
  class_definition += "}"
@@ -1076,11 +1096,21 @@ class StructureToCSharp:
1076
1096
  # Generate derived classes for each choice with property merging
1077
1097
  for choice_name, choice_schema_ref in choices.items():
1078
1098
  # Resolve the choice schema
1079
- if isinstance(choice_schema_ref, dict) and '$ref' in choice_schema_ref:
1080
- choice_schema = self.resolve_ref(choice_schema_ref['$ref'], self.schema_doc)
1099
+ # Handle both formats:
1100
+ # 1. Direct $ref: {"$ref": "#/definitions/Type"}
1101
+ # 2. Nested in type: {"type": {"$ref": "#/definitions/Type"}}
1102
+ ref_to_resolve = None
1103
+ if isinstance(choice_schema_ref, dict):
1104
+ if '$ref' in choice_schema_ref:
1105
+ ref_to_resolve = choice_schema_ref['$ref']
1106
+ elif 'type' in choice_schema_ref and isinstance(choice_schema_ref['type'], dict) and '$ref' in choice_schema_ref['type']:
1107
+ ref_to_resolve = choice_schema_ref['type']['$ref']
1108
+
1109
+ if ref_to_resolve:
1110
+ choice_schema = self.resolve_ref(ref_to_resolve, self.schema_doc)
1081
1111
  if not choice_schema:
1082
1112
  # Try resolving relative to the structure_schema itself
1083
- choice_schema = self.resolve_ref(choice_schema_ref['$ref'], structure_schema)
1113
+ choice_schema = self.resolve_ref(ref_to_resolve, structure_schema)
1084
1114
  else:
1085
1115
  choice_schema = choice_schema_ref
1086
1116
 
@@ -1219,9 +1249,19 @@ class StructureToCSharp:
1219
1249
  class_definition += field_def
1220
1250
 
1221
1251
  # Add constructor that sets the discriminator
1252
+ # If the selector exists in the base schema, use the original property name (snake_case)
1253
+ # Otherwise use the PascalCase version we defined in the union class
1254
+ base_properties = schema.get('$base_properties', [])
1255
+ if selector in base_properties:
1256
+ # Use the snake_case name from the base class
1257
+ selector_prop_name = selector
1258
+ else:
1259
+ # Use PascalCase name we defined in the union class
1260
+ selector_prop_name = pascal(selector)
1261
+
1222
1262
  class_definition += f"\n{INDENT}/// <summary>\n{INDENT}/// Constructor that sets the discriminator value\n{INDENT}/// </summary>\n"
1223
1263
  class_definition += f"{INDENT}public {class_name}()\n{INDENT}{{\n"
1224
- class_definition += f"{INDENT*2}this.{pascal(selector)} = \"{choice_name}\";\n"
1264
+ class_definition += f"{INDENT*2}this.{selector_prop_name} = \"{choice_name}\";\n"
1225
1265
  class_definition += f"{INDENT}}}\n"
1226
1266
 
1227
1267
  # Generate Equals and GetHashCode
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structurize
3
- Version: 3.2.1
3
+ Version: 3.2.2
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