Files
2026-07-13 13:22:34 +08:00

68 lines
2.7 KiB
Python

from autogeneration_utils import get_method_name
from google.protobuf.descriptor import FieldDescriptor
from mlflow.protos import databricks_pb2
def get_method_type(method_descriptor):
return method_descriptor.GetOptions().Extensions[databricks_pb2.rpc].endpoints[0].method
def process_method(method_descriptor, state):
"""
Given a method descriptor, add information being referenced into the GenerateSchemaState.
"""
if not method_descriptor.GetOptions().HasExtension(databricks_pb2.graphql):
return
rpcOptions = method_descriptor.GetOptions().Extensions[databricks_pb2.rpc]
# Only add those methods that are not internal.
if rpcOptions.visibility != databricks_pb2.INTERNAL:
name = get_method_name(method_descriptor)
if name in state.method_names:
return
state.method_names.add(name)
request_method = get_method_type(method_descriptor)
if request_method == "GET":
state.queries.add(method_descriptor)
else:
state.mutations.add(method_descriptor)
state.outputs.add(method_descriptor.output_type)
populate_message_types(method_descriptor.input_type, state, True, set())
populate_message_types(method_descriptor.output_type, state, False, set())
def populate_message_types(field_descriptor, state, is_input, visited):
"""
Given a field descriptor, recursively walk through the referenced message types and add
information being referenced into the GenerateSchemaState.
"""
if field_descriptor in visited:
# Break the loop for recursive types.
return
visited.add(field_descriptor)
if is_input:
add_message_descriptor_to_list(field_descriptor, state.inputs)
else:
add_message_descriptor_to_list(field_descriptor, state.types)
for sub_field in field_descriptor.fields:
type = sub_field.type
if type in (FieldDescriptor.TYPE_MESSAGE, FieldDescriptor.TYPE_GROUP):
populate_message_types(sub_field.message_type, state, is_input, visited)
elif type == FieldDescriptor.TYPE_ENUM:
state.enums.add(sub_field.enum_type)
else:
continue
def add_message_descriptor_to_list(descriptor, target_list):
# Always put the referenced message at the beginning, so that when generating the schema,
# the ordering can be maintained in a way that correspond to the reference graph.
# list.remove() and insert(0) are not optimal in terms of efficiency but are fine because
# the amount of data is very small here.
if descriptor not in target_list:
target_list.insert(0, descriptor)
else:
target_list.remove(descriptor)
target_list.insert(0, descriptor)