Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
normalize.py
Go to the documentation of this file.
1# Copyright 2010-2024 Google LLC
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6# http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14# A fork of net/proto2/contrib/pyutil/normalize.py. A lot of the code can be
15# deleted because we do not support proto2 (no groups, no extension). Further,
16# the code has been changed to not clear:
17# * optional scalar fields at their default value.
18# * durations
19# * messages in a oneof
20
21
22"""Utility functions for normalizing proto3 message objects in Python."""
23from google.protobuf import duration_pb2
24from google.protobuf import descriptor
25from google.protobuf import message
26
27
28def math_opt_normalize_proto(protobuf_message: message.Message) -> None:
29 """Clears all non-duration submessages that are not in one_ofs.
30
31 A message is considered `empty` if:
32 * every non-optional scalar fields has its default value,
33 * every optional scalar field is unset,
34 * every repeated/map fields is empty
35 * every oneof is unset,
36 * every duration field is unset
37 * all other message fields (singular, not oneof, not duration) are `empty`.
38 This function clears all `empty` fields from `message`.
39
40 This is useful for testing.
41
42 Args:
43 protobuf_message: The Message object to clear.
44 """
45 for field, value in protobuf_message.ListFields():
46 if field.type != field.TYPE_MESSAGE:
47 continue
48 if field.label == field.LABEL_REPEATED:
49 # Now the repeated case, recursively normalize each member. Note that
50 # there is no field presence for repeated fields, so we don't need to call
51 # ClearField().
52 #
53 # Maps need to be handled specially.
54 if (
55 field.message_type.has_options
56 and field.message_type.GetOptions().map_entry
57 ):
58 if (
59 field.message_type.fields_by_number[2].type
60 == descriptor.FieldDescriptor.TYPE_MESSAGE
61 ):
62 for item in value.values():
64 # The remaining case is a regular repeated field (a list).
65 else:
66 for item in value:
68 continue
69 # Last case, the non-repeated sub-message
71 # If field value is empty, not a Duration, and not in a oneof, clear it.
72 if (
73 not value.ListFields()
74 and field.message_type != duration_pb2.Duration.DESCRIPTOR
75 and field.containing_oneof is None
76 ):
77 protobuf_message.ClearField(field.name)
None math_opt_normalize_proto(message.Message protobuf_message)
Definition normalize.py:28