def py_name(self) -> str:
     """Pythonized method name."""
     return pythonize_method_name(self.proto_obj.name)
Example #2
0
def read_protobuf_service(service: ServiceDescriptorProto, index, proto_file,
                          content, output_types):
    input_package_name = content["input_package"]
    template_data = content["template_data"]
    # print(service, file=sys.stderr)
    data = {
        "name": service.name,
        "py_name": pythonize_class_name(service.name),
        "comment": get_comment(proto_file, [6, index]),
        "methods": [],
    }
    for j, method in enumerate(service.method):
        method_input_message = lookup_method_input_type(method, output_types)

        # This section ensures that method arguments having a default
        # value that is initialised as a List/Dict (mutable) is replaced
        # with None and initialisation is deferred to the beginning of the
        # method definition. This is done so to avoid any side-effects.
        # Reference: https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
        mutable_default_args = []

        if method_input_message:
            for field in method_input_message["properties"]:
                if (not method.client_streaming and field["zero"] != "None"
                        and is_mutable_field_type(field["type"])):
                    mutable_default_args.append(
                        (field["py_name"], field["zero"]))
                    field["zero"] = "None"

                if field["zero"] == "None":
                    template_data["typing_imports"].add("Optional")

        data["methods"].append({
            "name":
            method.name,
            "py_name":
            pythonize_method_name(method.name),
            "comment":
            get_comment(proto_file, [6, index, 2, j], indent=8),
            "route":
            f"/{input_package_name}.{service.name}/{method.name}",
            "input":
            get_type_reference(input_package_name, template_data["imports"],
                               method.input_type).strip('"'),
            "input_message":
            method_input_message,
            "output":
            get_type_reference(
                input_package_name,
                template_data["imports"],
                method.output_type,
                unwrap=False,
            ),
            "client_streaming":
            method.client_streaming,
            "server_streaming":
            method.server_streaming,
            "mutable_default_args":
            mutable_default_args,
        })

        if method.client_streaming:
            template_data["typing_imports"].add("AsyncIterable")
            template_data["typing_imports"].add("Iterable")
            template_data["typing_imports"].add("Union")
        if method.server_streaming:
            template_data["typing_imports"].add("AsyncIterator")
    template_data["services"].append(data)