Completed
Push — master ( 25ee45...3b97dd )
by Olivier
04:27
created

UaStatusCodeError.__new__()   A

Complexity

Conditions 4

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 4
c 1
b 0
f 1
dl 0
loc 19
rs 9.2
1
"""
2
Define exceptions to be raised at various places in the stack
3
"""
4
5
from opcua.compat import with_metaclass
6
7
class _AutoRegister(type):
8
    def __new__(mcs, name, bases, dict):
9
        SubClass = type.__new__(mcs, name, bases, dict)
10
11
        # register subclass in bases
12
        for base in bases:
13
            try:
14
                subclasses = base._subclasses
15
                code = dict['code']
16
            except (AttributeError, KeyError):
17
                pass
18
            else:
19
                subclasses[code] = SubClass
20
21
        return SubClass
22
23
class UaError(RuntimeError):
24
    pass
25
26
27
class UaStatusCodeError(with_metaclass(_AutoRegister, UaError)):
28
    """
29
    This exception is raised when a bad status code is encountered.
30
31
    It exposes the status code number in the `code' property, so the
32
    user can distinguish between the different status codes and maybe
33
    handle some of them.
34
35
    The list of status error codes can be found in opcua.ua.status_codes.
36
    """
37
38
    """ Dict containing all subclasses keyed to their status code. """
39
    _subclasses = {}
40
41
    def __new__(cls, *args):
42
        """
43
        Creates a new UaStatusCodeError but returns a more specific subclass
44
        if possible, e.g.
45
46
            UaStatusCodeError(0x80010000) => BadUnexpectedError()
47
        """
48
49
        # switch class to a more appropriate subclass
50
        if len(args) >= 1:
51
            code = args[0]
52
            try:
53
                cls = cls._subclasses[code]
54
            except (KeyError, AttributeError):
55
                pass
56
            else:
57
                args = args[1:]
58
59
        return UaError.__new__(cls, *args)
60
61
    def __init__(self, code=None):
62
        """
63
        :param code: The code of the exception. Only needed when not instanciating
64
                     a concrete subclass such as BadInternalError.
65
        """
66
        if code is None:
67
            if type(self) is UaStatusCodeError:
68
                raise TypeError("UaStatusCodeError(code) cannot be instantiated without a status code.")
69
        UaError.__init__(self, code)
70
71
    def __str__(self):
72
        # import here to avoid circular import problems
73
        import opcua.ua.status_codes as status_codes
74
75
        return "{1}({0})".format(*status_codes.get_name_and_doc(self.code))
76
77
    @property
78
    def code(self):
79
        """
80
        The code of the status error.
81
        """
82
        return self.args[0]
83
84
class UaStringParsingError(UaError):
85
    pass
86