diff --git a/protovalidate/internal/rules.py b/protovalidate/internal/rules.py index ba8b0de..2669faa 100644 --- a/protovalidate/internal/rules.py +++ b/protovalidate/internal/rules.py @@ -24,6 +24,17 @@ from buf.validate import validate_pb2 from protovalidate.internal.cel_field_presence import InterpretedRunner, in_has +# protobuf 7+ removed FieldDescriptor.label / LABEL_REPEATED in favour of is_repeated. +if hasattr(descriptor.FieldDescriptor, "is_repeated"): + + def _is_repeated(field: descriptor.FieldDescriptor) -> bool: + return field.is_repeated # type: ignore[attr-defined] + +else: + + def _is_repeated(field: descriptor.FieldDescriptor) -> bool: + return field.label == descriptor.FieldDescriptor.LABEL_REPEATED # type: ignore[attr-defined] + class CompilationError(Exception): pass @@ -155,7 +166,7 @@ def _scalar_field_value_to_cel(val: typing.Any, field: descriptor.FieldDescripto def _field_value_to_cel(val: typing.Any, field: descriptor.FieldDescriptor) -> celtypes.Value: - if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if _is_repeated(field): if field.message_type is not None and field.message_type.GetOptions().map_entry: return _map_field_value_to_cel(val, field) return _repeated_field_value_to_cel(val, field) @@ -165,7 +176,7 @@ def _field_value_to_cel(val: typing.Any, field: descriptor.FieldDescriptor) -> c def _is_empty_field(msg: message.Message, field: descriptor.FieldDescriptor) -> bool: if field.has_presence: return not _proto_message_has_field(msg, field) - if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if _is_repeated(field): return len(_proto_message_get_field(msg, field)) == 0 return _proto_message_get_field(msg, field) == field.default_value @@ -194,7 +205,7 @@ def _map_field_to_cel(msg: message.Message, field: descriptor.FieldDescriptor) - def field_to_cel(msg: message.Message, field: descriptor.FieldDescriptor) -> celtypes.Value: - if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if _is_repeated(field): return _repeated_field_to_cel(msg, field) elif field.message_type is not None and not _proto_message_has_field(msg, field): return None @@ -492,19 +503,15 @@ def check_field_type(field: descriptor.FieldDescriptor, expected: int, wrapper_n def _is_map(field: descriptor.FieldDescriptor): - return ( - field.label == descriptor.FieldDescriptor.LABEL_REPEATED - and field.message_type is not None - and field.message_type.GetOptions().map_entry - ) + return _is_repeated(field) and field.message_type is not None and field.message_type.GetOptions().map_entry def _is_list(field: descriptor.FieldDescriptor): - return field.label == descriptor.FieldDescriptor.LABEL_REPEATED and not _is_map(field) + return _is_repeated(field) and not _is_map(field) def _zero_value(field: descriptor.FieldDescriptor): - if field.message_type is not None and field.label != descriptor.FieldDescriptor.LABEL_REPEATED: + if field.message_type is not None and not _is_repeated(field): return _field_value_to_cel(message_factory.GetMessageClass(field.message_type)(), field) else: return _field_value_to_cel(field.default_value, field) @@ -1030,7 +1037,7 @@ def _new_field_rule( field: descriptor.FieldDescriptor, rules: validate_pb2.FieldRules, ) -> FieldRules: - if field.label != descriptor.FieldDescriptor.LABEL_REPEATED: + if not _is_repeated(field): return self._new_scalar_field_rule(field, rules) if field.message_type is not None and field.message_type.GetOptions().map_entry: key_rules = None @@ -1084,7 +1091,7 @@ def _new_rules(self, desc: descriptor.Descriptor) -> list[Rules]: if value_field.type != descriptor.FieldDescriptor.TYPE_MESSAGE: continue result.append(MapValMsgRule(self, field, key_field, value_field)) - elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + elif _is_repeated(field): result.append(RepeatedMsgRule(self, field)) else: result.append(SubMsgRule(self, field)) diff --git a/uv.lock b/uv.lock index 8d5319e..3406592 100644 --- a/uv.lock +++ b/uv.lock @@ -386,17 +386,17 @@ wheels = [ [[package]] name = "protobuf" -version = "6.33.5" +version = "7.34.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/00/04a2ab36b70a52d0356852979e08b44edde0435f2115dc66e25f2100f3ab/protobuf-7.34.0.tar.gz", hash = "sha256:3871a3df67c710aaf7bb8d214cc997342e63ceebd940c8c7fc65c9b3d697591a", size = 454726, upload-time = "2026-02-27T00:30:25.421Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" }, - { url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z" }, - { url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z" }, - { url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" }, - { url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" }, - { url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" }, - { url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" }, + { url = "https://files.pythonhosted.org/packages/13/c4/6322ab5c8f279c4c358bc14eb8aefc0550b97222a39f04eb3c1af7a830fa/protobuf-7.34.0-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:8e329966799f2c271d5e05e236459fe1cbfdb8755aaa3b0914fa60947ddea408", size = 429248, upload-time = "2026-02-27T00:30:14.924Z" }, + { url = "https://files.pythonhosted.org/packages/45/99/b029bbbc61e8937545da5b79aa405ab2d9cf307a728f8c9459ad60d7a481/protobuf-7.34.0-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:9d7a5005fb96f3c1e64f397f91500b0eb371b28da81296ae73a6b08a5b76cdd6", size = 325753, upload-time = "2026-02-27T00:30:17.247Z" }, + { url = "https://files.pythonhosted.org/packages/cc/79/09f02671eb75b251c5550a1c48e7b3d4b0623efd7c95a15a50f6f9fc1e2e/protobuf-7.34.0-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:4a72a8ec94e7a9f7ef7fe818ed26d073305f347f8b3b5ba31e22f81fd85fca02", size = 340200, upload-time = "2026-02-27T00:30:18.672Z" }, + { url = "https://files.pythonhosted.org/packages/b5/57/89727baef7578897af5ed166735ceb315819f1c184da8c3441271dbcfde7/protobuf-7.34.0-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:964cf977e07f479c0697964e83deda72bcbc75c3badab506fb061b352d991b01", size = 324268, upload-time = "2026-02-27T00:30:20.088Z" }, + { url = "https://files.pythonhosted.org/packages/1f/3e/38ff2ddee5cc946f575c9d8cc822e34bde205cf61acf8099ad88ef19d7d2/protobuf-7.34.0-cp310-abi3-win32.whl", hash = "sha256:f791ec509707a1d91bd02e07df157e75e4fb9fbdad12a81b7396201ec244e2e3", size = 426628, upload-time = "2026-02-27T00:30:21.555Z" }, + { url = "https://files.pythonhosted.org/packages/cb/71/7c32eaf34a61a1bae1b62a2ac4ffe09b8d1bb0cf93ad505f42040023db89/protobuf-7.34.0-cp310-abi3-win_amd64.whl", hash = "sha256:9f9079f1dde4e32342ecbd1c118d76367090d4aaa19da78230c38101c5b3dd40", size = 437901, upload-time = "2026-02-27T00:30:22.836Z" }, + { url = "https://files.pythonhosted.org/packages/a4/e7/14dc9366696dcb53a413449881743426ed289d687bcf3d5aee4726c32ebb/protobuf-7.34.0-py3-none-any.whl", hash = "sha256:e3b914dd77fa33fa06ab2baa97937746ab25695f389869afdf03e81f34e45dc7", size = 170716, upload-time = "2026-02-27T00:30:23.994Z" }, ] [[package]]