unisi 0.1.12__py3-none-any.whl → 0.1.14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
unisi/common.py CHANGED
@@ -1,4 +1,7 @@
1
- import jsonpickle
1
+ import jsonpickle, inspect
2
+
3
+ UpdateScreen = True
4
+ Redesign = 2
2
5
 
3
6
  def flatten(*arr):
4
7
  for a in arr:
@@ -6,22 +9,135 @@ def flatten(*arr):
6
9
  yield from flatten(*a)
7
10
  else:
8
11
  yield a
9
-
12
+
13
+ def compose_returns(*arr):
14
+ objs = set()
15
+ update_screen = False
16
+ for obj in flatten(*arr):
17
+ if obj is Redesign:
18
+ return obj
19
+ elif obj is True:
20
+ update_screen = True
21
+ elif obj is not None:
22
+ objs.add(obj)
23
+ if update_screen:
24
+ return True
25
+ if objs:
26
+ return list(objs)
27
+
28
+ def equal_dicts(dict1, dict2):
29
+ return dict1.keys() == dict2.keys() and all(dict1[key] == dict2[key] for key in dict1)
30
+
10
31
  class ArgObject:
11
32
  def __init__(self, **kwargs):
12
33
  self.__dict__.update(kwargs)
34
+ def __getattr__(self, _):
35
+ """return None for unknown props"""
36
+ return None
13
37
 
14
- class ReceivedMessage:
15
- def __init__(self, data):
16
- self.__dict__.update(data)
17
- self.screen = data.get('screen')
18
- self.value = data.get('value')
38
+ class ReceivedMessage(ArgObject):
39
+ def __init__(self, kwargs):
40
+ super().__init__(**kwargs)
19
41
  def __str__(self):
20
42
  return f'{self.block}/{self.element}->{self.event}({self.value})'
21
43
 
22
44
  def toJson(obj):
23
45
  return jsonpickle.encode(obj,unpicklable = False)
24
46
 
47
+ def set_defaults(self, param_defaults : dict):
48
+ for param, value in param_defaults.items():
49
+ if not hasattr(self, param):
50
+ setattr(self, param, value)
51
+
52
+ def pretty4(name):
53
+ pretty_name = name.replace('_',' ')
54
+ return pretty_name[0].upper() + pretty_name[1:]
55
+
56
+ def is_callable(obj):
57
+ return inspect.isfunction(obj) or inspect.ismethod(obj) or inspect.iscoroutine(obj) or callable(obj)
58
+
59
+ def context_object(target_type):
60
+ """
61
+ Finds the first argument of a specific type in the current function call stack.
62
+ """
63
+ frame = inspect.currentframe()
64
+ while frame:
65
+ args, _, _, values = inspect.getargvalues(frame)
66
+ if args and isinstance(values[args[0]], target_type):
67
+ return values[args[0]]
68
+ # Move to the previous frame in the call stack
69
+ frame = frame.f_back
70
+ return None
71
+
72
+ def get_default_args(func):
73
+ """
74
+ class F:
75
+ def example_function(a, b, c=10, d='hello'):
76
+ pass
77
+ f = F()
78
+ default_args = get_default_args(f.example_function)
79
+ print(default_args)
80
+ """
81
+ # Get the signature of the function
82
+ sig = inspect.signature(func)
83
+ # Dictionary to store arguments with their default values
84
+ defaults = {}
85
+ for name, param in sig.parameters.items():
86
+ if param.default != inspect.Parameter.empty:
87
+ defaults[name] = param.default
88
+ return defaults
89
+
90
+ references = ArgObject(context_user = None)
91
+
92
+ class Message:
93
+ def __init__(self, *gui_objects, user = None, type = 'update'):
94
+ self.type = type
95
+ if gui_objects:
96
+ self.updates = [{'data': gui} for gui in gui_objects]
97
+ if user:
98
+ self.fill_paths4(user)
99
+
100
+ def fill_paths4(self, user):
101
+ if hasattr(self, 'updates'):
102
+ invalid = []
103
+ for update in self.updates:
104
+ data = update["data"]
105
+ path = user.find_path(data)
106
+ if path:
107
+ update['path'] = path
108
+ else:
109
+ invalid.append(update)
110
+ user.log(f'Invalid element update {data.name}, type {data.type}.\n\
111
+ Such element not on the screen!')
112
+ for inv in invalid:
113
+ self.updates.remove(inv)
114
+
115
+ def contains(self, guiobj):
116
+ if hasattr(self, 'updates'):
117
+ for update in self.updates:
118
+ if guiobj is update['data']:
119
+ return True
120
+
121
+ def TypeMessage(type, value, *data, user = None):
122
+ message = Message(*data, user=user, type = type)
123
+ message.value = value
124
+ return message
125
+
126
+ def Warning(text, *data):
127
+ return TypeMessage('warning', text, *data)
128
+
129
+ def Error(text, *data):
130
+ return TypeMessage('error', text, *data)
131
+
132
+ def Info(text, *data):
133
+ return TypeMessage('info', text, *data)
134
+
135
+ def Answer(type, message, result):
136
+ ms = TypeMessage(type, result)
137
+ ms.message = message
138
+ return ms
139
+
140
+
25
141
 
26
142
 
27
143
 
unisi/containers.py CHANGED
@@ -1,4 +1,5 @@
1
- from .guielements import Gui, Range, Edit, Switch, Select, Tree
1
+ from .guielements import *
2
+ from .common import pretty4
2
3
  from numbers import Number
3
4
 
4
5
 
@@ -58,8 +59,7 @@ class ParamBlock(Block):
58
59
  cnt = 0
59
60
 
60
61
  for param, val in params.items():
61
- pretty_name = param.replace('_',' ')
62
- pretty_name = pretty_name[0].upper() + pretty_name[1:]
62
+ pretty_name = pretty4(param)
63
63
  t = type(val)
64
64
  if t == str or t == int or t == float:
65
65
  el = Edit(pretty_name, val)
unisi/dbelements.py ADDED
@@ -0,0 +1,155 @@
1
+ class Dblist:
2
+ def __init__(self, dbtable, init_list = None, cache = None):
3
+ self.cache = cache
4
+ self.limit = dbtable.limit
5
+ if cache is not None:
6
+ init_list = cache[:self.limit]
7
+ elif init_list is None:
8
+ raise AttributeError('init_list or cache has to be assigned!')
9
+
10
+ self.delta_list = {0 : init_list}
11
+ self.dbtable = dbtable
12
+ self.update = dict(type ='init', length = len(self),
13
+ limit = self.limit, data = init_list)
14
+
15
+ def get_delta_0(self):
16
+ return self.delta_list[0]
17
+
18
+ def __getattribute__(self, name):
19
+ if name == '__dict__':
20
+ return object.__getattribute__(self, 'update')
21
+ return object.__getattribute__(self, name)
22
+
23
+ def __getattr__(self, name):
24
+ return self.dbtable.limit if name == 'limit' else None
25
+
26
+ """ The methods causes invalid serialization!
27
+ def __iter__(self):
28
+ "Override the default iterator to provide custom behavior."
29
+ self._index = 0
30
+ return self
31
+
32
+ def __next__(self):
33
+ if self._index < len(self):
34
+ value = self[self._index]
35
+ self._index += 1
36
+ return value
37
+ else:
38
+ raise StopIteration
39
+ """
40
+
41
+ def __str__(self):
42
+ return f'\ndeltas: {self.delta_list}\nupdate: {self.update}'
43
+
44
+ def get_delta_chunk(self, index):
45
+ if index >= len(self):
46
+ return -1, None
47
+ delta_list = index // self.limit * self.limit
48
+
49
+ if self.cache is not None:
50
+ return delta_list, self.cache[delta_list:delta_list + self.limit]
51
+
52
+ lst = self.delta_list.get(delta_list)
53
+ if lst:
54
+ return delta_list, lst
55
+ lst = self.dbtable.read_rows(skip = delta_list)
56
+ self.delta_list[delta_list] = lst
57
+ return delta_list, lst
58
+
59
+ def __getitem__(self, index):
60
+ if self.cache is not None:
61
+ return self.cache[index]
62
+ delta_list, chunk = self.get_delta_chunk(index)
63
+ if chunk:
64
+ return chunk[index - delta_list]
65
+
66
+ def __setitem__(self, index, value):
67
+ if self.cache is not None:
68
+ self.cache[index] = value
69
+ else:
70
+ delta_list, chunk = self.get_delta_chunk(index)
71
+ if chunk:
72
+ chunk[index - delta_list] = value
73
+ self.update = dict(type = 'update', index = index, data = value)
74
+ self.dbtable.assign_row(value)
75
+
76
+ def clean_cache_from(self, delta_list):
77
+ """clear dirty delta_list cache"""
78
+ self.delta_list = {k: v for k, v in self.delta_list.items() if k < delta_list}
79
+
80
+ def __delitem__(self, index):
81
+ delta_list, chunk = self.get_delta_chunk(index)
82
+ if chunk:
83
+ self.dbtable.delete_row(index)
84
+ self.update = dict(type ='delete', index = index)
85
+ del chunk[index - delta_list]
86
+ limit = self.dbtable.limit
87
+ next_delta_list = delta_list + limit
88
+ while len(chunk) == limit - 1: #chunk was fully filled
89
+ next_list = self.delta_list.get(next_delta_list)
90
+ if next_list:
91
+ chunk.append(next_list[0])
92
+ chunk = next_list
93
+ next_delta_list += limit
94
+ del next_list[0]
95
+ else:
96
+ last = self.dbtable.read_rows(skip = next_delta_list - 1, limit = 1)[0]
97
+ chunk.append(last)
98
+ #clean dictionary from following elements
99
+ self.clean_cache_from(next_delta_list)
100
+ break
101
+
102
+ def __len__(self):
103
+ return len(self.cache) if self.cache is not None else self.dbtable.length
104
+
105
+ def append(self, value):
106
+ if self.cache is not None:
107
+ self.cache.append(value)
108
+ return value[-1]
109
+ index = len(self)
110
+ id = self.dbtable.append_row(value)
111
+ delta_list = index // self.limit * self.limit
112
+ list = self.delta_list.get(delta_list)
113
+ if list:
114
+ list.append(value)
115
+ self.update = dict(type = 'add', index = index, data = value)
116
+ return id
117
+
118
+ def extend(self, rows):
119
+ start = self.dbtable.length
120
+ rows = self.dbtable.append_rows(rows)
121
+ len_rows = len(rows)
122
+ delta_list_update = start
123
+
124
+ i_rows = 0
125
+ while len_rows > 0:
126
+ delta_list = start // self.limit * self.limit
127
+ list = self.delta_list.get(delta_list)
128
+ if list is None:
129
+ list = []
130
+ self.delta_list[delta_list] = list
131
+ can_fill = self.limit
132
+ else:
133
+ can_fill = self.limit - len(list)
134
+ if can_fill:
135
+ list.extend(rows[i_rows: i_rows + can_fill])
136
+
137
+ i_rows += can_fill
138
+ start += can_fill
139
+ len_rows -= can_fill
140
+ self.update = self.dbtable.get_init_list().update
141
+
142
+ def insert(self, index, value):
143
+ self.append(value)
144
+
145
+ def remove(self, value):
146
+ index = value[-1]
147
+ del self[index]
148
+
149
+ def pop(self, index = -1):
150
+ value = self[index]
151
+ del self[index]
152
+ return value
153
+
154
+ def clear(self):
155
+ self.dbtable.clear()
unisi/guielements.py CHANGED
@@ -1,3 +1,5 @@
1
+ from .common import set_defaults
2
+
1
3
  class Gui:
2
4
  def __init__(self, name, *args, **kwargs):
3
5
  self.name = name
@@ -20,7 +22,7 @@ class Gui:
20
22
  else:
21
23
  self.value = value
22
24
 
23
- Line = Gui("Line", type = 'line')
25
+ Line = Gui("__Line__", type = 'line')
24
26
 
25
27
  def smart_complete(lst, min_input_length = 0, max_output_length = 20):
26
28
  di = {it: it.lower() for it in lst}
@@ -105,10 +107,7 @@ class Video(Gui):
105
107
  def __init__(self,name, *args, **kwargs):
106
108
  super().__init__(name, *args, **kwargs)
107
109
  self.type = 'video'
108
- if not hasattr(self,'url'):
109
- self.url = self.name
110
- if not hasattr(self,'ratio'):
111
- self.ratio = None
110
+ set_defaults(self, {'url': self.name, 'ratio' : None})
112
111
 
113
112
  class Node:
114
113
  def __init__(self, name = '', color = '', size = 0, id = ''):
@@ -141,28 +140,17 @@ class Graph(Gui):
141
140
  def __init__(self, name, *args, **kwargs):
142
141
  super().__init__(name, *args, **kwargs)
143
142
  self.type='graph'
144
- if not hasattr(self,'value') or not self.value:
145
- self.value = graph_default_value
146
- if not hasattr(self, 'nodes'):
147
- self.nodes = []
148
- if not hasattr(self, 'edges'):
149
- self.edges = []
143
+ set_defaults(self,{'value': graph_default_value, 'nodes': [], 'edges': []})
150
144
 
151
145
  class Switch(Gui):
152
146
  def __init__(self,name, *args, **kwargs):
153
147
  super().__init__(name, *args, **kwargs)
154
- if not hasattr(self,'value'):
155
- self.value = False
156
- if not hasattr(self,'type'):
157
- self.type = 'switch'
148
+ set_defaults(self,{'value': False, 'type': 'switch'})
158
149
 
159
150
  class Select(Gui):
160
151
  def __init__(self,name, *args, **kwargs):
161
152
  super().__init__(name, *args, **kwargs)
162
- if not hasattr(self,'options'):
163
- self.options = []
164
- if not hasattr(self,'value'):
165
- self.value = None
153
+ set_defaults(self,{'options': [], 'value': None})
166
154
  if not hasattr(self, 'type'):
167
155
  self.type = 'select' if len(self.options) > 3 else 'radio'
168
156
 
@@ -170,10 +158,7 @@ class Tree(Gui):
170
158
  def __init__(self,name, *args, **kwargs):
171
159
  super().__init__(name, *args, **kwargs)
172
160
  self.type = 'tree'
173
- if not hasattr(self,'options'):
174
- self.options = {}
175
- if not hasattr(self,'value'):
176
- self.value = None
161
+ set_defaults(self,{'options': [], 'value': None})
177
162
 
178
163
  class TextArea(Gui):
179
164
  def __init__(self,name, *args, **kwargs):