Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/proto/marshal/rules/struct.py: 31%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

61 statements  

1# Copyright 2018 Google LLC 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# https://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14 

15import collections.abc 

16 

17from google.protobuf import struct_pb2 

18 

19from proto.marshal.collections import maps 

20from proto.marshal.collections import repeated 

21 

22 

23class ValueRule: 

24 """A rule to marshal between google.protobuf.Value and Python values.""" 

25 

26 def __init__(self, *, marshal): 

27 self._marshal = marshal 

28 

29 def to_python(self, value, *, absent: bool = None): 

30 """Coerce the given value to the appropriate Python type. 

31 

32 Note that both NullValue and absent fields return None. 

33 In order to disambiguate between these two options, 

34 use containment check, 

35 E.g. 

36 "value" in foo 

37 which is True for NullValue and False for an absent value. 

38 """ 

39 kind = value.WhichOneof("kind") 

40 if kind == "null_value" or absent: 

41 return None 

42 if kind == "bool_value": 

43 return bool(value.bool_value) 

44 if kind == "number_value": 

45 return float(value.number_value) 

46 if kind == "string_value": 

47 return str(value.string_value) 

48 if kind == "struct_value": 

49 return self._marshal.to_python( 

50 struct_pb2.Struct, 

51 value.struct_value, 

52 absent=False, 

53 ) 

54 if kind == "list_value": 

55 return self._marshal.to_python( 

56 struct_pb2.ListValue, 

57 value.list_value, 

58 absent=False, 

59 ) 

60 # If more variants are ever added, we want to fail loudly 

61 # instead of tacitly returning None. 

62 raise ValueError("Unexpected kind: %s" % kind) # pragma: NO COVER 

63 

64 def to_proto(self, value) -> struct_pb2.Value: 

65 """Return a protobuf Value object representing this value.""" 

66 if isinstance(value, struct_pb2.Value): 

67 return value 

68 if value is None: 

69 return struct_pb2.Value(null_value=0) 

70 if isinstance(value, bool): 

71 return struct_pb2.Value(bool_value=value) 

72 if isinstance(value, (int, float)): 

73 return struct_pb2.Value(number_value=float(value)) 

74 if isinstance(value, str): 

75 return struct_pb2.Value(string_value=value) 

76 if isinstance(value, collections.abc.Sequence): 

77 return struct_pb2.Value( 

78 list_value=self._marshal.to_proto(struct_pb2.ListValue, value), 

79 ) 

80 if isinstance(value, collections.abc.Mapping): 

81 return struct_pb2.Value( 

82 struct_value=self._marshal.to_proto(struct_pb2.Struct, value), 

83 ) 

84 raise ValueError("Unable to coerce value: %r" % value) 

85 

86 

87class ListValueRule: 

88 """A rule translating google.protobuf.ListValue and list-like objects.""" 

89 

90 def __init__(self, *, marshal): 

91 self._marshal = marshal 

92 

93 def to_python(self, value, *, absent: bool = None): 

94 """Coerce the given value to a Python sequence.""" 

95 return ( 

96 None 

97 if absent 

98 else repeated.RepeatedComposite(value.values, marshal=self._marshal) 

99 ) 

100 

101 def to_proto(self, value) -> struct_pb2.ListValue: 

102 # We got a proto, or else something we sent originally. 

103 # Preserve the instance we have. 

104 if isinstance(value, struct_pb2.ListValue): 

105 return value 

106 if isinstance(value, repeated.RepeatedComposite): 

107 return struct_pb2.ListValue(values=[v for v in value.pb]) 

108 

109 # We got a list (or something list-like); convert it. 

110 return struct_pb2.ListValue( 

111 values=[self._marshal.to_proto(struct_pb2.Value, v) for v in value] 

112 ) 

113 

114 

115class StructRule: 

116 """A rule translating google.protobuf.Struct and dict-like objects.""" 

117 

118 def __init__(self, *, marshal): 

119 self._marshal = marshal 

120 

121 def to_python(self, value, *, absent: bool = None): 

122 """Coerce the given value to a Python mapping.""" 

123 return ( 

124 None if absent else maps.MapComposite(value.fields, marshal=self._marshal) 

125 ) 

126 

127 def to_proto(self, value) -> struct_pb2.Struct: 

128 # We got a proto, or else something we sent originally. 

129 # Preserve the instance we have. 

130 if isinstance(value, struct_pb2.Struct): 

131 return value 

132 if isinstance(value, maps.MapComposite): 

133 return struct_pb2.Struct( 

134 fields={k: v for k, v in value.pb.items()}, 

135 ) 

136 

137 # We got a dict (or something dict-like); convert it. 

138 answer = struct_pb2.Struct( 

139 fields={ 

140 k: self._marshal.to_proto(struct_pb2.Value, v) for k, v in value.items() 

141 } 

142 ) 

143 return answer