def py_name(self) -> str: """Pythonized name.""" return pythonize_field_name(self.proto_name)
def read_protobuf_type(item: DescriptorProto, path: List[int], proto_file, content): input_package_name = content["input_package"] template_data = content["template_data"] data = { "name": item.name, "py_name": pythonize_class_name(item.name), "descriptor": item, "package": input_package_name, } if isinstance(item, DescriptorProto): # print(item, file=sys.stderr) if item.options.map_entry: # Skip generated map entry messages since we just use dicts return data.update({ "type": "Message", "comment": get_comment(proto_file, path), "properties": [], }) for i, f in enumerate(item.field): t = py_type(input_package_name, template_data["imports"], f) zero = get_py_zero(f.type) repeated = False packed = False field_type = f.Type.Name(f.type).lower()[5:] field_wraps = "" match_wrapper = re.match(r"\.google\.protobuf\.(.+)Value", f.type_name) if match_wrapper: wrapped_type = "TYPE_" + match_wrapper.group(1).upper() if hasattr(betterproto, wrapped_type): field_wraps = f"betterproto.{wrapped_type}" map_types = None if f.type == 11: # This might be a map... message_type = f.type_name.split(".").pop().lower() # message_type = py_type(package) map_entry = f"{f.name.replace('_', '').lower()}entry" if message_type == map_entry: for nested in item.nested_type: if nested.name.replace("_", "").lower() == map_entry: if nested.options.map_entry: # print("Found a map!", file=sys.stderr) k = py_type( input_package_name, template_data["imports"], nested.field[0], ) v = py_type( input_package_name, template_data["imports"], nested.field[1], ) t = f"Dict[{k}, {v}]" field_type = "map" map_types = ( f.Type.Name(nested.field[0].type), f.Type.Name(nested.field[1].type), ) template_data["typing_imports"].add("Dict") if f.label == 3 and field_type != "map": # Repeated field repeated = True t = f"List[{t}]" zero = "[]" template_data["typing_imports"].add("List") if f.type in [1, 2, 3, 4, 5, 6, 7, 8, 13, 15, 16, 17, 18]: packed = True one_of = "" if f.HasField("oneof_index"): one_of = item.oneof_decl[f.oneof_index].name if "Optional[" in t: template_data["typing_imports"].add("Optional") if "timedelta" in t: template_data["datetime_imports"].add("timedelta") elif "datetime" in t: template_data["datetime_imports"].add("datetime") data["properties"].append({ "name": f.name, "py_name": pythonize_field_name(f.name), "number": f.number, "comment": get_comment(proto_file, path + [2, i]), "proto_type": int(f.type), "field_type": field_type, "field_wraps": field_wraps, "map_types": map_types, "type": t, "zero": zero, "repeated": repeated, "packed": packed, "one_of": one_of, }) # print(f, file=sys.stderr) template_data["messages"].append(data) return data elif isinstance(item, EnumDescriptorProto): # print(item.name, path, file=sys.stderr) data.update({ "type": "Enum", "comment": get_comment(proto_file, path), "entries": [{ "name": v.name, "value": v.number, "comment": get_comment(proto_file, path + [2, i]), } for i, v in enumerate(item.value)], }) template_data["enums"].append(data) return data