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

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

29 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 

18 

19 

20class MapComposite(collections.abc.MutableMapping): 

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

22 

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

24 modify the underlying field container directly. 

25 """ 

26 

27 @cached_property 

28 def _pb_type(self): 

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

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

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

32 

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

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

35 

36 Args: 

37 sequence: A protocol buffers map. 

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

39 convert values going to and from this map. 

40 """ 

41 self._pb = sequence 

42 self._marshal = marshal 

43 

44 def __contains__(self, key): 

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

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

47 # 

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

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

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

51 

52 def __getitem__(self, key): 

53 # We handle raising KeyError ourselves, because otherwise protocol 

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

55 if key not in self: 

56 raise KeyError(key) 

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

58 

59 def __setitem__(self, key, value): 

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

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

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

63 # of itself create it. 

64 # 

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

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

67 self.pb[key].Clear() 

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

69 

70 def __delitem__(self, key): 

71 self.pb.pop(key) 

72 

73 def __len__(self): 

74 return len(self.pb) 

75 

76 def __iter__(self): 

77 return iter(self.pb) 

78 

79 @property 

80 def pb(self): 

81 return self._pb