This version won't print the full payload (which could be large).
It also prints human friendly values for types and flags.
durin42 |
hg-reviewers |
This version won't print the full payload (which could be large).
It also prints human friendly values for types and flags.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/wireprotoframing.py (24 lines) |
FRAME_TYPE_ERROR_RESPONSE: FLAGS_ERROR_RESPONSE, | FRAME_TYPE_ERROR_RESPONSE: FLAGS_ERROR_RESPONSE, | ||||
FRAME_TYPE_TEXT_OUTPUT: {}, | FRAME_TYPE_TEXT_OUTPUT: {}, | ||||
FRAME_TYPE_PROGRESS: {}, | FRAME_TYPE_PROGRESS: {}, | ||||
FRAME_TYPE_STREAM_SETTINGS: {}, | FRAME_TYPE_STREAM_SETTINGS: {}, | ||||
} | } | ||||
ARGUMENT_RECORD_HEADER = struct.Struct(r'<HH') | ARGUMENT_RECORD_HEADER = struct.Struct(r'<HH') | ||||
def humanflags(mapping, value): | |||||
"""Convert a numeric flags value to a human value, using a mapping table.""" | |||||
flags = [] | |||||
for val, name in sorted({v: k for k, v in mapping.iteritems()}.iteritems()): | |||||
if value & val: | |||||
flags.append(name) | |||||
return b'|'.join(flags) | |||||
@attr.s(slots=True) | @attr.s(slots=True) | ||||
class frameheader(object): | class frameheader(object): | ||||
"""Represents the data in a frame header.""" | """Represents the data in a frame header.""" | ||||
length = attr.ib() | length = attr.ib() | ||||
requestid = attr.ib() | requestid = attr.ib() | ||||
streamid = attr.ib() | streamid = attr.ib() | ||||
streamflags = attr.ib() | streamflags = attr.ib() | ||||
typeid = attr.ib() | typeid = attr.ib() | ||||
flags = attr.ib() | flags = attr.ib() | ||||
@attr.s(slots=True) | @attr.s(slots=True, repr=False) | ||||
class frame(object): | class frame(object): | ||||
"""Represents a parsed frame.""" | """Represents a parsed frame.""" | ||||
requestid = attr.ib() | requestid = attr.ib() | ||||
streamid = attr.ib() | streamid = attr.ib() | ||||
streamflags = attr.ib() | streamflags = attr.ib() | ||||
typeid = attr.ib() | typeid = attr.ib() | ||||
flags = attr.ib() | flags = attr.ib() | ||||
payload = attr.ib() | payload = attr.ib() | ||||
def __repr__(self): | |||||
typename = '<unknown>' | |||||
for name, value in FRAME_TYPES.iteritems(): | |||||
if value == self.typeid: | |||||
typename = name | |||||
break | |||||
return ('frame(size=%d; request=%d; stream=%d; streamflags=%s; ' | |||||
'type=%s; flags=%s)' % ( | |||||
len(self.payload), self.requestid, self.streamid, | |||||
humanflags(STREAM_FLAGS, self.streamflags), typename, | |||||
humanflags(FRAME_TYPE_FLAGS[self.typeid], self.flags))) | |||||
def makeframe(requestid, streamid, streamflags, typeid, flags, payload): | def makeframe(requestid, streamid, streamflags, typeid, flags, payload): | ||||
"""Assemble a frame into a byte array.""" | """Assemble a frame into a byte array.""" | ||||
# TODO assert size of payload. | # TODO assert size of payload. | ||||
frame = bytearray(FRAME_HEADER_SIZE + len(payload)) | frame = bytearray(FRAME_HEADER_SIZE + len(payload)) | ||||
# 24 bits length | # 24 bits length | ||||
# 16 bits request id | # 16 bits request id | ||||
# 8 bits stream id | # 8 bits stream id |