Skip to content

Overview

GitHub Workflow Status Code coverage PyPI - Downloads PyPI – Version PyPI – Python License

Tip

The code snippets in this documentation are automatically tested and should work «as is».

Quick examples

dataclass_example.py
from dataclasses import dataclass
from io import BytesIO

from pure_protobuf.annotations import Field
from pure_protobuf.message import BaseMessage
from typing_extensions import Annotated


@dataclass
class SearchRequest(BaseMessage):
    query: Annotated[str, Field(1)] = ""
    page_number: Annotated[int, Field(2)] = 0
    result_per_page: Annotated[int, Field(3)] = 0


request = SearchRequest(
    query="hello",
    page_number=1,
    result_per_page=10,
)
buffer = bytes(request)
assert buffer == b"\x0A\x05hello\x10\x01\x18\x0A"
assert SearchRequest.read_from(BytesIO(buffer)) == request
pydantic_example.py
from io import BytesIO

from pure_protobuf.annotations import Field
from pure_protobuf.message import BaseMessage
from pydantic import BaseModel
from typing_extensions import Annotated


class SearchRequest(BaseMessage, BaseModel):
    query: Annotated[str, Field(1)] = ""
    page_number: Annotated[int, Field(2)] = 0
    result_per_page: Annotated[int, Field(3)] = 0


request = SearchRequest(
    query="hello",
    page_number=1,
    result_per_page=10,
)
buffer = bytes(request)
assert buffer == b"\x0A\x05hello\x10\x01\x18\x0A"
assert SearchRequest.read_from(BytesIO(buffer)) == request

Prerequisite

BaseMessage requires a subclass to accept field values via keyword parameters in its __init__() method. For most cases, one should use something like the built-in dataclasses or a third-party package like pydantic. But it is certainly possible to go a «vanilla» way:

test_vanilla.py
from io import BytesIO

from pure_protobuf.annotations import Field
from pure_protobuf.message import BaseMessage
from typing_extensions import Annotated


class Message(BaseMessage):
    a: Annotated[int, Field(1)] = 0

    def __init__(self, a: int) -> None:
        self.a = a


assert Message.read_from(BytesIO(b"\x08\x96\x01")).a == 150