Skip to content

Commit 3ffdb0c

Browse files
Erik WilsherErik Wilsher
Erik Wilsher
authored and
Erik Wilsher
committed
Properties and attribute access
1 parent 3dd738e commit 3ffdb0c

File tree

3 files changed

+154
-31
lines changed

3 files changed

+154
-31
lines changed

pyprediktoredgeclient/hive.py

+154-30
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
__all__ = 'Instances', 'Error', 'Hive', 'Module', 'Attr', 'Property', 'Item', 'ItemVQT'
2+
13
import pkg_resources
24
import clr
5+
import functools
6+
import datetime
7+
import collections
8+
import System
39

410
dlls = [
511
'HiveNetApi.dll',
@@ -31,6 +37,10 @@
3137
def Instances():
3238
return Prediktor.APIS.Hive.HiveInstanceService.GetRegisteredInstances()
3339

40+
AttrFlags = Prediktor.APIS.Hive.Flags
41+
42+
ItemVQT = collections.namedtuple('ItemVQT', 'item_id value quality time')
43+
3444
class Error(Exception):
3545
"""Generic exception used to report problems in Apis.py"""
3646
def __init__(self, msg):
@@ -58,9 +68,10 @@ def __init__(self, instance_name=None, server_name=None):
5868
instance_name: optional name of the instance (default is None, i.e. the "ApisHive" instance)
5969
server_name: optional name of the server hostting the instance (default is None, i.e. "localhost")
6070
"""
61-
self.api = Prediktor.APIS.Hive.Hive.CreateServer(instance_name, server_name)
71+
self.api = Prediktor.APIS.Hive.Hive.CreateServer(instance_name, server_name or 'localhost')
6272
self._modtypes = { str(obj):obj for obj in self.api.ModuleTypes }
6373

74+
6475
def __str__(self):
6576
return self.api.ConfigurationName
6677

@@ -73,19 +84,24 @@ def __len__(self):
7384
def __getitem__(self, key):
7485
return self.get_module(key)
7586

87+
def __delitem__(self, key):
88+
return self.get_module(key).delete()
89+
7690
def __iter__(self):
7791
return self.api.GetModules()
7892

93+
@property
7994
def modules(self):
8095
"""Return a list containing all the modules in this hive instance"""
8196
return [ Module(self, obj) for obj in self.api.GetModules() ]
8297

8398
def get_module(self, key):
8499
"""Return the module with the specified name or index"""
85-
objs = self.api.GetModules()
86100
if isinstance(key, Module):
87101
return key
88102

103+
objs = self.api.GetModules()
104+
89105
if isinstance(key, int):
90106
return Module(self, objs[key])
91107

@@ -97,25 +113,50 @@ def get_module(self, key):
97113
raise Error("Invalid module name: ''".format(key))
98114
raise Error("Invalid index type: {}".format(type(key).__name__))
99115

100-
def types(self):
116+
@property
117+
def module_types(self):
101118
"""Return a list containing the name of all known module+types. These
102119
names can be used as input to Hive.add_module().
103120
"""
104-
return [ obj for obj in self.api.ModuleTypes ]
121+
return list(self.api.ModuleTypes)
105122

106-
def add_module(self, type, name=None):
123+
124+
def add_module(self, module_type, name=None):
107125
"""Create and return a new Hive.Module in the Hive.
108126
109127
Arguments:
110128
type: the name of a module type
111129
name: the name of the new module (default is None, i.e. use a generated name based on moduletype)
112130
"""
131+
if isinstance(module_type, str):
132+
for mt in self.module_types:
133+
if mt.ClassName == module_type:
134+
module_type = mt
135+
break
136+
else:
137+
raise ValueError(f"Unknown module type {module_type}")
138+
113139
if name is not None:
114-
type.set_InstanceName(name)
115-
obj = self.api.AddModule(type)
140+
module_type.set_InstanceName(name)
141+
obj = self.api.AddModule(module_type)
116142
return Module(self, obj)
117143

144+
def get_values(self, items, since=None):
145+
if not since:
146+
since = System.DateTime.MinValue
147+
itemIds = [i.item_id if isinstance(i, Item) else str(i) for i in items]
148+
handles = self.api.LookupItemHandles(itemIds)
118149

150+
h_out = System.Array[System.Int32]([])
151+
v_out = System.Array[System.Object]([])
152+
q_out = System.Array[System.UInt16]([])
153+
t_out = System.Array[System.DateTime]([])
154+
err_out = System.Array[System.Int32]([])
155+
check_out = System.Boolean(False)
156+
last_read=System.DateTime.Now
157+
158+
void, h, v, q, t, err, check, tor = self.api.ReadItems(since, handles, h_out, v_out, q_out, t_out, err_out, check_out, last_read)
159+
return [ItemVQT(itemIds[i], v[i], q[i], t[i]) for i in range(len(h))]
119160

120161
class Module:
121162
"""Class used to access a specific module in an ApisHive instance. The
@@ -127,7 +168,7 @@ def __init__(self, hive, api):
127168
self.api = api
128169

129170
def __str__(self):
130-
return self.name()
171+
return self.name
131172

132173
def __repr__(self):
133174
return "<Apis.Hive.Module: >".format(self)
@@ -138,15 +179,20 @@ def __len__(self):
138179
def __getitem__(self, key):
139180
return self.get_item(key)
140181

182+
def __delitem__(self, key):
183+
self.get_item(key).api.DeleteItem()
184+
141185
def __iter__(self):
142186
return self.api.GetItems()
143187

188+
@property
144189
def name(self):
145190
return self.api.Name
146191

192+
@property
147193
def items(self):
148194
"""Return a list containing all the items in this module"""
149-
return [ Item(self, obj) for obj in self.api.GetItems() ]
195+
return [ Item(self, obj) for obj in list(self.api.GetItems()) ]
150196

151197
def get_item(self, key):
152198
"""Return the item with the specified name or index"""
@@ -164,6 +210,33 @@ def get_item(self, key):
164210

165211
raise Error("Invalid index type: {}".format(type(key).__name__))
166212

213+
@property
214+
def item_types(self):
215+
"""Return the available item types for this module"""
216+
return list(self.api.GetItemTypes())
217+
218+
219+
def add_item(self, item_type, item_name):
220+
"""Add a new item to the hive"""
221+
if isinstance(item_type, str):
222+
for it in self.item_types:
223+
if it.Name==item_type:
224+
item_type = it
225+
break
226+
else:
227+
raise ValueError(f"unknown item type {item_type}")
228+
229+
template = it.GetNewItemTemplate(item_name)
230+
item, item_error, attr_error, check = self.api.AddItems([template], None, None, None)
231+
if check:
232+
for i, a_e in enumerate(attr_error):
233+
if a_e > 0:
234+
t_attr = template.Attributes[i]
235+
raise Error(f"Error setting {t_attr.Name}")
236+
237+
return Item(self, item[0])
238+
239+
@property
167240
def properties(self):
168241
return [ Property(self, obj) for obj in self.api.GetProperties() ]
169242

@@ -201,48 +274,61 @@ def update(self, value):
201274

202275
class Item:
203276
def __init__(self, module, api):
204-
self.module = module
205-
self.api = api
277+
super().__setattr__('module', module)
278+
super().__setattr__('api', api)
279+
# self.module = module
280+
# self.api = api
206281

207282
def __str__(self):
208-
return self.name()
283+
return self.name
209284

210285
def __repr__(self):
211-
return "<Apis.Hive.Module.Property: >".format(self)
286+
return f"<Apis.Hive.Module.Item: {self.name}>"
212287

213288
def __len__(self):
214-
return len(self.api.GetAttributes())
289+
return len(self.attr)
215290

216291
def __getitem__(self, key):
217-
return self.get_attr(key)
292+
return self.get_attr(key).value
293+
294+
__getattr__ = __getitem__
295+
296+
def __setitem__(self, key, value):
297+
attr = self.get_attr(key)
298+
attr.value = value
299+
300+
def __setattr__(self, key, value):
301+
try:
302+
attr = self.get_attr(key)
303+
attr.value = value
304+
305+
except Error:
306+
super().__setattr__(key, value)
218307

219308
def __iter__(self):
220309
return self.api.GetAttributes()
221310

311+
@property
222312
def name(self):
223313
return self.api.Name
224314

225-
def value(self):
226-
return self['Value'].value()
315+
@property
316+
def item_id(self):
317+
return self.api.ItemID
227318

228-
def attrs(self):
229-
return [ Attr(self, obj) for obj in self.api.GetAttributes() ]
230319

231320
def get_attr(self, key):
232321
"""Return the attr with the specified name or index"""
233322
if isinstance(key, Attr):
234323
return key
235-
324+
if isinstance(key, str):
325+
for attr in self.api.GetAttributes():
326+
if attr.Name == key:
327+
return Attr(self, attr)
236328
if isinstance(key, int):
237329
return Attr(self, self.api.GetAttributes()[key])
330+
raise Error(f"Invalid index: {repr(key)}")
238331

239-
if isinstance(key, str):
240-
for obj in self.api.GetAttributes():
241-
if obj.Name == key:
242-
return Attr(self, obj)
243-
raise Error("Invalid attribute name: '{}'".format(key))
244-
245-
raise Error("Invalid index type: {}".format(type(key).__name__))
246332

247333

248334
class Attr:
@@ -251,13 +337,51 @@ def __init__(self, item, api):
251337
self.api = api
252338

253339
def __str__(self):
254-
return "{}={}".format(self.name(), self.value())
340+
return "{}={}".format(self.name, self.value)
255341

256342
def __repr__(self):
257343
return "<Apis.Hive.Module.Attr: {}>".format(self)
258344

345+
@property
259346
def name(self):
260347
return self.api.Name
261348

262-
def value(self):
263-
return self.api.Value
349+
@property
350+
def flag(self):
351+
return self.api.Flag
352+
353+
354+
355+
def get_value(self):
356+
v = self.api.Value
357+
if self.flag & AttrFlags.Enumerated:
358+
attr_enum = self.api.GetEnumeration()
359+
for i,val in enumerate(attr_enum.Values):
360+
if val==v:
361+
return attr_enum.Names[i]
362+
raise Error(f"Enumerated property not found")
363+
return v
364+
365+
def set_value(self, value):
366+
if self.flag & AttrFlags.ReadOnly:
367+
print(f'should fail, {self.flag}')
368+
raise AttributeError(f"Attribute {self.name} on {self.item} is read only")
369+
370+
if self.flag & AttrFlags.Enumerated:
371+
attr_enum = self.api.GetEnumeration()
372+
for i,val in enumerate(attr_enum.Names):
373+
if str(val)==value:
374+
self.api.Value = attr_enum.Values[i]
375+
break
376+
else:
377+
raise Error(f"Enumerated property not found")
378+
else:
379+
try:
380+
self.api.Value = value
381+
except Exception as e:
382+
raise Error(f"Exception from Apis {e}")
383+
384+
385+
value = property(get_value, set_value, doc="Access the property value")
386+
387+

requirements.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
# do not add anything here. See setup.py
2-
-e .

tests/test_pyprediktoredgeclient.py

Whitespace-only changes.

0 commit comments

Comments
 (0)