1import re
2
3from omegaml.backends.virtualobj import VirtualObjectBackend
4
5
[docs]
6class VirtualObjectMixin(object):
7 """
8 process virtual objects
9
10 This checks if an object is a VirtualObject and if so
11 retrieves the handler and processes it.
12 """
13
14 def __init__(self):
15 self._vobj_meta = None
16
17 def _isvirtual(self, name):
18 self._vobj_meta = self.metadata(name)
19 return (self._vobj_meta is not None and
20 self._vobj_meta.kind == VirtualObjectBackend.KIND)
21
22 def _istool(self, name):
23 return name.startswith('tools/')
24
25 def _getvirtualobjfn(self, name, **kwargs):
26 virtualobjfn = super(VirtualObjectMixin, self).get(name, **kwargs)
27 if isinstance(virtualobjfn, type):
28 virtualobjfn = virtualobjfn()
29 return virtualobjfn
30
31 def _resolve_realname(self, name, kwargs):
32 # parse names in the format name{a=b,c=d} to name and update kwargs
33 if isinstance(name, str) and all(c in name for c in '{}'):
34 rx = r"(\w*=\w*)*"
35 real_name, fn_kwargs = name.split('{', 1)
36 fn_kwargs = fn_kwargs.split('}')[0]
37 matches = (v.split('=') for v in re.findall(rx, fn_kwargs) if v)
38 fn_kwargs = {
39 k: v for k, v in matches
40 }
41 kwargs.update(fn_kwargs)
42 name = real_name
43 return name, kwargs
44
45 def metadata(self, name, **kwargs):
46 dsname, _ = self._resolve_realname(name, kwargs)
47 return super().metadata(dsname)
48
49 def get(self, name, **kwargs):
50 # pass along some options to other mixins
51 raw = kwargs.get('raw')
52 should_version = self._model_version_applies(name)
53 raw = raw if raw is not None else should_version
54 is_tool = name.startswith('tools/')
55 name, kwargs = self._resolve_realname(name, kwargs)
56 if not raw and self._isvirtual(name) and not is_tool:
57 handler = self._getvirtualobjfn(name)
58 result = handler(method='get', meta=self._vobj_meta, store=self, **kwargs)
59 else:
60 result = super(VirtualObjectMixin, self).get(name, **kwargs)
61 return result
62
63 def put(self, obj, name, replace=False, attributes=None, **kwargs):
64 # pass along some options to other mixins
65 raw = kwargs.get('raw', False)
66 noversion = kwargs.get('noversion')
67 name, kwargs = self._resolve_realname(name, kwargs)
68 should_version = bool(noversion) if noversion is not None else self._model_version_applies(name)
69 raw = raw if raw is not None else should_version
70 if not should_version and not raw and not replace and self._isvirtual(name) and not self._istool(name):
71 result = self._getvirtualobjfn(name)(data=obj, method='put',
72 meta=self._vobj_meta, store=self, **kwargs)
73 else:
74 result = super(VirtualObjectMixin, self).put(obj, name, attributes=attributes, replace=replace, **kwargs)
75 return result
76
77 def drop(self, name, force=False, **kwargs):
78 version = kwargs.get('version')
79 should_version = version is not None or self._model_version_applies(name)
80 if not should_version and self._isvirtual(name):
81 try:
82 handler = self._getvirtualobjfn(name)
83 result = handler(method='drop', meta=self._vobj_meta, store=self, force=force)
84 except Exception as e:
85 if not force:
86 raise
87 else:
88 if not force:
89 return bool(result)
90 return super(VirtualObjectMixin, self).drop(name, force=force, **kwargs)