protobuf_to_pydantic
protobuf_to_pydantic copied to clipboard
Exclude pydantic 2.12
Newly released pydantic 2.12 breaks compatibility with this library:
'pydantic_core._pydantic_core.ValidationInfo' object has no attribute 'template'
Traceback (most recent call last):
File "/Users/.../.cache/uv/builds-v0/.tmpDBckzd/lib/python3.12/site-packages/protobuf_to_pydantic/plugin/main.py", line 14, in main
CodeGen(ConfigModel)
File "/Users/.../.cache/uv/builds-v0/.tmpDBckzd/lib/python3.12/site-packages/protobuf_to_pydantic/plugin/code_gen.py", line 32, in __init__
self.gen_config()
File "/Users/.../.cache/uv/builds-v0/.tmpDBckzd/lib/python3.12/site-packages/protobuf_to_pydantic/plugin/code_gen.py", line 141, in gen_config
self.config = self.config_class()
^^^^^^^^^^^^^^^^^^^
File "/Users/.../.cache/uv/builds-v0/.tmpDBckzd/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__
validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/.../.cache/uv/builds-v0/.tmpDBckzd/lib/python3.12/site-packages/protobuf_to_pydantic/plugin/config.py", line 117, in after_init
values.template_instance = values.template(values.local_dict, values.comment_prefix)
^^^^^^^^^^^^^^^
AttributeError: 'pydantic_core._pydantic_core.ValidationInfo' object has no attribute 'template'
This PR excludes 2.12 from the valid pydantic versions until a fix can be implemented
Hi folks,
I ran into this and Claude suggested a fix; with all the caveats regarding LLM-generated code, I offer here what it wrote. For what it's worth, I did test the suggested protobuf_to_pydantic patch + pydantic 2.12 and generation succeeded. The same protobufs also work just fine with unpatched protobuf_to_pydantic + pydantic 2.11
Problem Description
The protobuf-to-pydantic plugin fails during code generation when using Pydantic 2.12.0 or later with the following error:
AttributeError: 'pydantic_core._pydantic_core.ValidationInfo' object has no attribute 'template'
The error occurs in protobuf_to_pydantic/plugin/config.py at line 145 in the after_init method.
Root Cause
Pydantic 2.12.0 introduced a breaking change in the @model_validator(mode="after") decorator. The validator function signature changed:
- Pydantic 2.11.x and earlier: Validator receives model instance directly as first parameter
- Pydantic 2.12.0+: Validator function signature handling changed
The current implementation in config.py line 137-146 has an incorrect function signature:
@_pydantic_adapter.model_validator(mode="after")
def after_init(cls, values: Any) -> Any:
if _pydantic_adapter.is_v1:
# values: Dict[str, Any]
values["template_instance"] = values["template"](values["local_dict"], values["comment_prefix"])
return values
else:
# values: "ConfigModel"
values.template_instance = values.template(values.local_dict, values.comment_prefix)
return values
The function signature uses cls, values (suggesting a classmethod pattern), but it's not decorated as @classmethod. In Pydantic v2, mode="after" validators should receive the model instance as self.
Fix
Change the function signature on line 138:
Before:
@_pydantic_adapter.model_validator(mode="after")
def after_init(cls, values: Any) -> Any:
if _pydantic_adapter.is_v1:
# values: Dict[str, Any]
values["template_instance"] = values["template"](values["local_dict"], values["comment_prefix"])
return values
else:
# values: "ConfigModel"
values.template_instance = values.template(values.local_dict, values.comment_prefix)
return values
After:
@_pydantic_adapter.model_validator(mode="after")
def after_init(self) -> Any:
if _pydantic_adapter.is_v1:
# In v1, this is called as root_validator and receives values dict
self["template_instance"] = self["template"](self["local_dict"], self["comment_prefix"])
return self
else:
# In v2, self is the ConfigModel instance
self.template_instance = self.template(self.local_dict, self.comment_prefix)
return self
This fix:
- Changes the parameter from cls, values to just self
- Uses self consistently in both branches
- Works with both Pydantic 2.11.x and 2.12.0+
Verification
I've tested this patch with:
- ✅ Pydantic 2.11.10 - works perfectly
- ✅ Pydantic 2.12.0 - works with the patch, fails without it