ivoryos 0.1.9__py3-none-any.whl → 0.1.12__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 (37) hide show
  1. ivoryos/__init__.py +122 -99
  2. ivoryos/config.py +47 -47
  3. ivoryos/routes/auth/auth.py +100 -65
  4. ivoryos/routes/auth/templates/auth/login.html +25 -25
  5. ivoryos/routes/auth/templates/auth/signup.html +32 -32
  6. ivoryos/routes/control/control.py +400 -272
  7. ivoryos/routes/control/templates/control/controllers.html +75 -75
  8. ivoryos/routes/control/templates/control/controllers_home.html +50 -50
  9. ivoryos/routes/control/templates/control/controllers_new.html +89 -89
  10. ivoryos/routes/database/database.py +188 -114
  11. ivoryos/routes/database/templates/database/experiment_database.html +72 -72
  12. ivoryos/routes/design/design.py +543 -416
  13. ivoryos/routes/design/templates/design/experiment_builder.html +415 -415
  14. ivoryos/routes/design/templates/design/experiment_run.html +325 -325
  15. ivoryos/routes/main/main.py +42 -25
  16. ivoryos/routes/main/templates/main/help.html +141 -141
  17. ivoryos/routes/main/templates/main/home.html +68 -68
  18. ivoryos/static/.DS_Store +0 -0
  19. ivoryos/static/js/overlay.js +12 -12
  20. ivoryos/static/js/socket_handler.js +34 -34
  21. ivoryos/static/js/sortable_card.js +24 -24
  22. ivoryos/static/js/sortable_design.js +36 -36
  23. ivoryos/static/style.css +201 -201
  24. ivoryos/templates/base.html +143 -143
  25. ivoryos/utils/db_models.py +544 -518
  26. ivoryos/utils/form.py +328 -316
  27. ivoryos/utils/global_config.py +67 -67
  28. ivoryos/utils/llm_agent.py +183 -183
  29. ivoryos/utils/script_runner.py +166 -164
  30. ivoryos/utils/utils.py +437 -422
  31. ivoryos/version.py +1 -0
  32. {ivoryos-0.1.9.dist-info → ivoryos-0.1.12.dist-info}/LICENSE +21 -21
  33. {ivoryos-0.1.9.dist-info → ivoryos-0.1.12.dist-info}/METADATA +170 -169
  34. ivoryos-0.1.12.dist-info/RECORD +47 -0
  35. {ivoryos-0.1.9.dist-info → ivoryos-0.1.12.dist-info}/WHEEL +1 -1
  36. ivoryos-0.1.9.dist-info/RECORD +0 -45
  37. {ivoryos-0.1.9.dist-info → ivoryos-0.1.12.dist-info}/top_level.txt +0 -0
@@ -1,114 +1,188 @@
1
- from flask import Blueprint, redirect, url_for, flash, request, render_template, session, current_app
2
- from flask_login import login_required
3
-
4
- from ivoryos.utils.db_models import Script, db
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("/edit_workflow/<workflow_name>")
12
- @login_required
13
- def edit_workflow(workflow_name):
14
- row = Script.query.get(workflow_name)
15
- script = Script(**row.as_dict())
16
- post_script_file(script)
17
- pseudo_name = session.get("pseudo_deck", "")
18
- off_line = current_app.config["OFF_LINE"]
19
- if off_line and pseudo_name and not script.deck == pseudo_name:
20
- flash(f"Choose the deck with name {script.deck}")
21
- return redirect(url_for('design.experiment_builder'))
22
-
23
-
24
- @database.route("/delete_workflow/<workflow_name>")
25
- @login_required
26
- def delete_workflow(workflow_name):
27
- Script.query.filter(Script.name == workflow_name).delete()
28
- db.session.commit()
29
- return redirect(url_for('database.load_from_database'))
30
-
31
-
32
- @database.route("/publish")
33
- @login_required
34
- def publish():
35
- script = get_script_file()
36
- if not script.name or not script.deck:
37
- flash("Deck cannot be empty, try to re-submit deck configuration on the left panel")
38
- row = Script.query.get(script.name)
39
- if row and row.status == "finalized":
40
- flash("This is a protected script, use save as to rename.")
41
- elif row and not session['user'] == row.author:
42
- flash("You are not the author, use save as to rename.")
43
- else:
44
- db.session.merge(script)
45
- db.session.commit()
46
- flash("Saved!")
47
- return redirect(url_for('design.experiment_builder'))
48
-
49
-
50
- @database.route("/finalize")
51
- @login_required
52
- def finalize():
53
- script = get_script_file()
54
- script.finalize()
55
- if script.name:
56
- db.session.merge(script)
57
- db.session.commit()
58
- post_script_file(script)
59
- return redirect(url_for('design.experiment_builder'))
60
-
61
-
62
- @database.route("/database/", methods=['GET', 'POST'])
63
- @database.route("/database/<deck_name>", methods=['GET', 'POST'])
64
- @login_required
65
- def load_from_database(deck_name=None):
66
- session.pop('edit_action', None) # reset cache
67
- query = Script.query
68
- search_term = request.args.get("keyword", None)
69
- if search_term:
70
- query = query.filter(Script.name.like(f'%{search_term}%'))
71
- if deck_name is None:
72
- temp = Script.query.with_entities(Script.deck).distinct().all()
73
- deck_list = [i[0] for i in temp]
74
- else:
75
- query = query.filter(Script.deck == deck_name)
76
- deck_list = ["ALL"]
77
- page = request.args.get('page', default=1, type=int)
78
- per_page = 10
79
-
80
- workflows = query.paginate(page=page, per_page=per_page, error_out=False)
81
- return render_template("experiment_database.html", workflows=workflows, deck_list=deck_list, deck_name=deck_name)
82
-
83
-
84
- @database.route("/edit_run_name", methods=['GET', 'POST'])
85
- @login_required
86
- def edit_run_name():
87
- if request.method == "POST":
88
- run_name = request.form.get("run_name")
89
- exist_script = Script.query.get(run_name)
90
- if not exist_script:
91
- script = get_script_file()
92
- script.save_as(run_name)
93
- post_script_file(script)
94
- else:
95
- flash("Script name is already exist in database")
96
- return redirect(url_for("design.experiment_builder"))
97
-
98
-
99
- @database.route("/save_as", methods=['GET', 'POST'])
100
- @login_required
101
- def save_as():
102
- # script = get_script_file()
103
- if request.method == "POST":
104
- run_name = request.form.get("run_name")
105
- exist_script = Script.query.get(run_name)
106
- if not exist_script:
107
- script = get_script_file()
108
- script.save_as(run_name)
109
- script.author = session.get('user')
110
- post_script_file(script)
111
- publish()
112
- else:
113
- flash("Script name is already exist in database")
114
- return redirect(url_for("design.experiment_builder"))
1
+ from flask import Blueprint, redirect, url_for, flash, request, render_template, session, current_app
2
+ from flask_login import login_required
3
+
4
+ from ivoryos.utils.db_models import Script, db
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("/edit_workflow/<workflow_name>")
12
+ @login_required
13
+ def edit_workflow(workflow_name):
14
+ """
15
+ .. :quickref: Database; load workflow to canvas
16
+
17
+ load the selected workflow to the design canvas
18
+
19
+ .. http:get:: /edit_workflow/<workflow_name>
20
+
21
+ :param workflow_name: workflow name
22
+ :type workflow_name: str
23
+ :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
24
+ """
25
+ row = Script.query.get(workflow_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
+ return redirect(url_for('design.experiment_builder'))
33
+
34
+
35
+ @database.route("/delete_workflow/<workflow_name>")
36
+ @login_required
37
+ def delete_workflow(workflow_name: str):
38
+ """
39
+ .. :quickref: Database; delete workflow
40
+
41
+ delete workflow from database
42
+
43
+ .. http:get:: /delete_workflow/<workflow_name>
44
+
45
+ :param workflow_name: workflow name
46
+ :type workflow_name: str
47
+ :status 302: redirect to :http:get:`/ivoryos/database/`
48
+
49
+ """
50
+ Script.query.filter(Script.name == workflow_name).delete()
51
+ db.session.commit()
52
+ return redirect(url_for('database.load_from_database'))
53
+
54
+
55
+ @database.route("/publish")
56
+ @login_required
57
+ def publish():
58
+ """
59
+ .. :quickref: Database; save workflow to database
60
+
61
+ save workflow to database
62
+
63
+ .. http:get:: /publish
64
+
65
+ :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
66
+ """
67
+ script = get_script_file()
68
+ if not script.name or not script.deck:
69
+ flash("Deck cannot be empty, try to re-submit deck configuration on the left panel")
70
+ row = Script.query.get(script.name)
71
+ if row and row.status == "finalized":
72
+ flash("This is a protected script, use save as to rename.")
73
+ elif row and not session['user'] == row.author:
74
+ flash("You are not the author, use save as to rename.")
75
+ else:
76
+ db.session.merge(script)
77
+ db.session.commit()
78
+ flash("Saved!")
79
+ return redirect(url_for('design.experiment_builder'))
80
+
81
+
82
+ @database.route("/finalize")
83
+ @login_required
84
+ def finalize():
85
+ """
86
+ .. :quickref: Database; finalize the workflow
87
+
88
+ [protected workflow] prevent saving edited workflow to the same workflow name
89
+
90
+ .. http:get:: /finalize
91
+
92
+ :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
93
+
94
+ """
95
+ script = get_script_file()
96
+ script.finalize()
97
+ if script.name:
98
+ db.session.merge(script)
99
+ db.session.commit()
100
+ post_script_file(script)
101
+ return redirect(url_for('design.experiment_builder'))
102
+
103
+
104
+ @database.route("/database/")
105
+ @database.route("/database/<deck_name>")
106
+ @login_required
107
+ def load_from_database(deck_name=None):
108
+ """
109
+ .. :quickref: Database; database page
110
+
111
+ backend control through http requests
112
+
113
+ .. http:get:: /database/<deck_name>
114
+
115
+ :param deck_name: filter for deck name
116
+ :type deck_name: str
117
+
118
+ """
119
+ session.pop('edit_action', None) # reset cache
120
+ query = Script.query
121
+ search_term = request.args.get("keyword", None)
122
+ if search_term:
123
+ query = query.filter(Script.name.like(f'%{search_term}%'))
124
+ if deck_name is None:
125
+ temp = Script.query.with_entities(Script.deck).distinct().all()
126
+ deck_list = [i[0] for i in temp]
127
+ else:
128
+ query = query.filter(Script.deck == deck_name)
129
+ deck_list = ["ALL"]
130
+ page = request.args.get('page', default=1, type=int)
131
+ per_page = 10
132
+
133
+ workflows = query.paginate(page=page, per_page=per_page, error_out=False)
134
+ return render_template("experiment_database.html", workflows=workflows, deck_list=deck_list, deck_name=deck_name)
135
+
136
+
137
+ @database.route("/edit_run_name", methods=['POST'])
138
+ @login_required
139
+ def edit_run_name():
140
+ """
141
+ .. :quickref: Database; edit workflow name
142
+
143
+ edit the name of the current workflow, won't save to the database
144
+
145
+ .. http:post:: /edit_run_name
146
+
147
+ : form run_name: new workflow name
148
+ :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
149
+
150
+ """
151
+ if request.method == "POST":
152
+ run_name = request.form.get("run_name")
153
+ exist_script = Script.query.get(run_name)
154
+ if not exist_script:
155
+ script = get_script_file()
156
+ script.save_as(run_name)
157
+ post_script_file(script)
158
+ else:
159
+ flash("Script name is already exist in database")
160
+ return redirect(url_for("design.experiment_builder"))
161
+
162
+
163
+ @database.route("/save_as", methods=['POST'])
164
+ @login_required
165
+ def save_as():
166
+ """
167
+ .. :quickref: Database; save the run name as
168
+
169
+ save the workflow name as
170
+
171
+ .. http:post:: /save_as
172
+
173
+ : form run_name: new workflow name
174
+ :status 302: redirect to :http:get:`/ivoryos/experiment/build/`
175
+
176
+ """
177
+ if request.method == "POST":
178
+ run_name = request.form.get("run_name")
179
+ exist_script = Script.query.get(run_name)
180
+ if not exist_script:
181
+ script = get_script_file()
182
+ script.save_as(run_name)
183
+ script.author = session.get('user')
184
+ post_script_file(script)
185
+ publish()
186
+ else:
187
+ flash("Script name is already exist in database")
188
+ return redirect(url_for("design.experiment_builder"))
@@ -1,72 +1,72 @@
1
- {% extends 'base.html' %}
2
-
3
- {% block title %}IvoryOS | Design Database{% endblock %}
4
- {% block body %}
5
- <div class="database-filter">
6
- {% for deck_name in deck_list %}
7
- {% if deck_name == "ALL" %}<a class="btn btn-secondary" href="{{url_for('database.load_from_database')}}">Back</a>
8
- {% else %}<a class="btn btn-secondary" href="{{url_for('database.load_from_database',deck_name=deck_name)}}">{{deck_name}}</a>
9
- {% endif %}
10
- {% endfor %}
11
-
12
- <form id="search" style="display: inline-block;float: right;" action="{{url_for('database.load_from_database',deck_name=deck_name)}}" method="GET">
13
- <div class="input-group">
14
- <div class="form-outline">
15
- <input type="search" name="keyword" id="keyword" class="form-control" placeholder="Search workflows...">
16
- </div>
17
- <button type="submit" class="btn btn-primary">
18
- <i class="bi bi-search"></i>
19
- </button>
20
- </div>
21
- </form>
22
- </div>
23
-
24
- <table class="table table-hover" id="workflowLibrary">
25
- <thead>
26
- <tr>
27
- <th scope="col">Workflow name</th>
28
- <th scope="col">Deck </th>
29
- <th scope="col">Current status</th>
30
- <th scope="col">Time created</th>
31
- <th scope="col">Last modified</th>
32
- <th scope="col">Author</th>
33
- <th scope="col"></th>
34
- </tr>
35
- </thead>
36
- <tbody>
37
- {% for workflow in workflows %}
38
- <tr>
39
- <td><a href="{{ url_for('database.edit_workflow', workflow_name=workflow.name) }}">{{ workflow.name }}</a></td>
40
- <td>{{ workflow.deck }}</td>
41
- <td>{{ workflow.status }}</td>
42
- <td>{{ workflow.time_created }}</td>
43
- <td>{{ workflow.last_modified }}</td>
44
- <td>{{ workflow.author }}</td>
45
- <td>
46
- {#not workflow.status == "finalized" or#}
47
- {% if session['user'] == 'admin' or session['user'] == workflow.author %}
48
- <a href="{{ url_for('database.delete_workflow', workflow_name=workflow.name) }}">delete</a>
49
- {% else %}
50
- <a class="disabled-link" href="{{ url_for('database.delete_workflow', workflow_name=workflow.name) }}">delete</a>
51
- {% endif %}
52
- <td>
53
- </tr>
54
- {% endfor %}
55
- </tbody>
56
- </table>
57
-
58
- {# paging#}
59
- <div class="pagination justify-content-center">
60
- <div class="page-item {{ 'disabled' if not workflows.has_prev else '' }}">
61
- <a class="page-link" href="{{ url_for('database.load_from_database', page=workflows.prev_num) }}">Previous</a>
62
- </div>
63
- {% for num in workflows.iter_pages() %}
64
- <div class="page-item">
65
- <a class="page-link {{ 'active' if num == workflows.page else '' }}" href="{{ url_for('database.load_from_database', page=num) }}">{{ num }}</a>
66
- </div>
67
- {% endfor %}
68
- <div class="page-item {{ 'disabled' if not workflows.has_next else '' }}">
69
- <a class="page-link" href="{{ url_for('database.load_from_database', page=workflows.next_num) }}">Next</a>
70
- </div>
71
- </div>
72
- {% endblock %}
1
+ {% extends 'base.html' %}
2
+
3
+ {% block title %}IvoryOS | Design Database{% endblock %}
4
+ {% block body %}
5
+ <div class="database-filter">
6
+ {% for deck_name in deck_list %}
7
+ {% if deck_name == "ALL" %}<a class="btn btn-secondary" href="{{url_for('database.load_from_database')}}">Back</a>
8
+ {% else %}<a class="btn btn-secondary" href="{{url_for('database.load_from_database',deck_name=deck_name)}}">{{deck_name}}</a>
9
+ {% endif %}
10
+ {% endfor %}
11
+
12
+ <form id="search" style="display: inline-block;float: right;" action="{{url_for('database.load_from_database',deck_name=deck_name)}}" method="GET">
13
+ <div class="input-group">
14
+ <div class="form-outline">
15
+ <input type="search" name="keyword" id="keyword" class="form-control" placeholder="Search workflows...">
16
+ </div>
17
+ <button type="submit" class="btn btn-primary">
18
+ <i class="bi bi-search"></i>
19
+ </button>
20
+ </div>
21
+ </form>
22
+ </div>
23
+
24
+ <table class="table table-hover" id="workflowLibrary">
25
+ <thead>
26
+ <tr>
27
+ <th scope="col">Workflow name</th>
28
+ <th scope="col">Deck </th>
29
+ <th scope="col">Current status</th>
30
+ <th scope="col">Time created</th>
31
+ <th scope="col">Last modified</th>
32
+ <th scope="col">Author</th>
33
+ <th scope="col"></th>
34
+ </tr>
35
+ </thead>
36
+ <tbody>
37
+ {% for workflow in workflows %}
38
+ <tr>
39
+ <td><a href="{{ url_for('database.edit_workflow', workflow_name=workflow.name) }}">{{ workflow.name }}</a></td>
40
+ <td>{{ workflow.deck }}</td>
41
+ <td>{{ workflow.status }}</td>
42
+ <td>{{ workflow.time_created }}</td>
43
+ <td>{{ workflow.last_modified }}</td>
44
+ <td>{{ workflow.author }}</td>
45
+ <td>
46
+ {#not workflow.status == "finalized" or#}
47
+ {% if session['user'] == 'admin' or session['user'] == workflow.author %}
48
+ <a href="{{ url_for('database.delete_workflow', workflow_name=workflow.name) }}">delete</a>
49
+ {% else %}
50
+ <a class="disabled-link" href="{{ url_for('database.delete_workflow', workflow_name=workflow.name) }}">delete</a>
51
+ {% endif %}
52
+ <td>
53
+ </tr>
54
+ {% endfor %}
55
+ </tbody>
56
+ </table>
57
+
58
+ {# paging#}
59
+ <div class="pagination justify-content-center">
60
+ <div class="page-item {{ 'disabled' if not workflows.has_prev else '' }}">
61
+ <a class="page-link" href="{{ url_for('database.load_from_database', page=workflows.prev_num) }}">Previous</a>
62
+ </div>
63
+ {% for num in workflows.iter_pages() %}
64
+ <div class="page-item">
65
+ <a class="page-link {{ 'active' if num == workflows.page else '' }}" href="{{ url_for('database.load_from_database', page=num) }}">{{ num }}</a>
66
+ </div>
67
+ {% endfor %}
68
+ <div class="page-item {{ 'disabled' if not workflows.has_next else '' }}">
69
+ <a class="page-link" href="{{ url_for('database.load_from_database', page=workflows.next_num) }}">Next</a>
70
+ </div>
71
+ </div>
72
+ {% endblock %}