Official method to determine if betterproto.Message or betterproto.primitive was set
还没有人认领这个 Issue。
评估
调研方向
从 test.py 示例以及其中展示的 Message.parse、_serialized_on_wire、FieldMetadata 和 _get_field_default 入口点开始。复现默认值 primitive 和未知字节的情况,然后将受支持的行为与所要求的 parsed-versus-unset 区分进行比较。对于消息和 primitive 字段,覆盖所选择的 public behavior 即表示完成。
由索引模型根据 Issue 内容生成。
描述
Summary
The _serialized_on_wire attribute is 99% of the functionality I require.
Because it is a dunder attribute I can't rely on the attribute in future updates.
What is the feature request for?
The core library
The Problem
A method for determining if a betterproto field was set from parsed data in the protobuf bytes vs default value.
Fields in protobuf messages are optional by default.
It is important to detect if a field was set vs the default value.
For example, in Pydantic, optional values are None when unset.
This is done for the user by checking _serialized_on_wire.
I would like a supported function or non-dunder attribute exposing the _serialized_on_wire value.
Additionally, _serialized_on_wire is not enough when dealing with primitive types.
Currently, primitives types are check against the default value to determine their "_serialized_on_wire" status.
This causes primitive types that HAVE been set but match the default value to be indistinguishable from default set primitives.
Below is my testing code and function that works for my use case.
Other use cases will run into the primitive set issue.
# example.proto
syntax = "proto3";
option optimize_for = LITE_RUNTIME;
package example;
message NoPrimitives {
PrimitivesOne one = 1;
PrimitivesTwo two = 2;
}
message PrimitivesOne {
uint64 value1 = 1;
uint64 value2 = 2;
}
message PrimitivesTwo {
string value1 = 1;
string value2 = 2;
}
# test.py
import dataclasses
import betterproto
from proto_example import NoPrimitives, PrimitivesOne
data = b"foo"
no_primitives = NoPrimitives().parse(data)
# appends unparsed data at the end
# Is there a supported way to remove unpased bytes?
# I would have expected unparsable bytes to be dropped when converting back.
print(f"original: {data}")
print(f"reconstructed: {bytes(no_primitives)}")
# will return true because bytes exist, even if no bytes are "valid/parsed" in the protobuf structure
print(f"serialized: {no_primitives._serialized_on_wire}")
# a workable solution in my use case, but will not handle other possible cases
def serialized_on_wire(better_proto: betterproto.Message):
"""return true if proto message was serialized on wire"""
for field in dataclasses.fields(better_proto):
meta = betterproto.FieldMetadata.get(field)
v = getattr(better_proto, field.name)
if isinstance(v, betterproto.Message):
if v._serialized_on_wire:
return True
elif v != better_proto._get_field_default(field, meta):
return True
return False
# How to detect serialized_on_wire for messages with primitive types only? (int, string, ect...)
# Assuming primitive types are changed from defaults, desired behavoir.
data = b"foo"
no_primitives = NoPrimitives().parse(data)
no_primitives.one = 1
print(f"serialized original: {no_primitives._serialized_on_wire}")
print(f"serialized new: {serialized_on_wire(no_primitives)}")
# If primitive types correlate with default values, undesired behavoir.
primitives_one = PrimitivesOne().parse(b"")
print(f"serialized before manual set: {primitives_one._serialized_on_wire}")
# setting values that correlate with default values
# will set serialized on wire to true
primitives_one.value1 = 0
primitives_one.value2 = 0
# can detect items have been set but not which ones, to_dict will still return empty
print(f"serialized after manual set: {primitives_one._serialized_on_wire}")
print(f"serialized new: {serialized_on_wire(primitives_one)}")
# Valid values have been set but because they correlate with default values nothing is retured.
# I would like a way to detect if a value if the default value AND parsed over serial or set through python.
# Even if bytes have been given to parse but invalid/unparsed
print(f"empty dictionary: {primitives_one.to_dict() == {}}") # returns true
The Ideal Solution
Optional fields can be None when unset. (pydantics solution)
If default value returns are desired, there is already a flag for that.
For betterproto.Messages:
A method to return False if all primitive/non-primitive fields are unset.
For primitives:
Some other method for determining unset values beyond checking if the value is equal to the default value.
The Current Solution
99% solution for determining if an attribute if unset:
Check against the dunder attribute _serialized_on_wire directly and checking if primitives are equal to their default values.
Unable to determine if primitives are set but still equal to default value.
- 主要语言
- Python
- 星标
- 1.8k
- 派生
- 235
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
danielgtaylor/python-betterproto 的其他 Issue
-
难度 3/5 1-2 天 新手友好度 55/100
-
难度 5/5 一周以上 新手友好度 15/100
-
bug investigation needed
难度 3/5 1-2 天 新手友好度 42/100
-
bug investigation needed
难度 3/5 1-2 天 新手友好度 45/100
-
bug investigation needed
难度 4/5 3-5 天 新手友好度 38/100
danielgtaylor/python-betterproto#676 · 3 条评论 ·
查看 danielgtaylor/python-betterproto 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 76/100
aws-samples/sample-per-model-bedrock#464 ·
维护者通常 1 天内回复
-
lesson-submission pending-review
难度 2/5 1-3 小时 新手友好度 67/100
Ikalus1988/MisakaNet#3789 ·
维护者通常 1 天内回复
-
Python Volcengine provider returns failures instead of raising them可能已有人在做 @Ricardo-M-L 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 79/100
agent-infra/sandbox#248 ·
-
[Bug] cloud JSON directory loading assumes a Key field in fsspec listings可能已有人在做 @Ricardo-M-L 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 88/100
hiyouga/LlamaFactory#10910 ·
维护者通常 1 天内回复
-
Bundled uv is never updated and trusts the compromised eMudhra certificates可能已有人在做 @FabienDanieau 今天认领。 未关闭bug
难度 2/5 1-3 小时 新手友好度 76/100