Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/proto/marshal/collections/maps.py: 50%

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

30 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 

16 

17from proto.utils import cached_property 

18from google.protobuf.message import Message 

19 

20 

21class MapComposite(collections.abc.MutableMapping): 

22 """A view around a mutable sequence in protocol buffers. 

23 

24 This implements the full Python MutableMapping interface, but all methods 

25 modify the underlying field container directly. 

26 """ 

27 

28 @cached_property 

29 def _pb_type(self): 

30 """Return the protocol buffer type for this sequence.""" 

31 # Huzzah, another hack. Still less bad than RepeatedComposite. 

32 return type(self.pb.GetEntryClass()().value) 

33 

34 def __init__(self, sequence, *, marshal): 

35 """Initialize a wrapper around a protobuf map. 

36 

37 Args: 

38 sequence: A protocol buffers map. 

39 marshal (~.MarshalRegistry): An instantiated marshal, used to 

40 convert values going to and from this map. 

41 """ 

42 self._pb = sequence 

43 self._marshal = marshal 

44 

45 def __contains__(self, key): 

46 # Protocol buffers is so permissive that querying for the existence 

47 # of a key will in of itself create it. 

48 # 

49 # By taking a tuple of the keys and querying that, we avoid sending 

50 # the lookup to protocol buffers and therefore avoid creating the key. 

51 return key in tuple(self.keys()) 

52 

53 def __getitem__(self, key): 

54 # We handle raising KeyError ourselves, because otherwise protocol 

55 # buffers will create the key if it does not exist. 

56 if key not in self: 

57 raise KeyError(key) 

58 return self._marshal.to_python(self._pb_type, self.pb[key]) 

59 

60 def __setitem__(self, key, value): 

61 pb_value = self._marshal.to_proto(self._pb_type, value, strict=True) 

62 # Directly setting a key is not allowed; however, protocol buffers 

63 # is so permissive that querying for the existence of a key will in 

64 # of itself create it. 

65 # 

66 # Therefore, we create a key that way (clearing any fields that may 

67 # be set) and then merge in our values. 

68 self.pb[key].Clear() 

69 self.pb[key].MergeFrom(pb_value) 

70 

71 def __delitem__(self, key): 

72 self.pb.pop(key) 

73 

74 def __len__(self): 

75 return len(self.pb) 

76 

77 def __iter__(self): 

78 return iter(self.pb) 

79 

80 @property 

81 def pb(self): 

82 return self._pb