-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathobject.py
More file actions
194 lines (154 loc) · 6.32 KB
/
object.py
File metadata and controls
194 lines (154 loc) · 6.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
###################################################################################################
#
# Caffa
# Copyright (C) Kontur AS
#
# GNU Lesser General Public License Usage
# This library is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.
#
# See the GNU Lesser General Public License at <<http:#www.gnu.org/licenses/lgpl-2.1.html>>
# for more details.
#
import json
import logging
from .method import Method, create_method_class
class Object(object):
_log = logging.getLogger("caffa-object")
_methods = []
__frozen = False
@classmethod
def prep_attributes(cls):
setattr(cls, "_fields", None)
setattr(cls, "_client", None)
setattr(cls, "_local", None)
setattr(cls, "_method_list", None)
for method in cls._methods:
setattr(cls, method.static_name(), None)
cls.__frozen = True
def __init__(self, json_object="", client=None, local=False):
if isinstance(json_object, dict):
self._fields = json_object
else:
self._fields = json.loads(json_object)
self._client = client
self._local = local
if not self._local:
assert self._client is not None
self._method_list = []
for method in self.__class__._methods:
method_instance = method(self_object=self)
setattr(self, method.static_name(), method_instance)
self._method_list.append(method_instance)
@property
def keyword(self):
return self._fields["keyword"]
def __setattr__(self, key, value):
if not hasattr(self, key) and self.__class__.__frozen:
raise TypeError("%r does not have the property %s", self, key)
object.__setattr__(self, key, value)
def client(self):
return self._client
def to_dict(self):
content = {}
for key in self._fields:
value = self.get(key)
if isinstance(value, Object):
value = value.to_dict()
content[key] = value
return content
def to_json(self):
return json.loads(self.to_string())
def field_keywords(self):
keywords = []
for keyword in self._fields:
keywords.append(keyword)
return keywords
def get(self, field_keyword):
value = None
if not self._local and field_keyword != "keyword" and field_keyword != "uuid":
value = json.loads(
self._client.get_field_value(self._fields["uuid"], field_keyword)
)
elif self._fields and field_keyword in self._fields:
value = self._fields[field_keyword]
if isinstance(value, dict):
keyword = value["keyword"]
schema_location = ""
if "$id" in value:
schema_location = value["$id"]
else:
schema_location = self._client.schema_location_from_keyword(keyword)
schema_properties = self._client.schema_properties(schema_location)
cls = create_class(keyword, schema_properties)
value = cls(value, self._client, self._local)
return value
def set(self, field_keyword, value):
if isinstance(value, Object):
value = value.to_json()
if not self._local:
self._client.set_field_value(self.uuid, field_keyword, value)
else:
if hasattr(self._fields[field_keyword], "value"):
self._fields[field_keyword]["value"] = value
else:
self._fields[field_keyword] = value
def create_field(self, keyword, type, value):
self._fields[keyword] = {"type": type, "value": value}
def set_fields(self, **kwargs):
for key, value in kwargs.items():
self.set(key, value)
def execute(self, object_method, arguments):
return self.client().execute(self.uuid, object_method.name(), arguments)
def methods(self):
return self._method_list
def to_string(self):
return json.dumps(self.to_dict())
def raise_write_exception(self, property_name):
raise AttributeError("Property " + property_name + " is read only!")
def make_read_lambda(property_name):
return lambda self: self.get(property_name)
# Dummy read lambda used to avoid a proper caffa read call when asking
# for a write-only attribute
def make_dummy_read_lambda(property_name):
return lambda self: None
def make_write_lambda(property_name):
return lambda self, value: self.set(property_name, value)
def make_error_write_lambda(property_name):
return lambda self, value: self.raise_write_exception(property_name)
def create_class(name, schema_properties):
def __init__(self, json_object="", client=None, local=False):
Object.__init__(self, json_object, client, local)
newclass = type(name, (Object,), {"__init__": __init__})
for property_name, prop in schema_properties.items():
if property_name != "keyword" and property_name != "methods":
read_only = "readOnly" in prop and prop["readOnly"]
write_only = "writeOnly" in prop and prop["writeOnly"]
read_lambda = make_dummy_read_lambda(property_name)
write_lambda = make_error_write_lambda(property_name)
if not write_only:
read_lambda = make_read_lambda(property_name)
if not read_only:
write_lambda = make_write_lambda(property_name)
setattr(
newclass,
property_name,
property(
fget=read_lambda,
fset=write_lambda,
),
)
elif property_name == "methods":
for method_name, method_schema in prop["properties"].items():
method_schema = method_schema["properties"]
newclass._methods.append(
create_method_class(method_name, method_schema)
)
newclass.prep_attributes()
return newclass