Passed
Pull Request — master (#425)
by Carlos Eduardo
02:30
created

StatsReply._get_body_class()   B

Complexity

Conditions 5

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.0342

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
ccs 8
cts 9
cp 0.8889
rs 8.5454
cc 5
crap 5.0342
1
"""Response the stat request packet from the controller."""
2 1
from importlib import import_module
3
4 1
from pyof.foundation.base import GenericMessage
5 1
from pyof.foundation.basic_types import BinaryData, FixedTypeList, UBInt16
6 1
from pyof.v0x01.common.header import Header, Type
7 1
from pyof.v0x01.controller2switch.common import DescStats, StatsTypes
8
9 1
__all__ = ('StatsReply',)
10
11
12 1
class StatsReply(GenericMessage):
13
    """Class implements the response to the stats request."""
14
15
    #: OpenFlow :class:`~pyof.v0x01.common.header.Header`
16 1
    header = Header(message_type=Type.OFPT_STATS_REPLY)
17 1
    body_type = UBInt16(enum_ref=StatsTypes)
18 1
    flags = UBInt16()
19 1
    body = BinaryData()
20
21 1
    def __init__(self, xid=None, body_type=None, flags=None, body=b''):
22
        """The constructor just assigns parameters to object attributes.
23
24
        Args:
25
            body_type (StatsTypes): One of the OFPST_* constants.
26
            flags (int): OFPSF_REQ_* flags (none yet defined).
27
            body (BinaryData): Body of the request.
28
        """
29 1
        super().__init__(xid)
30 1
        self.body_type = body_type
31 1
        self.flags = flags
32 1
        self.body = body
33
34 1
    def pack(self, value=None):
35
        """Pack a StatsReply using the object's attributes.
36
37
        This method will pack the attribute body and body_type before pack the
38
        StatsReply object, then will return this struct as a binary data.
39
40
        Returns:
41
            bytes: Binary data with StatsReply packed.
42
        """
43 1
        buff = self.body
44 1
        if not value:
45 1
            value = self.body
46
47 1
        if value and hasattr(value, 'pack'):
48 1
            self.body = BinaryData(value.pack())
49 1
        stats_reply_packed = super().pack()
50
51 1
        self.body = buff
52 1
        return stats_reply_packed
53
54 1
    def unpack(self, buff, offset=0):
55
        """Unpack a binary message into this object's attributes.
56
57
        Unpack the binary value *buff* and update this object attributes based
58
        on the results. It is an inplace method and it receives the binary data
59
        of the message **without the header**.
60
61
        This class' unpack method is like the :meth:`.GenericMessage.unpack`
62
        one, except for the ``body`` attribute which has its type determined
63
        by the ``body_type`` attribute.
64
65
        Args:
66
            buff (bytes): Binary data package to be unpacked, without the
67
                header.
68
        """
69 1
        super().unpack(buff[offset:])
70 1
        self._unpack_body()
71
72 1
    def _unpack_body(self):
73
        """Unpack `body` replace it by the result."""
74 1
        obj = self._get_body_instance()
75 1
        obj.unpack(self.body.value)
76 1
        self.body = obj
77
78 1
    def _get_body_instance(self):
79
        """Method used to return the body instance."""
80 1
        pyof_class = self._get_body_class()
81
82 1
        if pyof_class is None:
83
            return BinaryData(b'')
84 1
        elif pyof_class is DescStats:
85 1
            return pyof_class()
86
87 1
        return FixedTypeList(pyof_class=pyof_class)
88
89 1
    def _get_body_class(self):
90 1
        if isinstance(self.body_type, (int, UBInt16)):
91 1
            self.body_type = self.body_type.enum_ref(self.body_type.value)
92
93 1
        body_name = self.body_type.name.replace('OFPST_', '').title()
94 1
        module = import_module('pyof.v0x01.controller2switch.common')
95
96 1
        for class_name in module.__all__:
97 1
            if 'Request' not in class_name and body_name in class_name:
98 1
                return getattr(module, class_name)
99
        return None
100