ivoryos 0.1.9__py3-none-any.whl → 0.1.10__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.
Potentially problematic release.
This version of ivoryos might be problematic. Click here for more details.
- ivoryos/__init__.py +118 -99
- ivoryos/config.py +47 -47
- ivoryos/routes/auth/auth.py +100 -65
- ivoryos/routes/auth/templates/auth/login.html +25 -25
- ivoryos/routes/auth/templates/auth/signup.html +32 -32
- ivoryos/routes/control/control.py +400 -272
- ivoryos/routes/control/templates/control/controllers.html +75 -75
- ivoryos/routes/control/templates/control/controllers_home.html +50 -50
- ivoryos/routes/control/templates/control/controllers_new.html +89 -89
- ivoryos/routes/database/database.py +188 -114
- ivoryos/routes/database/templates/database/experiment_database.html +72 -72
- ivoryos/routes/design/design.py +541 -416
- ivoryos/routes/design/templates/design/experiment_builder.html +415 -415
- ivoryos/routes/design/templates/design/experiment_run.html +325 -325
- ivoryos/routes/main/main.py +42 -25
- ivoryos/routes/main/templates/main/help.html +141 -141
- ivoryos/routes/main/templates/main/home.html +68 -68
- ivoryos/static/.DS_Store +0 -0
- ivoryos/static/js/overlay.js +12 -12
- ivoryos/static/js/socket_handler.js +34 -34
- ivoryos/static/js/sortable_card.js +24 -24
- ivoryos/static/js/sortable_design.js +36 -36
- ivoryos/static/style.css +201 -201
- ivoryos/templates/base.html +143 -143
- ivoryos/utils/db_models.py +518 -518
- ivoryos/utils/form.py +316 -316
- ivoryos/utils/global_config.py +67 -67
- ivoryos/utils/llm_agent.py +183 -183
- ivoryos/utils/script_runner.py +165 -164
- ivoryos/utils/utils.py +425 -422
- ivoryos/version.py +1 -0
- {ivoryos-0.1.9.dist-info → ivoryos-0.1.10.dist-info}/LICENSE +21 -21
- {ivoryos-0.1.9.dist-info → ivoryos-0.1.10.dist-info}/METADATA +170 -169
- ivoryos-0.1.10.dist-info/RECORD +47 -0
- {ivoryos-0.1.9.dist-info → ivoryos-0.1.10.dist-info}/WHEEL +1 -1
- ivoryos-0.1.9.dist-info/RECORD +0 -45
- {ivoryos-0.1.9.dist-info → ivoryos-0.1.10.dist-info}/top_level.txt +0 -0
|
@@ -1,272 +1,400 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
from flask import Blueprint, redirect, url_for, flash, request, render_template, session, current_app, jsonify
|
|
4
|
-
from flask_login import login_required
|
|
5
|
-
|
|
6
|
-
from ivoryos.utils.global_config import GlobalConfig
|
|
7
|
-
from ivoryos.utils import utils
|
|
8
|
-
from ivoryos.utils.form import create_form_from_module, format_name
|
|
9
|
-
|
|
10
|
-
global_config = GlobalConfig()
|
|
11
|
-
|
|
12
|
-
control = Blueprint('control', __name__, template_folder='templates/control')
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@control.route("/my_deck")
|
|
16
|
-
@login_required
|
|
17
|
-
def deck_controllers():
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
#
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
return
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from flask import Blueprint, redirect, url_for, flash, request, render_template, session, current_app, jsonify
|
|
4
|
+
from flask_login import login_required
|
|
5
|
+
|
|
6
|
+
from ivoryos.utils.global_config import GlobalConfig
|
|
7
|
+
from ivoryos.utils import utils
|
|
8
|
+
from ivoryos.utils.form import create_form_from_module, format_name
|
|
9
|
+
|
|
10
|
+
global_config = GlobalConfig()
|
|
11
|
+
|
|
12
|
+
control = Blueprint('control', __name__, template_folder='templates/control')
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@control.route("/my_deck")
|
|
16
|
+
@login_required
|
|
17
|
+
def deck_controllers():
|
|
18
|
+
"""
|
|
19
|
+
.. :quickref: Direct Control; controls home interface
|
|
20
|
+
|
|
21
|
+
deck control home interface for listing all deck instruments
|
|
22
|
+
|
|
23
|
+
.. http:get:: /my_deck
|
|
24
|
+
"""
|
|
25
|
+
deck_variables = global_config.deck_snapshot.keys()
|
|
26
|
+
deck_list = utils.import_history(os.path.join(current_app.config["OUTPUT_FOLDER"], 'deck_history.txt'))
|
|
27
|
+
return render_template('controllers_home.html', defined_variables=deck_variables, deck=True, history=deck_list)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@control.route("/new_controller/")
|
|
31
|
+
@control.route("/new_controller/<instrument>", methods=['GET', 'POST'])
|
|
32
|
+
@login_required
|
|
33
|
+
def new_controller(instrument=None):
|
|
34
|
+
"""
|
|
35
|
+
.. :quickref: Direct Control; connect to a new device
|
|
36
|
+
|
|
37
|
+
interface for connecting a new <instrument>
|
|
38
|
+
|
|
39
|
+
.. http:get:: /new_controller
|
|
40
|
+
|
|
41
|
+
:param instrument: instrument name
|
|
42
|
+
:type instrument: str
|
|
43
|
+
|
|
44
|
+
.. http:post:: /new_controller
|
|
45
|
+
|
|
46
|
+
:form device_name: module instance name (e.g. my_instance = MyClass())
|
|
47
|
+
:form kwargs: dynamic module initialization kwargs fields
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
device = None
|
|
51
|
+
args = None
|
|
52
|
+
if instrument:
|
|
53
|
+
|
|
54
|
+
device = find_instrument_by_name(instrument)
|
|
55
|
+
args = utils.inspect.signature(device.__init__)
|
|
56
|
+
|
|
57
|
+
if request.method == 'POST':
|
|
58
|
+
device_name = request.form.get("device_name", "")
|
|
59
|
+
if device_name and device_name in globals():
|
|
60
|
+
flash("Device name is defined. Try another name, or leave it as blank to auto-configure")
|
|
61
|
+
return render_template('controllers_new.html', instrument=instrument,
|
|
62
|
+
api_variables=global_config.api_variables,
|
|
63
|
+
device=device, args=args, defined_variables=global_config.defined_variables)
|
|
64
|
+
if device_name == "":
|
|
65
|
+
device_name = device.__name__.lower() + "_"
|
|
66
|
+
num = 1
|
|
67
|
+
while device_name + str(num) in global_config.defined_variables:
|
|
68
|
+
num += 1
|
|
69
|
+
device_name = device_name + str(num)
|
|
70
|
+
kwargs = request.form.to_dict()
|
|
71
|
+
kwargs.pop("device_name")
|
|
72
|
+
for i in kwargs:
|
|
73
|
+
if kwargs[i] in global_config.defined_variables:
|
|
74
|
+
kwargs[i] = global_config.defined_variables[kwargs[i]]
|
|
75
|
+
try:
|
|
76
|
+
utils.convert_config_type(kwargs, device.__init__.__annotations__, is_class=True)
|
|
77
|
+
except Exception as e:
|
|
78
|
+
flash(e)
|
|
79
|
+
try:
|
|
80
|
+
global_config.defined_variables[device_name] = device(**kwargs)
|
|
81
|
+
# global_config.defined_variables.add(device_name)
|
|
82
|
+
return redirect(url_for('control.controllers_home'))
|
|
83
|
+
except Exception as e:
|
|
84
|
+
flash(e)
|
|
85
|
+
return render_template('controllers_new.html', instrument=instrument, api_variables=global_config.api_variables,
|
|
86
|
+
device=device, args=args, defined_variables=global_config.defined_variables)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@control.route("/controllers")
|
|
90
|
+
@login_required
|
|
91
|
+
def controllers_home():
|
|
92
|
+
"""
|
|
93
|
+
.. :quickref: Direct Control; temp control home interface
|
|
94
|
+
|
|
95
|
+
temporarily connected devices home interface for listing all instruments
|
|
96
|
+
|
|
97
|
+
.. http:get:: /controllers
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
# defined_variables = parse_deck(deck)
|
|
101
|
+
return render_template('controllers_home.html', defined_variables=global_config.defined_variables)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@control.route("/controllers/<instrument>", methods=['GET', 'POST'])
|
|
105
|
+
@login_required
|
|
106
|
+
def controllers(instrument: str):
|
|
107
|
+
"""
|
|
108
|
+
.. :quickref: Direct Control; control interface
|
|
109
|
+
|
|
110
|
+
control interface for selected <instrument>
|
|
111
|
+
|
|
112
|
+
.. http:get:: /controllers
|
|
113
|
+
|
|
114
|
+
:param instrument: instrument name
|
|
115
|
+
:type instrument: str
|
|
116
|
+
|
|
117
|
+
.. http:post:: /controllers
|
|
118
|
+
|
|
119
|
+
:form hidden_name: function name (hidden field)
|
|
120
|
+
:form kwargs: dynamic kwargs field
|
|
121
|
+
|
|
122
|
+
"""
|
|
123
|
+
inst_object = find_instrument_by_name(instrument)
|
|
124
|
+
_forms = create_form_from_module(sdl_module=inst_object, autofill=False, design=False)
|
|
125
|
+
functions = list(_forms.keys())
|
|
126
|
+
|
|
127
|
+
order = get_session_by_instrument('card_order', instrument)
|
|
128
|
+
hidden_functions = get_session_by_instrument('hide_function', instrument)
|
|
129
|
+
|
|
130
|
+
for function in functions:
|
|
131
|
+
if function not in hidden_functions and function not in order:
|
|
132
|
+
order.append(function)
|
|
133
|
+
post_session_by_instrument('card_order', instrument, order)
|
|
134
|
+
forms = {name: _forms[name] for name in order if name in _forms}
|
|
135
|
+
if request.method == 'POST':
|
|
136
|
+
all_kwargs = request.form.copy()
|
|
137
|
+
method_name = all_kwargs.pop("hidden_name", None)
|
|
138
|
+
# if method_name is not None:
|
|
139
|
+
form = forms.get(method_name)
|
|
140
|
+
kwargs = {field.name: field.data for field in form if field.name != 'csrf_token'}
|
|
141
|
+
function_executable = getattr(inst_object, method_name)
|
|
142
|
+
if form and form.validate_on_submit():
|
|
143
|
+
try:
|
|
144
|
+
kwargs.pop("hidden_name")
|
|
145
|
+
output = function_executable(**kwargs)
|
|
146
|
+
flash(f"\nRun Success! Output value: {output}.")
|
|
147
|
+
except Exception as e:
|
|
148
|
+
flash(e.__str__())
|
|
149
|
+
else:
|
|
150
|
+
flash(form.errors)
|
|
151
|
+
return render_template('controllers.html', instrument=instrument, forms=forms, format_name=format_name)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@control.route("/backend_control/<instrument>", methods=['GET', 'POST'])
|
|
155
|
+
def backend_control(instrument: str=None):
|
|
156
|
+
"""
|
|
157
|
+
.. :quickref: Backend Control; backend control
|
|
158
|
+
|
|
159
|
+
backend control through http requests
|
|
160
|
+
|
|
161
|
+
.. http:get:: /backend_control
|
|
162
|
+
|
|
163
|
+
:param instrument: instrument name
|
|
164
|
+
:type instrument: str
|
|
165
|
+
|
|
166
|
+
.. http:post:: /backend_control
|
|
167
|
+
|
|
168
|
+
"""
|
|
169
|
+
inst_object = find_instrument_by_name(instrument)
|
|
170
|
+
forms = create_form_from_module(sdl_module=inst_object, autofill=False, design=False)
|
|
171
|
+
|
|
172
|
+
if request.method == 'POST':
|
|
173
|
+
all_kwargs = request.form.copy()
|
|
174
|
+
method_name = all_kwargs.pop("hidden_name", None)
|
|
175
|
+
# if method_name is not None:
|
|
176
|
+
form = forms.get(method_name, None)
|
|
177
|
+
kwargs = {field.name: field.data for field in form if field.name != 'csrf_token'}
|
|
178
|
+
function_executable = getattr(inst_object, method_name)
|
|
179
|
+
if form:
|
|
180
|
+
# print(kwargs)
|
|
181
|
+
try:
|
|
182
|
+
kwargs.pop("hidden_name")
|
|
183
|
+
output = function_executable(**kwargs)
|
|
184
|
+
json_output = jsonify(output)
|
|
185
|
+
except Exception as e:
|
|
186
|
+
json_output = jsonify(e.__str__())
|
|
187
|
+
return json_output, 400
|
|
188
|
+
else:
|
|
189
|
+
return "instrument not exist", 400
|
|
190
|
+
return '', 200
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@control.route("/backend_control", methods=['GET'])
|
|
194
|
+
def backend_client():
|
|
195
|
+
"""
|
|
196
|
+
.. :quickref: Backend Control; get snapshot
|
|
197
|
+
|
|
198
|
+
backend control through http requests
|
|
199
|
+
|
|
200
|
+
.. http:get:: /backend_control
|
|
201
|
+
"""
|
|
202
|
+
# Create a snapshot of the current deck configuration
|
|
203
|
+
snapshot = global_config.deck_snapshot.copy()
|
|
204
|
+
|
|
205
|
+
# Iterate through each instrument in the snapshot
|
|
206
|
+
for instrument_key, instrument_data in snapshot.items():
|
|
207
|
+
# Iterate through each function associated with the current instrument
|
|
208
|
+
for function_key, function_data in instrument_data.items():
|
|
209
|
+
# Convert the function signature to a string representation
|
|
210
|
+
function_data['signature'] = str(function_data['signature'])
|
|
211
|
+
|
|
212
|
+
json_output = jsonify(snapshot)
|
|
213
|
+
return json_output, 200
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@control.route("/import_api", methods=['POST'])
|
|
217
|
+
def import_api():
|
|
218
|
+
"""
|
|
219
|
+
.. :quickref: Advanced Features; Manually import API module(s)
|
|
220
|
+
|
|
221
|
+
importing other Python modules
|
|
222
|
+
|
|
223
|
+
.. http:post:: /import_api
|
|
224
|
+
|
|
225
|
+
:form filepath: API (Python class) module filepath
|
|
226
|
+
|
|
227
|
+
import the module and redirect to :http:get:`/ivoryos/new_controller/`
|
|
228
|
+
|
|
229
|
+
"""
|
|
230
|
+
filepath = request.form.get('filepath')
|
|
231
|
+
# filepath.replace('\\', '/')
|
|
232
|
+
name = os.path.split(filepath)[-1].split('.')[0]
|
|
233
|
+
try:
|
|
234
|
+
spec = utils.importlib.util.spec_from_file_location(name, filepath)
|
|
235
|
+
module = utils.importlib.util.module_from_spec(spec)
|
|
236
|
+
spec.loader.exec_module(module)
|
|
237
|
+
classes = utils.inspect.getmembers(module, utils.inspect.isclass)
|
|
238
|
+
if len(classes) == 0:
|
|
239
|
+
flash("Invalid import: no class found in the path")
|
|
240
|
+
return redirect(url_for("control.controllers_home"))
|
|
241
|
+
for i in classes:
|
|
242
|
+
globals()[i[0]] = i[1]
|
|
243
|
+
global_config.api_variables.add(i[0])
|
|
244
|
+
# should handle path error and file type error
|
|
245
|
+
except Exception as e:
|
|
246
|
+
flash(e.__str__())
|
|
247
|
+
return redirect(url_for("control.new_controller"))
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# @control.route("/disconnect", methods=["GET"])
|
|
251
|
+
# @control.route("/disconnect/<device_name>", methods=["GET"])
|
|
252
|
+
# def disconnect(device_name=None):
|
|
253
|
+
# """TODO handle disconnect device"""
|
|
254
|
+
# if device_name:
|
|
255
|
+
# try:
|
|
256
|
+
# exec(device_name + ".disconnect()")
|
|
257
|
+
# except Exception:
|
|
258
|
+
# pass
|
|
259
|
+
# global_config.defined_variables.remove(device_name)
|
|
260
|
+
# globals().pop(device_name)
|
|
261
|
+
# return redirect(url_for('control.controllers_home'))
|
|
262
|
+
#
|
|
263
|
+
# deck_variables = ["deck." + var for var in set(dir(deck))
|
|
264
|
+
# if not (var.startswith("_") or var[0].isupper() or var.startswith("repackage"))
|
|
265
|
+
# and not type(eval("deck." + var)).__module__ == 'builtins']
|
|
266
|
+
# for i in deck_variables:
|
|
267
|
+
# try:
|
|
268
|
+
# exec(i + ".disconnect()")
|
|
269
|
+
# except Exception:
|
|
270
|
+
# pass
|
|
271
|
+
# globals()["deck"] = None
|
|
272
|
+
# return redirect(url_for('control.deck_controllers'))
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@control.route("/import_deck", methods=['POST'])
|
|
276
|
+
def import_deck():
|
|
277
|
+
"""
|
|
278
|
+
.. :quickref: Advanced Features; Manually import a deck
|
|
279
|
+
|
|
280
|
+
.. http:post:: /import_deck
|
|
281
|
+
|
|
282
|
+
:form filepath: deck module filepath
|
|
283
|
+
|
|
284
|
+
import the module and redirect to the previous page
|
|
285
|
+
|
|
286
|
+
"""
|
|
287
|
+
script = utils.get_script_file()
|
|
288
|
+
filepath = request.form.get('filepath')
|
|
289
|
+
session['dismiss'] = request.form.get('dismiss')
|
|
290
|
+
update = request.form.get('update')
|
|
291
|
+
back = request.referrer
|
|
292
|
+
if session['dismiss']:
|
|
293
|
+
return redirect(back)
|
|
294
|
+
name = os.path.split(filepath)[-1].split('.')[0]
|
|
295
|
+
try:
|
|
296
|
+
module = utils.import_module_by_filepath(filepath=filepath, name=name)
|
|
297
|
+
utils.save_to_history(filepath, current_app.config["DECK_HISTORY"])
|
|
298
|
+
module_sigs = utils.create_deck_snapshot(module, save=update, output_path=current_app.config["DUMMY_DECK"])
|
|
299
|
+
if not len(module_sigs) > 0:
|
|
300
|
+
flash("Invalid hardware deck, connect instruments in deck script", "error")
|
|
301
|
+
return redirect(url_for("control.deck_controllers"))
|
|
302
|
+
global_config.deck = module
|
|
303
|
+
global_config.deck_snapshot = module_sigs
|
|
304
|
+
|
|
305
|
+
if script.deck is None:
|
|
306
|
+
script.deck = module.__name__
|
|
307
|
+
# file path error exception
|
|
308
|
+
except Exception as e:
|
|
309
|
+
flash(e.__str__())
|
|
310
|
+
return redirect(back)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@control.route('/save-order/<instrument>', methods=['POST'])
|
|
314
|
+
def save_order(instrument: str):
|
|
315
|
+
"""
|
|
316
|
+
.. :quickref: Control Customization; Save functions' order
|
|
317
|
+
|
|
318
|
+
.. http:post:: /save-order
|
|
319
|
+
|
|
320
|
+
save function drag and drop order for the given <instrument>
|
|
321
|
+
|
|
322
|
+
"""
|
|
323
|
+
# Save the new order for the specified group to session
|
|
324
|
+
data = request.json
|
|
325
|
+
post_session_by_instrument('card_order', instrument, data['order'])
|
|
326
|
+
return '', 204
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@control.route('/hide_function/<instrument>/<function>')
|
|
330
|
+
def hide_function(instrument, function):
|
|
331
|
+
"""
|
|
332
|
+
.. :quickref: Control Customization; Hide function
|
|
333
|
+
|
|
334
|
+
.. http:get:: /hide_function
|
|
335
|
+
|
|
336
|
+
Hide the given <instrument> and <function>
|
|
337
|
+
|
|
338
|
+
"""
|
|
339
|
+
back = request.referrer
|
|
340
|
+
functions = get_session_by_instrument("hidden_functions", instrument)
|
|
341
|
+
order = get_session_by_instrument("card_order", instrument)
|
|
342
|
+
if function not in functions:
|
|
343
|
+
functions.append(function)
|
|
344
|
+
order.remove(function)
|
|
345
|
+
post_session_by_instrument('hidden_functions', instrument, functions)
|
|
346
|
+
post_session_by_instrument('card_order', instrument, order)
|
|
347
|
+
return redirect(back)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@control.route('/remove_hidden/<instrument>/<function>')
|
|
351
|
+
def remove_hidden(instrument: str, function: str):
|
|
352
|
+
"""
|
|
353
|
+
.. :quickref: Control Customization; Remove a hidden function
|
|
354
|
+
|
|
355
|
+
.. http:get:: /remove_hidden
|
|
356
|
+
|
|
357
|
+
Un-hide the given <instrument> and <function>
|
|
358
|
+
|
|
359
|
+
"""
|
|
360
|
+
back = request.referrer
|
|
361
|
+
functions = get_session_by_instrument("hidden_functions", instrument)
|
|
362
|
+
order = get_session_by_instrument("card_order", instrument)
|
|
363
|
+
if function in functions:
|
|
364
|
+
functions.remove(function)
|
|
365
|
+
order.append(function)
|
|
366
|
+
post_session_by_instrument('hidden_functions', instrument, functions)
|
|
367
|
+
post_session_by_instrument('card_order', instrument, order)
|
|
368
|
+
return redirect(back)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def get_session_by_instrument(session_name, instrument):
|
|
372
|
+
"""get data from session by instrument"""
|
|
373
|
+
session_object = session.get(session_name, {})
|
|
374
|
+
functions = session_object.get(instrument, [])
|
|
375
|
+
return functions
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def post_session_by_instrument(session_name, instrument, data):
|
|
379
|
+
"""
|
|
380
|
+
save new data to session by instrument
|
|
381
|
+
:param session_name: "card_order" or "hidden_functions"
|
|
382
|
+
:param instrument: function name of class object
|
|
383
|
+
:param data: order list or hidden function list
|
|
384
|
+
"""
|
|
385
|
+
session_object = session.get(session_name, {})
|
|
386
|
+
session_object[instrument] = data
|
|
387
|
+
session[session_name] = session_object
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def find_instrument_by_name(name: str):
|
|
391
|
+
"""
|
|
392
|
+
find instrument class object by instance name
|
|
393
|
+
"""
|
|
394
|
+
if name.startswith("deck"):
|
|
395
|
+
name = name.replace("deck.", "")
|
|
396
|
+
return getattr(global_config.deck, name)
|
|
397
|
+
elif name in global_config.defined_variables:
|
|
398
|
+
return global_config.defined_variables[name]
|
|
399
|
+
elif name in globals():
|
|
400
|
+
return globals()[name]
|