Completed
Pull Request — master (#51)
by Thomas
02:39 queued 01:37
created

SerializableAttributesHolder.from_dict()   B

Complexity

Conditions 6

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
c 1
b 0
f 0
dl 0
loc 15
ccs 10
cts 10
cp 1
crap 6
rs 8
1 1
import json
2
3 1
from .attributesholder import AttributesHolder
4
5 1
class SerializableAttributesHolder(AttributesHolder):
6
    """AttributesHolder with methods handling serialization and
7
    deserialization according to the PPP datamodel specification."""
8 1
    def as_dict(self):
9
        """Returns a JSON-serializeable object representing this tree."""
10 1
        def conv(v):
11 1
            if isinstance(v, SerializableAttributesHolder):
12 1
                return v.as_dict()
13 1
            elif isinstance(v, list):
14 1
                return [conv(x) for x in v]
15 1
            elif isinstance(v, dict):
16 1
                return {x:conv(y) for (x,y) in v.items()}
17
            else:
18 1
                return v
19 1
        return {k.replace('_', '-'): conv(v) for (k, v) in self._attributes.items()}
20 1
    def as_json(self):
21
        """Return a JSON dump of the object."""
22 1
        return json.dumps(self.as_dict())
23
24 1
    @staticmethod
25
    def _test_can_import_json(data):
26
        """Sanity check on input JSON data"""
27 1
        pass
28
29 1
    @classmethod
30
    def from_json(cls, data):
31
        """Decode a JSON string and inflate a node instance."""
32
        # Decode JSON string
33 1
        assert isinstance(data, str)
34 1
        data = json.loads(data)
35 1
        assert isinstance(data, dict)
36 1
        return cls.from_dict(data)
37
38 1
    @classmethod
39
    def from_dict(cls, data):
40 1
        cls._test_can_import_json(data)
41
42
        # Find a class that will deserialize the dict as specifically
43
        # as possible
44 1
        while True:
45 1
            cls2 = cls._select_class(data)
46 1
            if cls is cls2:
47 1
                break
48 1
            cls = cls2
49 1
        conv = (lambda k,v: cls.deserialize_attribute(k, v)
50
                            if isinstance(v, dict) else v)
51 1
        data = {k.replace('-', '_'): conv(k,v) for (k, v) in data.items()}
52 1
        return cls(**data)
53
54 1
    @classmethod
55
    def deserialize_attribute(cls, key, value):
56 1
        return cls.from_dict(value)
57
58 1
    @classmethod
59
    def _select_class(cls, data):
60
        return cls
61