instead of explicit listing of of-wire attributes, use a heuristics to exclude internal attributes. (eg. buf, datapath, etc)
this commit changes __str__ outputs. update a test case accordingly. Signed-off-by: YAMAMOTO Takashi <yamam...@valinux.co.jp> --- ryu/ofproto/ofproto_parser.py | 27 +++++++++++++++++++++++---- ryu/ofproto/ofproto_v1_0_parser.py | 18 ------------------ ryu/tests/unit/ofproto/test_parser_v10.py | 13 ++++++++++--- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/ryu/ofproto/ofproto_parser.py b/ryu/ofproto/ofproto_parser.py index 26adead..5b4cf24 100644 --- a/ryu/ofproto/ofproto_parser.py +++ b/ryu/ofproto/ofproto_parser.py @@ -16,6 +16,7 @@ import logging import struct +import functools from ryu import exception @@ -50,7 +51,17 @@ def msg(datapath, version, msg_type, msg_len, xid, buf): return msg_parser(datapath, version, msg_type, msg_len, xid, buf) +def create_list_of_attributes(f): + @functools.wraps(f) + def wrapper(self, *args, **kwargs): + ret = f(self, *args, **kwargs) + self._attributes = set(dir(self)) + return ret + return wrapper + + class MsgBase(object): + @create_list_of_attributes def __init__(self, datapath): self.datapath = datapath self.version = None @@ -75,9 +86,10 @@ class MsgBase(object): self.buf = buffer(buf) def __str__(self): - return 'version: 0x%x msg_type 0x%x xid 0x%x' % (self.version, - self.msg_type, - self.xid) + buf = 'version: 0x%x msg_type 0x%x xid 0x%x' % (self.version, + self.msg_type, + self.xid) + return msg_str_attr(self, buf) @classmethod def parser(cls, datapath, version, msg_type, msg_len, xid, buf): @@ -135,7 +147,14 @@ def msg_pack_into(fmt, buf, offset, *args): struct.pack_into(fmt, buf, offset, *args) -def msg_str_attr(msg, buf, attr_list): +def msg_str_attr(msg, buf, attr_list=None): + if attr_list is None: + exclude = ['_attributes'] + try: + exclude += msg._attributes + except AttributeError: + pass + attr_list = set(dir(msg)) - set(exclude) for attr in attr_list: val = getattr(msg, attr, None) if val is not None: diff --git a/ryu/ofproto/ofproto_v1_0_parser.py b/ryu/ofproto/ofproto_v1_0_parser.py index 7081c31..46a6cc0 100644 --- a/ryu/ofproto/ofproto_v1_0_parser.py +++ b/ryu/ofproto/ofproto_v1_0_parser.py @@ -1620,12 +1620,6 @@ class OFPSwitchFeatures(MsgBase): def __init__(self, datapath): super(OFPSwitchFeatures, self).__init__(datapath) - def __str__(self): - buf = super(OFPSwitchFeatures, self).__str__() + ' port' - for _port_no, p in getattr(self, 'ports', {}).items(): - buf += ' ' + str(p) - return buf - @classmethod def parser(cls, datapath, version, msg_type, msg_len, xid, buf): msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type, @@ -1675,11 +1669,6 @@ class OFPPacketIn(MsgBase): def __init__(self, datapath): super(OFPPacketIn, self).__init__(datapath) - def __str__(self): - buf = super(OFPPacketIn, self).__str__() - return msg_str_attr(self, buf, - ('buffer_id', 'total_len', 'in_port', 'reason')) - @classmethod def parser(cls, datapath, version, msg_type, msg_len, xid, buf): msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type, @@ -1726,13 +1715,6 @@ class OFPFlowRemoved(MsgBase): def __init__(self, datapath): super(OFPFlowRemoved, self).__init__(datapath) - def __str__(self): - buf = super(OFPFlowRemoved, self).__str__() - return msg_str_attr(self, buf, - ('match', 'cookie', 'priority', 'reason', - 'duration_sec', 'duration_nsec', - 'idle_timeout', 'packet_count', 'byte_count')) - @classmethod def parser(cls, datapath, version, msg_type, msg_len, xid, buf): msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type, diff --git a/ryu/tests/unit/ofproto/test_parser_v10.py b/ryu/tests/unit/ofproto/test_parser_v10.py index 8723231..d4184c1 100644 --- a/ryu/tests/unit/ofproto/test_parser_v10.py +++ b/ryu/tests/unit/ofproto/test_parser_v10.py @@ -3560,7 +3560,11 @@ class TestOFPSwitchFeatures(unittest.TestCase): eq_(peer['val'], port.peer) # test __str__() - list_ = ('version:', 'msg_type', 'xid', 'port') + # + # an example: + # switch features ev version: 0x1 msg_type 0x6 xid 0x73a92862 datapath_id 8 n_tables 2 capabilities 0 actions 2047 ports {1: OFPPhyPort(port_no=1, hw_addr='\x1a\xc1Q\xff\xef\x8a', name='veth1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', config=0, state=0, curr=192, advertised=0, supported=0, peer=0), 2: OFPPhyPort(port_no=2, hw_addr='\xce/\xa2\x87\xf6p', name='veth3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', config=0, state=0, curr=192, advertised=0, supported=0, peer=0), 3: OFPPhyPort(port_no=3, hw_addr='\xca\x8a\x1e\xf3w\xef', name='veth5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', config=0, state=0, curr=192, advertised=0, supported=0, peer=0), 4: OFPPhyPort(port_no=4, hw_addr='\xfa\xbcw\x8d~\x0b', name='veth7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', config=0, state=0, curr=192, advertised=0, supported=0, peer=0)} n_buffers 256 + + list_ = ('version:', 'msg_type', 'xid', 'ports') check = {} str_ = str(res) str_ = str_.rsplit() @@ -3568,13 +3572,16 @@ class TestOFPSwitchFeatures(unittest.TestCase): i = 0 for s in str_: if s in list_: - check[str_[i]] = str_[i + 1] + if str_[i + 1].startswith('{'): # "{1: OFPPhyPort..." + check[str_[i]] = str_[i + 2] + else: + check[str_[i]] = str_[i + 1] i += 1 eq_(hex(version['val']).find(check['version:']), 0) eq_(hex(msg_type['val']).find(check['msg_type']), 0) eq_(hex(xid['val']).find(check['xid']), 0) - eq_(check['port'].find('OFPPhyPort'), 0) + eq_(check['ports'].find('OFPPhyPort'), 0) def test_serialize(self): # Not used. -- 1.8.0.1 ------------------------------------------------------------------------------ Learn Graph Databases - Download FREE O'Reilly Book "Graph Databases" is the definitive new guide to graph databases and their applications. This 200-page book is written by three acclaimed leaders in the field. The early access version is available now. Download your free book today! http://p.sf.net/sfu/neotech_d2d_may _______________________________________________ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel