Skip to content
This repository was archived by the owner on Jun 9, 2025. It is now read-only.

Commit 541484b

Browse files
Generate pydantic validators (#75)
* Generate pydantic validators * Add test proto file
1 parent 35ed922 commit 541484b

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

src/betterproto2_compiler/plugin/models.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,10 +410,43 @@ def py_type(self) -> str:
410410
def unwrapped_py_type(self) -> str:
411411
return self._py_type(wrap=False)
412412

413+
@property
414+
def annotations(self) -> list[str]:
415+
"""List of the Pydantic annotation to add to the field."""
416+
assert self.output_file.settings.pydantic_dataclasses
417+
418+
annotations = []
419+
420+
if self.proto_obj.type in (FieldType.TYPE_INT32, FieldType.TYPE_SFIXED32, FieldType.TYPE_SINT32):
421+
annotations.append("pydantic.Field(ge=-2**31, le=2**31 - 1)")
422+
423+
elif self.proto_obj.type in (FieldType.TYPE_UINT32, FieldType.TYPE_FIXED32):
424+
annotations.append("pydantic.Field(ge=0, le=2**32 - 1)")
425+
426+
elif self.proto_obj.type in (FieldType.TYPE_INT64, FieldType.TYPE_SFIXED64, FieldType.TYPE_SINT64):
427+
annotations.append("pydantic.Field(ge=-2**63, le=2**63 - 1)")
428+
429+
elif self.proto_obj.type in (FieldType.TYPE_UINT64, FieldType.TYPE_FIXED64):
430+
annotations.append("pydantic.Field(ge=0, le=2**64 - 1)")
431+
432+
elif self.proto_obj.type == FieldType.TYPE_FLOAT:
433+
annotations.append("pydantic.AfterValidator(betterproto2.validators.validate_float32)")
434+
435+
elif self.proto_obj.type == FieldType.TYPE_STRING:
436+
annotations.append("pydantic.AfterValidator(betterproto2.validators.validate_string)")
437+
438+
return annotations
439+
413440
@property
414441
def annotation(self) -> str:
415442
py_type = self.py_type
416443

444+
# Add the pydantic annotation if needed
445+
if self.output_file.settings.pydantic_dataclasses:
446+
annotations = self.annotations
447+
if annotations:
448+
py_type = f"typing.Annotated[{py_type}, {', '.join(annotations)}]"
449+
417450
if self.use_builtins:
418451
py_type = f"builtins.{py_type}"
419452
if self.repeated:

src/betterproto2_compiler/templates/header.py.j2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import typing
2828
from typing import TYPE_CHECKING
2929

3030
{% if output_file.settings.pydantic_dataclasses %}
31+
import pydantic
3132
from pydantic.dataclasses import dataclass
3233
from pydantic import model_validator
3334
{%- else -%}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
syntax = "proto3";
2+
3+
package validation;
4+
5+
message Message {
6+
int32 int32_value = 1;
7+
int64 int64_value = 2;
8+
uint32 uint32_value = 3;
9+
uint64 uint64_value = 4;
10+
sint32 sint32_value = 5;
11+
sint64 sint64_value = 6;
12+
fixed32 fixed32_value = 7;
13+
fixed64 fixed64_value = 8;
14+
sfixed32 sfixed32_value = 9;
15+
sfixed64 sfixed64_value = 10;
16+
17+
float float_value = 11;
18+
19+
string string_value = 12;
20+
}

0 commit comments

Comments
 (0)