ivoryos 1.0.9__py3-none-any.whl → 1.2.0b1__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.

Files changed (87) hide show
  1. ivoryos/__init__.py +26 -7
  2. ivoryos/routes/api/api.py +56 -0
  3. ivoryos/routes/auth/auth.py +5 -5
  4. ivoryos/routes/control/control.py +77 -372
  5. ivoryos/routes/control/control_file.py +36 -0
  6. ivoryos/routes/control/control_new_device.py +142 -0
  7. ivoryos/routes/control/templates/controllers.html +166 -0
  8. ivoryos/routes/control/templates/controllers_new.html +112 -0
  9. ivoryos/routes/control/utils.py +38 -0
  10. ivoryos/routes/data/data.py +129 -0
  11. ivoryos/routes/data/templates/components/step_card.html +13 -0
  12. ivoryos/routes/{database/templates/database → data/templates}/workflow_database.html +14 -8
  13. ivoryos/routes/{database/templates/database → data/templates}/workflow_view.html +3 -3
  14. ivoryos/routes/design/__init__.py +4 -0
  15. ivoryos/routes/design/design.py +298 -656
  16. ivoryos/routes/design/design_file.py +68 -0
  17. ivoryos/routes/design/design_step.py +145 -0
  18. ivoryos/routes/design/templates/components/action_form.html +53 -0
  19. ivoryos/routes/design/templates/components/actions_panel.html +25 -0
  20. ivoryos/routes/design/templates/components/autofill_toggle.html +10 -0
  21. ivoryos/routes/design/templates/components/canvas.html +5 -0
  22. ivoryos/routes/design/templates/components/canvas_footer.html +9 -0
  23. ivoryos/routes/design/templates/components/canvas_header.html +75 -0
  24. ivoryos/routes/design/templates/components/canvas_main.html +34 -0
  25. ivoryos/routes/design/templates/components/deck_selector.html +10 -0
  26. ivoryos/routes/design/templates/components/edit_action_form.html +38 -0
  27. ivoryos/routes/design/templates/components/instruments_panel.html +66 -0
  28. ivoryos/routes/design/templates/components/modals/drop_modal.html +17 -0
  29. ivoryos/routes/design/templates/components/modals/json_modal.html +22 -0
  30. ivoryos/routes/design/templates/components/modals/new_script_modal.html +17 -0
  31. ivoryos/routes/design/templates/components/modals/rename_modal.html +23 -0
  32. ivoryos/routes/design/templates/components/modals/saveas_modal.html +27 -0
  33. ivoryos/routes/design/templates/components/modals.html +6 -0
  34. ivoryos/routes/design/templates/components/python_code_overlay.html +39 -0
  35. ivoryos/routes/design/templates/components/sidebar.html +15 -0
  36. ivoryos/routes/design/templates/components/text_to_code_panel.html +20 -0
  37. ivoryos/routes/design/templates/experiment_builder.html +41 -0
  38. ivoryos/routes/execute/__init__.py +0 -0
  39. ivoryos/routes/execute/execute.py +317 -0
  40. ivoryos/routes/execute/execute_file.py +78 -0
  41. ivoryos/routes/execute/templates/components/error_modal.html +20 -0
  42. ivoryos/routes/execute/templates/components/logging_panel.html +31 -0
  43. ivoryos/routes/execute/templates/components/progress_panel.html +27 -0
  44. ivoryos/routes/execute/templates/components/run_panel.html +9 -0
  45. ivoryos/routes/execute/templates/components/run_tabs.html +17 -0
  46. ivoryos/routes/execute/templates/components/tab_bayesian.html +399 -0
  47. ivoryos/routes/execute/templates/components/tab_configuration.html +98 -0
  48. ivoryos/routes/execute/templates/components/tab_repeat.html +14 -0
  49. ivoryos/routes/execute/templates/experiment_run.html +294 -0
  50. ivoryos/routes/library/__init__.py +0 -0
  51. ivoryos/routes/library/library.py +159 -0
  52. ivoryos/routes/{database/templates/database/scripts_database.html → library/templates/library.html} +30 -22
  53. ivoryos/routes/main/main.py +1 -1
  54. ivoryos/routes/main/templates/{main/home.html → home.html} +4 -4
  55. ivoryos/socket_handlers.py +52 -0
  56. ivoryos/static/js/action_handlers.js +213 -0
  57. ivoryos/static/js/db_delete.js +23 -0
  58. ivoryos/static/js/script_metadata.js +39 -0
  59. ivoryos/static/js/sortable_design.js +89 -56
  60. ivoryos/static/js/ui_state.js +113 -0
  61. ivoryos/templates/base.html +4 -4
  62. ivoryos/utils/bo_campaign.py +179 -3
  63. ivoryos/utils/db_models.py +14 -5
  64. ivoryos/utils/form.py +5 -9
  65. ivoryos/utils/global_config.py +13 -1
  66. ivoryos/utils/py_to_json.py +225 -0
  67. ivoryos/utils/script_runner.py +49 -7
  68. ivoryos/utils/serilize.py +203 -0
  69. ivoryos/utils/task_runner.py +4 -1
  70. ivoryos/version.py +1 -1
  71. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0b1.dist-info}/METADATA +5 -8
  72. ivoryos-1.2.0b1.dist-info/RECORD +105 -0
  73. ivoryos/routes/control/templates/control/controllers.html +0 -78
  74. ivoryos/routes/control/templates/control/controllers_home.html +0 -55
  75. ivoryos/routes/control/templates/control/controllers_new.html +0 -89
  76. ivoryos/routes/database/database.py +0 -306
  77. ivoryos/routes/database/templates/database/step_card.html +0 -7
  78. ivoryos/routes/design/templates/design/experiment_builder.html +0 -521
  79. ivoryos/routes/design/templates/design/experiment_run.html +0 -558
  80. ivoryos-1.0.9.dist-info/RECORD +0 -61
  81. /ivoryos/routes/auth/templates/{auth/login.html → login.html} +0 -0
  82. /ivoryos/routes/auth/templates/{auth/signup.html → signup.html} +0 -0
  83. /ivoryos/routes/{database → data}/__init__.py +0 -0
  84. /ivoryos/routes/main/templates/{main/help.html → help.html} +0 -0
  85. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0b1.dist-info}/LICENSE +0 -0
  86. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0b1.dist-info}/WHEEL +0 -0
  87. {ivoryos-1.0.9.dist-info → ivoryos-1.2.0b1.dist-info}/top_level.txt +0 -0
@@ -1,306 +0,0 @@
1
- from flask import Blueprint, redirect, url_for, flash, request, render_template, session, current_app, jsonify
2
- from flask_login import login_required
3
-
4
- from ivoryos.utils.db_models import Script, db, WorkflowRun, WorkflowStep
5
- from ivoryos.utils.utils import get_script_file, post_script_file
6
-
7
- database = Blueprint('database', __name__, template_folder='templates/database')
8
-
9
-
10
-
11
- @database.route("/database/scripts/edit/<script_name>")
12
- @login_required
13
- def edit_workflow(script_name:str):
14
- """
15
- .. :quickref: Database; load workflow script to canvas
16
-
17
- load the selected workflow to the design canvas
18
-
19
- .. http:get:: /database/scripts/edit/<script_name>
20
-
21
- :param script_name: script name
22
- :type script_name: str
23
- :status 302: redirect to :http:get:`/ivoryos/design/script/`
24
- """
25
- row = Script.query.get(script_name)
26
- script = Script(**row.as_dict())
27
- post_script_file(script)
28
- pseudo_name = session.get("pseudo_deck", "")
29
- off_line = current_app.config["OFF_LINE"]
30
- if off_line and pseudo_name and not script.deck == pseudo_name:
31
- flash(f"Choose the deck with name {script.deck}")
32
- if request.accept_mimetypes.best_match(['application/json', 'text/html']) == 'application/json':
33
- return jsonify({
34
- "script": script.as_dict(),
35
- "python_script": script.compile(),
36
- })
37
- return redirect(url_for('design.experiment_builder'))
38
-
39
-
40
- @database.route("/database/scripts/delete/<script_name>")
41
- @login_required
42
- def delete_workflow(script_name: str):
43
- """
44
- .. :quickref: Database; delete workflow
45
-
46
- delete workflow from database
47
-
48
- .. http:get:: /database/scripts/delete/<script_name>
49
-
50
- :param script_name: workflow name
51
- :type script_name: str
52
- :status 302: redirect to :http:get:`/ivoryos/database/scripts/`
53
-
54
- """
55
- Script.query.filter(Script.name == script_name).delete()
56
- db.session.commit()
57
- return redirect(url_for('database.load_from_database'))
58
-
59
-
60
- @database.route("/database/scripts/save")
61
- @login_required
62
- def publish():
63
- """
64
- .. :quickref: Database; save workflow to database
65
-
66
- save workflow to database
67
-
68
- .. http:get:: /database/scripts/save
69
-
70
- :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
71
- """
72
- script = get_script_file()
73
- if not script.name or not script.deck:
74
- flash("Deck cannot be empty, try to re-submit deck configuration on the left panel")
75
- row = Script.query.get(script.name)
76
- if row and row.status == "finalized":
77
- flash("This is a protected script, use save as to rename.")
78
- elif row and not session['user'] == row.author:
79
- flash("You are not the author, use save as to rename.")
80
- else:
81
- db.session.merge(script)
82
- db.session.commit()
83
- flash("Saved!")
84
- return redirect(url_for('design.experiment_builder'))
85
-
86
-
87
- @database.route("/database/scripts/finalize")
88
- @login_required
89
- def finalize():
90
- """
91
- .. :quickref: Database; finalize the workflow
92
-
93
- [protected workflow] prevent saving edited workflow to the same workflow name
94
-
95
- .. http:get:: /finalize
96
-
97
- :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
98
-
99
- """
100
- script = get_script_file()
101
- script.finalize()
102
- if script.name:
103
- db.session.merge(script)
104
- db.session.commit()
105
- post_script_file(script)
106
- return redirect(url_for('design.experiment_builder'))
107
-
108
-
109
- @database.route("/database/scripts/", strict_slashes=False)
110
- @database.route("/database/scripts/<deck_name>")
111
- @login_required
112
- def load_from_database(deck_name=None):
113
- """
114
- .. :quickref: Database; database page
115
-
116
- backend control through http requests
117
-
118
- .. http:get:: /database/scripts/<deck_name>
119
-
120
- :param deck_name: filter for deck name
121
- :type deck_name: str
122
-
123
- """
124
- session.pop('edit_action', None) # reset cache
125
- query = Script.query
126
- search_term = request.args.get("keyword", None)
127
- if search_term:
128
- query = query.filter(Script.name.like(f'%{search_term}%'))
129
- if deck_name is None:
130
- temp = Script.query.with_entities(Script.deck).distinct().all()
131
- deck_list = [i[0] for i in temp]
132
- else:
133
- query = query.filter(Script.deck == deck_name)
134
- deck_list = ["ALL"]
135
- page = request.args.get('page', default=1, type=int)
136
- per_page = 10
137
-
138
- scripts = query.paginate(page=page, per_page=per_page, error_out=False)
139
- if request.accept_mimetypes.best_match(['application/json', 'text/html']) == 'application/json':
140
- scripts = query.all()
141
- script_names = [script.name for script in scripts]
142
- return jsonify({
143
- "workflows": script_names,
144
- })
145
- else:
146
- # return HTML
147
- return render_template("scripts_database.html", scripts=scripts, deck_list=deck_list, deck_name=deck_name)
148
-
149
-
150
- @database.route("/database/scripts/rename", methods=['POST'])
151
- @login_required
152
- def edit_run_name():
153
- """
154
- .. :quickref: Database; edit workflow name
155
-
156
- edit the name of the current workflow, won't save to the database
157
-
158
- .. http:post:: database/scripts/rename
159
-
160
- : form run_name: new workflow name
161
- :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
162
-
163
- """
164
- if request.method == "POST":
165
- run_name = request.form.get("run_name")
166
- exist_script = Script.query.get(run_name)
167
- if not exist_script:
168
- script = get_script_file()
169
- script.save_as(run_name)
170
- post_script_file(script)
171
- else:
172
- flash("Script name is already exist in database")
173
- return redirect(url_for("design.experiment_builder"))
174
-
175
-
176
- @database.route("/database/scripts/save_as", methods=['POST'])
177
- @login_required
178
- def save_as():
179
- """
180
- .. :quickref: Database; save the run name as
181
-
182
- save the current workflow script as
183
-
184
- .. http:post:: /database/scripts/save_as
185
-
186
- : form run_name: new workflow name
187
- :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
188
-
189
- """
190
- if request.method == "POST":
191
- run_name = request.form.get("run_name")
192
- register_workflow = request.form.get("register_workflow")
193
- exist_script = Script.query.get(run_name)
194
- if not exist_script:
195
- script = get_script_file()
196
- script.save_as(run_name)
197
- script.registered = register_workflow == "on"
198
- script.author = session.get('user')
199
- post_script_file(script)
200
- publish()
201
- else:
202
- flash("Script name is already exist in database")
203
- return redirect(url_for("design.experiment_builder"))
204
-
205
-
206
- # -----------------------------------------------------------
207
- # ------------------ Workflow logs -----------------------
208
- # -----------------------------------------------------------
209
- @database.route('/database/workflows/')
210
- def list_workflows():
211
- """
212
- .. :quickref: Database; list all workflow logs
213
-
214
- list all workflow logs
215
-
216
- .. http:get:: /database/workflows/
217
-
218
- """
219
- query = WorkflowRun.query.order_by(WorkflowRun.id.desc())
220
- search_term = request.args.get("keyword", None)
221
- if search_term:
222
- query = query.filter(WorkflowRun.name.like(f'%{search_term}%'))
223
- page = request.args.get('page', default=1, type=int)
224
- per_page = 10
225
-
226
- workflows = query.paginate(page=page, per_page=per_page, error_out=False)
227
- if request.accept_mimetypes.best_match(['application/json', 'text/html']) == 'application/json':
228
- workflows = query.all()
229
- workflow_data = {w.id:{"workflow_name":w.name, "start_time":w.start_time} for w in workflows}
230
- return jsonify({
231
- "workflow_data": workflow_data,
232
- })
233
- else:
234
- return render_template('workflow_database.html', workflows=workflows)
235
-
236
-
237
- @database.route("/database/workflows/<int:workflow_id>")
238
- def get_workflow_steps(workflow_id:int):
239
- """
240
- .. :quickref: Database; list all workflow logs
241
-
242
- list all workflow logs
243
-
244
- .. http:get:: /database/workflows/<int:workflow_id>
245
-
246
- """
247
- workflow = db.session.get(WorkflowRun, workflow_id)
248
- steps = WorkflowStep.query.filter_by(workflow_id=workflow_id).order_by(WorkflowStep.start_time).all()
249
-
250
- # Use full objects for template rendering
251
- grouped = {
252
- "prep": [],
253
- "script": {},
254
- "cleanup": [],
255
- }
256
-
257
- # Use dicts for JSON response
258
- grouped_json = {
259
- "prep": [],
260
- "script": {},
261
- "cleanup": [],
262
- }
263
-
264
- for step in steps:
265
- step_dict = step.as_dict()
266
-
267
- if step.phase == "prep":
268
- grouped["prep"].append(step)
269
- grouped_json["prep"].append(step_dict)
270
-
271
- elif step.phase == "script":
272
- grouped["script"].setdefault(step.repeat_index, []).append(step)
273
- grouped_json["script"].setdefault(step.repeat_index, []).append(step_dict)
274
-
275
- elif step.phase == "cleanup" or step.method_name == "stop":
276
- grouped["cleanup"].append(step)
277
- grouped_json["cleanup"].append(step_dict)
278
-
279
- if request.accept_mimetypes.best_match(['application/json', 'text/html']) == 'application/json':
280
- return jsonify({
281
- "workflow_info": workflow.as_dict(),
282
- "steps": grouped_json,
283
- })
284
- else:
285
- return render_template("workflow_view.html", workflow=workflow, grouped=grouped)
286
-
287
-
288
- @database.route("/database/workflows/delete/<int:workflow_id>")
289
- @login_required
290
- def delete_workflow_data(workflow_id: int):
291
- """
292
- .. :quickref: Database; delete experiment data from database
293
-
294
- delete workflow data from database
295
-
296
- .. http:get:: /database/workflows/delete/<int:workflow_id>
297
-
298
- :param workflow_id: workflow id
299
- :type workflow_id: int
300
- :status 302: redirect to :http:get:`/ivoryos/database/workflows/`
301
-
302
- """
303
- run = WorkflowRun.query.get(workflow_id)
304
- db.session.delete(run)
305
- db.session.commit()
306
- return redirect(url_for('database.list_workflows'))
@@ -1,7 +0,0 @@
1
- <div class="card mb-2 {{ 'border-danger text-danger bg-light' if step.run_error else 'border-secondary' }}">
2
- <div class="card-body p-2">
3
- <strong>{{ step.method_name }}</strong>
4
- <small>Start: {{ step.start_time }}</small>
5
- <small>End: {{ step.end_time }}</small>
6
- </div>
7
- </div>