ivoryos 1.3.5a0__py3-none-any.whl → 1.3.6__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 +6 -2
- ivoryos/optimizer/ax_optimizer.py +3 -3
- ivoryos/optimizer/base_optimizer.py +2 -1
- ivoryos/optimizer/registry.py +3 -1
- ivoryos/routes/design/design.py +12 -3
- ivoryos/routes/design/design_step.py +38 -13
- ivoryos/routes/design/templates/components/canvas_main.html +6 -1
- ivoryos/routes/design/templates/components/edit_action_form.html +2 -0
- ivoryos/server.py +5 -1
- ivoryos/static/js/action_handlers.js +48 -11
- ivoryos/utils/bo_campaign.py +1 -1
- ivoryos/utils/db_models.py +14 -5
- ivoryos/utils/form.py +8 -4
- ivoryos/utils/script_runner.py +4 -2
- ivoryos/version.py +1 -1
- {ivoryos-1.3.5a0.dist-info → ivoryos-1.3.6.dist-info}/METADATA +15 -2
- {ivoryos-1.3.5a0.dist-info → ivoryos-1.3.6.dist-info}/RECORD +20 -20
- {ivoryos-1.3.5a0.dist-info → ivoryos-1.3.6.dist-info}/WHEEL +0 -0
- {ivoryos-1.3.5a0.dist-info → ivoryos-1.3.6.dist-info}/licenses/LICENSE +0 -0
- {ivoryos-1.3.5a0.dist-info → ivoryos-1.3.6.dist-info}/top_level.txt +0 -0
ivoryos/__init__.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from ivoryos.server import run
|
|
1
|
+
from ivoryos.server import run, global_config
|
|
2
2
|
from ivoryos.optimizer.registry import OPTIMIZER_REGISTRY
|
|
3
3
|
from ivoryos.version import __version__ as ivoryos_version
|
|
4
4
|
from ivoryos.utils.decorators import block, BUILDING_BLOCKS
|
|
5
|
-
from ivoryos.app import app
|
|
5
|
+
from ivoryos.app import app, create_app, socketio, db
|
|
6
6
|
|
|
7
7
|
__all__ = [
|
|
8
8
|
"block",
|
|
@@ -11,4 +11,8 @@ __all__ = [
|
|
|
11
11
|
"run",
|
|
12
12
|
"app",
|
|
13
13
|
"ivoryos_version",
|
|
14
|
+
"create_app",
|
|
15
|
+
"socketio",
|
|
16
|
+
"global_config",
|
|
17
|
+
"db"
|
|
14
18
|
]
|
|
@@ -30,7 +30,7 @@ class AxOptimizer(OptimizerBase):
|
|
|
30
30
|
@staticmethod
|
|
31
31
|
def _create_generator_mapping():
|
|
32
32
|
"""Create a mapping from string values to Generator enum members."""
|
|
33
|
-
from ax.
|
|
33
|
+
from ax.adapter import Generators
|
|
34
34
|
return {member.value: member for member in Generators}
|
|
35
35
|
|
|
36
36
|
def _convert_parameter_to_ax_format(self, parameter_space):
|
|
@@ -96,8 +96,8 @@ class AxOptimizer(OptimizerBase):
|
|
|
96
96
|
step_2 = optimizer_config.get("step_2", {})
|
|
97
97
|
step_1_generator = step_1.get("model", "Sobol")
|
|
98
98
|
step_2_generator = step_2.get("model", "BOTorch")
|
|
99
|
-
generator_1 = GenerationStep(
|
|
100
|
-
generator_2 = GenerationStep(
|
|
99
|
+
generator_1 = GenerationStep(generator=generators.get(step_1_generator), num_trials=step_1.get("num_samples", 5))
|
|
100
|
+
generator_2 = GenerationStep(generator=generators.get(step_2_generator), num_trials=step_2.get("num_samples", -1))
|
|
101
101
|
return GenerationStrategy(steps=[generator_1, generator_2])
|
|
102
102
|
|
|
103
103
|
def suggest(self, n=1):
|
|
@@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class OptimizerBase(ABC):
|
|
8
|
-
def __init__(self, experiment_name:str, parameter_space: list, objective_config: dict, optimizer_config: dict):
|
|
8
|
+
def __init__(self, experiment_name:str, parameter_space: list, objective_config: dict, optimizer_config: dict, datapath:str=None):
|
|
9
9
|
"""
|
|
10
10
|
:param experiment_name: arbitrary name
|
|
11
11
|
:param parameter_space: list of parameter names
|
|
@@ -29,6 +29,7 @@ class OptimizerBase(ABC):
|
|
|
29
29
|
self.parameter_space = parameter_space
|
|
30
30
|
self.objective_config = objective_config
|
|
31
31
|
self.optimizer_config = optimizer_config
|
|
32
|
+
self.datapath = datapath
|
|
32
33
|
|
|
33
34
|
@abstractmethod
|
|
34
35
|
def suggest(self, n=1):
|
ivoryos/optimizer/registry.py
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from ivoryos.optimizer.ax_optimizer import AxOptimizer
|
|
4
4
|
from ivoryos.optimizer.baybe_optimizer import BaybeOptimizer
|
|
5
|
+
from ivoryos.optimizer.nimo_optimizer import NIMOOptimizer
|
|
5
6
|
|
|
6
7
|
OPTIMIZER_REGISTRY = {
|
|
7
8
|
"ax": AxOptimizer,
|
|
8
|
-
"baybe": BaybeOptimizer
|
|
9
|
+
"baybe": BaybeOptimizer,
|
|
10
|
+
"nimo": NIMOOptimizer,
|
|
9
11
|
}
|
ivoryos/routes/design/design.py
CHANGED
|
@@ -87,8 +87,11 @@ def experiment_builder():
|
|
|
87
87
|
|
|
88
88
|
# edit_action_info = session.get("edit_action")
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
try:
|
|
91
|
+
exec_string = script.python_script if script.python_script else script.compile(current_app.config['SCRIPT_FOLDER'])
|
|
92
|
+
except Exception as e:
|
|
93
|
+
exec_string = {}
|
|
94
|
+
flash(f"Error in Python script: {e}")
|
|
92
95
|
session['python_code'] = exec_string
|
|
93
96
|
|
|
94
97
|
design_buttons = {stype: create_action_button(script, stype) for stype in script.stypes}
|
|
@@ -382,7 +385,13 @@ def methods_handler(instrument: str = ''):
|
|
|
382
385
|
success = False
|
|
383
386
|
msg = [f"{field}: {', '.join(messages)}" for field, messages in form.errors.items()]
|
|
384
387
|
utils.post_script_file(script)
|
|
385
|
-
|
|
388
|
+
#TODO
|
|
389
|
+
try:
|
|
390
|
+
exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
|
|
391
|
+
except Exception as e:
|
|
392
|
+
exec_string = {}
|
|
393
|
+
msg = f"Compilation failed: {str(e)}"
|
|
394
|
+
# exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
|
|
386
395
|
session['python_code'] = exec_string
|
|
387
396
|
design_buttons = {stype: create_action_button(script, stype) for stype in script.stypes}
|
|
388
397
|
html = render_template("components/canvas_main.html", script=script, buttons_dict=design_buttons)
|
|
@@ -23,12 +23,16 @@ def get_step(uuid: int):
|
|
|
23
23
|
"""
|
|
24
24
|
script = utils.get_script_file()
|
|
25
25
|
action = script.find_by_uuid(uuid)
|
|
26
|
-
if
|
|
27
|
-
|
|
26
|
+
if action is None:
|
|
27
|
+
return jsonify({"warning": "Step not found, please refresh the page."}), 404
|
|
28
|
+
|
|
29
|
+
elif request.method == 'GET':
|
|
30
|
+
forms = create_form_from_action(action, script=script)
|
|
28
31
|
# session['edit_action'] = action
|
|
29
32
|
return render_template("components/edit_action_form.html",
|
|
30
33
|
action=action,
|
|
31
|
-
forms=
|
|
34
|
+
forms=forms)
|
|
35
|
+
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
@steps.post("/draft/steps/<int:uuid>")
|
|
@@ -47,6 +51,7 @@ def save_step(uuid: int):
|
|
|
47
51
|
"""
|
|
48
52
|
script = utils.get_script_file()
|
|
49
53
|
action = script.find_by_uuid(uuid)
|
|
54
|
+
warning = None
|
|
50
55
|
if action is not None:
|
|
51
56
|
forms = create_form_from_action(action, script=script)
|
|
52
57
|
kwargs = {field.name: field.data for field in forms if field.name != 'csrf_token'}
|
|
@@ -55,14 +60,19 @@ def save_step(uuid: int):
|
|
|
55
60
|
kwargs = script.validate_variables(kwargs)
|
|
56
61
|
script.update_by_uuid(uuid=uuid, args=kwargs, output=save_as)
|
|
57
62
|
else:
|
|
58
|
-
|
|
63
|
+
warning = f"Compilation failed: {str(forms.errors)}"
|
|
59
64
|
utils.post_script_file(script)
|
|
60
|
-
|
|
65
|
+
try:
|
|
66
|
+
exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
|
|
67
|
+
except Exception as e:
|
|
68
|
+
exec_string = {}
|
|
69
|
+
warning = f"Compilation failed: {str(e)}"
|
|
61
70
|
session['python_code'] = exec_string
|
|
62
71
|
design_buttons = {stype: create_action_button(script, stype) for stype in script.stypes}
|
|
63
72
|
return render_template("components/canvas_main.html",
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
script=script,
|
|
74
|
+
buttons_dict=design_buttons,
|
|
75
|
+
warning=warning)
|
|
66
76
|
|
|
67
77
|
@steps.delete("/draft/steps/<int:uuid>")
|
|
68
78
|
def delete_step(uuid: int):
|
|
@@ -82,12 +92,17 @@ def delete_step(uuid: int):
|
|
|
82
92
|
if request.method == 'DELETE':
|
|
83
93
|
script.delete_action(uuid)
|
|
84
94
|
utils.post_script_file(script)
|
|
85
|
-
|
|
95
|
+
warning = None
|
|
96
|
+
try:
|
|
97
|
+
exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
|
|
98
|
+
except Exception as e:
|
|
99
|
+
exec_string = {}
|
|
100
|
+
warning = f"Compilation failed: {str(e)}"
|
|
86
101
|
session['python_code'] = exec_string
|
|
87
102
|
design_buttons = {stype: create_action_button(script, stype) for stype in script.stypes}
|
|
88
103
|
return render_template("components/canvas_main.html",
|
|
89
104
|
script=script,
|
|
90
|
-
buttons_dict=design_buttons)
|
|
105
|
+
buttons_dict=design_buttons, warning=warning)
|
|
91
106
|
|
|
92
107
|
|
|
93
108
|
@steps.route("/draft/steps/<int:uuid>/duplicate", methods=["POST"], strict_slashes=False,)
|
|
@@ -107,13 +122,18 @@ def duplicate_action(uuid: int):
|
|
|
107
122
|
script = utils.get_script_file()
|
|
108
123
|
script.duplicate_action(uuid)
|
|
109
124
|
utils.post_script_file(script)
|
|
110
|
-
|
|
125
|
+
warning = None
|
|
126
|
+
try:
|
|
127
|
+
exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
|
|
128
|
+
except Exception as e:
|
|
129
|
+
exec_string = {}
|
|
130
|
+
warning = f"Compilation failed: {str(e)}"
|
|
111
131
|
session['python_code'] = exec_string
|
|
112
132
|
design_buttons = {stype: create_action_button(script, stype) for stype in script.stypes}
|
|
113
133
|
|
|
114
134
|
return render_template("components/canvas_main.html",
|
|
115
135
|
script=script,
|
|
116
|
-
buttons_dict=design_buttons)
|
|
136
|
+
buttons_dict=design_buttons, warning=warning)
|
|
117
137
|
|
|
118
138
|
|
|
119
139
|
@steps.route("/draft/steps/order", methods=['POST'])
|
|
@@ -133,13 +153,18 @@ def update_list():
|
|
|
133
153
|
script = utils.get_script_file()
|
|
134
154
|
script.currently_editing_order = order.split(",", len(script.currently_editing_script))
|
|
135
155
|
script.sort_actions()
|
|
156
|
+
warning = None
|
|
136
157
|
|
|
137
158
|
utils.post_script_file(script)
|
|
138
|
-
|
|
159
|
+
try:
|
|
160
|
+
exec_string = script.compile(current_app.config['SCRIPT_FOLDER'])
|
|
161
|
+
except Exception as e:
|
|
162
|
+
exec_string = {}
|
|
163
|
+
warning = f"Compilation failed: {str(e)}"
|
|
139
164
|
session['python_code'] = exec_string
|
|
140
165
|
|
|
141
166
|
# Return the updated canvas HTML instead of JSON
|
|
142
167
|
design_buttons = {stype: create_action_button(script, stype) for stype in script.stypes}
|
|
143
168
|
return render_template("components/canvas_main.html",
|
|
144
169
|
script=script,
|
|
145
|
-
buttons_dict=design_buttons)
|
|
170
|
+
buttons_dict=design_buttons, warning=warning)
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
<i class="bi bi-arrow-return-left"></i>
|
|
7
7
|
</a>
|
|
8
8
|
</div>
|
|
9
|
+
{% if action %}
|
|
9
10
|
<h5> {{ action['action'] | format_name }} </h5>
|
|
10
11
|
<form role="form" method='POST' name="{{instrument}}"
|
|
11
12
|
action="{{ url_for('design.design_steps.get_step', uuid=action['uuid']) }}"
|
|
@@ -36,3 +37,4 @@
|
|
|
36
37
|
<button type="submit" class="btn btn-primary">Save</button>
|
|
37
38
|
<button type="button" class="btn btn-primary" id="back">Back</button>
|
|
38
39
|
</form>
|
|
40
|
+
{% endif %}
|
ivoryos/server.py
CHANGED
|
@@ -50,6 +50,7 @@ def run(module=None, host="0.0.0.0", port=None, debug=None, llm_server=None, mod
|
|
|
50
50
|
blueprint_plugins: Union[list, Blueprint] = [],
|
|
51
51
|
exclude_names: list = [],
|
|
52
52
|
notification_handler=None,
|
|
53
|
+
optimizer_registry: dict = None,
|
|
53
54
|
):
|
|
54
55
|
"""
|
|
55
56
|
Start ivoryOS app server.
|
|
@@ -91,7 +92,10 @@ def run(module=None, host="0.0.0.0", port=None, debug=None, llm_server=None, mod
|
|
|
91
92
|
app.config["LOGGERS_PATH"] = logger_output_name or app.config["LOGGERS_PATH"] # default.log
|
|
92
93
|
logger_path = os.path.join(app.config["OUTPUT_FOLDER"], app.config["LOGGERS_PATH"])
|
|
93
94
|
dummy_deck_path = os.path.join(app.config["OUTPUT_FOLDER"], app.config["DUMMY_DECK"])
|
|
94
|
-
|
|
95
|
+
if optimizer_registry:
|
|
96
|
+
global_config.optimizers = optimizer_registry
|
|
97
|
+
else:
|
|
98
|
+
global_config.optimizers = OPTIMIZER_REGISTRY
|
|
95
99
|
if module:
|
|
96
100
|
app.config["MODULE"] = module
|
|
97
101
|
app.config["OFF_LINE"] = False
|
|
@@ -103,6 +103,12 @@ function submitEditForm(event) {
|
|
|
103
103
|
document.getElementById('instrument-panel').innerHTML = previousHtmlState;
|
|
104
104
|
previousHtmlState = null; // Clear the stored state
|
|
105
105
|
}
|
|
106
|
+
const parser = new DOMParser();
|
|
107
|
+
const doc = parser.parseFromString(html, 'text/html');
|
|
108
|
+
const warningDiv = doc.querySelector('#warning');
|
|
109
|
+
if (warningDiv && warningDiv.textContent.trim()) {
|
|
110
|
+
alert(warningDiv.textContent.trim()); // or use a nicer toast
|
|
111
|
+
}
|
|
106
112
|
}
|
|
107
113
|
})
|
|
108
114
|
.catch(error => {
|
|
@@ -149,6 +155,13 @@ function duplicateAction(uuid) {
|
|
|
149
155
|
.then(response => response.text())
|
|
150
156
|
.then(html => {
|
|
151
157
|
updateActionCanvas(html);
|
|
158
|
+
|
|
159
|
+
const parser = new DOMParser();
|
|
160
|
+
const doc = parser.parseFromString(html, 'text/html');
|
|
161
|
+
const warningDiv = doc.querySelector('#warning');
|
|
162
|
+
if (warningDiv && warningDiv.textContent.trim()) {
|
|
163
|
+
alert(warningDiv.textContent.trim()); // or use a nicer toast
|
|
164
|
+
}
|
|
152
165
|
})
|
|
153
166
|
.catch(error => console.error('Error:', error));
|
|
154
167
|
}
|
|
@@ -159,33 +172,50 @@ function editAction(uuid) {
|
|
|
159
172
|
return;
|
|
160
173
|
}
|
|
161
174
|
|
|
162
|
-
// Save current state before fetching new content
|
|
163
175
|
previousHtmlState = document.getElementById('instrument-panel').innerHTML;
|
|
164
176
|
|
|
165
177
|
fetch(scriptStepUrl.replace('0', uuid), {
|
|
166
|
-
method: 'GET',
|
|
178
|
+
method: 'GET', // no need for Content-Type on GET
|
|
167
179
|
headers: {
|
|
168
180
|
'Content-Type': 'application/json'
|
|
169
181
|
}
|
|
170
182
|
})
|
|
171
|
-
.then(response =>
|
|
183
|
+
.then(response => {
|
|
184
|
+
if (!response.ok) {
|
|
185
|
+
return response.json().then(err => {
|
|
186
|
+
if (err.warning) {
|
|
187
|
+
alert(err.warning); // <-- should fire now
|
|
188
|
+
}
|
|
189
|
+
// restore panel so user isn't stuck
|
|
190
|
+
if (previousHtmlState) {
|
|
191
|
+
document.getElementById('instrument-panel').innerHTML = previousHtmlState;
|
|
192
|
+
previousHtmlState = null;
|
|
193
|
+
}
|
|
194
|
+
throw new Error("Step fetch failed: " + response.status);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return response.text();
|
|
198
|
+
})
|
|
172
199
|
.then(html => {
|
|
173
200
|
document.getElementById('instrument-panel').innerHTML = html;
|
|
174
201
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
202
|
+
const backButton = document.getElementById('back');
|
|
203
|
+
if (backButton) {
|
|
204
|
+
backButton.addEventListener('click', function(e) {
|
|
205
|
+
e.preventDefault();
|
|
206
|
+
if (previousHtmlState) {
|
|
207
|
+
document.getElementById('instrument-panel').innerHTML = previousHtmlState;
|
|
208
|
+
previousHtmlState = null;
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
183
212
|
})
|
|
184
213
|
.catch(error => console.error('Error:', error));
|
|
185
214
|
}
|
|
186
215
|
|
|
187
216
|
|
|
188
217
|
|
|
218
|
+
|
|
189
219
|
function deleteAction(uuid) {
|
|
190
220
|
if (!uuid) {
|
|
191
221
|
console.error('Invalid UUID');
|
|
@@ -202,6 +232,13 @@ function deleteAction(uuid) {
|
|
|
202
232
|
.then(html => {
|
|
203
233
|
// Find the first list element's content and replace it
|
|
204
234
|
updateActionCanvas(html);
|
|
235
|
+
// Optionally, check if a warning element exists
|
|
236
|
+
const parser = new DOMParser();
|
|
237
|
+
const doc = parser.parseFromString(html, 'text/html');
|
|
238
|
+
const warningDiv = doc.querySelector('#warning');
|
|
239
|
+
if (warningDiv && warningDiv.textContent.trim()) {
|
|
240
|
+
alert(warningDiv.textContent.trim()); // or use a nicer toast
|
|
241
|
+
}
|
|
205
242
|
})
|
|
206
243
|
.catch(error => console.error('Error:', error));
|
|
207
244
|
}
|
ivoryos/utils/bo_campaign.py
CHANGED
|
@@ -209,7 +209,7 @@ def parse_optimization_form(form_data: Dict[str, str]):
|
|
|
209
209
|
parameter["bounds"] = bounds
|
|
210
210
|
|
|
211
211
|
elif value == "choice":
|
|
212
|
-
choices_field = f"{param_name}
|
|
212
|
+
choices_field = f"{param_name}_value"
|
|
213
213
|
if choices_field in form_data and form_data[choices_field]:
|
|
214
214
|
# Split choices by comma and clean whitespace
|
|
215
215
|
choices = [choice.strip() for choice in form_data[choices_field].split(',')]
|
ivoryos/utils/db_models.py
CHANGED
|
@@ -644,12 +644,21 @@ class Script(db.Model):
|
|
|
644
644
|
args_str = args_str.replace(f"'#{args[arg][1:]}'", args[arg][1:])
|
|
645
645
|
elif isinstance(args[arg], dict):
|
|
646
646
|
# print(args[arg])
|
|
647
|
-
|
|
647
|
+
if not args[arg]:
|
|
648
|
+
continue
|
|
649
|
+
# Extract the variable name (first key in the dict)
|
|
648
650
|
value = next(iter(args[arg]))
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
651
|
+
var_type = args[arg].get(value)
|
|
652
|
+
|
|
653
|
+
# Only process if it's a function_output variable reference
|
|
654
|
+
if var_type == "function_output":
|
|
655
|
+
variables = self.get_variables()
|
|
656
|
+
if value not in variables:
|
|
657
|
+
raise ValueError(f"Variable ({value}) is not defined.")
|
|
658
|
+
# Replace the dict string representation with just the variable name
|
|
659
|
+
args_str = args_str.replace(f"{args[arg]}", value)
|
|
660
|
+
|
|
661
|
+
# elif self._is_variable(arg):
|
|
653
662
|
# print("is variable")
|
|
654
663
|
# args_str = args_str.replace(f"'{args[arg]}'", args[arg])
|
|
655
664
|
return args_str
|
ivoryos/utils/form.py
CHANGED
|
@@ -405,7 +405,7 @@ def create_form_from_action(action: dict, script=None, design=True):
|
|
|
405
405
|
for name, param_type in arg_types.items():
|
|
406
406
|
# formatted_param_name = format_name(name)
|
|
407
407
|
value = args.get(name, "")
|
|
408
|
-
if type(value) is dict:
|
|
408
|
+
if type(value) is dict and value:
|
|
409
409
|
value = next(iter(value))
|
|
410
410
|
field_kwargs = {
|
|
411
411
|
"label": name,
|
|
@@ -556,9 +556,13 @@ def _action_button(action: dict, variables: dict):
|
|
|
556
556
|
arg_list = []
|
|
557
557
|
for k, v in action['args'].items():
|
|
558
558
|
if isinstance(v, dict):
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
559
|
+
if not v:
|
|
560
|
+
value = v # Keep the original value if not a dict
|
|
561
|
+
else:
|
|
562
|
+
value = next(iter(v)) # Extract the first key if it's a dict
|
|
563
|
+
# show warning color for variable calling when there is no definition
|
|
564
|
+
|
|
565
|
+
style = "background-color: khaki" if v.get(value) == "function_output" and value not in variables.keys() else ""
|
|
562
566
|
else:
|
|
563
567
|
value = v # Keep the original value if not a dict
|
|
564
568
|
arg_list.append(f"{k} = {value}") # Format the key-value pair
|
ivoryos/utils/script_runner.py
CHANGED
|
@@ -195,11 +195,12 @@ class ScriptRunner:
|
|
|
195
195
|
|
|
196
196
|
# Update exec_locals with the returned locals
|
|
197
197
|
exec_locals.update(result_locals)
|
|
198
|
-
|
|
198
|
+
|
|
199
199
|
|
|
200
200
|
else:
|
|
201
|
-
print("just exec synchronously")
|
|
201
|
+
# print("just exec synchronously")
|
|
202
202
|
exec(line, exec_globals, exec_locals)
|
|
203
|
+
exec_globals.update(exec_locals)
|
|
203
204
|
# return locals_dict
|
|
204
205
|
# exec(line, exec_globals, exec_locals)
|
|
205
206
|
# step.run_error = False
|
|
@@ -217,6 +218,7 @@ class ScriptRunner:
|
|
|
217
218
|
|
|
218
219
|
step.run_error = True
|
|
219
220
|
self.toggle_pause()
|
|
221
|
+
exec_locals.pop("__async_exec_wrapper", None)
|
|
220
222
|
step.end_time = datetime.now()
|
|
221
223
|
step.output = exec_locals
|
|
222
224
|
db.session.commit()
|
ivoryos/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.3.
|
|
1
|
+
__version__ = "1.3.6"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ivoryos
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.6
|
|
4
4
|
Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
|
|
5
5
|
Author-email: Ivory Zhang <ivoryzhang@chem.ubc.ca>
|
|
6
6
|
License: MIT
|
|
@@ -9,6 +9,7 @@ Requires-Python: >=3.7
|
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: bcrypt
|
|
12
|
+
Requires-Dist: Flask[async]
|
|
12
13
|
Requires-Dist: Flask-Login
|
|
13
14
|
Requires-Dist: Flask-Session
|
|
14
15
|
Requires-Dist: Flask-SocketIO
|
|
@@ -17,9 +18,21 @@ Requires-Dist: Flask-WTF
|
|
|
17
18
|
Requires-Dist: SQLAlchemy-Utils
|
|
18
19
|
Requires-Dist: python-dotenv
|
|
19
20
|
Requires-Dist: astor; python_version < "3.9"
|
|
21
|
+
Provides-Extra: optimizer-ax
|
|
22
|
+
Requires-Dist: ax-platform; extra == "optimizer-ax"
|
|
23
|
+
Provides-Extra: optimizer-baybe
|
|
24
|
+
Requires-Dist: baybe; extra == "optimizer-baybe"
|
|
25
|
+
Provides-Extra: optimizer-nimo
|
|
26
|
+
Requires-Dist: nimo; extra == "optimizer-nimo"
|
|
20
27
|
Provides-Extra: optimizer
|
|
21
|
-
Requires-Dist: ax-platform; extra == "optimizer"
|
|
28
|
+
Requires-Dist: ax-platform>=1.1.2; extra == "optimizer"
|
|
22
29
|
Requires-Dist: baybe; extra == "optimizer"
|
|
30
|
+
Provides-Extra: doc
|
|
31
|
+
Requires-Dist: sphinx; extra == "doc"
|
|
32
|
+
Requires-Dist: sphinx-rtd-theme; extra == "doc"
|
|
33
|
+
Requires-Dist: sphinxcontrib-httpdomain; extra == "doc"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest; extra == "dev"
|
|
23
36
|
Dynamic: license-file
|
|
24
37
|
|
|
25
38
|
[](https://ivoryos.readthedocs.io/en/latest/?badge=latest)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
ivoryos/__init__.py,sha256=
|
|
1
|
+
ivoryos/__init__.py,sha256=gEvBO2y5TRq06Itjjej3iAcq73UsihqKPWcb2HykPwM,463
|
|
2
2
|
ivoryos/app.py,sha256=G6kzEOVzCduj7Fc2r1rMbMFHgDzZQV0lC20Oxps7RSM,4839
|
|
3
3
|
ivoryos/config.py,sha256=y3RxNjiIola9tK7jg-mHM8EzLMwiLwOzoisXkDvj0gA,2174
|
|
4
|
-
ivoryos/server.py,sha256=
|
|
4
|
+
ivoryos/server.py,sha256=Idr41Boa8rPsh3bVJ8xy2Flwfxa1Xu6f2T0oMp4qBEk,7121
|
|
5
5
|
ivoryos/socket_handlers.py,sha256=VWVWiIdm4jYAutwGu6R0t1nK5MuMyOCL0xAnFn06jWQ,1302
|
|
6
|
-
ivoryos/version.py,sha256=
|
|
7
|
-
ivoryos/optimizer/ax_optimizer.py,sha256=
|
|
8
|
-
ivoryos/optimizer/base_optimizer.py,sha256=
|
|
6
|
+
ivoryos/version.py,sha256=5ZbAQtod5QalTI1C2N07edlxplzG_Q2XvGOSyOok4uA,22
|
|
7
|
+
ivoryos/optimizer/ax_optimizer.py,sha256=k7RzhNMjh3MseOE-_FADVX72lYLDyXz-XE3juSBRWTk,7116
|
|
8
|
+
ivoryos/optimizer/base_optimizer.py,sha256=gNBX9m3RxoYklwEBkqeDGZlU7c6e9e5kN0ZeTtnxnCE,2044
|
|
9
9
|
ivoryos/optimizer/baybe_optimizer.py,sha256=EdrrRiYO-IOx610cPXiQhH4qG8knUP0uiZ0YoyaGIU8,7954
|
|
10
|
-
ivoryos/optimizer/registry.py,sha256=
|
|
10
|
+
ivoryos/optimizer/registry.py,sha256=dLMo5cszcwa06hfBxdINQIGpkHtRe5-J3J7t76Jq6X0,306
|
|
11
11
|
ivoryos/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
ivoryos/routes/api/api.py,sha256=97Y7pqTwOaWgZgI5ovEPxEBm6Asrt0Iy0VhBkVp2xqA,2304
|
|
13
13
|
ivoryos/routes/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -27,9 +27,9 @@ ivoryos/routes/data/templates/workflow_database.html,sha256=ofvHcovpwmJXo1SFiSrL
|
|
|
27
27
|
ivoryos/routes/data/templates/workflow_view.html,sha256=Ti17kzlPlYTmzx5MkdsPlXJ1_k6QgMYQBM6FHjG50go,12491
|
|
28
28
|
ivoryos/routes/data/templates/components/step_card.html,sha256=XWsr7qxAY76RCuQHETubWjWBlPgs2HkviH4ju6qfBKo,1923
|
|
29
29
|
ivoryos/routes/design/__init__.py,sha256=zS3HXKaw0ALL5n6t_W1rUz5Uj5_tTQ-Y1VMXyzewvR0,113
|
|
30
|
-
ivoryos/routes/design/design.py,sha256=
|
|
30
|
+
ivoryos/routes/design/design.py,sha256=HPjjoGH9mzSP6TxVNUYWgwhfzkpRt5BF38agL_tJvXk,18760
|
|
31
31
|
ivoryos/routes/design/design_file.py,sha256=MVIc5uGSaGxZhs86hfPjX2n0iy1OcXeLq7b9Ucdg4VQ,2115
|
|
32
|
-
ivoryos/routes/design/design_step.py,sha256=
|
|
32
|
+
ivoryos/routes/design/design_step.py,sha256=M3l37kP1kU4_bolLBU1MWJgEW0LUXojo9UdQgysZyXs,5943
|
|
33
33
|
ivoryos/routes/design/templates/experiment_builder.html,sha256=hh-d2tOc_40gww5WfUYIf8sM3qBaALZnR8Sx7Ja4tpU,1623
|
|
34
34
|
ivoryos/routes/design/templates/components/action_form.html,sha256=kXJOrJLbFsMHHWVSuMQHpt1xFrUMnwgzTG8e6Qfn0Cg,3042
|
|
35
35
|
ivoryos/routes/design/templates/components/actions_panel.html,sha256=jHTR58saTUIZInBdC-vLc1ZTbStLiULeWbupjB4hQzo,977
|
|
@@ -37,9 +37,9 @@ ivoryos/routes/design/templates/components/autofill_toggle.html,sha256=CRVQUHoQT
|
|
|
37
37
|
ivoryos/routes/design/templates/components/canvas.html,sha256=bKLCJaG1B36Yy9Vsnz4P5qiX4BPdfaGe9JeQQzu9rsI,268
|
|
38
38
|
ivoryos/routes/design/templates/components/canvas_footer.html,sha256=5VRRacMZbzx0hUej0NPP-PmXM_AtUqduHzDS7a60cQY,435
|
|
39
39
|
ivoryos/routes/design/templates/components/canvas_header.html,sha256=7iIzLDGHX7MnmBbf98nWtLDprbeIgoNV4dJUO1zE4Tc,3598
|
|
40
|
-
ivoryos/routes/design/templates/components/canvas_main.html,sha256=
|
|
40
|
+
ivoryos/routes/design/templates/components/canvas_main.html,sha256=nLEtp3U2YtfJwob1kR8ua8-UVdu9hwc6z1L5UMNVz8c,1524
|
|
41
41
|
ivoryos/routes/design/templates/components/deck_selector.html,sha256=ryTRpljYezo0AzGLCJu_qOMokjjnft3GIxddmNGtBA0,657
|
|
42
|
-
ivoryos/routes/design/templates/components/edit_action_form.html,sha256=
|
|
42
|
+
ivoryos/routes/design/templates/components/edit_action_form.html,sha256=idhUKOqewIxgqMKYKLutqOjopKQVLvddB6uufoBA3Lo,1912
|
|
43
43
|
ivoryos/routes/design/templates/components/instruments_panel.html,sha256=tRKd-wOqKjaMJCLuGgRmHtxIgSjklhBkuX8arm5aTCU,4268
|
|
44
44
|
ivoryos/routes/design/templates/components/modals.html,sha256=6Dl8I8oD4ln7kK8C5e92pFVVH5KDte-vVTL0U_6NSTg,306
|
|
45
45
|
ivoryos/routes/design/templates/components/python_code_overlay.html,sha256=GUHgsmUWQf0P1Fbg5W0OJC34TXCUIMQVUkS7KDoauyI,1264
|
|
@@ -74,7 +74,7 @@ ivoryos/static/logo.webp,sha256=lXgfQR-4mHTH83k7VV9iB54-oC2ipe6uZvbwdOnLETc,1497
|
|
|
74
74
|
ivoryos/static/style.css,sha256=zQVx35A5g6JMJ-K84-6fSKtzXGjp_p5ZVG6KLHPM2IE,4021
|
|
75
75
|
ivoryos/static/gui_annotation/Slide1.png,sha256=Lm4gdOkUF5HIUFaB94tl6koQVkzpitKj43GXV_XYMMc,121727
|
|
76
76
|
ivoryos/static/gui_annotation/Slide2.PNG,sha256=z3wQ9oVgg4JTWVLQGKK_KhtepRHUYP1e05XUWGT2A0I,118761
|
|
77
|
-
ivoryos/static/js/action_handlers.js,sha256=
|
|
77
|
+
ivoryos/static/js/action_handlers.js,sha256=MdYfXLRNSMAkfO_lkDb8Mr--MlZA7SluEQ5AB3Jqw7k,6704
|
|
78
78
|
ivoryos/static/js/db_delete.js,sha256=l67fqUaN_FVDaL7v91Hd7LyRbxnqXx9nyjF34-7aewY,561
|
|
79
79
|
ivoryos/static/js/overlay.js,sha256=dPxop19es0E0ZUSY3d_4exIk7CJuQEnlW5uTt5fZfzI,483
|
|
80
80
|
ivoryos/static/js/script_metadata.js,sha256=m8VYZ8OGT2oTx1kXMXq60bKQI9WCbJNkzcFDzLvRuGc,1188
|
|
@@ -84,20 +84,20 @@ ivoryos/static/js/sortable_design.js,sha256=ASc9P6_423Mczeg6QH6LVtyxLyWhpxWJP2nE
|
|
|
84
84
|
ivoryos/static/js/ui_state.js,sha256=XYsOcfGlduqLlqHySvPrRrR50CiAsml51duqneigsRY,3368
|
|
85
85
|
ivoryos/templates/base.html,sha256=cl5w6E8yskbUzdiJFal6fZjnPuFNKEzc7BrrbRd6bMI,8581
|
|
86
86
|
ivoryos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
87
|
-
ivoryos/utils/bo_campaign.py,sha256=
|
|
87
|
+
ivoryos/utils/bo_campaign.py,sha256=AqTE4aIUWL26P0-o1qvL2ms4MjYzNQABNxZFisxBsyg,9712
|
|
88
88
|
ivoryos/utils/client_proxy.py,sha256=74G3HAuq50iEHkSvlMZFmQaukm613FbRgOdzO_T3dMg,10191
|
|
89
|
-
ivoryos/utils/db_models.py,sha256=
|
|
89
|
+
ivoryos/utils/db_models.py,sha256=TbOydX7rC1jGfei2mVYaexlE3lyq1Igb1VQuHJlMRKQ,31945
|
|
90
90
|
ivoryos/utils/decorators.py,sha256=p1Bdl3dCeaHNv6-cCCUOZMiFu9kRaqqQnkFJUkzPoJE,991
|
|
91
|
-
ivoryos/utils/form.py,sha256=
|
|
91
|
+
ivoryos/utils/form.py,sha256=f1yXHlOQX1YnJ2j_UW6iHmh4pTAGAs9sAlhyQB8yBIo,22505
|
|
92
92
|
ivoryos/utils/global_config.py,sha256=leYoEXvAS0AH4xQpYsqu4HI9CJ9-wiLM-pIh_bEG4Ak,3087
|
|
93
93
|
ivoryos/utils/llm_agent.py,sha256=-lVCkjPlpLues9sNTmaT7bT4sdhWvV2DiojNwzB2Lcw,6422
|
|
94
94
|
ivoryos/utils/py_to_json.py,sha256=ZtejHgwdEAUCVVMYeVNR8G7ceLINue294q6WpiJ6jn0,9734
|
|
95
|
-
ivoryos/utils/script_runner.py,sha256=
|
|
95
|
+
ivoryos/utils/script_runner.py,sha256=gIYdTEFNWZFmPf9cf31y3wAUKUeJk_qnjohYDKevWNw,20749
|
|
96
96
|
ivoryos/utils/serilize.py,sha256=lkBhkz8r2bLmz2_xOb0c4ptSSOqjIu6krj5YYK4Nvj8,6784
|
|
97
97
|
ivoryos/utils/task_runner.py,sha256=xiMzK8gQ0mHsg0A1Ah8fmXe3azpaJh4hJiQJLHA11ZQ,3682
|
|
98
98
|
ivoryos/utils/utils.py,sha256=dIc4BO55eS3lCA0nhbIncS5d7sLaKZy5hJS1I_Sm45o,14949
|
|
99
|
-
ivoryos-1.3.
|
|
100
|
-
ivoryos-1.3.
|
|
101
|
-
ivoryos-1.3.
|
|
102
|
-
ivoryos-1.3.
|
|
103
|
-
ivoryos-1.3.
|
|
99
|
+
ivoryos-1.3.6.dist-info/licenses/LICENSE,sha256=p2c8S8i-8YqMpZCJnadLz1-ofxnRMILzz6NCMIypRag,1084
|
|
100
|
+
ivoryos-1.3.6.dist-info/METADATA,sha256=wUfp7SCz5Vtw7CrpuoKeirxfuf71F6deGzjBlx2Zuj8,8516
|
|
101
|
+
ivoryos-1.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
102
|
+
ivoryos-1.3.6.dist-info/top_level.txt,sha256=FRIWWdiEvRKqw-XfF_UK3XV0CrnNb6EmVbEgjaVazRM,8
|
|
103
|
+
ivoryos-1.3.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|