in tasks/tools/typings_generator.py [0:0]
def fix_anomalies(schema: Dict):
"""
the original json schema gets generated as below, where inner model classes,
that are referred from API request response classes, are generated with
multiple references in definitions.
schema:
properties: {
Car: {
$ref: #/definitions/<uuid>__Car
}
}
definitions: {
<uuid>__Car: {
},
ideadatamodel__Car: {
},
ListCars: {
listing: {
$ref: <uuid>__Car
}
}
}
goal is to unify all these references to a single reference:
#/definitions/Car
one major caveat to this implementation is the Model class names must be unique.
this issue can be eliminated as long as all model class names are unique across modules.
"""
definitions = Utils.get_value_as_dict('definitions', schema)
# find anomalies in schema properties
properties = Utils.get_value_as_dict('properties', schema)
if properties is not None:
for name, value in properties.items():
ref = Utils.get_value_as_string('$ref', value)
if '__' not in ref:
continue
definition_key = ref.replace('#/definitions/', '')
definition = Utils.get_value_as_dict(definition_key, definitions)
definitions[name] = definition
updated_ref = f'#/definitions/{name}'
value['$ref'] = updated_ref
# traverse definitions and replace anomalies
add_definitions = {}
def get_update_ref(ref_value: Optional[str]) -> Optional[str]:
if ref_value is None:
return None
if '__' not in ref:
return ref
ref_type_name = ref.split('__')[-1]
return f'#/definitions/{ref_type_name}'
if definitions is not None:
for name, value in definitions.items():
if '__' in name:
title = Utils.get_value_as_string('title', value)
add_definitions[title] = value
current_properties = Utils.get_value_as_dict('properties', value)
if current_properties is None:
continue
for prop_name, prop_value in current_properties.items():
prop_type = Utils.get_value_as_string('type', prop_value)
if prop_type is not None and prop_type == 'array':
array_items = Utils.get_value_as_dict('items', prop_value)
any_of_types = Utils.get_value_as_list('anyOf', array_items)
if any_of_types is not None:
for any_of in any_of_types:
ref = Utils.get_value_as_string('$ref', any_of)
updated_ref = get_update_ref(ref)
if updated_ref is not None:
any_of['$ref'] = updated_ref
else:
ref = Utils.get_value_as_string('$ref', array_items)
updated_ref = get_update_ref(ref)
if updated_ref is not None:
array_items['$ref'] = updated_ref
else:
ref = Utils.get_value_as_string('$ref', prop_value)
updated_ref = get_update_ref(ref)
if updated_ref is not None:
prop_value['$ref'] = updated_ref
# clean-up definitions
to_delete = []
for name in definitions:
if '__' in name:
to_delete.append(name)
for name in to_delete:
del definitions[name]
# add updated refs
for name in add_definitions:
definitions[name] = add_definitions[name]