wireproto: implement custom __repr__ for frame
authorGregory Szorc <gregory.szorc@gmail.com>
Wed, 28 Mar 2018 13:01:28 -0700
changeset 37298 5ef2da00e935
parent 37297 97eedbd5a56c
child 37299 e9aadee698cf
wireproto: implement custom __repr__ for frame This version won't print the full payload (which could be large). It also prints human friendly values for types and flags. Differential Revision: https://phab.mercurial-scm.org/D2985
mercurial/wireprotoframing.py
--- a/mercurial/wireprotoframing.py	Wed Mar 28 12:44:35 2018 -0700
+++ b/mercurial/wireprotoframing.py	Wed Mar 28 13:01:28 2018 -0700
@@ -106,6 +106,15 @@
 
 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)
 class frameheader(object):
     """Represents the data in a frame header."""
@@ -117,7 +126,7 @@
     typeid = attr.ib()
     flags = attr.ib()
 
-@attr.s(slots=True)
+@attr.s(slots=True, repr=False)
 class frame(object):
     """Represents a parsed frame."""
 
@@ -128,6 +137,19 @@
     flags = 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):
     """Assemble a frame into a byte array."""
     # TODO assert size of payload.