Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/protobuf/message.py: 49%

90 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:40 +0000

1# Protocol Buffers - Google's data interchange format 

2# Copyright 2008 Google Inc. All rights reserved. 

3# 

4# Use of this source code is governed by a BSD-style 

5# license that can be found in the LICENSE file or at 

6# https://developers.google.com/open-source/licenses/bsd 

7 

8# TODO: We should just make these methods all "pure-virtual" and move 

9# all implementation out, into reflection.py for now. 

10 

11 

12"""Contains an abstract base class for protocol messages.""" 

13 

14__author__ = 'robinson@google.com (Will Robinson)' 

15 

16class Error(Exception): 

17 """Base error type for this module.""" 

18 pass 

19 

20 

21class DecodeError(Error): 

22 """Exception raised when deserializing messages.""" 

23 pass 

24 

25 

26class EncodeError(Error): 

27 """Exception raised when serializing messages.""" 

28 pass 

29 

30 

31class Message(object): 

32 

33 """Abstract base class for protocol messages. 

34 

35 Protocol message classes are almost always generated by the protocol 

36 compiler. These generated types subclass Message and implement the methods 

37 shown below. 

38 """ 

39 

40 # TODO: Link to an HTML document here. 

41 

42 # TODO: Document that instances of this class will also 

43 # have an Extensions attribute with __getitem__ and __setitem__. 

44 # Again, not sure how to best convey this. 

45 

46 # TODO: Document these fields and methods. 

47 

48 __slots__ = [] 

49 

50 #: The :class:`google.protobuf.Descriptor` 

51 # for this message type. 

52 DESCRIPTOR = None 

53 

54 def __deepcopy__(self, memo=None): 

55 clone = type(self)() 

56 clone.MergeFrom(self) 

57 return clone 

58 

59 def __eq__(self, other_msg): 

60 """Recursively compares two messages by value and structure.""" 

61 raise NotImplementedError 

62 

63 def __ne__(self, other_msg): 

64 # Can't just say self != other_msg, since that would infinitely recurse. :) 

65 return not self == other_msg 

66 

67 def __hash__(self): 

68 raise TypeError('unhashable object') 

69 

70 def __str__(self): 

71 """Outputs a human-readable representation of the message.""" 

72 raise NotImplementedError 

73 

74 def __unicode__(self): 

75 """Outputs a human-readable representation of the message.""" 

76 raise NotImplementedError 

77 

78 def MergeFrom(self, other_msg): 

79 """Merges the contents of the specified message into current message. 

80 

81 This method merges the contents of the specified message into the current 

82 message. Singular fields that are set in the specified message overwrite 

83 the corresponding fields in the current message. Repeated fields are 

84 appended. Singular sub-messages and groups are recursively merged. 

85 

86 Args: 

87 other_msg (Message): A message to merge into the current message. 

88 """ 

89 raise NotImplementedError 

90 

91 def CopyFrom(self, other_msg): 

92 """Copies the content of the specified message into the current message. 

93 

94 The method clears the current message and then merges the specified 

95 message using MergeFrom. 

96 

97 Args: 

98 other_msg (Message): A message to copy into the current one. 

99 """ 

100 if self is other_msg: 

101 return 

102 self.Clear() 

103 self.MergeFrom(other_msg) 

104 

105 def Clear(self): 

106 """Clears all data that was set in the message.""" 

107 raise NotImplementedError 

108 

109 def SetInParent(self): 

110 """Mark this as present in the parent. 

111 

112 This normally happens automatically when you assign a field of a 

113 sub-message, but sometimes you want to make the sub-message 

114 present while keeping it empty. If you find yourself using this, 

115 you may want to reconsider your design. 

116 """ 

117 raise NotImplementedError 

118 

119 def IsInitialized(self): 

120 """Checks if the message is initialized. 

121 

122 Returns: 

123 bool: The method returns True if the message is initialized (i.e. all of 

124 its required fields are set). 

125 """ 

126 raise NotImplementedError 

127 

128 # TODO: MergeFromString() should probably return None and be 

129 # implemented in terms of a helper that returns the # of bytes read. Our 

130 # deserialization routines would use the helper when recursively 

131 # deserializing, but the end user would almost always just want the no-return 

132 # MergeFromString(). 

133 

134 def MergeFromString(self, serialized): 

135 """Merges serialized protocol buffer data into this message. 

136 

137 When we find a field in `serialized` that is already present 

138 in this message: 

139 

140 - If it's a "repeated" field, we append to the end of our list. 

141 - Else, if it's a scalar, we overwrite our field. 

142 - Else, (it's a nonrepeated composite), we recursively merge 

143 into the existing composite. 

144 

145 Args: 

146 serialized (bytes): Any object that allows us to call 

147 ``memoryview(serialized)`` to access a string of bytes using the 

148 buffer interface. 

149 

150 Returns: 

151 int: The number of bytes read from `serialized`. 

152 For non-group messages, this will always be `len(serialized)`, 

153 but for messages which are actually groups, this will 

154 generally be less than `len(serialized)`, since we must 

155 stop when we reach an ``END_GROUP`` tag. Note that if 

156 we *do* stop because of an ``END_GROUP`` tag, the number 

157 of bytes returned does not include the bytes 

158 for the ``END_GROUP`` tag information. 

159 

160 Raises: 

161 DecodeError: if the input cannot be parsed. 

162 """ 

163 # TODO: Document handling of unknown fields. 

164 # TODO: When we switch to a helper, this will return None. 

165 raise NotImplementedError 

166 

167 def ParseFromString(self, serialized): 

168 """Parse serialized protocol buffer data in binary form into this message. 

169 

170 Like :func:`MergeFromString()`, except we clear the object first. 

171 

172 Raises: 

173 message.DecodeError if the input cannot be parsed. 

174 """ 

175 self.Clear() 

176 return self.MergeFromString(serialized) 

177 

178 def SerializeToString(self, **kwargs): 

179 """Serializes the protocol message to a binary string. 

180 

181 Keyword Args: 

182 deterministic (bool): If true, requests deterministic serialization 

183 of the protobuf, with predictable ordering of map keys. 

184 

185 Returns: 

186 A binary string representation of the message if all of the required 

187 fields in the message are set (i.e. the message is initialized). 

188 

189 Raises: 

190 EncodeError: if the message isn't initialized (see :func:`IsInitialized`). 

191 """ 

192 raise NotImplementedError 

193 

194 def SerializePartialToString(self, **kwargs): 

195 """Serializes the protocol message to a binary string. 

196 

197 This method is similar to SerializeToString but doesn't check if the 

198 message is initialized. 

199 

200 Keyword Args: 

201 deterministic (bool): If true, requests deterministic serialization 

202 of the protobuf, with predictable ordering of map keys. 

203 

204 Returns: 

205 bytes: A serialized representation of the partial message. 

206 """ 

207 raise NotImplementedError 

208 

209 # TODO: Decide whether we like these better 

210 # than auto-generated has_foo() and clear_foo() methods 

211 # on the instances themselves. This way is less consistent 

212 # with C++, but it makes reflection-type access easier and 

213 # reduces the number of magically autogenerated things. 

214 # 

215 # TODO: Be sure to document (and test) exactly 

216 # which field names are accepted here. Are we case-sensitive? 

217 # What do we do with fields that share names with Python keywords 

218 # like 'lambda' and 'yield'? 

219 # 

220 # nnorwitz says: 

221 # """ 

222 # Typically (in python), an underscore is appended to names that are 

223 # keywords. So they would become lambda_ or yield_. 

224 # """ 

225 def ListFields(self): 

226 """Returns a list of (FieldDescriptor, value) tuples for present fields. 

227 

228 A message field is non-empty if HasField() would return true. A singular 

229 primitive field is non-empty if HasField() would return true in proto2 or it 

230 is non zero in proto3. A repeated field is non-empty if it contains at least 

231 one element. The fields are ordered by field number. 

232 

233 Returns: 

234 list[tuple(FieldDescriptor, value)]: field descriptors and values 

235 for all fields in the message which are not empty. The values vary by 

236 field type. 

237 """ 

238 raise NotImplementedError 

239 

240 def HasField(self, field_name): 

241 """Checks if a certain field is set for the message. 

242 

243 For a oneof group, checks if any field inside is set. Note that if the 

244 field_name is not defined in the message descriptor, :exc:`ValueError` will 

245 be raised. 

246 

247 Args: 

248 field_name (str): The name of the field to check for presence. 

249 

250 Returns: 

251 bool: Whether a value has been set for the named field. 

252 

253 Raises: 

254 ValueError: if the `field_name` is not a member of this message. 

255 """ 

256 raise NotImplementedError 

257 

258 def ClearField(self, field_name): 

259 """Clears the contents of a given field. 

260 

261 Inside a oneof group, clears the field set. If the name neither refers to a 

262 defined field or oneof group, :exc:`ValueError` is raised. 

263 

264 Args: 

265 field_name (str): The name of the field to check for presence. 

266 

267 Raises: 

268 ValueError: if the `field_name` is not a member of this message. 

269 """ 

270 raise NotImplementedError 

271 

272 def WhichOneof(self, oneof_group): 

273 """Returns the name of the field that is set inside a oneof group. 

274 

275 If no field is set, returns None. 

276 

277 Args: 

278 oneof_group (str): the name of the oneof group to check. 

279 

280 Returns: 

281 str or None: The name of the group that is set, or None. 

282 

283 Raises: 

284 ValueError: no group with the given name exists 

285 """ 

286 raise NotImplementedError 

287 

288 def HasExtension(self, field_descriptor): 

289 """Checks if a certain extension is present for this message. 

290 

291 Extensions are retrieved using the :attr:`Extensions` mapping (if present). 

292 

293 Args: 

294 field_descriptor: The field descriptor for the extension to check. 

295 

296 Returns: 

297 bool: Whether the extension is present for this message. 

298 

299 Raises: 

300 KeyError: if the extension is repeated. Similar to repeated fields, 

301 there is no separate notion of presence: a "not present" repeated 

302 extension is an empty list. 

303 """ 

304 raise NotImplementedError 

305 

306 def ClearExtension(self, field_descriptor): 

307 """Clears the contents of a given extension. 

308 

309 Args: 

310 field_descriptor: The field descriptor for the extension to clear. 

311 """ 

312 raise NotImplementedError 

313 

314 def UnknownFields(self): 

315 """Returns the UnknownFieldSet. 

316 

317 Returns: 

318 UnknownFieldSet: The unknown fields stored in this message. 

319 """ 

320 raise NotImplementedError 

321 

322 def DiscardUnknownFields(self): 

323 """Clears all fields in the :class:`UnknownFieldSet`. 

324 

325 This operation is recursive for nested message. 

326 """ 

327 raise NotImplementedError 

328 

329 def ByteSize(self): 

330 """Returns the serialized size of this message. 

331 

332 Recursively calls ByteSize() on all contained messages. 

333 

334 Returns: 

335 int: The number of bytes required to serialize this message. 

336 """ 

337 raise NotImplementedError 

338 

339 @classmethod 

340 def FromString(cls, s): 

341 raise NotImplementedError 

342 

343# TODO: Remove it in OSS 

344 @staticmethod 

345 def RegisterExtension(field_descriptor): 

346 raise NotImplementedError 

347 

348 def _SetListener(self, message_listener): 

349 """Internal method used by the protocol message implementation. 

350 Clients should not call this directly. 

351 

352 Sets a listener that this message will call on certain state transitions. 

353 

354 The purpose of this method is to register back-edges from children to 

355 parents at runtime, for the purpose of setting "has" bits and 

356 byte-size-dirty bits in the parent and ancestor objects whenever a child or 

357 descendant object is modified. 

358 

359 If the client wants to disconnect this Message from the object tree, she 

360 explicitly sets callback to None. 

361 

362 If message_listener is None, unregisters any existing listener. Otherwise, 

363 message_listener must implement the MessageListener interface in 

364 internal/message_listener.py, and we discard any listener registered 

365 via a previous _SetListener() call. 

366 """ 

367 raise NotImplementedError 

368 

369 def __getstate__(self): 

370 """Support the pickle protocol.""" 

371 return dict(serialized=self.SerializePartialToString()) 

372 

373 def __setstate__(self, state): 

374 """Support the pickle protocol.""" 

375 self.__init__() 

376 serialized = state['serialized'] 

377 # On Python 3, using encoding='latin1' is required for unpickling 

378 # protos pickled by Python 2. 

379 if not isinstance(serialized, bytes): 

380 serialized = serialized.encode('latin1') 

381 self.ParseFromString(serialized) 

382 

383 def __reduce__(self): 

384 message_descriptor = self.DESCRIPTOR 

385 if message_descriptor.containing_type is None: 

386 return type(self), (), self.__getstate__() 

387 # the message type must be nested. 

388 # Python does not pickle nested classes; use the symbol_database on the 

389 # receiving end. 

390 container = message_descriptor 

391 return (_InternalConstructMessage, (container.full_name,), 

392 self.__getstate__()) 

393 

394 

395def _InternalConstructMessage(full_name): 

396 """Constructs a nested message.""" 

397 from google.protobuf import symbol_database # pylint:disable=g-import-not-at-top 

398 

399 return symbol_database.Default().GetSymbol(full_name)()