unisi 0.2.7__py3-none-any.whl → 0.2.9__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/__init__.py +2 -2
- unisi/autotest.py +1 -0
- unisi/common.py +24 -0
- unisi/containers.py +37 -30
- unisi/dbunits.py +1 -0
- unisi/graphs.py +4 -4
- unisi/kdb.py +1 -0
- unisi/llmrag.py +1 -0
- unisi/multimon.py +1 -0
- unisi/proxy.py +1 -0
- unisi/reloader.py +1 -0
- unisi/server.py +61 -0
- unisi/tables.py +2 -1
- unisi/units.py +37 -7
- unisi/users.py +39 -80
- unisi/utils.py +5 -5
- unisi/voicecom.py +292 -0
- unisi/web/css/{882.d3c09c5d.css → 450.f5cbf6d1.css} +1 -1
- unisi/web/index.html +1 -1
- unisi/web/js/450.ea87a6d5.js +1 -0
- unisi/web/js/{app.57a98df1.js → app.7317dfbe.js} +1 -1
- {unisi-0.2.7.dist-info → unisi-0.2.9.dist-info}/METADATA +3 -4
- {unisi-0.2.7.dist-info → unisi-0.2.9.dist-info}/RECORD +26 -25
- {unisi-0.2.7.dist-info → unisi-0.2.9.dist-info}/WHEEL +1 -1
- unisi/web/js/882.aa6d1721.js +0 -1
- {unisi-0.2.7.dist-info → unisi-0.2.9.dist-info}/entry_points.txt +0 -0
- {unisi-0.2.7.dist-info → unisi-0.2.9.dist-info}/licenses/LICENSE +0 -0
unisi/__init__.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
from .utils import *
|
2
2
|
from .units import *
|
3
|
-
from .users import User
|
4
|
-
from .server import start
|
3
|
+
from .users import User
|
4
|
+
from .server import start, handle, context_user, context_screen
|
5
5
|
from .tables import *
|
6
6
|
from .containers import *
|
7
7
|
from .proxy import *
|
unisi/autotest.py
CHANGED
unisi/common.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
import jsonpickle, inspect, asyncio
|
2
3
|
|
3
4
|
UpdateScreen = True
|
@@ -48,6 +49,12 @@ class ReceivedMessage(ArgObject):
|
|
48
49
|
self.__dict__.update(kwargs)
|
49
50
|
def __str__(self):
|
50
51
|
return f'{self.block}/{self.element}->{self.event}({self.value})'
|
52
|
+
@property
|
53
|
+
def screen_type(self):
|
54
|
+
return self.block == 'root' and self.element is None
|
55
|
+
@property
|
56
|
+
def voice_type(self):
|
57
|
+
return self.block == 'voice' and self.element is None
|
51
58
|
|
52
59
|
def toJson(obj):
|
53
60
|
return jsonpickle.encode(obj,unpicklable = False)
|
@@ -58,6 +65,8 @@ def set_defaults(self, param_defaults : dict):
|
|
58
65
|
setattr(self, param, value)
|
59
66
|
|
60
67
|
def pretty4(name):
|
68
|
+
if name.startswith('_'):
|
69
|
+
name = name[1:]
|
61
70
|
pretty_name = name.replace('_',' ')
|
62
71
|
return pretty_name[0].upper() + pretty_name[1:]
|
63
72
|
|
@@ -147,6 +156,21 @@ def Answer(type, message, result):
|
|
147
156
|
ms.message = message
|
148
157
|
return ms
|
149
158
|
|
159
|
+
def delete_unit(units, name):
|
160
|
+
"""Deletes a unit with the given name from a nested list of units.
|
161
|
+
Returns True if the unit was found and deleted, False otherwise.
|
162
|
+
"""
|
163
|
+
for i in range(len(units)):
|
164
|
+
if isinstance(units[i], list | tuple):
|
165
|
+
if delete_unit(units[i], name):
|
166
|
+
if not units[i]: # if the sublist became empty after deletion
|
167
|
+
units.pop(i) # remove sublist also
|
168
|
+
return True
|
169
|
+
elif units[i].name == name:
|
170
|
+
units.pop(i)
|
171
|
+
return True
|
172
|
+
return False
|
173
|
+
|
150
174
|
|
151
175
|
|
152
176
|
|
unisi/containers.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
from .units import *
|
2
|
-
from .common import pretty4, flatten
|
3
|
+
from .common import pretty4, flatten, delete_unit
|
3
4
|
from numbers import Number
|
4
5
|
|
5
6
|
class Block(Unit):
|
@@ -33,7 +34,7 @@ class Block(Unit):
|
|
33
34
|
elif isinstance(elem.llm, dict):
|
34
35
|
if elem.type != 'table':
|
35
36
|
raise AttributeError(f'{elem.name} llm parameter is a dictionary only for tables, not for {elem.type}!')
|
36
|
-
elem.
|
37
|
+
elem._llm_dependencies = {fld: (deps if isinstance(deps, list | bool) else [deps]) for fld, deps in elem.llm.items()}
|
37
38
|
elem.llm = True
|
38
39
|
continue
|
39
40
|
else:
|
@@ -42,12 +43,18 @@ class Block(Unit):
|
|
42
43
|
elem.llm = exactly
|
43
44
|
for dependency in dependencies:
|
44
45
|
dependency.add_changed_handler(elem.emit)
|
45
|
-
elem.
|
46
|
+
elem._llm_dependencies = dependencies
|
46
47
|
else:
|
47
48
|
elem.llm = None
|
48
49
|
print(f'Empty dependency list for llm calculation for {elem.name} {elem.type}!')
|
49
|
-
|
50
|
-
|
50
|
+
|
51
|
+
user = Unishare.context_user()
|
52
|
+
if hasattr(self,'closable'):
|
53
|
+
def close(*_):
|
54
|
+
delete_unit(user.screen.blocks, self.name)
|
55
|
+
self.close = close
|
56
|
+
|
57
|
+
self.set_reactivity(user)
|
51
58
|
|
52
59
|
def set_reactivity(self, user, override = False):
|
53
60
|
if user:
|
@@ -88,26 +95,26 @@ class ParamBlock(Block):
|
|
88
95
|
|
89
96
|
for param, val in params.items():
|
90
97
|
pretty_name = pretty4(param)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
98
|
+
match val:
|
99
|
+
case True | False:
|
100
|
+
el = Switch(pretty_name, val)
|
101
|
+
case str() | int() | float():
|
102
|
+
el = Edit(pretty_name, val)
|
103
|
+
case tuple() | list():
|
104
|
+
if len(val) != 2:
|
105
|
+
raise ValueError('Composite value has to contain the current value and options value!')
|
106
|
+
options = val[1]
|
107
|
+
if not isinstance(options, list | tuple | dict):
|
108
|
+
raise ValueError('Options value (the second parameter) has to be a list or tuple!')
|
109
|
+
if len(options) == 3 and all(map(lambda e: isinstance(e, Number), options)):
|
110
|
+
el = Range(pretty_name, val[0], options = options)
|
111
|
+
elif isinstance(options, list | tuple):
|
112
|
+
el = Select(pretty_name, val[0], options = options, type = 'select')
|
113
|
+
else:
|
114
|
+
el = Tree(pretty_name, val[0], options = options)
|
115
|
+
case _:
|
116
|
+
raise ValueError(f'The {param} value {val} is not supported. Look at ParamBlock documentation!')
|
117
|
+
|
111
118
|
self.name2elem[param] = el
|
112
119
|
|
113
120
|
if cnt % row == 0:
|
@@ -129,9 +136,9 @@ class Dialog:
|
|
129
136
|
self.icon = icon
|
130
137
|
self.value = [[], *content] if content else []
|
131
138
|
|
132
|
-
class Screen:
|
133
|
-
def __init__(self, name
|
134
|
-
self.
|
135
|
-
self.
|
136
|
-
self.type = 'screen'
|
139
|
+
class Screen(Unit):
|
140
|
+
def __init__(self, name):
|
141
|
+
self._mark_changed = None
|
142
|
+
self.name = name
|
143
|
+
self.type = 'screen'
|
137
144
|
|
unisi/dbunits.py
CHANGED
unisi/graphs.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
from .units import *
|
2
3
|
from .tables import Table
|
3
4
|
from .containers import Block
|
@@ -77,11 +78,10 @@ def unit2image(unit):
|
|
77
78
|
class Net(Graph):
|
78
79
|
"""Graph of Units"""
|
79
80
|
replace4state = dict(nodes = '_nodes', edges = '_edges', value = '_value')
|
80
|
-
def __init__(self, name, topology = Topology(), **kwargs):
|
81
|
-
Unit.__init__(self, name, **kwargs)
|
82
|
-
if not hasattr(self, 'value'):
|
83
|
-
self.value = graph_default_value
|
81
|
+
def __init__(self, name, value = graph_default_value, topology = Topology(), **kwargs):
|
82
|
+
Unit.__init__(self, name, **kwargs)
|
84
83
|
self.type = 'graph'
|
84
|
+
self.value = value
|
85
85
|
self.topology = topology
|
86
86
|
self._inside_converter = False
|
87
87
|
changed_handler = getattr(self, 'changed', None)
|
unisi/kdb.py
CHANGED
unisi/llmrag.py
CHANGED
unisi/multimon.py
CHANGED
unisi/proxy.py
CHANGED
unisi/reloader.py
CHANGED
unisi/server.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
from aiohttp import web, WSMsgType
|
2
3
|
from .users import *
|
3
4
|
from pathlib import Path
|
@@ -6,9 +7,69 @@ from .autotest import recorder, run_tests
|
|
6
7
|
from .common import *
|
7
8
|
from.llmrag import setup_llmrag
|
8
9
|
from .dbunits import dbupdates
|
10
|
+
from .kdb import Database
|
9
11
|
from config import port, upload_dir
|
10
12
|
import traceback, json
|
11
13
|
|
14
|
+
def context_user():
|
15
|
+
return context_object(User)
|
16
|
+
|
17
|
+
def context_screen():
|
18
|
+
user = context_user()
|
19
|
+
return user.screen if user else None
|
20
|
+
|
21
|
+
def message_logger(str, type = 'error'):
|
22
|
+
user = context_user()
|
23
|
+
user.log(str, type)
|
24
|
+
|
25
|
+
Unishare.context_user = context_user
|
26
|
+
Unishare.message_logger = message_logger
|
27
|
+
User.type = User
|
28
|
+
|
29
|
+
if config.db_dir:
|
30
|
+
Unishare.db = Database(config.db_dir, message_logger)
|
31
|
+
|
32
|
+
def make_user(request):
|
33
|
+
session = f'{request.remote}-{User.count}'
|
34
|
+
if requested_connect := request.query_string if config.share else None:
|
35
|
+
user = Unishare.sessions.get(requested_connect, None)
|
36
|
+
if not user:
|
37
|
+
error = f'Session id "{requested_connect}" is unknown. Connection refused!'
|
38
|
+
with logging_lock:
|
39
|
+
logging.error(error)
|
40
|
+
return None, Error(error)
|
41
|
+
user = User.type(session, user)
|
42
|
+
ok = user.screens
|
43
|
+
elif config.mirror and User.count:
|
44
|
+
user = User.type(session, User.last_user)
|
45
|
+
ok = user.screens
|
46
|
+
elif not User.count:
|
47
|
+
user = User.last_user
|
48
|
+
user.session = session
|
49
|
+
user.monitor(session)
|
50
|
+
ok = True
|
51
|
+
else:
|
52
|
+
user = User.type(session)
|
53
|
+
ok = user.load()
|
54
|
+
|
55
|
+
User.count += 1
|
56
|
+
Unishare.sessions[session] = user
|
57
|
+
return user, ok
|
58
|
+
|
59
|
+
def handle(elem, event):
|
60
|
+
def h(fn):
|
61
|
+
key = elem, event
|
62
|
+
handler_map = User.last_user.__handlers__
|
63
|
+
func = handler_map.get(key, None)
|
64
|
+
if func:
|
65
|
+
handler_map[key] = compose_handlers(func, fn)
|
66
|
+
else:
|
67
|
+
handler_map[key] = fn
|
68
|
+
return fn
|
69
|
+
return h
|
70
|
+
|
71
|
+
Unishare.handle = handle
|
72
|
+
|
12
73
|
async def post_handler(request):
|
13
74
|
reader = await request.multipart()
|
14
75
|
field = await reader.next()
|
unisi/tables.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
from .units import Unit
|
2
3
|
from .common import *
|
3
4
|
from .dbunits import Dblist, dbupdates
|
@@ -199,7 +200,7 @@ class Table(Unit):
|
|
199
200
|
tasks = []
|
200
201
|
for index in self.selected_list:
|
201
202
|
values = {field: value for field, value in zip(self.headers, self.rows[index]) if value}
|
202
|
-
for fld, deps in self.
|
203
|
+
for fld, deps in self._llm_dependencies.items():
|
203
204
|
if fld not in values:
|
204
205
|
if deps is True:
|
205
206
|
context = values
|
unisi/units.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
from .common import *
|
2
3
|
from .llmrag import get_property
|
3
4
|
|
@@ -22,13 +23,26 @@ class ChangedProxy:
|
|
22
23
|
elif not callable(value) and not isinstance(value, atomics):
|
23
24
|
return ChangedProxy(value, self)
|
24
25
|
return value
|
26
|
+
|
27
|
+
def __setattr__(self, name, value):
|
28
|
+
if name in ('_obj', '_unit'):
|
29
|
+
super().__setattr__(name, value)
|
30
|
+
else:
|
31
|
+
self._obj.__setattr__(name, value)
|
32
|
+
self._unit._mark_changed()
|
25
33
|
|
26
34
|
def __setitem__(self, key, value):
|
27
35
|
self._obj[key] = value
|
28
36
|
self._unit._mark_changed ()
|
29
37
|
|
30
38
|
def __getitem__(self, key):
|
31
|
-
|
39
|
+
value = self._obj[key]
|
40
|
+
if not callable(value) and not isinstance(value, atomics):
|
41
|
+
value = ChangedProxy(value, self._unit)
|
42
|
+
return value
|
43
|
+
|
44
|
+
def __eq__(self, other):
|
45
|
+
return self._obj.__eq__(other._obj) if isinstance(other, ChangedProxy) else self._obj.__eq__(other)
|
32
46
|
|
33
47
|
def __delitem__(self, key):
|
34
48
|
del self._obj[key]
|
@@ -42,6 +56,16 @@ class ChangedProxy:
|
|
42
56
|
return len(self._obj)
|
43
57
|
except TypeError:
|
44
58
|
return 0
|
59
|
+
|
60
|
+
def __hash__(self):
|
61
|
+
return hash(self._obj)
|
62
|
+
|
63
|
+
def __iadd__(self, other):
|
64
|
+
if isinstance(self._obj, list):
|
65
|
+
self.extend(other)
|
66
|
+
return self # Important: __iadd__ must return self
|
67
|
+
|
68
|
+
raise TypeError(f"Unsupported operand type for += with '{type(self._obj).__name__}'")
|
45
69
|
|
46
70
|
def __getstate__(self):
|
47
71
|
return self._obj
|
@@ -81,9 +105,7 @@ class Unit:
|
|
81
105
|
|
82
106
|
def __setattr__(self, name, value):
|
83
107
|
#it is correct condition order
|
84
|
-
if name != "
|
85
|
-
if name != "__dict__" and not isinstance(value, atomics) and not callable(value):
|
86
|
-
value = ChangedProxy(value, self)
|
108
|
+
if name[0] != "_" and self._mark_changed:
|
87
109
|
self._mark_changed(name, value)
|
88
110
|
super().__setattr__(name, value)
|
89
111
|
|
@@ -103,7 +125,13 @@ class Unit:
|
|
103
125
|
def delattr(self, attr):
|
104
126
|
if hasattr(self, attr):
|
105
127
|
delattr(self, attr)
|
106
|
-
|
128
|
+
|
129
|
+
def __eq__(self, other):
|
130
|
+
return super().__eq__(other._obj) if isinstance(other, ChangedProxy) else super().__eq__(other)
|
131
|
+
|
132
|
+
def __hash__(self):
|
133
|
+
return super().__hash__()
|
134
|
+
|
107
135
|
@property
|
108
136
|
def compact_view(self) -> str:
|
109
137
|
"""reduce for external (llm) using if required"""
|
@@ -112,9 +140,9 @@ class Unit:
|
|
112
140
|
async def emit(self, *_ ):
|
113
141
|
"""calcute value by system llm, can be used as a handler"""
|
114
142
|
if Unishare.llm_model and (exactly := getattr(self, 'llm', None)) is not None:
|
115
|
-
elems = [e.compact_view for e in self.
|
143
|
+
elems = [e.compact_view for e in self._llm_dependencies if e.value != '' and e.value is not None]
|
116
144
|
#exactly is requirment that all elements have to have valid value
|
117
|
-
if not exactly or len(elems) == len(self.
|
145
|
+
if not exactly or len(elems) == len(self._llm_dependencies):
|
118
146
|
context = ','.join(elems)
|
119
147
|
self.value = await get_property(self.name, context, self.type, options = getattr(self, 'options', None))
|
120
148
|
return self
|
@@ -153,6 +181,7 @@ def smart_complete(lst, min_input_length = 0, max_output_length = 20):
|
|
153
181
|
class Edit(Unit):
|
154
182
|
def __init__(self, name, *args, **kwargs):
|
155
183
|
super().__init__(name, *args, **kwargs)
|
184
|
+
self.x = -1
|
156
185
|
has_value = hasattr(self,'value')
|
157
186
|
if 'type' not in kwargs:
|
158
187
|
if has_value:
|
@@ -263,6 +292,7 @@ class Tree(Unit):
|
|
263
292
|
class TextArea(Unit):
|
264
293
|
def __init__(self,name, *args, **kwargs):
|
265
294
|
super().__init__(name, *args, **kwargs)
|
295
|
+
self.x = -1
|
266
296
|
self.type = 'text'
|
267
297
|
|
268
298
|
|
unisi/users.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
from .utils import *
|
2
3
|
from .units import *
|
3
4
|
from .common import *
|
5
|
+
from .voicecom import VoiceCom
|
4
6
|
from .containers import Dialog, Screen
|
5
7
|
from .multimon import notify_monitor, logging_lock, run_external_process
|
6
|
-
from .kdb import Database
|
7
8
|
from .dbunits import dbshare, dbupdates
|
8
9
|
import sys, asyncio, logging, importlib
|
9
10
|
|
@@ -17,6 +18,7 @@ class User:
|
|
17
18
|
self.active_dialog = None
|
18
19
|
self.last_message = None
|
19
20
|
self.changed_units = set()
|
21
|
+
self.voice = None
|
20
22
|
|
21
23
|
if share:
|
22
24
|
self.screens = share.screens
|
@@ -53,7 +55,7 @@ class User:
|
|
53
55
|
if user is not self and screen is user.screen_module])
|
54
56
|
|
55
57
|
async def reflect(self, message, result):
|
56
|
-
if self.reflections and not
|
58
|
+
if self.reflections and not message.screen_type:
|
57
59
|
if result:
|
58
60
|
await self.broadcast(result)
|
59
61
|
if message:
|
@@ -77,7 +79,7 @@ class User:
|
|
77
79
|
module.user = self
|
78
80
|
|
79
81
|
spec.loader.exec_module(module)
|
80
|
-
screen = Screen(getattr(module, 'name', ''))
|
82
|
+
screen = Screen(getattr(module, 'name', ''))
|
81
83
|
#set system vars
|
82
84
|
for var, val in screen.defaults.items():
|
83
85
|
setattr(screen, var, getattr(module, var, val))
|
@@ -87,22 +89,23 @@ class User:
|
|
87
89
|
screen.toolbar += User.toolbar
|
88
90
|
else:
|
89
91
|
screen.toolbar = User.toolbar
|
90
|
-
|
92
|
+
screen.set_reactivity(self)
|
93
|
+
module.screen = screen#ChangedProxy(screen, screen)
|
91
94
|
return module
|
92
95
|
|
93
96
|
async def delete(self):
|
94
97
|
uss = Unishare.sessions
|
95
98
|
if uss and uss.get(self.session):
|
96
|
-
del uss[self.session]
|
97
|
-
|
99
|
+
del uss[self.session]
|
98
100
|
if self.reflections: #reflections is common array
|
99
101
|
if len(self.reflections) == 2:
|
100
102
|
self.reflections.clear() #1 element in user.reflections has no sense
|
101
103
|
else:
|
102
104
|
self.reflections.remove(self)
|
103
|
-
|
104
105
|
if notify_monitor:
|
105
106
|
await notify_monitor('-', self.session, self.last_message)
|
107
|
+
if config.share:
|
108
|
+
self.log(f'User is disconnected, session: {self.session}', type = 'info')
|
106
109
|
|
107
110
|
def set_clean(self):
|
108
111
|
#remove user modules from sys
|
@@ -143,7 +146,7 @@ class User:
|
|
143
146
|
def screen(self):
|
144
147
|
return self.screen_module.screen
|
145
148
|
|
146
|
-
def set_screen(self,name):
|
149
|
+
def set_screen(self,name):
|
147
150
|
return asyncio.run(self.process(ArgObject(block = 'root', element = None, value = name)))
|
148
151
|
|
149
152
|
async def result4message(self, message):
|
@@ -197,6 +200,8 @@ class User:
|
|
197
200
|
else:
|
198
201
|
for bl in flatten(self.blocks):
|
199
202
|
if bl.name == blname:
|
203
|
+
if not elname:
|
204
|
+
return bl
|
200
205
|
for c in flatten(bl.value):
|
201
206
|
if c.name == elname:
|
202
207
|
return c
|
@@ -213,9 +218,10 @@ class User:
|
|
213
218
|
return ['toolbar', e.name]
|
214
219
|
|
215
220
|
def prepare_result(self, raw):
|
216
|
-
|
217
|
-
|
218
|
-
|
221
|
+
reload_screen = self.screen in self.changed_units
|
222
|
+
if reload_screen or raw is True or raw == Redesign:
|
223
|
+
self.screen.reload = reload_screen or raw == Redesign
|
224
|
+
raw = self.screen
|
219
225
|
else:
|
220
226
|
match raw:
|
221
227
|
case None:
|
@@ -240,12 +246,15 @@ class User:
|
|
240
246
|
|
241
247
|
async def process(self, message):
|
242
248
|
screen_change_message = message.screen and self.screen.name != message.screen
|
243
|
-
if screen_change_message or
|
249
|
+
if screen_change_message or message.screen_type:
|
244
250
|
for s in self.screens:
|
245
251
|
if s.name == message.value:
|
246
|
-
self.screen_module = s
|
252
|
+
self.screen_module = s
|
247
253
|
if screen_change_message:
|
248
254
|
break
|
255
|
+
if self.voice:
|
256
|
+
self.voice.set_screen(s)
|
257
|
+
self.voice.start()
|
249
258
|
if getattr(s.screen,'prepare', None):
|
250
259
|
s.screen.prepare()
|
251
260
|
return True
|
@@ -253,14 +262,23 @@ class User:
|
|
253
262
|
error = f'Unknown screen name: {message.value}'
|
254
263
|
self.log(error)
|
255
264
|
return Error(error)
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
265
|
+
elif message.voice_type:
|
266
|
+
if not self.voice:
|
267
|
+
self.voice = VoiceCom(self)
|
268
|
+
if message.event == 'listen':
|
269
|
+
if message.value:
|
270
|
+
self.voice.start()
|
271
|
+
else:
|
272
|
+
self.voice.stop()
|
273
|
+
else:
|
274
|
+
self.voice.process_word(message.value)
|
275
|
+
else:
|
276
|
+
elem = self.find_element(message)
|
277
|
+
if elem:
|
278
|
+
return await self.process_element(elem, message)
|
279
|
+
error = f'Element {message.block}/{message.element} does not exist!'
|
280
|
+
self.log(error)
|
281
|
+
return Error(error)
|
264
282
|
|
265
283
|
async def process_element(self, elem, message):
|
266
284
|
event = message.event
|
@@ -340,62 +358,3 @@ class User:
|
|
340
358
|
sync_calls.append(user.send(update4user))
|
341
359
|
dbupdates.clear()
|
342
360
|
await asyncio.gather(*sync_calls)
|
343
|
-
|
344
|
-
def context_user():
|
345
|
-
return context_object(User)
|
346
|
-
|
347
|
-
def context_screen():
|
348
|
-
user = context_user()
|
349
|
-
return user.screen if user else None
|
350
|
-
|
351
|
-
def message_logger(str, type = 'error'):
|
352
|
-
user = context_user()
|
353
|
-
user.log(str, type)
|
354
|
-
|
355
|
-
Unishare.context_user = context_user
|
356
|
-
Unishare.message_logger = message_logger
|
357
|
-
User.type = User
|
358
|
-
|
359
|
-
if config.db_dir:
|
360
|
-
Unishare.db = Database(config.db_dir, message_logger)
|
361
|
-
|
362
|
-
def make_user(request):
|
363
|
-
session = f'{request.remote}-{User.count}'
|
364
|
-
if requested_connect := request.query_string if config.share else None:
|
365
|
-
user = Unishare.sessions.get(requested_connect, None)
|
366
|
-
if not user:
|
367
|
-
error = f'Session id "{requested_connect}" is unknown. Connection refused!'
|
368
|
-
with logging_lock:
|
369
|
-
logging.error(error)
|
370
|
-
return None, Error(error)
|
371
|
-
user = User.type(session, user)
|
372
|
-
ok = user.screens
|
373
|
-
elif config.mirror and User.count:
|
374
|
-
user = User.type(session, User.last_user)
|
375
|
-
ok = user.screens
|
376
|
-
elif not User.count:
|
377
|
-
user = User.last_user
|
378
|
-
user.session = session
|
379
|
-
user.monitor(session)
|
380
|
-
ok = True
|
381
|
-
else:
|
382
|
-
user = User.type(session)
|
383
|
-
ok = user.load()
|
384
|
-
|
385
|
-
User.count += 1
|
386
|
-
Unishare.sessions[session] = user
|
387
|
-
return user, ok
|
388
|
-
|
389
|
-
def handle(elem, event):
|
390
|
-
def h(fn):
|
391
|
-
key = elem, event
|
392
|
-
handler_map = User.last_user.__handlers__
|
393
|
-
func = handler_map.get(key, None)
|
394
|
-
if func:
|
395
|
-
handler_map[key] = compose_handlers(func, fn)
|
396
|
-
else:
|
397
|
-
handler_map[key] = fn
|
398
|
-
return fn
|
399
|
-
return h
|
400
|
-
|
401
|
-
Unishare.handle = handle
|
unisi/utils.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
import os, platform, requests, logging
|
2
3
|
from .common import set_defaults
|
3
4
|
from .containers import Screen
|
@@ -41,7 +42,8 @@ set_defaults(config, dict(
|
|
41
42
|
froze_time= None,
|
42
43
|
monitor_tick = 0.005,
|
43
44
|
pool = None,
|
44
|
-
db_dir = None
|
45
|
+
db_dir = None,
|
46
|
+
lang = 'en-US'
|
45
47
|
))
|
46
48
|
|
47
49
|
Screen.defaults = dict(
|
@@ -51,16 +53,14 @@ Screen.defaults = dict(
|
|
51
53
|
header = config.appname,
|
52
54
|
toolbar = [],
|
53
55
|
order = 0,
|
54
|
-
reload = config.hot_reload
|
56
|
+
reload = config.hot_reload,
|
57
|
+
lang = config.lang
|
55
58
|
)
|
56
59
|
|
57
60
|
if config.froze_time == 0:
|
58
61
|
print('froze_time in config.py can not be 0!')
|
59
62
|
config.froze_time = None
|
60
63
|
|
61
|
-
def is_screen_switch(message):
|
62
|
-
return message and message.block == 'root' and message.element is None
|
63
|
-
|
64
64
|
def filename2url(fn):
|
65
65
|
if fn[0] == '/' or fn[1] == ':': #if full path
|
66
66
|
fn = fn[len(app_dir):]
|