Official method to determine if betterproto.Message or betterproto.primitive was set
まだ誰も着手していません。
評価
調査の方向性
test.py の例と、そこに示されている Message.parse、_serialized_on_wire、FieldMetadata、_get_field_default のエントリポイントから始めます。デフォルト値が設定された primitive のケースと unknown-byte のケースを再現し、サポートされている動作を、要求されている parsed と unset の区別と比較します。messages と primitive fields について、選択した 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 ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
danielgtaylor/python-betterproto のほかの issue
-
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
-
難易度 5/5 1週間以上 初心者へのやさしさ 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時間 初心者へのやさしさ 67/100
MISP/misp-workbench#496 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1〜3時間 初心者へのやさしさ 88/100
fossasia/visdom-dev#69 ·
メンテナーはふだん 3 日以内に返信
-
[Bug] Parameters named like a property break to_xcal()対応中かも @atharvasalunke1267 が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
collective/icalendar#2018 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信