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

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

60 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, repeated 

20 

21 

22class ValueRule: 

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

24 

25 def __init__(self, *, marshal): 

26 self._marshal = marshal 

27 

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

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

30 

31 Note that both NullValue and absent fields return None. 

32 In order to disambiguate between these two options, 

33 use containment check, 

34 E.g. 

35 "value" in foo 

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

37 """ 

38 kind = value.WhichOneof("kind") 

39 if kind == "null_value" or absent: 

40 return None 

41 if kind == "bool_value": 

42 return bool(value.bool_value) 

43 if kind == "number_value": 

44 return float(value.number_value) 

45 if kind == "string_value": 

46 return str(value.string_value) 

47 if kind == "struct_value": 

48 return self._marshal.to_python( 

49 struct_pb2.Struct, 

50 value.struct_value, 

51 absent=False, 

52 ) 

53 if kind == "list_value": 

54 return self._marshal.to_python( 

55 struct_pb2.ListValue, 

56 value.list_value, 

57 absent=False, 

58 ) 

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

60 # instead of tacitly returning None. 

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

62 

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

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

65 if isinstance(value, struct_pb2.Value): 

66 return value 

67 if value is None: 

68 return struct_pb2.Value(null_value=0) 

69 if isinstance(value, bool): 

70 return struct_pb2.Value(bool_value=value) 

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

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

73 if isinstance(value, str): 

74 return struct_pb2.Value(string_value=value) 

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

76 return struct_pb2.Value( 

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

78 ) 

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

80 return struct_pb2.Value( 

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

82 ) 

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

84 

85 

86class ListValueRule: 

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

88 

89 def __init__(self, *, marshal): 

90 self._marshal = marshal 

91 

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

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

94 return ( 

95 None 

96 if absent 

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

98 ) 

99 

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

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

102 # Preserve the instance we have. 

103 if isinstance(value, struct_pb2.ListValue): 

104 return value 

105 if isinstance(value, repeated.RepeatedComposite): 

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

107 

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

109 return struct_pb2.ListValue( 

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

111 ) 

112 

113 

114class StructRule: 

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

116 

117 def __init__(self, *, marshal): 

118 self._marshal = marshal 

119 

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

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

122 return ( 

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

124 ) 

125 

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

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

128 # Preserve the instance we have. 

129 if isinstance(value, struct_pb2.Struct): 

130 return value 

131 if isinstance(value, maps.MapComposite): 

132 return struct_pb2.Struct( 

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

134 ) 

135 

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

137 answer = struct_pb2.Struct( 

138 fields={ 

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

140 } 

141 ) 

142 return answer