On Fri, May 10, 2013 at 03:01:13PM +0900, YAMAMOTO Takashi wrote:
> 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)

Clever trick.
Is the result of str(msg) non-deterministic depending on the internal hash?

thanks,


>      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
> 

-- 
yamahata

------------------------------------------------------------------------------
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