@@ -0,0 +1,1989 @@
+import json%0A%0Afrom .attributesholder import AttributesHolder%0A%0Aclass SerializableAttributesHolder(AttributesHolder):%0A    %22%22%22AttributesHolder with methods handling serialization and%0A    deserialization according to the PPP datamodel specification.%22%22%22%0A    def as_dict(self):%0A        %22%22%22Returns a JSON-serializeable object representing this tree.%22%22%22%0A        def conv(v):%0A            if isinstance(v, SerializableAttributesHolder):%0A                return v.as_dict()%0A            elif isinstance(v, list):%0A                return %5Bconv(x) for x in v%5D%0A            elif isinstance(v, dict):%0A                return %7Bx:conv(y) for (x,y) in v.items()%7D%0A            else:%0A                return v%0A        return %7Bk.replace('_', '-'): conv(v) for (k, v) in self._attributes.items()%7D%0A    def as_json(self):%0A        %22%22%22Return a JSON dump of the object.%22%22%22%0A        return json.dumps(self.as_dict())%0A%0A    @staticmethod%0A    def _test_can_import_json(data):%0A        %22%22%22Sanity check on input JSON data%22%22%22%0A        pass%0A%0A    @classmethod%0A    def from_json(cls, data):%0A        %22%22%22Decode a JSON string and inflate a node instance.%22%22%22%0A        # Decode JSON string%0A        assert isinstance(data, str)%0A        data = json.loads(data)%0A        assert isinstance(data, dict)%0A        return cls.from_dict(data)%0A%0A    @classmethod%0A    def from_dict(cls, data):%0A        cls._test_can_import_json(data)%0A%0A        # Find a class that will deserialize the dict as specifically%0A        # as possible%0A        while True:%0A            cls2 = cls._select_class(data)%0A            if cls is cls2:%0A                break%0A            cls = cls2%0A        conv = (lambda k,v: cls.deserialize_attribute(k, v)%0A                            if isinstance(v, dict) else v)%0A        data = %7Bk.replace('-', '_'): conv(k,v) for (k, v) in data.items()%7D%0A        return cls(**data)%0A%0A    @classmethod%0A    def deserialize_attribute(cls, key, value):%0A        return cls.from_dict(value)%0A%0A    @classmethod%0A    def _select_class(cls, data):%0A        return cls%0A

Add missing file.