Passed
Push — master ( b005e0...59f1dd )
by Olivier
02:01
created

asyncua.common.utils   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 47
dl 0
loc 85
rs 10
c 0
b 0
f 0
wmc 15

9 Methods

Rating   Name   Duplication   Size   Complexity  
A ServiceError.__init__() 0 3 1
A Buffer.__init__() 0 6 2
A Buffer.__str__() 0 2 1
A Buffer.__len__() 0 2 1
A Buffer.skip() 0 8 2
A Buffer.__bytes__() 0 3 1
A Buffer.copy() 0 7 3
A Buffer.read() 0 10 2
A Buffer.__bool__() 0 2 1

1 Function

Rating   Name   Duplication   Size   Complexity  
A create_nonce() 0 2 1
1
"""
2
Helper function and classes that do not rely on asyncua library.
3
Helper function and classes depending on ua object are in ua_utils.py
4
"""
5
6
import os
7
import logging
8
from ..ua.uaerrors import UaError
9
10
_logger = logging.getLogger(__name__)
11
12
13
class ServiceError(UaError):
14
    def __init__(self, code):
15
        super(ServiceError, self).__init__('UA Service Error')
16
        self.code = code
17
18
19
class NotEnoughData(UaError):
20
    pass
21
22
23
class SocketClosedException(UaError):
24
    pass
25
26
27
class Buffer:
28
    """
29
    Alternative to io.BytesIO making debug easier
30
    and added a few convenience methods.
31
    """
32
33
    def __init__(self, data, start_pos=0, size=-1):
34
        self._data = data
35
        self._cur_pos = start_pos
36
        if size == -1:
37
            size = len(data) - start_pos
38
        self._size = size
39
40
    def __str__(self):
41
        return f"Buffer(size:{self._size}, data:{self._data[self._cur_pos:self._cur_pos + self._size]})"
42
    __repr__ = __str__
43
44
    def __len__(self):
45
        return self._size
46
47
    def __bool__(self):
48
        return self._size > 0
49
50
    def __bytes__(self):
51
        """Return remains of buffer as bytes."""
52
        return self._data[self._cur_pos:]
53
54
    def read(self, size):
55
        """
56
        read and pop number of bytes for buffer
57
        """
58
        if size > self._size:
59
            raise NotEnoughData(f"Not enough data left in buffer, request for {size}, we have {self._size}")
60
        self._size -= size
61
        pos = self._cur_pos
62
        self._cur_pos += size
63
        return self._data[pos:self._cur_pos]
64
65
    def copy(self, size=-1):
66
        """
67
        return a shadow copy, optionally only copy 'size' bytes
68
        """
69
        if size == -1 or size > self._size:
70
            size = self._size
71
        return Buffer(self._data, self._cur_pos, size)
72
73
    def skip(self, size):
74
        """
75
        skip size bytes in buffer
76
        """
77
        if size > self._size:
78
            raise NotEnoughData(f"Not enough data left in buffer, request for {size}, we have {self._size}")
79
        self._size -= size
80
        self._cur_pos += size
81
82
83
def create_nonce(size=32):
84
    return os.urandom(size)
85