pythonhacktoberfeststeamauthenticationauthenticatorsteam-authenticatorsteam-clientsteam-guard-codessteam-websteamworksvalvewebapi
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.5 KiB
114 lines
3.5 KiB
|
|
import six
|
|
from types import GeneratorType as _GeneratorType
|
|
from google.protobuf.message import Message as _ProtoMessageType
|
|
|
|
|
|
if six.PY2:
|
|
_list_types = list, xrange, _GeneratorType
|
|
else:
|
|
_list_types = list, range, _GeneratorType, map, filter
|
|
|
|
protobuf_mask = 0x80000000
|
|
|
|
|
|
def is_proto(emsg):
|
|
"""
|
|
:param emsg: emsg number
|
|
:type emsg: int
|
|
:return: True or False
|
|
:rtype: bool
|
|
"""
|
|
return (int(emsg) & protobuf_mask) > 0
|
|
|
|
def set_proto_bit(emsg):
|
|
"""
|
|
:param emsg: emsg number
|
|
:type emsg: int
|
|
:return: emsg with proto bit set
|
|
:rtype: int
|
|
"""
|
|
return int(emsg) | protobuf_mask
|
|
|
|
def clear_proto_bit(emsg):
|
|
"""
|
|
:param emsg: emsg number
|
|
:type emsg: int
|
|
:return: emsg with proto bit removed
|
|
:rtype: int
|
|
"""
|
|
return int(emsg) & ~protobuf_mask
|
|
|
|
def proto_to_dict(message):
|
|
"""Converts protobuf message instance to dict
|
|
|
|
:param message: protobuf message instance
|
|
:return: parameters and their values
|
|
:rtype: dict
|
|
:raises: :class:`.TypeError` if ``message`` is not a proto message
|
|
"""
|
|
if not isinstance(message, _ProtoMessageType):
|
|
raise TypeError("Expected `message` to be a instance of protobuf message")
|
|
|
|
data = {}
|
|
|
|
for desc, field in message.ListFields():
|
|
if desc.type == desc.TYPE_MESSAGE:
|
|
if desc.label == desc.LABEL_REPEATED:
|
|
data[desc.name] = list(map(proto_to_dict, field))
|
|
else:
|
|
data[desc.name] = proto_to_dict(field)
|
|
else:
|
|
data[desc.name] = list(field) if desc.label == desc.LABEL_REPEATED else field
|
|
|
|
return data
|
|
|
|
def proto_fill_from_dict(message, data, clear=True):
|
|
"""Fills protobuf message parameters inplace from a :class:`dict`
|
|
|
|
:param message: protobuf message instance
|
|
:param data: parameters and values
|
|
:type data: dict
|
|
:param clear: whether clear exisiting values
|
|
:type clear: bool
|
|
:return: value of message paramater
|
|
:raises: incorrect types or values will raise
|
|
"""
|
|
if not isinstance(message, _ProtoMessageType):
|
|
raise TypeError("Expected `message` to be a instance of protobuf message")
|
|
if not isinstance(data, dict):
|
|
raise TypeError("Expected `data` to be of type `dict`")
|
|
|
|
if clear: message.Clear()
|
|
field_descs = message.DESCRIPTOR.fields_by_name
|
|
|
|
for key, val in data.items():
|
|
desc = field_descs[key]
|
|
|
|
if desc.type == desc.TYPE_MESSAGE:
|
|
if desc.label == desc.LABEL_REPEATED:
|
|
if not isinstance(val, _list_types):
|
|
raise TypeError("Expected %s to be of type list, got %s" % (repr(key), type(val)))
|
|
|
|
list_ref = getattr(message, key)
|
|
|
|
# Takes care of overwriting list fields when merging partial data (clear=False)
|
|
if not clear: del list_ref[:] # clears the list
|
|
|
|
for item in val:
|
|
item_message = getattr(message, key).add()
|
|
proto_fill_from_dict(item_message, item)
|
|
else:
|
|
if not isinstance(val, dict):
|
|
raise TypeError("Expected %s to be of type dict, got %s" % (repr(key), type(dict)))
|
|
|
|
proto_fill_from_dict(getattr(message, key), val)
|
|
else:
|
|
if isinstance(val, _list_types):
|
|
list_ref = getattr(message, key)
|
|
if not clear: del list_ref[:] # clears the list
|
|
list_ref.extend(val)
|
|
else:
|
|
setattr(message, key, val)
|
|
|
|
return message
|
|
|