unisi 0.2.8__py3-none-any.whl → 0.3.1__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 +9 -6
- unisi/containers.py +32 -27
- unisi/dbunits.py +1 -0
- unisi/graphs.py +1 -0
- 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 +65 -7
- unisi/tables.py +1 -0
- unisi/units.py +38 -7
- unisi/users.py +29 -84
- unisi/utils.py +7 -4
- unisi/voicecom.py +276 -96
- unisi/web/css/{748.d3c09c5d.css → 364.9c989936.css} +1 -1
- unisi/web/index.html +1 -1
- unisi/web/js/364.72b2882d.js +1 -0
- unisi/web/js/app.99853ae7.js +1 -0
- {unisi-0.2.8.dist-info → unisi-0.3.1.dist-info}/METADATA +2 -4
- {unisi-0.2.8.dist-info → unisi-0.3.1.dist-info}/RECORD +26 -26
- {unisi-0.2.8.dist-info → unisi-0.3.1.dist-info}/WHEEL +1 -1
- unisi/web/js/748.213707d6.js +0 -1
- unisi/web/js/app.8df2e0ff.js +0 -1
- {unisi-0.2.8.dist-info → unisi-0.3.1.dist-info}/entry_points.txt +0 -0
- {unisi-0.2.8.dist-info → unisi-0.3.1.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
|
@@ -42,12 +43,6 @@ class ArgObject:
|
|
42
43
|
def __getattr__(self, _):
|
43
44
|
"""return None for unknown props"""
|
44
45
|
return None
|
45
|
-
|
46
|
-
class ReceivedMessage(ArgObject):
|
47
|
-
def __init__(self, kwargs):
|
48
|
-
self.__dict__.update(kwargs)
|
49
|
-
def __str__(self):
|
50
|
-
return f'{self.block}/{self.element}->{self.event}({self.value})'
|
51
46
|
@property
|
52
47
|
def screen_type(self):
|
53
48
|
return self.block == 'root' and self.element is None
|
@@ -55,6 +50,12 @@ class ReceivedMessage(ArgObject):
|
|
55
50
|
def voice_type(self):
|
56
51
|
return self.block == 'voice' and self.element is None
|
57
52
|
|
53
|
+
class ReceivedMessage(ArgObject):
|
54
|
+
def __init__(self, kwargs):
|
55
|
+
self.__dict__.update(kwargs)
|
56
|
+
def __str__(self):
|
57
|
+
return f'{self.block}/{self.element}->{self.event}({self.value})'
|
58
|
+
|
58
59
|
def toJson(obj):
|
59
60
|
return jsonpickle.encode(obj,unpicklable = False)
|
60
61
|
|
@@ -64,6 +65,8 @@ def set_defaults(self, param_defaults : dict):
|
|
64
65
|
setattr(self, param, value)
|
65
66
|
|
66
67
|
def pretty4(name):
|
68
|
+
if name.startswith('_'):
|
69
|
+
name = name[1:]
|
67
70
|
pretty_name = name.replace('_',' ')
|
68
71
|
return pretty_name[0].upper() + pretty_name[1:]
|
69
72
|
|
unisi/containers.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# Copyright © 2024 UNISI Tech. All rights reserved.
|
1
2
|
from .units import *
|
2
3
|
from .common import pretty4, flatten, delete_unit
|
3
4
|
from numbers import Number
|
@@ -50,8 +51,7 @@ class Block(Unit):
|
|
50
51
|
user = Unishare.context_user()
|
51
52
|
if hasattr(self,'closable'):
|
52
53
|
def close(*_):
|
53
|
-
delete_unit(user.screen.blocks, self.name)
|
54
|
-
return Redesign
|
54
|
+
delete_unit(user.screen.blocks, self.name)
|
55
55
|
self.close = close
|
56
56
|
|
57
57
|
self.set_reactivity(user)
|
@@ -80,6 +80,11 @@ class Block(Unit):
|
|
80
80
|
self.scaler.changed(self.scaler, sval)
|
81
81
|
self.set_reactivity(Unishare.context_user())
|
82
82
|
|
83
|
+
def find(self, elem: Unit | str):
|
84
|
+
for e in flatten(self.value):
|
85
|
+
if e == elem or e.name == elem:
|
86
|
+
return e
|
87
|
+
|
83
88
|
class ParamBlock(Block):
|
84
89
|
def __init__(self, name, *args, row = 3, **params):
|
85
90
|
""" does not need reactivity so Block init is not used"""
|
@@ -95,26 +100,26 @@ class ParamBlock(Block):
|
|
95
100
|
|
96
101
|
for param, val in params.items():
|
97
102
|
pretty_name = pretty4(param)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
103
|
+
match val:
|
104
|
+
case True | False:
|
105
|
+
el = Switch(pretty_name, val)
|
106
|
+
case str() | int() | float():
|
107
|
+
el = Edit(pretty_name, val)
|
108
|
+
case tuple() | list():
|
109
|
+
if len(val) != 2:
|
110
|
+
raise ValueError('Composite value has to contain the current value and options value!')
|
111
|
+
options = val[1]
|
112
|
+
if not isinstance(options, list | tuple | dict):
|
113
|
+
raise ValueError('Options value (the second parameter) has to be a list or tuple!')
|
114
|
+
if len(options) == 3 and all(map(lambda e: isinstance(e, Number), options)):
|
115
|
+
el = Range(pretty_name, val[0], options = options)
|
116
|
+
elif isinstance(options, list | tuple):
|
117
|
+
el = Select(pretty_name, val[0], options = options, type = 'select')
|
118
|
+
else:
|
119
|
+
el = Tree(pretty_name, val[0], options = options)
|
120
|
+
case _:
|
121
|
+
raise ValueError(f'The {param} value {val} is not supported. Look at ParamBlock documentation!')
|
122
|
+
|
118
123
|
self.name2elem[param] = el
|
119
124
|
|
120
125
|
if cnt % row == 0:
|
@@ -136,9 +141,9 @@ class Dialog:
|
|
136
141
|
self.icon = icon
|
137
142
|
self.value = [[], *content] if content else []
|
138
143
|
|
139
|
-
class Screen:
|
140
|
-
def __init__(self, name
|
141
|
-
self.
|
142
|
-
self.
|
143
|
-
self.type = 'screen'
|
144
|
+
class Screen(Unit):
|
145
|
+
def __init__(self, name):
|
146
|
+
self._mark_changed = None
|
147
|
+
self.name = name
|
148
|
+
self.type = 'screen'
|
144
149
|
|
unisi/dbunits.py
CHANGED
unisi/graphs.py
CHANGED
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,14 +1,75 @@
|
|
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
|
4
5
|
from .reloader import empty_app
|
5
6
|
from .autotest import recorder, run_tests
|
6
7
|
from .common import *
|
7
|
-
from.llmrag import setup_llmrag
|
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()
|
@@ -21,7 +82,6 @@ async def post_handler(request):
|
|
21
82
|
break
|
22
83
|
size += len(chunk)
|
23
84
|
f.write(chunk)
|
24
|
-
|
25
85
|
return web.Response(text=filename)
|
26
86
|
|
27
87
|
async def static_serve(request):
|
@@ -34,14 +94,12 @@ async def static_serve(request):
|
|
34
94
|
file_path = None
|
35
95
|
#unmask win path
|
36
96
|
if rpath.startswith('/') and rpath[2] == ':':
|
37
|
-
rpath = rpath[1:]
|
38
|
-
|
39
|
-
for dir in dirs:
|
97
|
+
rpath = rpath[1:]
|
98
|
+
for dir in config.public_dirs:
|
40
99
|
if rpath.startswith(dir):
|
41
100
|
if os.path.exists(rpath):
|
42
101
|
file_path = Path(rpath)
|
43
|
-
break
|
44
|
-
|
102
|
+
break
|
45
103
|
return web.FileResponse(file_path) if file_path else web.HTTPNotFound()
|
46
104
|
|
47
105
|
async def websocket_handler(request):
|
unisi/tables.py
CHANGED
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
|
@@ -49,6 +73,7 @@ class ChangedProxy:
|
|
49
73
|
atomics = (int, float, complex, bool, str, bytes, ChangedProxy, type(None))
|
50
74
|
|
51
75
|
class Unit:
|
76
|
+
action_list = set(['complete', 'update', 'changed','delete','append', 'modify', 'complete'])
|
52
77
|
def __init__(self, name, *args, **kwargs):
|
53
78
|
self._mark_changed = None
|
54
79
|
self.name = name
|
@@ -81,9 +106,7 @@ class Unit:
|
|
81
106
|
|
82
107
|
def __setattr__(self, name, value):
|
83
108
|
#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)
|
109
|
+
if name[0] != "_" and self._mark_changed:
|
87
110
|
self._mark_changed(name, value)
|
88
111
|
super().__setattr__(name, value)
|
89
112
|
|
@@ -103,7 +126,13 @@ class Unit:
|
|
103
126
|
def delattr(self, attr):
|
104
127
|
if hasattr(self, attr):
|
105
128
|
delattr(self, attr)
|
106
|
-
|
129
|
+
|
130
|
+
def __eq__(self, other):
|
131
|
+
return super().__eq__(other._obj) if isinstance(other, ChangedProxy) else super().__eq__(other)
|
132
|
+
|
133
|
+
def __hash__(self):
|
134
|
+
return super().__hash__()
|
135
|
+
|
107
136
|
@property
|
108
137
|
def compact_view(self) -> str:
|
109
138
|
"""reduce for external (llm) using if required"""
|
@@ -126,8 +155,8 @@ class Unit:
|
|
126
155
|
obj.value = value
|
127
156
|
self.changed = compose_handlers(changed_handler, handler)
|
128
157
|
|
129
|
-
def __getstate__(self):
|
130
|
-
return {n: v for n, v in self.__dict__.items() if n[0] != '_'}
|
158
|
+
def __getstate__(self):
|
159
|
+
return {n: (True if n in Unit.action_list else v) for n, v in self.__dict__.items() if n[0] != '_'}
|
131
160
|
|
132
161
|
def __str__(self):
|
133
162
|
return f'{type(self).__name__}({self.name})'
|
@@ -153,6 +182,7 @@ def smart_complete(lst, min_input_length = 0, max_output_length = 20):
|
|
153
182
|
class Edit(Unit):
|
154
183
|
def __init__(self, name, *args, **kwargs):
|
155
184
|
super().__init__(name, *args, **kwargs)
|
185
|
+
self.x = 0
|
156
186
|
has_value = hasattr(self,'value')
|
157
187
|
if 'type' not in kwargs:
|
158
188
|
if has_value:
|
@@ -263,6 +293,7 @@ class Tree(Unit):
|
|
263
293
|
class TextArea(Unit):
|
264
294
|
def __init__(self,name, *args, **kwargs):
|
265
295
|
super().__init__(name, *args, **kwargs)
|
296
|
+
self.x = 0
|
266
297
|
self.type = 'text'
|
267
298
|
|
268
299
|
|
unisi/users.py
CHANGED
@@ -1,10 +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 *
|
4
5
|
from .voicecom import VoiceCom
|
5
6
|
from .containers import Dialog, Screen
|
6
7
|
from .multimon import notify_monitor, logging_lock, run_external_process
|
7
|
-
from .kdb import Database
|
8
8
|
from .dbunits import dbshare, dbupdates
|
9
9
|
import sys, asyncio, logging, importlib
|
10
10
|
|
@@ -23,7 +23,7 @@ class User:
|
|
23
23
|
if share:
|
24
24
|
self.screens = share.screens
|
25
25
|
self.screen_module = share.screen_module if share.screens else []
|
26
|
-
self.
|
26
|
+
self.handlers = share.handlers
|
27
27
|
|
28
28
|
if share.reflections:
|
29
29
|
share.reflections.append(self)
|
@@ -34,7 +34,7 @@ class User:
|
|
34
34
|
self.screens = []
|
35
35
|
self.reflections = []
|
36
36
|
self.screen_module = None
|
37
|
-
self.
|
37
|
+
self.handlers = {}
|
38
38
|
|
39
39
|
User.last_user = self
|
40
40
|
self.monitor(session, share)
|
@@ -79,7 +79,7 @@ class User:
|
|
79
79
|
module.user = self
|
80
80
|
|
81
81
|
spec.loader.exec_module(module)
|
82
|
-
screen = Screen(getattr(module, 'name', ''))
|
82
|
+
screen = Screen(getattr(module, 'name', ''))
|
83
83
|
#set system vars
|
84
84
|
for var, val in screen.defaults.items():
|
85
85
|
setattr(screen, var, getattr(module, var, val))
|
@@ -89,22 +89,23 @@ class User:
|
|
89
89
|
screen.toolbar += User.toolbar
|
90
90
|
else:
|
91
91
|
screen.toolbar = User.toolbar
|
92
|
-
|
92
|
+
screen.set_reactivity(self)
|
93
|
+
module.screen = screen#ChangedProxy(screen, screen)
|
93
94
|
return module
|
94
95
|
|
95
96
|
async def delete(self):
|
96
97
|
uss = Unishare.sessions
|
97
98
|
if uss and uss.get(self.session):
|
98
|
-
del uss[self.session]
|
99
|
-
|
99
|
+
del uss[self.session]
|
100
100
|
if self.reflections: #reflections is common array
|
101
101
|
if len(self.reflections) == 2:
|
102
102
|
self.reflections.clear() #1 element in user.reflections has no sense
|
103
103
|
else:
|
104
104
|
self.reflections.remove(self)
|
105
|
-
|
106
105
|
if notify_monitor:
|
107
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')
|
108
109
|
|
109
110
|
def set_clean(self):
|
110
111
|
#remove user modules from sys
|
@@ -145,8 +146,8 @@ class User:
|
|
145
146
|
def screen(self):
|
146
147
|
return self.screen_module.screen
|
147
148
|
|
148
|
-
def set_screen(self,name):
|
149
|
-
return
|
149
|
+
def set_screen(self,name):
|
150
|
+
return self.screen_process(ArgObject(block = 'root', element = None, value = name))
|
150
151
|
|
151
152
|
async def result4message(self, message):
|
152
153
|
result = None
|
@@ -217,10 +218,10 @@ class User:
|
|
217
218
|
return ['toolbar', e.name]
|
218
219
|
|
219
220
|
def prepare_result(self, raw):
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
raw =
|
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
|
224
225
|
else:
|
225
226
|
match raw:
|
226
227
|
case None:
|
@@ -242,8 +243,8 @@ class User:
|
|
242
243
|
|
243
244
|
self.changed_units.clear()
|
244
245
|
return raw
|
245
|
-
|
246
|
-
|
246
|
+
|
247
|
+
def screen_process(self, message):
|
247
248
|
screen_change_message = message.screen and self.screen.name != message.screen
|
248
249
|
if screen_change_message or message.screen_type:
|
249
250
|
for s in self.screens:
|
@@ -261,17 +262,20 @@ class User:
|
|
261
262
|
error = f'Unknown screen name: {message.value}'
|
262
263
|
self.log(error)
|
263
264
|
return Error(error)
|
264
|
-
|
265
|
-
|
265
|
+
|
266
|
+
async def process(self, message):
|
267
|
+
if screen_result := self.screen_process(message):
|
268
|
+
return screen_result
|
269
|
+
elif message.voice_type:
|
266
270
|
if not self.voice:
|
267
|
-
self.voice = VoiceCom(self)
|
268
|
-
created = True
|
271
|
+
self.voice = VoiceCom(self)
|
269
272
|
if message.event == 'listen':
|
270
|
-
|
273
|
+
if message.value:
|
274
|
+
self.voice.start()
|
275
|
+
else:
|
276
|
+
self.voice.stop()
|
271
277
|
else:
|
272
|
-
self.voice.
|
273
|
-
if created:
|
274
|
-
return Redesign
|
278
|
+
self.voice.process_word(message.value)
|
275
279
|
else:
|
276
280
|
elem = self.find_element(message)
|
277
281
|
if elem:
|
@@ -283,7 +287,7 @@ class User:
|
|
283
287
|
async def process_element(self, elem, message):
|
284
288
|
event = message.event
|
285
289
|
query = event == 'complete' or event == 'append' or event == 'get'
|
286
|
-
handler = self.
|
290
|
+
handler = self.handlers.get((elem, event), None)
|
287
291
|
if handler:
|
288
292
|
return await self.eval_handler(handler, elem, message.value)
|
289
293
|
|
@@ -358,62 +362,3 @@ class User:
|
|
358
362
|
sync_calls.append(user.send(update4user))
|
359
363
|
dbupdates.clear()
|
360
364
|
await asyncio.gather(*sync_calls)
|
361
|
-
|
362
|
-
def context_user():
|
363
|
-
return context_object(User)
|
364
|
-
|
365
|
-
def context_screen():
|
366
|
-
user = context_user()
|
367
|
-
return user.screen if user else None
|
368
|
-
|
369
|
-
def message_logger(str, type = 'error'):
|
370
|
-
user = context_user()
|
371
|
-
user.log(str, type)
|
372
|
-
|
373
|
-
Unishare.context_user = context_user
|
374
|
-
Unishare.message_logger = message_logger
|
375
|
-
User.type = User
|
376
|
-
|
377
|
-
if config.db_dir:
|
378
|
-
Unishare.db = Database(config.db_dir, message_logger)
|
379
|
-
|
380
|
-
def make_user(request):
|
381
|
-
session = f'{request.remote}-{User.count}'
|
382
|
-
if requested_connect := request.query_string if config.share else None:
|
383
|
-
user = Unishare.sessions.get(requested_connect, None)
|
384
|
-
if not user:
|
385
|
-
error = f'Session id "{requested_connect}" is unknown. Connection refused!'
|
386
|
-
with logging_lock:
|
387
|
-
logging.error(error)
|
388
|
-
return None, Error(error)
|
389
|
-
user = User.type(session, user)
|
390
|
-
ok = user.screens
|
391
|
-
elif config.mirror and User.count:
|
392
|
-
user = User.type(session, User.last_user)
|
393
|
-
ok = user.screens
|
394
|
-
elif not User.count:
|
395
|
-
user = User.last_user
|
396
|
-
user.session = session
|
397
|
-
user.monitor(session)
|
398
|
-
ok = True
|
399
|
-
else:
|
400
|
-
user = User.type(session)
|
401
|
-
ok = user.load()
|
402
|
-
|
403
|
-
User.count += 1
|
404
|
-
Unishare.sessions[session] = user
|
405
|
-
return user, ok
|
406
|
-
|
407
|
-
def handle(elem, event):
|
408
|
-
def h(fn):
|
409
|
-
key = elem, event
|
410
|
-
handler_map = User.last_user.__handlers__
|
411
|
-
func = handler_map.get(key, None)
|
412
|
-
if func:
|
413
|
-
handler_map[key] = compose_handlers(func, fn)
|
414
|
-
else:
|
415
|
-
handler_map[key] = fn
|
416
|
-
return fn
|
417
|
-
return h
|
418
|
-
|
419
|
-
Unishare.handle = handle
|
unisi/utils.py
CHANGED
@@ -1,10 +1,10 @@
|
|
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
|
4
5
|
|
5
6
|
blocks_dir = 'blocks'
|
6
7
|
screens_dir = 'screens'
|
7
|
-
public_dirs = 'public_dirs'
|
8
8
|
testdir = 'autotest'
|
9
9
|
|
10
10
|
divpath = '\\' if platform.system() == 'Windows' else '/'
|
@@ -18,7 +18,7 @@ except:
|
|
18
18
|
f = open('config.py', 'w')
|
19
19
|
f.write("""port = 8000
|
20
20
|
upload_dir = 'web'
|
21
|
-
hot_reload
|
21
|
+
hot_reload = True
|
22
22
|
logfile = 'log'
|
23
23
|
autotest = '*'
|
24
24
|
appname = 'Unisi app'
|
@@ -41,7 +41,9 @@ set_defaults(config, dict(
|
|
41
41
|
froze_time= None,
|
42
42
|
monitor_tick = 0.005,
|
43
43
|
pool = None,
|
44
|
-
db_dir = None
|
44
|
+
db_dir = None,
|
45
|
+
lang = 'en-US',
|
46
|
+
public_dirs = []
|
45
47
|
))
|
46
48
|
|
47
49
|
Screen.defaults = dict(
|
@@ -51,7 +53,8 @@ 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:
|