ivoryos 1.0.1__py3-none-any.whl → 1.0.4__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.

@@ -35,19 +35,19 @@
35
35
  </tr>
36
36
  </thead>
37
37
  <tbody>
38
- {% for workflow in workflows %}
38
+ {% for script in scripts %}
39
39
  <tr>
40
- <td><a href="{{ url_for('database.edit_workflow', workflow_name=workflow.name) }}">{{ workflow.name }}</a></td>
41
- <td>{{ workflow.deck }}</td>
42
- <td>{{ workflow.status }}</td>
43
- <td>{{ workflow.time_created }}</td>
44
- <td>{{ workflow.last_modified }}</td>
45
- <td>{{ workflow.author }}</td>
40
+ <td><a href="{{ url_for('database.edit_workflow', script_name=script.name) }}">{{ script.name }}</a></td>
41
+ <td>{{ script.deck }}</td>
42
+ <td>{{ script.status }}</td>
43
+ <td>{{ script.time_created }}</td>
44
+ <td>{{ script.last_modified }}</td>
45
+ <td>{{ script.author }}</td>
46
46
  {# <td>{{ workflow.registered }}</td>#}
47
47
  <td>
48
48
  {#not workflow.status == "finalized" or#}
49
- {% if session['user'] == 'admin' or session['user'] == workflow.author %}
50
- <a href="{{ url_for('database.delete_workflow', workflow_name=workflow.name) }}">delete</a>
49
+ {% if session['user'] == 'admin' or session['user'] == script.author %}
50
+ <a href="{{ url_for('database.delete_workflow', script_name=script.name) }}">delete</a>
51
51
  {% else %}
52
52
  <a class="disabled-link">delete</a>
53
53
  {% endif %}
@@ -57,18 +57,27 @@
57
57
  </tbody>
58
58
  </table>
59
59
 
60
- {# paging#}
60
+ {# paging#}
61
61
  <div class="pagination justify-content-center">
62
- <div class="page-item {{ 'disabled' if not workflows.has_prev else '' }}">
63
- <a class="page-link" href="{{ url_for('database.load_from_database', page=workflows.prev_num) }}">Previous</a>
62
+ <div class="page-item {{ 'disabled' if not scripts.has_prev else '' }}">
63
+ <a class="page-link" href="{{ url_for('database.load_from_database', page=scripts.prev_num) }}">Previous</a>
64
64
  </div>
65
- {% for num in workflows.iter_pages() %}
66
- <div class="page-item">
67
- <a class="page-link {{ 'active' if num == workflows.page else '' }}" href="{{ url_for('database.load_from_database', page=num) }}">{{ num }}</a>
68
- </div>
65
+
66
+ {% for num in scripts.iter_pages() %}
67
+ {% if num %}
68
+ <div class="page-item {{ 'active' if num == scripts.page else '' }}">
69
+ <a class="page-link" href="{{ url_for('database.load_from_database', page=num) }}">{{ num }}</a>
70
+ </div>
71
+ {% else %}
72
+ <div class="page-item disabled">
73
+ <span class="page-link">…</span>
74
+ </div>
75
+ {% endif %}
69
76
  {% endfor %}
70
- <div class="page-item {{ 'disabled' if not workflows.has_next else '' }}">
71
- <a class="page-link" href="{{ url_for('database.load_from_database', page=workflows.next_num) }}">Next</a>
77
+
78
+ <div class="page-item {{ 'disabled' if not scripts.has_next else '' }}">
79
+ <a class="page-link" href="{{ url_for('database.load_from_database', page=scripts.next_num) }}">Next</a>
72
80
  </div>
73
81
  </div>
82
+
74
83
  {% endblock %}
@@ -2,11 +2,24 @@
2
2
 
3
3
  {% block title %}IvoryOS | Design Database{% endblock %}
4
4
  {% block body %}
5
+ <div class="div">
6
+ <form id="search" style="display: inline-block;float: right;" action="{{url_for('database.list_workflows',deck_name=deck_name)}}" method="GET">
7
+ <div class="input-group">
8
+ <div class="form-outline">
9
+ <input type="search" name="keyword" id="keyword" class="form-control" placeholder="Search workflows...">
10
+ </div>
11
+ <button type="submit" class="btn btn-primary">
12
+ <i class="bi bi-search"></i>
13
+ </button>
14
+ </div>
15
+ </form>
16
+ </div>
5
17
 
6
- <table class="table table-hover" id="workflowResultLibrary">
18
+ <table class="table table-hover" id="workflowResultLibrary">
7
19
  <thead>
8
20
  <tr>
9
21
  <th scope="col">Workflow name</th>
22
+ <th scope="col">Workflow ID</th>
10
23
  <th scope="col">Start time</th>
11
24
  <th scope="col">End time</th>
12
25
  <th scope="col">Data</th>
@@ -16,6 +29,7 @@
16
29
  {% for workflow in workflows %}
17
30
  <tr>
18
31
  <td><a href="{{ url_for('database.get_workflow_steps', workflow_id=workflow.id) }}">{{ workflow.name }}</a></td>
32
+ <td>{{ workflow.id }}</td>
19
33
  <td>{{ workflow.start_time.strftime("%Y-%m-%d %H:%M:%S") if workflow.start_time else '' }}</td>
20
34
  <td>{{ workflow.end_time.strftime("%Y-%m-%d %H:%M:%S") if workflow.end_time else '' }}</td>
21
35
 
@@ -36,16 +50,24 @@
36
50
  </tbody>
37
51
  </table>
38
52
 
39
- {# paging#}
53
+ {# paging#}
40
54
  <div class="pagination justify-content-center">
41
55
  <div class="page-item {{ 'disabled' if not workflows.has_prev else '' }}">
42
56
  <a class="page-link" href="{{ url_for('database.list_workflows', page=workflows.prev_num) }}">Previous</a>
43
57
  </div>
58
+
44
59
  {% for num in workflows.iter_pages() %}
45
- <div class="page-item">
46
- <a class="page-link {{ 'active' if num == workflows.page else '' }}" href="{{ url_for('database.list_workflows', page=num) }}">{{ num }}</a>
47
- </div>
60
+ {% if num %}
61
+ <div class="page-item {{ 'active' if num == workflows.page else '' }}">
62
+ <a class="page-link" href="{{ url_for('database.list_workflows', page=num) }}">{{ num }}</a>
63
+ </div>
64
+ {% else %}
65
+ <div class="page-item disabled">
66
+ <span class="page-link">…</span>
67
+ </div>
68
+ {% endif %}
48
69
  {% endfor %}
70
+
49
71
  <div class="page-item {{ 'disabled' if not workflows.has_next else '' }}">
50
72
  <a class="page-link" href="{{ url_for('database.list_workflows', page=workflows.next_num) }}">Next</a>
51
73
  </div>
@@ -3,6 +3,7 @@ import json
3
3
  import os
4
4
  import pickle
5
5
  import sys
6
+ import time
6
7
 
7
8
  from flask import Blueprint, redirect, url_for, flash, jsonify, send_file, request, render_template, session, \
8
9
  current_app, g
@@ -11,7 +12,6 @@ from flask_socketio import SocketIO
11
12
  from werkzeug.utils import secure_filename
12
13
 
13
14
  from ivoryos.utils import utils
14
- from ivoryos.utils.client_proxy import create_function, export_to_python
15
15
  from ivoryos.utils.global_config import GlobalConfig
16
16
  from ivoryos.utils.form import create_builtin_form, create_action_button, format_name, create_form_from_pseudo, \
17
17
  create_form_from_action, create_all_builtin_forms
@@ -74,8 +74,8 @@ def handle_abort_action():
74
74
  socketio.emit('log', {'message': message})
75
75
 
76
76
 
77
- @design.route("/experiment/build/", methods=['GET', 'POST'])
78
- @design.route("/experiment/build/<instrument>/", methods=['GET', 'POST'])
77
+ @design.route("/design/script/", methods=['GET', 'POST'])
78
+ @design.route("/design/script/<instrument>/", methods=['GET', 'POST'])
79
79
  @login_required
80
80
  def experiment_builder(instrument=None):
81
81
  """
@@ -86,7 +86,7 @@ def experiment_builder(instrument=None):
86
86
  This route allows users to build and edit experiment workflows. Users can interact with available instruments,
87
87
  define variables, and manage experiment scripts.
88
88
 
89
- .. http:get:: /experiment/build
89
+ .. http:get:: /design/script
90
90
 
91
91
  Load the experiment builder interface.
92
92
 
@@ -94,7 +94,7 @@ def experiment_builder(instrument=None):
94
94
  :type instrument: str
95
95
  :status 200: Experiment builder loaded successfully.
96
96
 
97
- .. http:post:: /experiment/build
97
+ .. http:post:: /design/script
98
98
 
99
99
  Submit form data to add or modify actions in the experiment script.
100
100
 
@@ -120,7 +120,7 @@ def experiment_builder(instrument=None):
120
120
  if deck and script.deck is None:
121
121
  script.deck = os.path.splitext(os.path.basename(deck.__file__))[
122
122
  0] if deck.__name__ == "__main__" else deck.__name__
123
- script.sort_actions()
123
+ # script.sort_actions()
124
124
 
125
125
  pseudo_deck_name = session.get('pseudo_deck', '')
126
126
  pseudo_deck_path = os.path.join(current_app.config["DUMMY_DECK"], pseudo_deck_name)
@@ -202,11 +202,11 @@ def experiment_builder(instrument=None):
202
202
  logic_type = kwargs.pop('builtin_name')
203
203
  if 'variable' in kwargs:
204
204
  try:
205
- script.add_variable(**kwargs, insert_position=insert_position)
205
+ script.add_variable(insert_position=insert_position, **kwargs)
206
206
  except ValueError:
207
207
  flash("Invalid variable type")
208
208
  else:
209
- script.add_logic_action(logic_type=logic_type, **kwargs, insert_position=insert_position)
209
+ script.add_logic_action(logic_type=logic_type, insert_position=insert_position, **kwargs)
210
210
  else:
211
211
  flash(form.errors)
212
212
  elif request.method == 'POST' and "workflow_name" in request.form:
@@ -240,6 +240,10 @@ def experiment_builder(instrument=None):
240
240
  forms = create_form_from_pseudo(functions, autofill=autofill, script=script)
241
241
 
242
242
  utils.post_script_file(script)
243
+
244
+ exec_string = script.python_script if script.python_script else script.compile(current_app.config['SCRIPT_FOLDER'])
245
+ session['python_code'] = exec_string
246
+
243
247
  design_buttons = create_action_button(script)
244
248
  return render_template('experiment_builder.html', off_line=off_line, instrument=instrument, history=deck_list,
245
249
  script=script, defined_variables=deck_variables,
@@ -248,17 +252,17 @@ def experiment_builder(instrument=None):
248
252
  use_llm=enable_llm)
249
253
 
250
254
 
251
- @design.route("/generate_code", methods=['POST'])
255
+ @design.route("/design/generate_code", methods=['POST'])
252
256
  @login_required
253
257
  def generate_code():
254
258
  """
255
259
  .. :quickref: Text to Code; Generate code from user input and update the design canvas.
256
260
 
257
- .. http:post:: /generate_code
261
+ .. http:post:: /design/generate_code
258
262
 
259
263
  :form prompt: user's prompt
260
264
  :status 200: and then redirects to :http:get:`/experiment/build`
261
- :status 400: failed to initialize the AI agent redirects to :http:get:`/experiment/build`
265
+ :status 400: failed to initialize the AI agent redirects to :http:get:`/design/script`
262
266
 
263
267
  """
264
268
  agent = global_config.agent
@@ -296,24 +300,25 @@ def generate_code():
296
300
  return redirect(url_for("design.experiment_builder", instrument=instrument, use_llm=True))
297
301
 
298
302
 
299
- @design.route("/experiment", methods=['GET', 'POST'])
303
+ @design.route("/design/campaign", methods=['GET', 'POST'])
300
304
  @login_required
301
305
  def experiment_run():
302
306
  """
303
307
  .. :quickref: Workflow Execution; Execute/iterate the workflow
304
308
 
305
- .. http:get:: /experiment
309
+ .. http:get:: /design/campaign
306
310
 
307
311
  Compile the workflow and load the experiment execution interface.
308
312
 
309
- .. http:post:: /experiment
313
+ .. http:post:: /design/campaign
310
314
 
311
315
  Start workflow execution
312
316
 
313
317
  """
314
318
  deck = global_config.deck
315
319
  script = utils.get_script_file()
316
- script.sort_actions()
320
+
321
+ # script.sort_actions() # handled in update list
317
322
  off_line = current_app.config["OFF_LINE"]
318
323
  deck_list = utils.import_history(os.path.join(current_app.config["OUTPUT_FOLDER"], 'deck_history.txt'))
319
324
  # if not off_line and deck is None:
@@ -328,7 +333,7 @@ def experiment_run():
328
333
  # todo
329
334
  exec_string = script.python_script if script.python_script else script.compile(current_app.config['SCRIPT_FOLDER'])
330
335
  # exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
331
-
336
+ # print(exec_string)
332
337
  except Exception as e:
333
338
  flash(e.__str__())
334
339
  # handle api request
@@ -345,12 +350,13 @@ def experiment_run():
345
350
  if filename:
346
351
  # config_preview = list(csv.DictReader(open(os.path.join(current_app.config['CSV_FOLDER'], filename))))
347
352
  config = list(csv.DictReader(open(os.path.join(current_app.config['CSV_FOLDER'], filename))))
348
- config_preview = config[1:6]
353
+ config_preview = config[1:]
349
354
  arg_type = config.pop(0) # first entry is types
350
355
  try:
351
356
  for key, func_str in exec_string.items():
352
357
  exec(func_str)
353
358
  line_collection = script.convert_to_lines(exec_string)
359
+
354
360
  except Exception:
355
361
  flash(f"Please check {key} syntax!!")
356
362
  return redirect(url_for("design.experiment_builder"))
@@ -408,6 +414,9 @@ def experiment_run():
408
414
  else:
409
415
  flash(e)
410
416
  if request.accept_mimetypes.best_match(['application/json', 'text/html']) == 'application/json':
417
+ # wait to get a workflow ID
418
+ while not global_config.runner_status:
419
+ time.sleep(1)
411
420
  return jsonify({"status": "task started", "task_id": global_config.runner_status.get("id")})
412
421
  else:
413
422
  return render_template('experiment_run.html', script=script.script_dict, filename=filename,
@@ -418,15 +427,15 @@ def experiment_run():
418
427
  history=deck_list, pause_status=runner.pause_status())
419
428
 
420
429
 
421
- @design.route("/toggle_script_type/<stype>")
430
+ @design.route("/design/script/toggle/<stype>")
422
431
  @login_required
423
432
  def toggle_script_type(stype=None):
424
433
  """
425
434
  .. :quickref: Workflow Design; toggle the experimental phase for design canvas.
426
435
 
427
- .. http:get:: /toggle_script_type
436
+ .. http:get:: /design/script/toggle/<stype>
428
437
 
429
- :status 200: and then redirects to :http:get:`/experiment/build`
438
+ :status 200: and then redirects to :http:get:`/design/script`
430
439
 
431
440
  """
432
441
  script = utils.get_script_file()
@@ -435,27 +444,37 @@ def toggle_script_type(stype=None):
435
444
  return redirect(url_for('design.experiment_builder'))
436
445
 
437
446
 
438
- @design.route("/updateList", methods=['GET', 'POST'])
447
+ @design.route("/updateList", methods=['POST'])
439
448
  @login_required
440
449
  def update_list():
441
450
  order = request.form['order']
442
451
  script = utils.get_script_file()
443
452
  script.currently_editing_order = order.split(",", len(script.currently_editing_script))
453
+ script.sort_actions()
454
+ exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
444
455
  utils.post_script_file(script)
445
- return jsonify('Successfully Updated')
456
+ session['python_code'] = exec_string
457
+
458
+ return jsonify({'success': True})
459
+
460
+
461
+ @design.route("/toggle_show_code", methods=["POST"])
462
+ def toggle_show_code():
463
+ session["show_code"] = not session.get("show_code", False)
464
+ return redirect(request.referrer or url_for("design.experiment_builder"))
446
465
 
447
466
 
448
467
  # --------------------handle all the import/export and download/upload--------------------------
449
- @design.route("/clear")
468
+ @design.route("/design/clear")
450
469
  @login_required
451
470
  def clear():
452
471
  """
453
472
  .. :quickref: Workflow Design; clear the design canvas.
454
473
 
455
- .. http:get:: /clear
474
+ .. http:get:: /design/clear
456
475
 
457
476
  :form prompt: user's prompt
458
- :status 200: clear canvas and then redirects to :http:get:`/experiment/build`
477
+ :status 200: clear canvas and then redirects to :http:get:`/design/script`
459
478
  """
460
479
  deck = global_config.deck
461
480
  pseudo_name = session.get("pseudo_deck", "")
@@ -471,16 +490,16 @@ def clear():
471
490
  return redirect(url_for("design.experiment_builder"))
472
491
 
473
492
 
474
- @design.route("/import_pseudo", methods=['POST'])
493
+ @design.route("/design/import/pseudo", methods=['POST'])
475
494
  @login_required
476
495
  def import_pseudo():
477
496
  """
478
497
  .. :quickref: Workflow Design; Import pseudo deck from deck history
479
498
 
480
- .. http:post:: /import_pseudo
499
+ .. http:post:: /design/import/pseudo
481
500
 
482
501
  :form pkl_name: pseudo deck name
483
- :status 302: load pseudo deck and then redirects to :http:get:`/experiment/build`
502
+ :status 302: load pseudo deck and then redirects to :http:get:`/design/script`
484
503
  """
485
504
  pkl_name = request.form.get('pkl_name')
486
505
  script = utils.get_script_file()
@@ -494,16 +513,16 @@ def import_pseudo():
494
513
  return redirect(url_for("design.experiment_builder"))
495
514
 
496
515
 
497
- @design.route('/uploads', methods=['POST'])
516
+ @design.route('/design/uploads', methods=['POST'])
498
517
  @login_required
499
518
  def upload():
500
519
  """
501
520
  .. :quickref: Workflow Execution; upload a workflow config file (.CSV)
502
521
 
503
- .. http:post:: /uploads
522
+ .. http:post:: /design/uploads
504
523
 
505
524
  :form file: workflow CSV config file
506
- :status 302: save csv file and then redirects to :http:get:`/experiment`
525
+ :status 302: save csv file and then redirects to :http:get:`/design/campaign`
507
526
  """
508
527
  if request.method == "POST":
509
528
  f = request.files['file']
@@ -519,14 +538,20 @@ def upload():
519
538
  return redirect(url_for("design.experiment_run"))
520
539
 
521
540
 
522
- @design.route('/download_results/<filename>')
541
+ @design.route('/design/workflow/download/<filename>')
523
542
  @login_required
524
543
  def download_results(filename):
544
+ """
545
+ .. :quickref: Workflow Design; download a workflow data file
546
+
547
+ .. http:get:: /design/workflow/download/<filename>
548
+
549
+ """
525
550
  filepath = os.path.join(current_app.config["DATA_FOLDER"], filename)
526
551
  return send_file(os.path.abspath(filepath), as_attachment=True)
527
552
 
528
553
 
529
- @design.route('/load_json', methods=['POST'])
554
+ @design.route('/design/load_json', methods=['POST'])
530
555
  @login_required
531
556
  def load_json():
532
557
  """
@@ -535,7 +560,7 @@ def load_json():
535
560
  .. http:post:: /load_json
536
561
 
537
562
  :form file: workflow design JSON file
538
- :status 302: load pseudo deck and then redirects to :http:get:`/experiment/build`
563
+ :status 302: load pseudo deck and then redirects to :http:get:`/design/script`
539
564
  """
540
565
  if request.method == "POST":
541
566
  f = request.files['file']
@@ -549,9 +574,15 @@ def load_json():
549
574
  return redirect(url_for("design.experiment_builder"))
550
575
 
551
576
 
552
- @design.route('/download/<filetype>')
577
+ @design.route('/design/script/download/<filetype>')
553
578
  @login_required
554
579
  def download(filetype):
580
+ """
581
+ .. :quickref: Workflow Design Ext; download a workflow design file
582
+
583
+ .. http:get:: /design/script/download/<filetype>
584
+
585
+ """
555
586
  script = utils.get_script_file()
556
587
  run_name = script.name if script.name else "untitled"
557
588
  if filetype == "configure":
@@ -569,40 +600,28 @@ def download(filetype):
569
600
  outfile.write(json_object)
570
601
  elif filetype == "python":
571
602
  filepath = os.path.join(current_app.config["SCRIPT_FOLDER"], f"{run_name}.py")
572
- elif filetype == "proxy":
573
- snapshot = global_config.deck_snapshot.copy()
574
- class_definitions = {}
575
- # Iterate through each instrument in the snapshot
576
- for instrument_key, instrument_data in snapshot.items():
577
- # Iterate through each function associated with the current instrument
578
- for function_key, function_data in instrument_data.items():
579
- # Convert the function signature to a string representation
580
- function_data['signature'] = str(function_data['signature'])
581
- class_name = instrument_key.split('.')[-1] # Extracting the class name from the path
582
- class_definitions[class_name.capitalize()] = create_function(request.url_root, class_name, instrument_data)
583
- # Export the generated class definitions to a .py script
584
- export_to_python(class_definitions, current_app.config["OUTPUT_FOLDER"])
585
- filepath = os.path.join(current_app.config["OUTPUT_FOLDER"], "generated_proxy.py")
603
+ else:
604
+ return "Unsupported file type", 400
586
605
  return send_file(os.path.abspath(filepath), as_attachment=True)
587
606
 
588
607
 
589
- @design.route("/edit/<uuid>", methods=['GET', 'POST'])
608
+ @design.route("/design/step/edit/<uuid>", methods=['GET', 'POST'])
590
609
  @login_required
591
610
  def edit_action(uuid: str):
592
611
  """
593
612
  .. :quickref: Workflow Design; edit parameters of an action step on canvas
594
613
 
595
- .. http:get:: /edit
614
+ .. http:get:: /design/step/edit/<uuid>
596
615
 
597
616
  Load parameter form of an action step
598
617
 
599
- .. http:post:: /edit
618
+ .. http:post:: /design/step/edit/<uuid>
600
619
 
601
620
  :param uuid: The step's uuid
602
621
  :type uuid: str
603
622
 
604
623
  :form dynamic form: workflow step dynamic inputs
605
- :status 302: save changes and then redirects to :http:get:`/experiment/build`
624
+ :status 302: save changes and then redirects to :http:get:`/design/script`
606
625
  """
607
626
  script = utils.get_script_file()
608
627
  action = script.find_by_uuid(uuid)
@@ -625,18 +644,18 @@ def edit_action(uuid: str):
625
644
  return redirect(url_for('design.experiment_builder'))
626
645
 
627
646
 
628
- @design.route("/delete/<id>")
647
+ @design.route("/design/step/delete/<id>")
629
648
  @login_required
630
649
  def delete_action(id: int):
631
650
  """
632
651
  .. :quickref: Workflow Design; delete an action step on canvas
633
652
 
634
- .. http:get:: /delete
653
+ .. http:get:: /design/step/delete/<id>
635
654
 
636
655
  :param id: The step number id
637
656
  :type id: int
638
657
 
639
- :status 302: save changes and then redirects to :http:get:`/experiment/build`
658
+ :status 302: save changes and then redirects to :http:get:`/design/script`
640
659
  """
641
660
  back = request.referrer
642
661
  script = utils.get_script_file()
@@ -645,18 +664,18 @@ def delete_action(id: int):
645
664
  return redirect(back)
646
665
 
647
666
 
648
- @design.route("/duplicate/<id>")
667
+ @design.route("/design/step/duplicate/<id>")
649
668
  @login_required
650
669
  def duplicate_action(id: int):
651
670
  """
652
671
  .. :quickref: Workflow Design; duplicate an action step on canvas
653
672
 
654
- .. http:get:: /duplicate
673
+ .. http:get:: /design/step/duplicate/<id>
655
674
 
656
675
  :param id: The step number id
657
676
  :type id: int
658
677
 
659
- :status 302: save changes and then redirects to :http:get:`/experiment/build`
678
+ :status 302: save changes and then redirects to :http:get:`/design/script`
660
679
  """
661
680
  back = request.referrer
662
681
  script = utils.get_script_file()
@@ -667,8 +686,15 @@ def duplicate_action(id: int):
667
686
 
668
687
  # ---- HTTP API Endpoints ----
669
688
 
670
- @design.route("/api/status", methods=["GET"])
689
+ @design.route("/api/runner/status", methods=["GET"])
671
690
  def runner_status():
691
+ """
692
+ .. :quickref: Workflow Design; get the execution status
693
+
694
+ .. http:get:: /api/runner/status
695
+
696
+ :status 200: status
697
+ """
672
698
  runner_busy = global_config.runner_lock.locked()
673
699
  status = {"busy": runner_busy}
674
700
  task_status = global_config.runner_status
@@ -692,39 +718,69 @@ def runner_status():
692
718
 
693
719
 
694
720
 
695
- @design.route("/api/abort_pending", methods=["POST"])
721
+ @design.route("/api/runner/abort_pending", methods=["POST"])
696
722
  def api_abort_pending():
723
+ """
724
+ .. :quickref: Workflow Design; abort pending action(s) during execution
725
+
726
+ .. http:get:: /api/runner/abort_pending
727
+
728
+ :status 200: {"status": "ok"}
729
+ """
697
730
  abort_pending()
698
731
  return jsonify({"status": "ok"}), 200
699
732
 
700
- @design.route("/api/abort_current", methods=["POST"])
733
+ @design.route("/api/runner/abort_current", methods=["POST"])
701
734
  def api_abort_current():
735
+ """
736
+ .. :quickref: Workflow Design; abort right after current action during execution
737
+
738
+ .. http:get:: /api/runner/abort_current
739
+
740
+ :status 200: {"status": "ok"}
741
+ """
702
742
  abort_current()
703
743
  return jsonify({"status": "ok"}), 200
704
744
 
705
- @design.route("/api/pause", methods=["POST"])
745
+ @design.route("/api/runner/pause", methods=["POST"])
706
746
  def api_pause():
747
+ """
748
+ .. :quickref: Workflow Design; pause during execution
749
+
750
+ .. http:get:: /api/runner/pause
751
+
752
+ :status 200: {"status": "ok"}
753
+ """
707
754
  msg = pause()
708
755
  return jsonify({"status": "ok", "pause_status": msg}), 200
709
756
 
710
- @design.route("/api/retry", methods=["POST"])
757
+ @design.route("/api/runner/retry", methods=["POST"])
711
758
  def api_retry():
759
+ """
760
+ .. :quickref: Workflow Design; retry when error occur during execution
761
+
762
+ .. http:get:: /api/runner/retry
763
+
764
+ :status 200: {"status": "ok"}
765
+ """
712
766
  retry()
713
767
  return jsonify({"status": "ok, retrying failed step"}), 200
714
768
 
715
769
 
716
- @design.route("/api/get_script", methods=["GET", "POST"])
717
- def get_script():
718
- script = utils.get_script_file()
719
- script.sort_actions()
720
- script_collection = script.compile()
721
- if request.method == "POST":
722
- # create a brand-new script
723
- deck = global_config.deck
724
- deck_name = os.path.splitext(os.path.basename(deck.__file__))[0] if deck.__name__ == "__main__" else deck.__name__
725
- script = Script(author=session.get('user'), deck=deck_name)
726
- script_collection = request.get_json()
727
- script.python_script = script_collection
728
- utils.post_script_file(script)
729
- return jsonify({"status": "ok"}), 200
730
- return jsonify(script_collection), 200
770
+ @design.route("/api/design/submit", methods=["POST"])
771
+ def submit_script():
772
+ """
773
+ .. :quickref: Workflow Design; submit script
774
+
775
+ .. http:get:: /api/design/submit
776
+
777
+ :status 200: {"status": "ok"}
778
+ """
779
+ deck = global_config.deck
780
+ deck_name = os.path.splitext(os.path.basename(deck.__file__))[0] if deck.__name__ == "__main__" else deck.__name__
781
+ script = Script(author=session.get('user'), deck=deck_name)
782
+ script_collection = request.get_json()
783
+ script.python_script = script_collection
784
+ # todo check script format
785
+ utils.post_script_file(script)
786
+ return jsonify({"status": "ok"}), 200