structurize 2.19.0__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.
Files changed (70) hide show
  1. avrotize/__init__.py +64 -0
  2. avrotize/__main__.py +6 -0
  3. avrotize/_version.py +34 -0
  4. avrotize/asn1toavro.py +160 -0
  5. avrotize/avrotize.py +152 -0
  6. avrotize/avrotocpp.py +483 -0
  7. avrotize/avrotocsharp.py +1075 -0
  8. avrotize/avrotocsv.py +121 -0
  9. avrotize/avrotodatapackage.py +173 -0
  10. avrotize/avrotodb.py +1383 -0
  11. avrotize/avrotogo.py +476 -0
  12. avrotize/avrotographql.py +197 -0
  13. avrotize/avrotoiceberg.py +210 -0
  14. avrotize/avrotojava.py +2156 -0
  15. avrotize/avrotojs.py +250 -0
  16. avrotize/avrotojsons.py +481 -0
  17. avrotize/avrotojstruct.py +345 -0
  18. avrotize/avrotokusto.py +364 -0
  19. avrotize/avrotomd.py +137 -0
  20. avrotize/avrotools.py +168 -0
  21. avrotize/avrotoparquet.py +208 -0
  22. avrotize/avrotoproto.py +359 -0
  23. avrotize/avrotopython.py +624 -0
  24. avrotize/avrotorust.py +435 -0
  25. avrotize/avrotots.py +598 -0
  26. avrotize/avrotoxsd.py +344 -0
  27. avrotize/cddltostructure.py +1841 -0
  28. avrotize/commands.json +3337 -0
  29. avrotize/common.py +834 -0
  30. avrotize/constants.py +72 -0
  31. avrotize/csvtoavro.py +132 -0
  32. avrotize/datapackagetoavro.py +76 -0
  33. avrotize/dependencies/cpp/vcpkg/vcpkg.json +19 -0
  34. avrotize/dependencies/typescript/node22/package.json +16 -0
  35. avrotize/dependency_resolver.py +348 -0
  36. avrotize/dependency_version.py +432 -0
  37. avrotize/jsonstoavro.py +2167 -0
  38. avrotize/jsonstostructure.py +2642 -0
  39. avrotize/jstructtoavro.py +878 -0
  40. avrotize/kstructtoavro.py +93 -0
  41. avrotize/kustotoavro.py +455 -0
  42. avrotize/parquettoavro.py +157 -0
  43. avrotize/proto2parser.py +498 -0
  44. avrotize/proto3parser.py +403 -0
  45. avrotize/prototoavro.py +382 -0
  46. avrotize/structuretocddl.py +597 -0
  47. avrotize/structuretocpp.py +697 -0
  48. avrotize/structuretocsharp.py +2295 -0
  49. avrotize/structuretocsv.py +365 -0
  50. avrotize/structuretodatapackage.py +659 -0
  51. avrotize/structuretodb.py +1125 -0
  52. avrotize/structuretogo.py +720 -0
  53. avrotize/structuretographql.py +502 -0
  54. avrotize/structuretoiceberg.py +355 -0
  55. avrotize/structuretojava.py +853 -0
  56. avrotize/structuretojsons.py +498 -0
  57. avrotize/structuretokusto.py +639 -0
  58. avrotize/structuretomd.py +322 -0
  59. avrotize/structuretoproto.py +764 -0
  60. avrotize/structuretopython.py +772 -0
  61. avrotize/structuretorust.py +714 -0
  62. avrotize/structuretots.py +653 -0
  63. avrotize/structuretoxsd.py +679 -0
  64. avrotize/xsdtoavro.py +413 -0
  65. structurize-2.19.0.dist-info/METADATA +107 -0
  66. structurize-2.19.0.dist-info/RECORD +70 -0
  67. structurize-2.19.0.dist-info/WHEEL +5 -0
  68. structurize-2.19.0.dist-info/entry_points.txt +2 -0
  69. structurize-2.19.0.dist-info/licenses/LICENSE +201 -0
  70. structurize-2.19.0.dist-info/top_level.txt +1 -0
avrotize/avrotojs.py ADDED
@@ -0,0 +1,250 @@
1
+ """ Convert Avro schema to TypeScript classes """
2
+
3
+ import json
4
+ import os
5
+ from typing import Any, Dict, List, Set, Union
6
+
7
+ from avrotize.common import pascal
8
+
9
+ INDENT = ' ' * 4
10
+
11
+ def is_javascript_reserved_word(word: str) -> bool:
12
+ """ Check if word is a TypeScript reserved word """
13
+ reserved_words = [
14
+ 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
15
+ 'default', 'delete', 'do', 'else', 'export', 'extends', 'finally',
16
+ 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'return',
17
+ 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void',
18
+ 'while', 'with', 'yield'
19
+ ]
20
+ return word in reserved_words
21
+
22
+ def is_javascript_primitive(word: str) -> bool:
23
+ """ Check if word is a TypeScript primitive """
24
+ primitives = ['null', 'boolean', 'number', 'string', 'Date']
25
+ return word in primitives
26
+
27
+ class AvroToJavaScript:
28
+ """ Convert Avro schema to TypeScript classes """
29
+
30
+ def __init__(self, base_package: str = '', avro_annotation=False) -> None:
31
+ self.base_package = base_package
32
+ self.avro_annotation = avro_annotation
33
+ self.output_dir = os.getcwd()
34
+
35
+ def map_primitive_to_javascript(self, avro_type: str) -> str:
36
+ """ Map Avro primitive type to TypeScript type """
37
+ mapping = {
38
+ 'null': 'null',
39
+ 'boolean': 'boolean',
40
+ 'int': 'number',
41
+ 'long': 'number',
42
+ 'float': 'number',
43
+ 'double': 'number',
44
+ 'bytes': 'string',
45
+ 'string': 'string',
46
+ }
47
+ return mapping.get(avro_type, avro_type)
48
+
49
+ def convert_logical_type_to_javascript(self, avro_type: Dict) -> str:
50
+ """ Convert Avro logical type to TypeScript type """
51
+ if 'logicalType' in avro_type:
52
+ if avro_type['logicalType'] in ['decimal', 'uuid']:
53
+ return 'string'
54
+ if avro_type['logicalType'] in ['date', 'time-millis', 'time-micros', 'timestamp-millis', 'timestamp-micros']:
55
+ return 'Date'
56
+ if avro_type['logicalType'] == 'duration':
57
+ return 'string'
58
+ return 'any'
59
+
60
+ def is_javascript_primitive(self, avro_type: str) -> bool:
61
+ """ Check if Avro type is a TypeScript primitive """
62
+ return avro_type in ['null', 'boolean', 'number', 'string', 'Date']
63
+
64
+ def convert_avro_type_to_javascript(self, avro_type: Union[str, Dict, List], parent_namespace: str, import_types: set) -> str | List[Any]:
65
+ """ Convert Avro type to TypeScript type """
66
+ if isinstance(avro_type, str):
67
+ mapped_type = self.map_primitive_to_javascript(avro_type)
68
+ if mapped_type == avro_type and not self.is_javascript_primitive(mapped_type):
69
+ import_types.add(mapped_type)
70
+ return pascal(mapped_type.split('.')[-1])
71
+ return mapped_type
72
+ elif isinstance(avro_type, list):
73
+ return [self.convert_avro_type_to_javascript(t, parent_namespace, import_types) for t in avro_type]
74
+ elif isinstance(avro_type, dict):
75
+ if 'type' in avro_type and avro_type['type'] == 'record':
76
+ class_ref = self.generate_class(avro_type, parent_namespace)
77
+ import_types.add(class_ref)
78
+ return class_ref.split('.')[-1]
79
+ elif 'type' in avro_type and avro_type['type'] == 'enum':
80
+ enum_ref = self.generate_enum(avro_type, parent_namespace)
81
+ import_types.add(enum_ref)
82
+ return enum_ref.split('.')[-1]
83
+ elif 'type' in avro_type and avro_type['type'] == 'array':
84
+ return [self.convert_avro_type_to_javascript(avro_type["items"], parent_namespace, import_types)]
85
+ if 'type' in avro_type and avro_type['type'] == 'map':
86
+ return [self.convert_avro_type_to_javascript(avro_type["values"], parent_namespace, import_types)]
87
+ if 'logicalType' in avro_type:
88
+ return self.convert_logical_type_to_javascript(avro_type)
89
+ return self.convert_avro_type_to_javascript(avro_type['type'], parent_namespace, import_types)
90
+ return 'any'
91
+
92
+ def generate_class(self, avro_schema: Dict, parent_namespace: str) -> str:
93
+ """ Generate TypeScript class from Avro record """
94
+
95
+ def add_check(arr_check, ft):
96
+ if isinstance(ft, list):
97
+ for ft2 in ft:
98
+ add_check(arr_check, ft2)
99
+ elif ft == 'null':
100
+ arr_check.append('v !== null')
101
+ elif is_javascript_primitive(ft):
102
+ arr_check.append(f'typeof v !== "{ft}"')
103
+ else:
104
+ arr_check.append(f'!(v instanceof {ft})')
105
+
106
+ import_types: Set[str] = set()
107
+ class_name = pascal(avro_schema['name'])
108
+ namespace = avro_schema.get('namespace', '')
109
+ if not namespace and parent_namespace:
110
+ namespace = parent_namespace
111
+ if self.base_package:
112
+ namespace = f'{self.base_package}.{namespace}'
113
+ fields = avro_schema.get('fields', [])
114
+ doc = avro_schema.get('doc', '')
115
+
116
+ constructor_body = ''
117
+ class_body = ''
118
+ if self.avro_annotation:
119
+ avro_schema_json = json.dumps(avro_schema)
120
+ avro_schema_json = avro_schema_json.replace('"', '§')
121
+ avro_schema_json = f"\"+\n{' '*8}\"".join([avro_schema_json[i:i+80] for i in range(0, len(avro_schema_json), 80)])
122
+ avro_schema_json = avro_schema_json.replace('§', '\\"')
123
+ class_body += f'{class_name}.AvroType = avro.parse("{avro_schema_json}");\n'
124
+ for field in fields:
125
+ field_name = field['name']
126
+ field_doc = field.get('doc', '')
127
+ field_avro_type = field['type']
128
+ if is_javascript_reserved_word(field_name):
129
+ field_name += '_'
130
+ field_type = self.convert_avro_type_to_javascript(field['type'], namespace, import_types)
131
+ if field_doc:
132
+ constructor_body += f'{INDENT}/** {field_doc} */\n'
133
+ constructor_body += f'{INDENT}_{field_name} = null;\n'
134
+ class_body += f'Object.defineProperty({class_name}.prototype, "{field_name}", {{\n'
135
+ class_body += f'{INDENT}get: function() {{'+'\n'
136
+ class_body += f'{INDENT}{INDENT}return this._{field_name};\n'
137
+ class_body += f'{INDENT}}},\n'
138
+ class_body += f'{INDENT}set: function(value) {{'+'\n'
139
+ type_check = []
140
+ if field_avro_type == 'array':
141
+ arr = '!Array.isArray(value) || value.some(v => '
142
+ arr_check: List[str] = []
143
+ for ft in field_type if isinstance(field_type, list) else [field_type]:
144
+ add_check(arr_check, ft)
145
+ arr += ' || '.join(arr_check) + ')'
146
+ type_check.append(arr)
147
+ elif field_avro_type == 'map':
148
+ map = '!Object.entries(value).every(([k, v]) => typeof k === "string" && '
149
+ map_check: List[str] = []
150
+ for ft in field_type if isinstance(field_type, list) else [field_type]:
151
+ add_check(map_check, ft)
152
+ map += ' && '.join(map_check) + ')'
153
+ type_check.append(map)
154
+ else:
155
+ for ft in field_type if isinstance(field_type, list) else [field_type]:
156
+ add_check(type_check, ft)
157
+ class_body += f'{INDENT}{INDENT}if ( {" && ".join(type_check)} ) throw new Error(`Invalid type for {field_name}. Expected {field_type}, got ${{value}}`);\n'
158
+ class_body += f'{INDENT}{INDENT}this._{field_name} = value;\n'
159
+ class_body += f'{INDENT}}}'+'\n'
160
+ class_body += '});\n\n'
161
+
162
+ imports = ''
163
+ if self.avro_annotation:
164
+ imports += "var avro = require('avro-js');\n"
165
+ for import_type in import_types:
166
+ import_type_package = import_type.rsplit('.',1)[0]
167
+ import_type_type = pascal(import_type.split('.')[-1])
168
+ import_type_package = import_type_package.replace('.', '/')
169
+ namespace_path = namespace.replace('.', '/')
170
+
171
+ if import_type_package:# get the relative path from the namespace to the import_type_package
172
+ import_type_package = os.path.relpath(import_type_package, namespace_path).replace(os.sep, '/')
173
+ if not import_type_package.startswith('.'):
174
+ import_type_package = f'./{import_type_package}'
175
+ imports += f"var {import_type_type} = require('{import_type_package}/{import_type_type}').{import_type_type};\n"
176
+ else:
177
+ imports += f"var {import_type_type} = require('{import_type_type}'){import_type_type};\n"
178
+
179
+ class_definition = imports + '\n'
180
+ if doc:
181
+ class_definition += f'/** {doc} */\n'
182
+ class_definition += f"function {class_name}() {{\n{constructor_body}}}\n\n{class_body}\nmodule.exports = {class_name};\n"
183
+ self.write_to_file(namespace, class_name, class_definition)
184
+ return f'{namespace}.{class_name}'
185
+
186
+ def generate_enum(self, avro_schema: Dict, parent_namespace: str) -> str:
187
+ """ Generate TypeScript enum from Avro enum """
188
+ enum_name = pascal(avro_schema['name'])
189
+ namespace = avro_schema.get('namespace', '')
190
+ if not namespace and parent_namespace:
191
+ namespace = parent_namespace
192
+ if self.base_package:
193
+ namespace = f'{self.base_package}.{namespace}'
194
+ symbols = avro_schema.get('symbols', [])
195
+
196
+ enum_body = ''
197
+ for symbol in symbols:
198
+ if is_javascript_reserved_word(symbol):
199
+ symbol += '_'
200
+ enum_body += f'{INDENT}{symbol}: "{symbol}",\n'
201
+
202
+ enum_definition = ''
203
+ if 'doc' in avro_schema:
204
+ enum_definition += f"/** {avro_schema['doc']} */\n"
205
+ enum_definition += f"const {enum_name} = Object.freeze({{\n{enum_body}}});\n\n"
206
+ enum_definition += f"module.exports = {enum_name};\n"
207
+ self.write_to_file(namespace, enum_name, enum_definition)
208
+ return f'{namespace}.{enum_name}'
209
+
210
+ def write_to_file(self, namespace: str, name: str, content: str):
211
+ """ Write TypeScript class to file """
212
+ directory_path = os.path.join(self.output_dir, namespace.replace('.', os.sep))
213
+ if not os.path.exists(directory_path):
214
+ os.makedirs(directory_path, exist_ok=True)
215
+
216
+ file_path = os.path.join(directory_path, f"{name}.js")
217
+ with open(file_path, 'w', encoding='utf-8') as file:
218
+ file.write(content)
219
+
220
+ def convert_schema(self, schema: List|Dict, output_dir: str):
221
+ """ Convert Avro schema to TypeScript classes """
222
+ self.output_dir = output_dir
223
+ if isinstance(schema, dict):
224
+ schema = [schema]
225
+
226
+ for avro_schema in schema:
227
+ if avro_schema['type'] == 'record':
228
+ self.generate_class(avro_schema, self.base_package)
229
+ elif avro_schema['type'] == 'enum':
230
+ self.generate_enum(avro_schema, self.base_package)
231
+
232
+ def convert(self, avro_schema_path: str, output_dir: str):
233
+ """ Convert Avro schema to TypeScript classes """
234
+ with open(avro_schema_path, 'r', encoding='utf-8') as file:
235
+ schema = json.load(file)
236
+ self.convert_schema(schema, output_dir)
237
+
238
+ def convert_avro_to_javascript(avro_schema_path, js_dir_path, package_name='', avro_annotation=False):
239
+ """ Convert Avro schema to TypeScript classes """
240
+
241
+ if not package_name:
242
+ package_name = os.path.splitext(os.path.basename(avro_schema_path))[0].replace('-', '_')
243
+
244
+ converter = AvroToJavaScript(package_name, avro_annotation=avro_annotation)
245
+ converter.convert(avro_schema_path, js_dir_path)
246
+
247
+ def convert_avro_schema_to_javascript(avro_schema, js_dir_path, package_name='', avro_annotation=False):
248
+ """ Convert Avro schema to TypeScript classes """
249
+ converter = AvroToJavaScript(package_name, avro_annotation=avro_annotation)
250
+ converter.convert_schema(avro_schema, js_dir_path)