Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
`protobuf-py` is an **ergonomic and modern Protobuf library** for Python.

Well-typed, generated code you can read. High-performance encoder/decoder written in Rust. 100% conformance. <br />
Zero dependencies or tooling required.
Zero third-party dependencies or tooling required.

[Getting started](https://protobufpy.com/getting-started/installation/) •
[Examples](https://github.com/bufbuild/protobuf-py/tree/main/examples/protobuf) •
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
The only modern, complete Python protobuf library.

100% Protobuf conformance with full support for `proto2`, `proto3`, and editions.
Generated code is readable, typed, and works out of the box with no dependencies or extra tooling required.
Native Rust module for high-performance encoding/decoding.
Generated code is readable, typed, and works out of the box with no third-party dependencies
or extra tooling required. Native Rust module for high-performance encoding/decoding.

The Pythonic API results in code that you are happy to read.

Expand Down
5 changes: 3 additions & 2 deletions packages/protoc-gen-py/src/protoc_gen_py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from itertools import chain
from typing import TYPE_CHECKING, Any

from typing_extensions import assert_never

from protobuf import (
DescEnum,
DescEnumValue,
Expand All @@ -42,7 +44,6 @@
from protobuf._descriptors import SupportedFieldPresence
from protobuf._names import proto_camel_case
from protobuf._sanitization import escape_extension_name
from protobuf._typing import assert_never
from protobuf.plugin import File, Ident, Module, Schema, get_comments, run

if TYPE_CHECKING:
Expand Down Expand Up @@ -484,7 +485,7 @@ def _generate_docstring(
f.print("```")


def _provenance_text( # noqa: RET503
def _provenance_text(
desc: DescMessage
| DescField
| DescEnum
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
"Typing :: Typed",
]
dependencies = [
"typing_extensions>=4.13.0",
]

[project.urls]
Documentation = "https://protobufpy.com/"
Expand Down
5 changes: 3 additions & 2 deletions src/protobuf/_descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from enum import IntEnum
from typing import TYPE_CHECKING, Literal, TypeAlias, cast, final

from ._typing import assert_never
from typing_extensions import assert_never

from ._wire import WireType

try:
Expand Down Expand Up @@ -513,7 +514,7 @@ def __post_init__(self) -> None:
"""The wire type for the unpacked encoding, used to validate when parsing an unpacked repeated field."""


def element_wire_type( # noqa: RET503
def element_wire_type(
element_type: DescMessage | DescEnum | ScalarType, *, delimited_encoding: bool
) -> WireType:
match element_type:
Expand Down
7 changes: 4 additions & 3 deletions src/protobuf/_field_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from math import copysign
from typing import Any

from typing_extensions import assert_never

from ._descriptors import (
DescField,
DescFieldValue,
Expand All @@ -29,10 +31,9 @@
ScalarType,
SupportedFieldPresence,
)
from ._typing import assert_never


def scalar_zero_value(scalar_type: ScalarType) -> Any: # noqa: RET503
def scalar_zero_value(scalar_type: ScalarType) -> Any:
"""Return the zero value for a scalar type."""
match scalar_type:
case ScalarType.BOOL:
Expand Down Expand Up @@ -77,7 +78,7 @@ def requires_presence(member: DescField) -> bool:
return False


def default_value(member: DescFieldValue | DescOneof) -> Any: # noqa: RET503
def default_value(member: DescFieldValue | DescOneof) -> Any:
"""Return the default value for the given field or oneof."""
match member:
case DescOneof() | DescFieldValueMessage():
Expand Down
3 changes: 2 additions & 1 deletion src/protobuf/_from_binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, TypeVar

from typing_extensions import assert_never

from ._descriptors import (
DescEnum,
DescFieldValueEnum,
Expand All @@ -29,7 +31,6 @@
)
from ._enum import Enum
from ._field_values import scalar_zero_value
from ._typing import assert_never
from ._wire._binary_reader import DEPTH_LIMIT, BinaryReader
from ._wire._binary_writer import BinaryWriter
from ._wire._wire_type import WireType
Expand Down
4 changes: 3 additions & 1 deletion src/protobuf/_from_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING, Literal, TypeVar, cast

from typing_extensions import assert_never

from ._descriptors import (
DescEnum,
DescExtension,
Expand All @@ -32,7 +34,6 @@
ScalarType,
)
from ._oneof import Oneof
from ._typing import JsonValue, assert_never
from ._validate import (
FLOAT32_MAX,
FLOAT32_MIN,
Expand All @@ -56,6 +57,7 @@
from ._enum import Enum
from ._message import Message
from ._registry import Registry
from ._typing import JsonValue
from .wkt import ListValue, NullValue, Struct, Value

T = TypeVar("T", bound=Message)
Expand Down
9 changes: 5 additions & 4 deletions src/protobuf/_jsonschema.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
from textwrap import dedent
from typing import TYPE_CHECKING, Any, TypeAlias

from typing_extensions import assert_never

from ._descriptors import (
DescEnum,
DescField,
Expand All @@ -31,7 +33,6 @@
DescMessage,
ScalarType,
)
from ._typing import assert_never
from ._wkt_registry import (
WktAny,
WktDuration,
Expand Down Expand Up @@ -108,7 +109,7 @@ def to_json(self) -> dict[str, JSON]:
return res


def _generate_wkt_schema(wkt: WktMatch) -> JsonSchemaField | None: # noqa: RET503
def _generate_wkt_schema(wkt: WktMatch) -> JsonSchemaField | None:
match wkt:
case WktTimestamp():
return JsonSchemaField(type="string", format="date-time")
Expand Down Expand Up @@ -165,7 +166,7 @@ def _scalar_field(scalar: ScalarType, description: str = "") -> JsonSchemaField:
return JsonSchemaField(type=_scalar_type(scalar), description=description)


def _scalar_type(s: ScalarType) -> str: # noqa: RET503
def _scalar_type(s: ScalarType) -> str:
match s:
case ScalarType.BOOL:
return "boolean"
Expand Down Expand Up @@ -310,7 +311,7 @@ def singular(value: DescMessage | DescEnum | ScalarType) -> CoreSchema:
return enum_ref(value)
return leaf(_scalar_field(value))

def field_core(field: DescField) -> CoreSchema: # noqa: RET503
def field_core(field: DescField) -> CoreSchema:
description = _generate_docstring(field)
# Scalars carry title/description in their own JSON body. List and dict
# schemas are generated by pydantic, so their title/description are merged
Expand Down
6 changes: 4 additions & 2 deletions src/protobuf/_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
from __future__ import annotations

from copy import copy, deepcopy
from typing import TYPE_CHECKING, Any, ClassVar, Generic, TypeVar, overload
from typing import TYPE_CHECKING, Any, ClassVar, Generic, overload

from typing_extensions import TypeVar

from . import _native_message
from ._descriptors import (
Expand Down Expand Up @@ -50,7 +52,7 @@
Self = TypeVar("Self", bound="Message")

# TypeVar for making Message generic over its field names
FieldNamesT = TypeVar("FieldNamesT", bound=str)
FieldNamesT = TypeVar("FieldNamesT", bound=str, default=Any)

M = TypeVar("M", bound="Message")
E = TypeVar("E")
Expand Down
5 changes: 3 additions & 2 deletions src/protobuf/_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
from collections import defaultdict
from typing import TYPE_CHECKING, TypeVar, final

from typing_extensions import assert_never

from ._descriptors import DescEnum, DescExtension, DescFile, DescMessage, DescService
from ._extension import Extension
from ._message import Message
from ._typing import assert_never

if TYPE_CHECKING:
from collections.abc import Iterator
Expand Down Expand Up @@ -119,7 +120,7 @@ def add(
case Registry():
self._extend(desc_or_reg)
case _:
assert_never(desc_or_reg) # ty: ignore[invalid-argument-type] # https://github.com/astral-sh/ty/issues/4370
assert_never(desc_or_reg) # ty: ignore[type-assertion-failure] # https://github.com/astral-sh/ty/issues/4370

def file(self, path: str) -> DescFile | None:
"""Look up a file descriptor by its path.
Expand Down
3 changes: 2 additions & 1 deletion src/protobuf/_to_binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any

from typing_extensions import assert_never

from ._descriptors import (
DescEnum,
DescFieldValueEnum,
Expand All @@ -26,7 +28,6 @@
DescMessage,
ScalarType,
)
from ._typing import assert_never
from ._wire._binary_writer import BinaryWriter
from ._wire._wire_type import WireType

Expand Down
6 changes: 4 additions & 2 deletions src/protobuf/_to_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any

from typing_extensions import assert_never

from ._descriptors import (
DescEnum,
DescFieldValueEnum,
Expand All @@ -33,14 +35,14 @@
SupportedFieldPresence,
)
from ._oneof import Oneof
from ._typing import JsonPrimitive, JsonValue, assert_never
from ._wkt_registry import is_null_value_enum, match_wkt

if TYPE_CHECKING:
from types import NotImplementedType

from ._message import Message
from ._registry import Registry
from ._typing import JsonPrimitive, JsonValue
from .wkt import Struct, Value


Expand Down Expand Up @@ -115,7 +117,7 @@ def _enum_to_json_value(
return value


def _container_value_to_json_value( # noqa: RET503
def _container_value_to_json_value(
desc_element: ScalarType | DescEnum | DescMessage, value: Any, opts: ToJsonOptions
) -> JsonValue:
match desc_element:
Expand Down
9 changes: 2 additions & 7 deletions src/protobuf/_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# Small set of helpers and Python 3.10 compatibility shims
# Small set of helpers
from __future__ import annotations

from typing import NoReturn as Never, TypeAlias
from typing import TypeAlias

JsonPrimitive: TypeAlias = bool | int | float | str | None
JsonValue: TypeAlias = JsonPrimitive | list["JsonValue"] | dict[str, "JsonValue"]


def assert_never(value: Never) -> Never:
msg = f"unexpected value: {value!r}"
raise AssertionError(msg)
5 changes: 3 additions & 2 deletions src/protobuf/_unknown.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

from typing import TYPE_CHECKING, Any

from typing_extensions import assert_never

from ._descriptors import (
DescEnum,
DescFieldValue,
Expand All @@ -41,7 +43,6 @@
write_message_field,
write_scalar_field,
)
from ._typing import assert_never
from ._wire import BinaryReader, BinaryWriter

if TYPE_CHECKING:
Expand All @@ -66,7 +67,7 @@ def has_unknown_field(
return number in uf


def get_unknown_field( # noqa: RET503
def get_unknown_field(
message: Message, number: int, field_value: DescFieldValue
) -> Any:
if not (uf := message._unknown_fields) or not (binary_fields := uf.get(number)):
Expand Down
3 changes: 2 additions & 1 deletion src/protobuf/_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import math
from typing import TYPE_CHECKING, Any

from typing_extensions import assert_never

from ._descriptors import (
DescEnum,
DescField,
Expand All @@ -30,7 +32,6 @@
SupportedFieldPresence,
)
from ._oneof import Oneof
from ._typing import assert_never

if TYPE_CHECKING:
from ._message import Message
Expand Down
5 changes: 3 additions & 2 deletions src/protobuf/_wire/_text_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@

import re

from typing_extensions import assert_never

from protobuf._descriptors import DescEnum, ScalarType
from protobuf._typing import assert_never


def parse_text_format_enum_value(desc: DescEnum, value: str) -> int:
Expand All @@ -28,7 +29,7 @@ def parse_text_format_enum_value(desc: DescEnum, value: str) -> int:
return value_desc.number


def parse_text_format_scalar_value( # noqa: RET503
def parse_text_format_scalar_value(
scalar: ScalarType, value: str
) -> int | float | bytes | str | bool:
"""Parse a scalar value from the Protobuf text format."""
Expand Down
5 changes: 3 additions & 2 deletions src/protobuf/plugin/_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
from contextlib import AbstractContextManager, contextmanager
from typing import TYPE_CHECKING, Any, Final, Protocol

from typing_extensions import assert_never

from protobuf import DescEnum, DescExtension, DescFile, DescMessage, ScalarType
from protobuf._typing import assert_never
from protobuf.plugin._ident import Ident, Module

if TYPE_CHECKING:
Expand Down Expand Up @@ -555,7 +556,7 @@ def _resolve(self, ident: Ident) -> str:
return self._resolve(Ident(candidate, ident.module)) or candidate


def _scalar_type(scalar: ScalarType) -> str: # noqa: RET503
def _scalar_type(scalar: ScalarType) -> str:
"""Map a protobuf scalar type to its Python type name."""
match scalar:
case ScalarType.DOUBLE | ScalarType.FLOAT:
Expand Down
Loading
Loading