Description
Optional fields generate very long and repetitive code.
The idea is to use shorter and simpler code, and internally consider it as a field having optional=True, group=f"_{field_name}"
.
Related to #459.
Proto file
syntax = "proto3";
message Foo {
optional uint32 bar = 1;
};
Currently generated code
from dataclasses import dataclass
import betterproto
@dataclass(eq=False, repr=False)
class Foo(betterproto.Message):
bar: Optional[int] = betterproto.uint32_field(
1, optional=True, group="_bar"
)
Idea A
Read the type-hint of the field, and if it's a union of a type with None
, consider it an optional field.
This might be a bad idea if unions of a type + None
are used for something other than optional fields.
An example implementation of detecting optional fields can be found here: cattrs/converters.py
.
from dataclasses import dataclass
from typing import Union, Optional
import betterproto
@dataclass(eq=False, repr=False)
class Foo(betterproto.Message):
bar: Optional[int] = betterproto.uint32_field(1)
Idea B
Use a custom type-hint that indicates a field is optional, and is correctly understood by type-checkers as Optional
.
from dataclasses import dataclass
import betterproto
@dataclass(eq=False, repr=False)
class Foo(betterproto.Message):
bar: betterproto.OptionalField[int] = betterproto.uint32_field(1)
It could possibly be implemented something like this:
Annotated
from typing import Optional, TypeVar
from typing_extensions import Annotated
T = TypeVar("T")
optional_metadata = object() # or another sentinel
OptionalField = Annotated[Optional[T], optional_metadata]
Idea C
Automatically add group=f"_{field_name}"
if optional=True
and no group
specified.
from dataclasses import dataclass
import betterproto
@dataclass(eq=False, repr=False)
class Foo(betterproto.Message):
bar: Optional[int] = betterproto.uint32_field(1, optional=True)