structurize 3.6.0__tar.gz → 3.6.1__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.6.0/structurize.egg-info → structurize-3.6.1}/PKG-INFO +1 -1
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/_version.py +3 -3
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/jstructtoavro.py +53 -7
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretokusto.py +32 -3
- {structurize-3.6.0 → structurize-3.6.1/structurize.egg-info}/PKG-INFO +1 -1
- {structurize-3.6.0 → structurize-3.6.1}/.gitignore +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/LICENSE +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/MANIFEST.in +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/README.md +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/__init__.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/__main__.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/asn1toavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotize.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotocpp.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotocsharp.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotocsv.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotodatapackage.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotodb.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotogo.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotographql.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotoiceberg.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotojava.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotojs.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotojsons.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotojstruct.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotokusto.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotomd.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotools.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotoparquet.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotoproto.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotopython.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotorust.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotots.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrototsml.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrotoxsd.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/avrovalidator.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/cddltostructure.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/choice_inference.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/commands.json +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/common.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/constants.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/csvtoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/datapackagetoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/dependencies/cpp/vcpkg/vcpkg.json +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/dependencies/typescript/node22/package.json +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/dependency_resolver.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/dependency_version.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/jsonstoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/jsonstostructure.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/jsontoschema.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/kstructtoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/kustotoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/kustotojstruct.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/mcp_server.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/openapitostructure.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/parquettoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/proto2parser.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/proto3parser.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/prototoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/schema_inference.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/sqltoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretocddl.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretocpp.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretocsharp.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretocsv.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretodatapackage.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretodb.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretogo.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretographql.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretoiceberg.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretojava.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretojs.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretojsons.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretomd.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretoproto.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretopython.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretorust.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretots.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretotsml.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/structuretoxsd.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/tmslvalidate.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/validate.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/xmltoschema.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/avrotize/xsdtoavro.py +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/build.ps1 +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/build.sh +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/pyproject.toml +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/setup.cfg +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/structurize.egg-info/SOURCES.txt +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/structurize.egg-info/dependency_links.txt +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/structurize.egg-info/entry_points.txt +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/structurize.egg-info/requires.txt +0 -0
- {structurize-3.6.0 → structurize-3.6.1}/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.6.
|
|
3
|
+
Version: 3.6.1
|
|
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.6.
|
|
22
|
-
__version_tuple__ = version_tuple = (3, 6,
|
|
21
|
+
__version__ = version = '3.6.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 6, 1)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'ga0404973f'
|
|
@@ -8,7 +8,7 @@ This is the reverse operation of avrotojstruct.py.
|
|
|
8
8
|
import json
|
|
9
9
|
from typing import Any, Dict, List, Union, Optional
|
|
10
10
|
|
|
11
|
-
from avrotize.common import ANY_VALUE_RECORD, any_value_name, deduplicate_any_value_record, generic_type
|
|
11
|
+
from avrotize.common import ANY_VALUE_RECORD, any_value_name, deduplicate_any_value_record, generic_type, avro_name, avro_name_with_altname
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class JsonStructureToAvro:
|
|
@@ -388,10 +388,16 @@ class JsonStructureToAvro:
|
|
|
388
388
|
|
|
389
389
|
fields = []
|
|
390
390
|
for prop_name, prop_schema in properties.items():
|
|
391
|
+
# Property keys may be non-identifiers (e.g. "dr-type", "1"). Avro field
|
|
392
|
+
# names must match [A-Za-z_][A-Za-z0-9_]*, so sanitize and preserve the
|
|
393
|
+
# original wire key as an Avro alias for round-trip fidelity (issue #382).
|
|
394
|
+
avro_field_name, original_name = avro_name_with_altname(prop_name)
|
|
391
395
|
field = {
|
|
392
|
-
'name':
|
|
393
|
-
'type': self._convert_type_reference(prop_schema, name_hint=
|
|
396
|
+
'name': avro_field_name,
|
|
397
|
+
'type': self._convert_type_reference(prop_schema, name_hint=avro_field_name)
|
|
394
398
|
}
|
|
399
|
+
if original_name is not None:
|
|
400
|
+
field['aliases'] = [original_name]
|
|
395
401
|
|
|
396
402
|
# Build documentation with annotations
|
|
397
403
|
doc = self._build_doc_with_annotations(
|
|
@@ -418,22 +424,61 @@ class JsonStructureToAvro:
|
|
|
418
424
|
avro_record['fields'] = fields
|
|
419
425
|
return avro_record
|
|
420
426
|
|
|
427
|
+
def _sanitize_enum_symbols(self, symbols: List[Any]) -> tuple:
|
|
428
|
+
"""
|
|
429
|
+
Sanitize JSON Structure enum values into valid Avro enum symbols.
|
|
430
|
+
|
|
431
|
+
Avro enum symbols must match [A-Za-z_][A-Za-z0-9_]* and be unique. JSON
|
|
432
|
+
Structure enum values may be arbitrary (e.g. "N/A", "KAR-MQTT", 1). This
|
|
433
|
+
sanitizes each value, resolves collisions with a numeric suffix, and returns
|
|
434
|
+
both the symbol list and a mapping of sanitized-symbol -> original-value for
|
|
435
|
+
any symbol that was changed (issue #383).
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
tuple: (avro_symbols, symbol_mapping)
|
|
439
|
+
"""
|
|
440
|
+
avro_symbols: List[str] = []
|
|
441
|
+
symbol_mapping: Dict[str, Any] = {}
|
|
442
|
+
seen = set()
|
|
443
|
+
for value in symbols:
|
|
444
|
+
base = avro_name(str(value))
|
|
445
|
+
candidate = base
|
|
446
|
+
suffix = 1
|
|
447
|
+
while candidate in seen:
|
|
448
|
+
candidate = f"{base}_{suffix}"
|
|
449
|
+
suffix += 1
|
|
450
|
+
seen.add(candidate)
|
|
451
|
+
avro_symbols.append(candidate)
|
|
452
|
+
if candidate != str(value):
|
|
453
|
+
symbol_mapping[candidate] = value
|
|
454
|
+
return avro_symbols, symbol_mapping
|
|
455
|
+
|
|
421
456
|
def _convert_enum(self, schema: Dict[str, Any], namespace: Optional[str], name: str) -> Dict[str, Any]:
|
|
422
457
|
"""Convert JSON Structure enum to Avro enum."""
|
|
458
|
+
avro_symbols, symbol_mapping = self._sanitize_enum_symbols(schema['enum'])
|
|
423
459
|
avro_enum: Dict[str, Any] = {
|
|
424
460
|
'type': 'enum',
|
|
425
461
|
'name': name,
|
|
426
|
-
'symbols':
|
|
462
|
+
'symbols': avro_symbols
|
|
427
463
|
}
|
|
428
464
|
|
|
429
465
|
if namespace:
|
|
430
466
|
avro_enum['namespace'] = namespace
|
|
431
467
|
|
|
468
|
+
doc_parts = []
|
|
432
469
|
if 'description' in schema:
|
|
433
|
-
|
|
470
|
+
doc_parts.append(schema['description'])
|
|
471
|
+
if symbol_mapping:
|
|
472
|
+
doc_parts.append(
|
|
473
|
+
'Original enum values (Avro symbol -> wire value): '
|
|
474
|
+
+ json.dumps(symbol_mapping))
|
|
475
|
+
if doc_parts:
|
|
476
|
+
avro_enum['doc'] = ' '.join(doc_parts)
|
|
434
477
|
|
|
435
478
|
if 'default' in schema:
|
|
436
|
-
|
|
479
|
+
original_values = list(schema['enum'])
|
|
480
|
+
if schema['default'] in original_values:
|
|
481
|
+
avro_enum['default'] = avro_symbols[original_values.index(schema['default'])]
|
|
437
482
|
|
|
438
483
|
return avro_enum
|
|
439
484
|
|
|
@@ -531,11 +576,12 @@ class JsonStructureToAvro:
|
|
|
531
576
|
# Build enum type for discriminator
|
|
532
577
|
enum_name = f'{name}Type'
|
|
533
578
|
choice_names = list(choices.keys())
|
|
579
|
+
discriminator_symbols, _ = self._sanitize_enum_symbols(choice_names)
|
|
534
580
|
|
|
535
581
|
discriminator_enum: Dict[str, Any] = {
|
|
536
582
|
'type': 'enum',
|
|
537
583
|
'name': enum_name,
|
|
538
|
-
'symbols':
|
|
584
|
+
'symbols': discriminator_symbols
|
|
539
585
|
}
|
|
540
586
|
|
|
541
587
|
if namespace:
|
|
@@ -1,12 +1,41 @@
|
|
|
1
1
|
"""Converts a JSON Structure schema to a Kusto table schema."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import re
|
|
4
5
|
import sys
|
|
5
6
|
from typing import Any, List, Optional, Dict, Union
|
|
6
7
|
from avrotize.common import build_flat_type_dict, inline_avro_references, strip_first_doc
|
|
7
8
|
from azure.kusto.data import KustoClient, KustoConnectionStringBuilder, ClientRequestProperties
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
_KUSTO_BARE_IDENTIFIER = re.compile(r'^[A-Za-z_][A-Za-z0-9_]*$')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def kusto_column_name(name: str) -> str:
|
|
15
|
+
"""Return a Kusto-quoted column identifier.
|
|
16
|
+
|
|
17
|
+
Bare identifiers ([A-Za-z_][A-Za-z0-9_]*) are wrapped as [name]; any other
|
|
18
|
+
name (e.g. "dr-type") is quoted as ['name'] so hyphens and other characters
|
|
19
|
+
are valid (issue #382).
|
|
20
|
+
"""
|
|
21
|
+
if _KUSTO_BARE_IDENTIFIER.match(name):
|
|
22
|
+
return f"[{name}]"
|
|
23
|
+
escaped = name.replace('\\', '\\\\').replace("'", "\\'")
|
|
24
|
+
return f"['{escaped}']"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def kusto_json_path(name: str, prefix: str = "$") -> str:
|
|
28
|
+
"""Return a JSONPath expression for an ingestion-mapping property name.
|
|
29
|
+
|
|
30
|
+
Bare identifiers use dotted notation (``$.name``); any other name uses
|
|
31
|
+
bracket notation (``$['dr-type']``) so non-identifier keys are valid.
|
|
32
|
+
"""
|
|
33
|
+
if _KUSTO_BARE_IDENTIFIER.match(name):
|
|
34
|
+
return f"{prefix}.{name}"
|
|
35
|
+
escaped = name.replace('\\', '\\\\').replace("'", "\\'")
|
|
36
|
+
return f"{prefix}['{escaped}']"
|
|
37
|
+
|
|
38
|
+
|
|
10
39
|
def kusto_string_literal(value: str) -> str:
|
|
11
40
|
"""Return a KQL verbatim string literal for a raw Python string."""
|
|
12
41
|
return '@"' + value.replace('"', '""') + '"'
|
|
@@ -268,7 +297,7 @@ class StructureToKusto:
|
|
|
268
297
|
if isinstance(prop_schema, dict) and 'const' in prop_schema:
|
|
269
298
|
continue
|
|
270
299
|
column_type = self.convert_structure_type_to_kusto_type(prop_schema, schema_doc)
|
|
271
|
-
columns.append(f"
|
|
300
|
+
columns.append(f" {kusto_column_name(column_name)}: {column_type}")
|
|
272
301
|
if emit_cloudevents_columns:
|
|
273
302
|
columns.append(" [___type]: string")
|
|
274
303
|
columns.append(" [___source]: string")
|
|
@@ -365,7 +394,7 @@ class StructureToKusto:
|
|
|
365
394
|
continue
|
|
366
395
|
column_name = prop_name
|
|
367
396
|
mapping_entries.append(
|
|
368
|
-
f" {{\"column\": \"{column_name}\", \"path\": \"
|
|
397
|
+
f" {{\"column\": \"{column_name}\", \"path\": \"{kusto_json_path(prop_name)}\"}}")
|
|
369
398
|
kusto.append("```\n[\n" + ",\n".join(mapping_entries) + "\n]\n```\n\n")
|
|
370
399
|
|
|
371
400
|
if emit_cloudevents_columns:
|
|
@@ -383,7 +412,7 @@ class StructureToKusto:
|
|
|
383
412
|
continue
|
|
384
413
|
column_name = prop_name
|
|
385
414
|
ce_entries.append(
|
|
386
|
-
f" {{\"column\": \"{column_name}\", \"path\": \"$.data
|
|
415
|
+
f" {{\"column\": \"{column_name}\", \"path\": \"{kusto_json_path(prop_name, '$.data')}\"}}")
|
|
387
416
|
kusto.append("```\n[\n" + ",\n".join(ce_entries) + "\n]\n```\n\n")
|
|
388
417
|
|
|
389
418
|
if emit_cloudevents_columns:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: structurize
|
|
3
|
-
Version: 3.6.
|
|
3
|
+
Version: 3.6.1
|
|
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
|
{structurize-3.6.0 → structurize-3.6.1}/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
|