### Install proto-schema-parser Source: https://github.com/criccomini/proto-schema-parser/blob/main/README.md Install the package using pip. ```bash pip install proto-schema-parser ``` -------------------------------- ### Generate Lexer/Parser with ANTLR Source: https://github.com/criccomini/proto-schema-parser/blob/main/DEVELOPER.md Run this command to generate the lexer and parser files from ANTLR grammar files. Ensure you have the necessary dependencies installed via pdm. ```bash pdm run antlr ``` -------------------------------- ### AST Representation of Protobuf Schema Source: https://github.com/criccomini/proto-schema-parser/blob/main/README.md This is an example of the AST object generated by the Parser, representing the structure of a protobuf schema. ```python File( syntax='proto3', file_elements=[ Message( name='SearchRequest', elements=[ Field( name='query', number=1, type='string', cardinality=None, options=[]), Field( name='page_number', number=2, type='int32', cardinality=None, options=[]), Field( name='result_per_page', number=3, type='int32', cardinality=None, options=[])])]) ``` -------------------------------- ### Manually Build and Generate File AST Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Demonstrates manual construction of an `ast.File` node, including package and message definitions, and then generating the corresponding .proto content. ```python from proto_schema_parser.generator import Generator from proto_schema_parser import ast manual = ast.File( syntax="proto3", file_elements=[ ast.Package(name="io.example"), ast.Message( name="Ping", elements=[ast.Field(name="payload", number=1, type="bytes")], ), ], ) print(Generator().generate(manual)) ``` -------------------------------- ### Parse Proto3 and Edition Files Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Shows how to parse both proto3 and edition-based .proto files using the Parser. Verifies the extracted syntax and edition attributes. ```python from proto_schema_parser.parser import Parser from proto_schema_parser import ast # proto3 file proto3_file = Parser().parse('syntax = "proto3";\nmessage Foo { string bar = 1; }') assert proto3_file.syntax == "proto3" assert proto3_file.edition is None # edition 2023 file edition_file = Parser().parse('edition = "2023";\nmessage Foo { string bar = 1; }') assert edition_file.syntax is None assert edition_file.edition == "2023" ``` -------------------------------- ### Parser.__init__(setup_lexer, setup_parser) Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Customizes the parser's error handling by attaching a custom ANTLR error listener, allowing syntax errors to be raised as Python exceptions. ```APIDOC ## Parser.__init__(setup_lexer, setup_parser) ### Description Attaches a custom ANTLR error listener to raise Python exceptions on syntax errors instead of printing to stderr. ### Method `Parser.__init__(setup_lexer=None, setup_parser=None)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **setup_lexer** (callable) - Optional - A callback function to set up the lexer. * **setup_parser** (callable) - Optional - A callback function to set up the parser, allowing for custom error listeners. ### Request Example ```python import antlr4.error.ErrorListener as antlr4_el import proto_schema_parser.antlr.ProtobufParser as psp_antlr from proto_schema_parser.parser import Parser class StrictErrorListener(antlr4_el.ErrorListener): def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e): raise SyntaxError(f"line {line}:{column}: {msg}") def setup_parser(parser: psp_antlr.ProtobufParser) -> None: parser.removeErrorListeners() parser.addErrorListener(StrictErrorListener()) try: # Missing semicolon after field number — will raise SyntaxError bad_schema = """ syntax = \"proto3\"; message Broken { string name = 1 } """ Parser(setup_parser=setup_parser).parse(bad_schema) except SyntaxError as e: print(e) # line 5:4: mismatched input '}' expecting {';', '['} ``` ### Response This method does not return a value directly, but configures the parser instance. ``` -------------------------------- ### Publish to PyPI Source: https://github.com/criccomini/proto-schema-parser/blob/main/DEVELOPER.md Execute this command to publish the project to PyPI. Remember to create a GitHub release and update the version number beforehand. ```bash pdm run publish ``` -------------------------------- ### Parsing and Inspecting Service and RPC Methods Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Demonstrates parsing a proto schema with a service definition, including unary and streaming RPC methods. Accesses method names, input/output types, and options. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto3"; service GreetService { // Simple unary call rpc SayHello (HelloRequest) returns (HelloReply); // Server-streaming RPC rpc SayHelloStream (HelloRequest) returns (stream HelloReply); // Bidirectional streaming rpc Chat (stream ChatMessage) returns (stream ChatMessage) { option (google.api.http) = { post: "/v1/chat" body: "*" }; } } """ file = Parser().parse(schema) svc = next(e for e in file.file_elements if isinstance(e, ast.Service)) for elem in svc.elements: if isinstance(elem, ast.Method): in_s = "stream " if elem.input_type.stream else "" out_s = "stream " if elem.output_type.stream else "" print(f"rpc {elem.name}({in_s}{elem.input_type.type}) -> ({out_s}{elem.output_type.type})") for opt in elem.elements: if isinstance(opt, ast.Option): print(f" option {opt.name} = {opt.value}") print(Generator().generate(file)) ``` -------------------------------- ### Parsing and Building Message Literal Options Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Illustrates parsing a proto schema with complex options like google.api.http, which use message literals. Also shows how to programmatically construct such options. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto3"; service SearchService { rpc Search (SearchRequest) returns (SearchResponse) { option (google.api.http) = { get: "/v1/search/{query}" additional_bindings { post: "/v1/search" body: "*" } }; } } """ file = Parser().parse(schema) svc = next(e for e in file.file_elements if isinstance(e, ast.Service)) method = next(e for e in svc.elements if isinstance(e, ast.Method)) http = next(e for e in method.elements if isinstance(e, ast.Option)) assert isinstance(http.value, ast.MessageLiteral) for field in http.value.elements: if isinstance(field, ast.MessageLiteralField): print(field.name, "->", field.value) # get -> /v1/search/{query} # additional_bindings -> MessageLiteral(...) # Build the same option programmatically option = ast.Option( name="(google.api.http)", value=ast.MessageLiteral(elements=[ ast.MessageLiteralField(name="post", value="/v1/items"), ast.MessageLiteralField(name="body", value="*"), ast.MessageLiteralField( name="additional_bindings", value=ast.MessageLiteral(elements=[ ast.MessageLiteralField(name="get", value="/v1/items/{id}"), ]), ), ]), ) print(Generator()._generate_option(option)) ``` -------------------------------- ### Parse and Generate Protobuf with Editions Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Parses a .proto text using edition 2023, asserts its properties, and then generates .proto text from an AST. Also demonstrates constructing and generating an edition 2024 file. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast text = """edition = "2023"; package com.example; import "other.proto"; message Example { string field = 1; } """ file = Parser().parse(text) assert file.syntax is None assert file.edition == "2023" pkg = next(e for e in file.file_elements if isinstance(e, ast.Package)) assert pkg.name == "com.example" # Round-trip generated = Generator().generate(file) parsed_again = Parser().parse(generated) assert parsed_again.edition == "2023" # Manually construct an edition-2024 file edition_file = ast.File( edition="2024", file_elements=[ ast.Message( name="Person", elements=[ast.Field(name="name", number=1, type="string")], ) ], ) print(Generator().generate(edition_file)) ``` -------------------------------- ### Represent a .proto File in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a .proto file, holding its syntax, edition, and a list of its elements. ```python class File: ``` -------------------------------- ### proto_schema_parser.ast.File Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a .proto file, including its syntax, edition, and elements. ```APIDOC ## proto_schema_parser.ast.File ### Description Represents a .proto file. ### Class Signature ```python class File: ``` ### Attributes - **syntax** (Union[str, None]) - The syntax level of the .proto file. - **edition** (Union[str, None]) - The edition level of the .proto file. - **file_elements** (List[FileElement]) - A list of file elements in the .proto file. ``` -------------------------------- ### proto_schema_parser.parser.Parser.__init__ Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Initializes a new instance of the Parser class. Allows for optional customization of the lexer and parser behavior through callback functions. ```APIDOC ## proto_schema_parser.parser.Parser.__init__ ### Description Initializes a new instance of the Parser class. ### Method Signature def __init__(self, setup_lexer: Optional[SetupLexerCb] = None, setup_parser: Optional[SetupParserCb] = None) -> None: ### Parameters #### Path Parameters - **setup_lexer** (`Optional[SetupLexerCb]`): A callback function to modify the lexer during parsing. Defaults to None. - **setup_parser** (`Optional[SetupParserCb]`): A callback function to modify the parser during parsing. Defaults to None. ``` -------------------------------- ### Define a Service in Protocol Buffers Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a service definition in Protocol Buffers. Includes the service name and its constituent methods or elements. ```python class Service: """Represents a service in a message.""" name: str elements: List[ServiceElement] = field(default_factory=list) ``` -------------------------------- ### proto_schema_parser.ast.Package Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a package declaration in a .proto file. ```APIDOC ## proto_schema_parser.ast.Package ### Description Represents a package declaration in a .proto file. ### Class Signature ```python class Package: ``` ### Attributes - **name** (str) - The name of the package. ``` -------------------------------- ### proto_schema_parser.ast.Option Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an option defined in a .proto file. ```APIDOC ## proto_schema_parser.ast.Option ### Description Represents an option in a .proto file. ### Class Signature ```python class Option: ``` ### Attributes - **name** (str) - The name of the option. - **value** (Union[ScalarValue, MessageLiteral]) - The value of the option. ``` -------------------------------- ### proto_schema_parser.ast.Import Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an import declaration in a .proto file. ```APIDOC ## proto_schema_parser.ast.Import ### Description Represents an import declaration in a .proto file. ### Class Signature ```python class Import: ``` ### Attributes - **name** (str) - The name of the imported file. - **weak** (bool) - True if the import is weak, False otherwise. - **public** (bool) - True if the import is public, False otherwise. ``` -------------------------------- ### Represent a Package Declaration in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a package declaration in a .proto file. Stores the package name. ```python class Package: ``` -------------------------------- ### Generate Protobuf Schema Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Generates a protobuf schema string from an abstract syntax tree (AST). ```python def generate(self, file: ast.File) -> str: ``` -------------------------------- ### Represent an Option in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an option declaration in a .proto file. Stores the option name and its value. ```python class Option: ``` -------------------------------- ### Initialize Parser Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Initializes a new instance of the Parser class, optionally accepting callbacks to modify the lexer or parser. ```python def __init__(self, setup_lexer: Optional[SetupLexerCb] = None, setup_parser: Optional[SetupParserCb] = None) -> None: ``` -------------------------------- ### Generate Protobuf Schema from AST Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Serializes an AST back into a Protobuf schema string. Preserves comments, indentation, and structural elements. Demonstrates a round-trip parse-mutate-generate process. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator schema = """syntax = "proto3"; package com.example; message SearchRequest { string query = 1; optional int32 page_number = 2; int32 results_per_page = 3; } """ # Round-trip: parse → mutate → generate file = Parser().parse(schema) ``` -------------------------------- ### Parse Protobuf Schema String Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Parses a string representing a protobuf schema and returns its abstract syntax tree (AST) representation. ```python def parse(self, text: str) -> ast.File: ``` -------------------------------- ### Define Message with Fields and Reserved Ranges Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Illustrates the creation of a `ast.File` node representing a proto2 message with various field types (required, optional, repeated), comments, reserved ranges, and reserved names. Generates the .proto output. ```python from proto_schema_parser import ast from proto_schema_parser.generator import Generator file = ast.File( syntax="proto2", file_elements=[ ast.Message( name="Person", elements=[ ast.Comment(text="// Unique identifier"), ast.Field(name="id", number=1, type="int32", cardinality=ast.FieldCardinality.REQUIRED), ast.Field(name="name", number=2, type="string", cardinality=ast.FieldCardinality.REQUIRED), ast.Field(name="email", number=3, type="string", cardinality=ast.FieldCardinality.OPTIONAL), ast.Field( name="phones", number=4, type="PhoneNumber", cardinality=ast.FieldCardinality.REPEATED, options=[ast.Option(name="packed", value=True)], ), ast.Reserved(ranges=["10", "15 to 20"]), ast.Reserved(names=["old_field", "legacy_id"]), ], ) ], ) print(Generator().generate(file)) ``` -------------------------------- ### Generated Protobuf Schema String Source: https://github.com/criccomini/proto-schema-parser/blob/main/README.md This is the resulting protobuf schema string generated from an AST object. ```proto syntax = "proto3"; message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3; } ``` -------------------------------- ### Parse Protobuf Schema to AST Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Parses a Protobuf schema string into an AST. Supports proto2, proto3, and edition-based schemas. Demonstrates iterating through parsed elements like messages, fields, enums, and services. ```python from proto_schema_parser.parser import Parser from proto_schema_parser import ast text = """ syntax = "proto3"; package com.example; import "google/protobuf/timestamp.proto"; message User { // Primary key required string id = 1; optional string email = 2; repeated string roles = 3 [packed = true]; map metadata = 4; enum Status { UNKNOWN = 0; ACTIVE = 1; DELETED = 2; } optional Status status = 5 [default = ACTIVE]; } service UserService { rpc GetUser (GetUserRequest) returns (User); rpc ListUsers (ListUsersRequest) returns (stream User); } """ file: ast.File = Parser().parse(text) # Top-level attributes print(file.syntax) # "proto3" print(file.edition) # None # Iterate file-level elements for element in file.file_elements: if isinstance(element, ast.Package): print("package:", element.name) # com.example elif isinstance(element, ast.Import): print("import:", element.name, "public:", element.public, "weak:", element.weak) elif isinstance(element, ast.Message): print("message:", element.name) for field in element.elements: if isinstance(field, ast.Field): print(f" field: {field.cardinality} {field.type} {field.name} = {field.number}") elif isinstance(field, ast.MapField): print(f" map<{field.key_type},{field.value_type}> {field.name} = {field.number}") elif isinstance(field, ast.Enum): for v in field.elements: if isinstance(v, ast.EnumValue): print(f" enum value: {v.name} = {v.number}") elif isinstance(element, ast.Service): print("service:", element.name) for rpc in element.elements: if isinstance(rpc, ast.Method): print(f" rpc {rpc.name}(stream={rpc.input_type.stream}) -> (stream={rpc.output_type.stream})") ``` -------------------------------- ### Parsing and Inspecting Map Fields Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Shows how to parse a proto schema containing map fields and extract their key types, value types, names, and numbers. Supports various key and value types. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto3"; message Config { map labels = 1; map blobs = 2; map messages = 3; } """ file = Parser().parse(schema) msg = next(e for e in file.file_elements if isinstance(e, ast.Message)) for elem in msg.elements: if isinstance(elem, ast.MapField): print(f"map<{elem.key_type},{elem.value_type}> {elem.name} = {elem.number}") # map labels = 1 # map blobs = 2 # map messages = 3 print(Generator().generate(file)) ``` -------------------------------- ### Parse proto2 Extensions with ast.Extension Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Parses a proto2 schema to extract and print information about extensions and extension ranges using ast.Extension and ast.ExtensionRange. The generated proto code is also printed. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto2"; message MyOptions { extensions 1000 to 1999; } extend MyOptions { optional string description = 1000; optional bool deprecated = 1001; } """ file = Parser().parse(schema) for elem in file.file_elements: if isinstance(elem, ast.Message): for sub in elem.elements: if isinstance(sub, ast.ExtensionRange): print("extension ranges:", sub.ranges) # ['1000 to 1999'] elif isinstance(elem, ast.Extension): print("extend:", elem.typeName) for f in elem.elements: if isinstance(f, ast.Field): print(f" {f.cardinality.value.lower()} {f.type} {f.name} = {f.number}") print(Generator().generate(file)) ``` -------------------------------- ### Parse Protobuf Schema with Editions Source: https://github.com/criccomini/proto-schema-parser/blob/main/README.md Parse a protobuf file using edition syntax, such as 'edition = "2023";'. The parser will correctly identify the edition and set the `edition` attribute on the AST object. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator # Parse a protobuf file using edition syntax text = """ edition = "2023"; message SearchRequest { string query = 1; int32 page_number = 2; } """ result = Parser().parse(text) # result.edition will be "2023" # result.syntax will be None # Generate back to protobuf format proto = Generator().generate(result) ``` -------------------------------- ### Represent a Message in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a message definition within a .proto file. Includes the message name and its constituent elements. ```python class Message: ``` -------------------------------- ### Parsing and Inspecting OneOf Fields Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Demonstrates parsing a proto schema with a oneof field and accessing its name and nested fields. Ensure the proto schema syntax is valid. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto3"; message Notification { string recipient = 1; oneof channel { option (my_oneof_option) = "example"; string email = 2; string sms = 3; string push_id = 4; } } """ file = Parser().parse(schema) msg = next(e for e in file.file_elements if isinstance(e, ast.Message)) oneof = next(e for e in msg.elements if isinstance(e, ast.OneOf)) print("oneof name:", oneof.name) # channel for elem in oneof.elements: if isinstance(elem, ast.Field): print(" field:", elem.name, elem.type) print(Generator().generate(file)) ``` -------------------------------- ### Define a Method in a Protocol Buffer Service Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a method within a Protocol Buffers service. Includes the method name, input type, output type, and any associated elements. ```python class Method: """Represents a method in a service.""" name: str input_type: MessageType output_type: MessageType elements: List[MethodElement] = field(default_factory=list) ``` -------------------------------- ### Parser Class Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md The Parser class takes a string representing a protobuf schema and returns an abstract syntax tree (AST). ```python class Parser: ``` -------------------------------- ### Generator Class Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md The Generator class takes an abstract syntax tree (AST) and generates a protobuf schema string. ```python class Generator: ``` -------------------------------- ### proto_schema_parser.ast.Comment Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a comment within a .proto file. ```APIDOC ## proto_schema_parser.ast.Comment ### Description Represents a comment in a .proto file. ### Class Signature ```python class Comment: ``` ### Attributes - **text** (str) - The text of the comment. ``` -------------------------------- ### Represent an Import Declaration in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an import statement in a .proto file, including its name and whether it's weak or public. ```python class Import: ``` -------------------------------- ### Generator.generate(file: ast.File) Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Serializes an ast.File AST back into a valid Protobuf schema string, preserving comments, indentation, and all structural elements. ```APIDOC ## Generator.generate(file: ast.File) ### Description Serializes an `ast.File` AST back into a valid Protobuf schema string. Preserves inline and block comments, proper indentation, field cardinalities, options, and all structural elements. ### Method `Generator.generate(file: ast.File) -> str` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **file** (ast.File) - Required - The AST object to serialize into a Protobuf schema string. ### Request Example ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator schema = """syntax = \"proto3\"; package com.example; message SearchRequest { string query = 1; optional int32 page_number = 2; int32 results_per_page = 3; } """ # Round-trip: parse → mutate → generate file = Parser().parse(schema) # Example of generating the schema string from the AST # generator = Generator() # generated_schema = generator.generate(file) # print(generated_schema) ``` ### Response #### Success Response (200) * **str** - A string containing the generated Protobuf schema. ``` -------------------------------- ### proto_schema_parser.generator.Generator.generate Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Generates a protobuf schema string from an abstract syntax tree (AST). This method takes a fully constructed AST representing a .proto file and outputs its string representation. ```APIDOC ## proto_schema_parser.generator.Generator.generate ### Description Generates a protobuf schema string from an abstract syntax tree (AST). ### Method Signature def generate(self, file: ast.File) -> str: ### Parameters #### Path Parameters - **file** (`ast.File`): The abstract syntax tree of the .proto file. ### Returns - `str`: The generated protobuf schema string. ``` -------------------------------- ### Add Field to Message AST Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Demonstrates how to programmatically add a new field to an existing message node in the AST and then generate the updated .proto content. ```python from proto_schema_parser import ast from proto_schema_parser.generator import Generator # Assuming 'file' is an existing ast.File object # For demonstration, let's create a sample file object: file = ast.File( syntax="proto3", file_elements=[ ast.Message( name="SearchRequest", elements=[ ast.Field(name="query", number=1, type="string"), ast.Field(name="page_number", number=2, type="int32", cardinality=ast.FieldCardinality.OPTIONAL), ast.Field(name="results_per_page", number=3, type="int32") ] ) ] ) message = next(e for e in file.file_elements if isinstance(e, ast.Message)) message.elements.append( ast.Field(name="sort_order", number=4, type="string", cardinality=ast.FieldCardinality.OPTIONAL) ) output = Generator().generate(file) print(output) ``` -------------------------------- ### Parse Protobuf Schema to AST Source: https://github.com/criccomini/proto-schema-parser/blob/main/README.md Use the Parser class to parse a protobuf schema string into an AST object. This is useful for analyzing or manipulating schema structures programmatically. ```python from proto_schema_parser.parser import Parser text = """ syntax = "proto3"; message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3; } """ result = Parser().parse(text) ``` -------------------------------- ### Parser.parse(text: str) Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Parses a protobuf schema string into an ast.File AST. Supports proto2, proto3, and edition-based schemas. ```APIDOC ## Parser.parse(text: str) ### Description Parses a protobuf schema string into an `ast.File` AST. Accepts proto2, proto3, and edition-based schemas. Optionally accepts `setup_lexer` and `setup_parser` callbacks in the constructor to customise ANTLR behaviour (e.g., to attach a custom error listener). ### Method `Parser.parse(text: str) -> ast.File` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **text** (str) - Required - The protobuf schema string to parse. ### Request Example ```python from proto_schema_parser.parser import Parser from proto_schema_parser import ast text = """ syntax = \"proto3\"; package com.example; import \"google/protobuf/timestamp.proto\"; message User { // Primary key required string id = 1; optional string email = 2; repeated string roles = 3 [packed = true]; map metadata = 4; enum Status { UNKNOWN = 0; ACTIVE = 1; DELETED = 2; } optional Status status = 5 [default = ACTIVE]; } service UserService { rpc GetUser (GetUserRequest) returns (User); rpc ListUsers (ListUsersRequest) returns (stream User); } """ file: ast.File = Parser().parse(text) # Top-level attributes print(file.syntax) # \"proto3\" print(file.edition) # None # Iterate file-level elements for element in file.file_elements: if isinstance(element, ast.Package): print(\"package:\", element.name) # com.example elif isinstance(element, ast.Import): print(\"import:\", element.name, \"public:\", element.public, \"weak:\", element.weak) elif isinstance(element, ast.Message): print(\"message:\", element.name) for field in element.elements: if isinstance(field, ast.Field): print(f\" field: {field.cardinality} {field.type} {field.name} = {field.number}\") elif isinstance(field, ast.MapField): print(f\" map<{field.key_type},{field.value_type}> {field.name} = {field.number}\") elif isinstance(field, ast.Enum): for v in field.elements: if isinstance(v, ast.EnumValue): print(f\" enum value: {v.name} = {v.number}\") elif isinstance(element, ast.Service): print(\"service:\", element.name) for rpc in element.elements: if isinstance(rpc, ast.Method): print(f\" rpc {rpc.name}(stream={rpc.input_type.stream}) -> (stream={rpc.output_type.stream})\") ``` ### Response #### Success Response (200) * **ast.File** - The parsed Abstract Syntax Tree representation of the protobuf schema. ``` -------------------------------- ### proto_schema_parser.ast.Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a message definition within a .proto file. ```APIDOC ## proto_schema_parser.ast.Message ### Description Represents a message in a .proto file. ### Class Signature ```python class Message: ``` ### Attributes - **name** (str) - The name of the message. - **elements** (List[MessageElement]) - The elements of the message. ``` -------------------------------- ### proto_schema_parser.parser.Parser.parse Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Parses a string representing a protobuf schema and returns its abstract syntax tree (AST) representation. This is the primary method for converting schema text into a structured format. ```APIDOC ## proto_schema_parser.parser.Parser.parse ### Description Parses a string representing a protobuf schema and returns an abstract syntax tree (AST). ### Method Signature def parse(self, text: str) -> ast.File: ### Parameters #### Path Parameters - **text** (`str`): The string representing the protobuf schema. ### Returns - `ast.File`: The abstract syntax tree representation of the protobuf schema. ``` -------------------------------- ### Represent a Message Literal Field in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a field within a message literal in a .proto file. Includes the field name and its value. ```python class MessageLiteralField: ``` -------------------------------- ### Parse proto2 Groups with ast.Group Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Parses a proto2 schema containing a group field to demonstrate the usage of the ast.Group node. It prints the group's name, number, cardinality, and its fields. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto2"; message SearchResponse { repeated group Result = 1 { required string url = 2; optional string title = 3; repeated string snippet = 4; } } """ file = Parser().parse(schema) msg = next(e for e in file.file_elements if isinstance(e, ast.Message)) grp = next(e for e in msg.elements if isinstance(e, ast.Group)) print("group:", grp.name, "number:", grp.number, "cardinality:", grp.cardinality) for f in grp.elements: if isinstance(f, ast.Field): print(f" {f.name}: {f.type} (cardinality={f.cardinality})") print(Generator().generate(file)) ``` -------------------------------- ### Parse and Generate Enum with Reserved Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Parses a .proto schema containing an enum with options, values (including hex literals), and reserved ranges/names. It then iterates through the enum elements and regenerates the .proto content. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto3"; enum Color { option allow_alias = true; // First value must be zero in proto3 UNKNOWN = 0; RED = 1; GREEN = 2; BLUE = 0xC8; // hex literal → parsed as 200 reserved 50 to 100; reserved "TRANSPARENT"; } """ file = Parser().parse(schema) color_enum = next(e for e in file.file_elements if isinstance(e, ast.Enum)) for elem in color_enum.elements: if isinstance(elem, ast.EnumValue): print(f"{elem.name} = {elem.number}") # BLUE = 200 (not 0xC8) elif isinstance(elem, ast.EnumReserved): print("reserved ranges:", elem.ranges, "names:", elem.names) # Re-generate print(Generator().generate(file)) ``` -------------------------------- ### Represent a Comment in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a comment found within a .proto file. Stores the comment text. ```python class Comment: ``` -------------------------------- ### Generate Protobuf Schema from AST Source: https://github.com/criccomini/proto-schema-parser/blob/main/README.md Use the Generator class to convert an AST object back into a protobuf schema string. This is useful for serializing modified or newly created schema structures. ```python from proto_schema_parser.generator import Generator proto = Generator().generate(result) ``` -------------------------------- ### proto_schema_parser.ast.MessageLiteral Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a message literal structure. ```APIDOC ## proto_schema_parser.ast.MessageLiteral ### Description Represents a message literal. ### Class Signature ```python class MessageLiteral: ``` ### Attributes - **elements** (List[MessageLiteralElement]) - The elements (fields and comments) of the message literal. ``` -------------------------------- ### Define an Extension in a Protocol Buffer Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an extension declaration within a Protocol Buffers message. Includes the type name and its elements. ```python class Extension: """Represents an extension in a message.""" typeName: str elements: List[ExtensionElement] = field(default_factory=list) ``` -------------------------------- ### Define a Message Type Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a message type, indicating its name and whether it's a stream. ```python class MessageType: """Represents a message type in a message.""" type: str stream: bool = False ``` -------------------------------- ### Custom Error Handling with ANTLR Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Customizes ANTLR error handling to raise Python exceptions on syntax errors. Useful for integrating with existing error reporting mechanisms. ```python import antlr4.error.ErrorListener as antlr4_el import proto_schema_parser.antlr.ProtobufParser as psp_antlr from proto_schema_parser.parser import Parser class StrictErrorListener(antlr4_el.ErrorListener): def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e): raise SyntaxError(f"line {line}:{column}: {msg}") def setup_parser(parser: psp_antlr.ProtobufParser) -> None: parser.removeErrorListeners() parser.addErrorListener(StrictErrorListener()) try: # Missing semicolon after field number — will raise SyntaxError bad_schema = """ syntax = "proto3"; message Broken { string name = 1 } """ Parser(setup_parser=setup_parser).parse(bad_schema) except SyntaxError as e: print(e) # line 5:4: mismatched input '}' expecting {';', '['} ``` -------------------------------- ### Handle Unquoted Identifiers with ast.Identifier Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Shows how ast.Identifier represents unquoted names used as option values, such as enum constants. The generator emits these without quotes. It also demonstrates building an option with an Identifier value. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto3"; service MyService { option (lifecycle) = DEPRECATED; option (major_version) = 2; } """ file = Parser().parse(schema) svc = next(e for e in file.file_elements if isinstance(e, ast.Service)) for opt in svc.elements: if isinstance(opt, ast.Option): print(opt.name, type(opt.value).__name__, repr(opt.value)) # (lifecycle) Identifier Identifier(name='DEPRECATED') # (major_version) int 2 # Build an option with an Identifier value opt = ast.Option(name="status", value=ast.Identifier(name="ACTIVE")) print(Generator()._generate_option(opt, indent_level=0)) # option status = ACTIVE; ``` -------------------------------- ### Define a Field in a Protocol Buffer Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a standard field within a Protocol Buffers message. Includes name, number, type, optional cardinality, and options. ```python class Field: """Represents a field in a message.""" name: str number: int type: str cardinality: Union[FieldCardinality, None] = None options: List[Option] = field(default_factory=list) ``` -------------------------------- ### Define a Map Field in a Protocol Buffer Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a map field within a Protocol Buffers message. Includes name, number, key type, value type, and options. ```python class MapField: """Represents a map field in a message.""" name: str number: int key_type: str value_type: str options: List[Option] = field(default_factory=list) ``` -------------------------------- ### Define an Extension Range in a Protocol Buffer Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an extension range within a Protocol Buffers message. Includes a list of ranges and associated options. ```python class ExtensionRange: """Represents an extension range in a message.""" ranges: List[str] options: List[Option] = field(default_factory=list) ``` -------------------------------- ### Define an OneOf in a Protocol Buffer Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an oneof construct within a Protocol Buffers message. Includes name and its constituent elements. ```python class OneOf: """Represents an oneof in a message.""" name: str elements: List[OneOfElement] = field(default_factory=list) ``` -------------------------------- ### proto_schema_parser.ast.MessageLiteralField Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a field within a message literal. ```APIDOC ## proto_schema_parser.ast.MessageLiteralField ### Description Represents a field in a message literal. ### Class Signature ```python class MessageLiteralField: ``` ### Attributes - **name** (str) - The name of the field. - **value** (MessageValue) - The value of the field. ``` -------------------------------- ### Define a Group in a Protocol Buffer Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a group within a Protocol Buffers message. Includes name, number, optional cardinality, and child elements. ```python class Group: """Represents a group in a message.""" name: str number: int cardinality: Union[FieldCardinality, None] = None elements: List[MessageElement] = field(default_factory=list) ``` -------------------------------- ### Define Reserved Fields in a Protocol Buffer Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents reserved fields (ranges or names) within a Protocol Buffers message. ```python class Reserved: """Represents a reserved range or name in a message.""" ranges: List[str] names: List[str] ``` -------------------------------- ### Define Field Cardinality in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents the cardinality of a field within a Protocol Buffer schema. This is an enumeration class. ```python class FieldCardinality(str, PyEnum): ``` -------------------------------- ### Preserve Comments with ast.Comment Source: https://context7.com/criccomini/proto-schema-parser/llms.txt Demonstrates how ast.Comment preserves both line and block comments from the schema. The 'inline' attribute indicates if a comment is a trailing comment. ```python from proto_schema_parser.parser import Parser from proto_schema_parser.generator import Generator from proto_schema_parser import ast schema = """ syntax = "proto3"; // file-level trailing comment message Order { // Field comment (standalone) string id = 1; int32 quantity = 2; // inline trailing comment /* Multi-line block comment */ string note = 3; } """ file = Parser().parse(schema) def collect_comments(elements): for e in elements: if isinstance(e, ast.Comment): print(f" Comment(inline={e.inline}): {e.text!r}") elif isinstance(e, ast.Message): collect_comments(e.elements) collect_comments(file.file_elements) # Comment(inline=True): '// file-level trailing comment' # Comment(inline=False): '// Field comment (standalone)' # Comment(inline=True): '// inline trailing comment' # Comment(inline=False): '/* Multi-line\n block comment */' # Round-trip preserves all comments exactly assert Generator().generate(Parser().parse(Generator().generate(file))) == Generator().generate(file) ``` -------------------------------- ### Define an Enum Value Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a single value within a Protocol Buffers enum. Includes name, number, and optional options. ```python class EnumValue: """Represents an enum value in an enum.""" name: str number: int options: List[Option] = field(default_factory=list) ``` -------------------------------- ### Represent a Message Literal in Python Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents a message literal, which is a way to define message values inline. It contains a list of its elements. ```python class MessageLiteral: ``` -------------------------------- ### proto_schema_parser.ast.FieldCardinality Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents the cardinality of a field in a Protocol Buffer definition. ```APIDOC ## proto_schema_parser.ast.FieldCardinality ### Description Represents the cardinality of a field in a Protocol Buffer definition. ### Class Signature ```python class FieldCardinality(str, PyEnum): ``` ``` -------------------------------- ### Define Reserved Fields in a Protocol Buffer Enum Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents reserved fields (ranges or names) within a Protocol Buffers enum. ```python class EnumReserved: """Represents a reserved range or name in an enum.""" ranges: List[str] names: List[str] ``` -------------------------------- ### Identifier AST Node Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an unquoted identifier, used for scalar types that cannot be parsed into basic types. ```python class Identifier: ``` -------------------------------- ### Define an Enum in a Protocol Buffer Message Source: https://github.com/criccomini/proto-schema-parser/blob/main/DOCUMENTATION.md Represents an enum type within a Protocol Buffers message. Includes the enum name and its constituent elements. ```python class Enum: """Represents an enum in a message.""" name: str elements: List[EnumElement] = field(default_factory=list) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.