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

Reply via email to