ivoryos 0.1.12__py3-none-any.whl → 0.1.18__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/utils/form.py CHANGED
@@ -1,3 +1,4 @@
1
+ from wtforms.fields.choices import SelectField
1
2
  from wtforms.fields.core import Field
2
3
  from wtforms.validators import InputRequired
3
4
  from wtforms.widgets.core import TextInput
@@ -8,16 +9,15 @@ import inspect
8
9
 
9
10
 
10
11
  def find_variable(data, script):
11
- # TODO: needs to check for valid order of variables, important when editting
12
- added_variables: list[dict[str, str]] = [action for action in script.currently_editing_script if
13
- action["instrument"] == "variable"
14
- # or action["return"] # TODO find returns
15
- ]
16
- for added_variable in added_variables:
17
- if added_variable["action"] == data:
18
- return data, added_variable["args"]
19
- # if added_variable["return"] == data:
20
- # return data, None
12
+ """
13
+ find user defined variables and return values in the script:Script
14
+ :param data: string of input variable name
15
+ :param script:Script object
16
+ """
17
+ variables: dict[str, str] = script.get_variables()
18
+ for variable_name, variable_type in variables.items():
19
+ if variable_name == data:
20
+ return data, variable_type # variable_type int float str or "function_output"
21
21
  return None, None
22
22
 
23
23
 
@@ -36,7 +36,7 @@ class VariableOrStringField(Field):
36
36
 
37
37
  def _value(self):
38
38
  if self.script:
39
- variable, value = find_variable(self.data, self.script)
39
+ variable, variable_type = find_variable(self.data, self.script)
40
40
  if variable:
41
41
  return variable
42
42
 
@@ -52,7 +52,7 @@ class VariableOrFloatField(Field):
52
52
 
53
53
  def _value(self):
54
54
  if self.script:
55
- variable, value = find_variable(self.data, self.script)
55
+ variable, variable_type = find_variable(self.data, self.script)
56
56
  if variable:
57
57
  return variable
58
58
 
@@ -73,14 +73,15 @@ class VariableOrFloatField(Field):
73
73
  try:
74
74
  if self.script:
75
75
  try:
76
- variable, value = find_variable(valuelist[0], self.script)
76
+ variable, variable_type = find_variable(valuelist[0], self.script)
77
77
  if variable:
78
- float(value)
79
- self.data = str(variable)
78
+ if not variable_type == "function_output":
79
+ if variable_type not in ["float", "int"]:
80
+ raise ValueError("Variable is not a valid float")
81
+ self.data = variable
80
82
  return
81
83
  except ValueError:
82
84
  pass
83
-
84
85
  self.data = float(valuelist[0])
85
86
  except ValueError as exc:
86
87
  self.data = None
@@ -99,7 +100,7 @@ class VariableOrIntField(Field):
99
100
 
100
101
  def _value(self):
101
102
  if self.script:
102
- variable, value = find_variable(self.data, self.script)
103
+ variable, variable_type = find_variable(self.data, self.script)
103
104
  if variable:
104
105
  return variable
105
106
 
@@ -109,34 +110,16 @@ class VariableOrIntField(Field):
109
110
  return str(self.data)
110
111
  return ""
111
112
 
112
- # def process_data(self, value):
113
- #
114
- # if self.script:
115
- # variable, var_value = find_variable(value, self.script)
116
- # if variable:
117
- # try:
118
- # int(var_value)
119
- # self.data = str(variable)
120
- # return
121
- # except ValueError:
122
- # pass
123
- # if value is None or value is unset_value:
124
- # self.data = None
125
- # return
126
- # try:
127
- # self.data = int(value)
128
- # except (ValueError, TypeError) as exc:
129
- # self.data = None
130
- # raise ValueError(self.gettext("Not a valid integer value.")) from exc
131
-
132
113
  def process_formdata(self, valuelist):
133
114
  if not valuelist:
134
115
  return
135
116
  if self.script:
136
- variable, var_value = find_variable(valuelist[0], self.script)
117
+ variable, variable_type = find_variable(valuelist[0], self.script)
137
118
  if variable:
138
119
  try:
139
- int(var_value)
120
+ if not variable_type == "function_output":
121
+ if not variable_type == "int":
122
+ raise ValueError("Not a valid integer value")
140
123
  self.data = str(variable)
141
124
  return
142
125
  except ValueError:
@@ -155,6 +138,7 @@ class VariableOrIntField(Field):
155
138
 
156
139
  class VariableOrBoolField(BooleanField):
157
140
  widget = TextInput()
141
+ false_values = (False, "false", "", "False", "f", "F")
158
142
 
159
143
  def __init__(self, label='', validators=None, script=None, **kwargs):
160
144
  super(VariableOrBoolField, self).__init__(label, validators, **kwargs)
@@ -163,30 +147,34 @@ class VariableOrBoolField(BooleanField):
163
147
  def process_data(self, value):
164
148
 
165
149
  if self.script:
166
- variable, var_value = find_variable(value, self.script)
150
+ variable, variable_type = find_variable(value, self.script)
167
151
  if variable:
168
- try:
169
- bool(var_value)
170
- return variable
171
- except ValueError:
172
- return
152
+ if not variable_type == "function_output":
153
+ raise ValueError("Not accepting boolean variables")
154
+ return variable
173
155
 
174
156
  self.data = bool(value)
175
157
 
176
158
  def process_formdata(self, valuelist):
177
- if not valuelist or type(valuelist) is list and valuelist[0] == '':
159
+ # todo
160
+ # print(valuelist)
161
+ if not valuelist or not type(valuelist) is list:
178
162
  self.data = False
179
- elif valuelist and valuelist[0].startswith("#"):
180
- if not self.script.editing_type == "script":
181
- raise ValueError(self.gettext("Variable is not supported in prep/cleanup"))
182
- self.data = valuelist[0]
183
163
  else:
184
- self.data = True
164
+ value = valuelist[0] if type(valuelist) is list else valuelist
165
+ if value.startswith("#"):
166
+ if not self.script.editing_type == "script":
167
+ raise ValueError(self.gettext("Variable is not supported in prep/cleanup"))
168
+ self.data = valuelist[0]
169
+ elif value in self.false_values:
170
+ self.data = False
171
+ else:
172
+ self.data = True
185
173
 
186
174
  def _value(self):
187
175
 
188
176
  if self.script:
189
- variable, value = find_variable(self.raw_data, self.script)
177
+ variable, variable_type = find_variable(self.raw_data, self.script)
190
178
  if variable:
191
179
  return variable
192
180
 
@@ -202,7 +190,15 @@ def format_name(name):
202
190
  return text.capitalize()
203
191
 
204
192
 
205
- def create_form_for_method(method, method_name, autofill, script=None, design=True):
193
+ def create_form_for_method(method, autofill, script=None, design=True):
194
+ """
195
+ Create forms for each method or signature
196
+ :param method: dict(docstring, signature)
197
+ :param autofill:bool if autofill is enabled
198
+ :param script:Script object
199
+ :param design: if design is enabled
200
+ """
201
+
206
202
  class DynamicForm(FlaskForm):
207
203
  pass
208
204
 
@@ -238,40 +234,125 @@ def create_form_for_method(method, method_name, autofill, script=None, design=Tr
238
234
  return DynamicForm
239
235
 
240
236
 
241
- # Create forms for each method in DummySDLDeck
242
- def create_add_form(attr, attr_name, autofill, script=None, design=True):
243
- dynamic_form = create_form_for_method(attr, attr_name, autofill, script, design)
237
+ def create_add_form(attr, attr_name, autofill: bool, script=None, design: bool = True):
238
+ """
239
+ Create forms for each method or signature
240
+ :param attr: dict(docstring, signature)
241
+ :param attr_name: method name
242
+ :param autofill:bool if autofill is enabled
243
+ :param script:Script object
244
+ :param design: if design is enabled. Design allows string input for parameter names ("#param") for all fields
245
+ """
246
+ signature = attr.get('signature', {})
247
+ docstring = attr.get('docstring', "")
248
+ dynamic_form = create_form_for_method(signature, autofill, script, design)
244
249
  if design:
245
250
  return_value = StringField(label='Save value as', render_kw={"placeholder": "Optional"})
246
251
  setattr(dynamic_form, 'return', return_value)
247
- hidden_method_name = HiddenField(name=f'hidden_name', render_kw={"value": f'{attr_name}'})
252
+ hidden_method_name = HiddenField(name=f'hidden_name', description=docstring, render_kw={"value": f'{attr_name}'})
248
253
  setattr(dynamic_form, 'hidden_name', hidden_method_name)
249
254
  return dynamic_form
250
255
 
251
256
 
252
- def create_form_from_module(sdl_module, autofill: bool, script=None, design=True):
253
- # sdl_deck = DummySDLDeck(DummyPump("COM1"), DummyBalance("COM2"))
257
+ def create_form_from_module(sdl_module, autofill: bool = False, script=None, design: bool = False):
258
+ """
259
+ Create forms for each method, used for control routes
260
+ :param sdl_module: method module
261
+ :param autofill:bool if autofill is enabled
262
+ :param script:Script object
263
+ :param design: if design is enabled
264
+ """
254
265
  method_forms = {}
255
266
  for attr_name in dir(sdl_module):
256
- attr = getattr(sdl_module, attr_name)
257
- if inspect.ismethod(attr) and not attr_name.startswith('_'):
267
+ method = getattr(sdl_module, attr_name)
268
+ if inspect.ismethod(method) and not attr_name.startswith('_'):
269
+ signature = inspect.signature(method)
270
+ docstring = inspect.getdoc(method)
271
+ attr = dict(signature=signature, docstring=docstring)
258
272
  form_class = create_add_form(attr, attr_name, autofill, script, design)
259
273
  method_forms[attr_name] = form_class()
260
274
  return method_forms
261
275
 
262
276
 
263
277
  def create_form_from_pseudo(pseudo: dict, autofill: bool, script=None, design=True):
264
- '''{'dose_liquid': < Signature(amount_in_ml: float, rate_ml_per_minute: float) >}'''
278
+ """
279
+ Create forms for pseudo method, used for design routes
280
+ :param pseudo:{'dose_liquid': {
281
+ "docstring": "some docstring",
282
+ "signature": Signature(amount_in_ml: float, rate_ml_per_minute: float) }
283
+ }
284
+ :param autofill:bool if autofill is enabled
285
+ :param script:Script object
286
+ :param design: if design is enabled
287
+ """
265
288
  method_forms = {}
266
289
  for attr_name, signature in pseudo.items():
290
+ # signature = info.get('signature', {})
267
291
  form_class = create_add_form(signature, attr_name, autofill, script, design)
268
292
  method_forms[attr_name] = form_class()
269
293
  return method_forms
270
294
 
271
295
 
272
- def create_builtin_form(logic_type, autofill, script):
296
+ def create_form_from_action(action: dict, script=None, design=True):
297
+ '''
298
+ Create forms for single action, used for design routes
299
+ :param action: {'action': 'dose_solid', 'arg_types': {'amount_in_mg': 'float', 'bring_in': 'bool'},
300
+ 'args': {'amount_in_mg': 5.0, 'bring_in': False}, 'id': 9,
301
+ 'instrument': 'deck.sdl', 'return': '', 'uuid': 266929188668995}
302
+ :param script:Script object
303
+ :param design: if design is enabled
304
+
305
+ '''
306
+
307
+ arg_types = action.get("arg_types", {})
308
+ args = action.get("args", {})
309
+ save_as = action.get("return")
310
+
311
+ class DynamicForm(FlaskForm):
312
+ pass
313
+
314
+ annotation_mapping = {
315
+ "int": (VariableOrIntField if design else IntegerField, 'Enter integer value'),
316
+ "float": (VariableOrFloatField if design else FloatField, 'Enter numeric value'),
317
+ "str": (VariableOrStringField if design else StringField, 'Enter text'),
318
+ "bool": (VariableOrBoolField if design else BooleanField, 'Empty for false')
319
+ }
320
+
321
+ for name, param_type in arg_types.items():
322
+ formatted_param_name = format_name(name)
323
+ value = args.get(name, "")
324
+ if type(value) is dict:
325
+ value = next(iter(value))
326
+ field_kwargs = {
327
+ "label": formatted_param_name,
328
+ "default": f'{value}',
329
+ "validators": [InputRequired()],
330
+ **({"script": script})
331
+ }
332
+ param_type = param_type if type(param_type) is str else f"{param_type}"
333
+ field_class, placeholder_text = annotation_mapping.get(
334
+ param_type,
335
+ (VariableOrStringField if design else StringField, f'Enter {param_type} value')
336
+ )
337
+ render_kwargs = {"placeholder": placeholder_text}
338
+
339
+ # Create the field with additional rendering kwargs for placeholder text
340
+ field = field_class(**field_kwargs, render_kw=render_kwargs)
341
+ setattr(DynamicForm, name, field)
342
+
343
+ if design:
344
+ return_value = StringField(label='Save value as', default=f"{save_as}", render_kw={"placeholder": "Optional"})
345
+ setattr(DynamicForm, 'return', return_value)
346
+ return DynamicForm()
347
+
348
+
349
+ def create_builtin_form(logic_type, script):
350
+ """
351
+ Create a builtin form {if, while, variable, repeat, wait}
352
+ """
273
353
  class BuiltinFunctionForm(FlaskForm):
274
354
  pass
355
+
275
356
  placeholder_text = {
276
357
  'wait': 'Enter second',
277
358
  'repeat': 'Enter an integer'
@@ -296,33 +377,63 @@ def create_builtin_form(logic_type, autofill, script):
296
377
  variable_field = StringField(label=f'variable', validators=[InputRequired()],
297
378
  description="Your variable name cannot include space",
298
379
  render_kw=render_kwargs)
380
+ type_field = SelectField(
381
+ 'Select Input Type',
382
+ choices=[('int', 'Integer'), ('float', 'Float'), ('str', 'String')],
383
+ default='str' # Optional default value
384
+ )
299
385
  setattr(BuiltinFunctionForm, "variable", variable_field)
386
+ setattr(BuiltinFunctionForm, "type", type_field)
300
387
  hidden_field = HiddenField(name=f'builtin_name', render_kw={"value": f'{logic_type}'})
301
388
  setattr(BuiltinFunctionForm, "builtin_name", hidden_field)
302
389
  return BuiltinFunctionForm()
303
390
 
304
391
 
305
- def create_action_button(s: dict):
306
- if s['instrument'] in ['if', 'while', 'repeat']:
307
- text = f"{s['action']} {s['args']}"
308
- elif s['instrument'] == 'variable':
309
- text = f"{s['action']} = {s['args']}"
310
- else:
311
- # regular action button
312
- prefix = f"{s['return']} = " if s['return'] else ""
313
- action_text = f"{s['instrument'].split('.')[-1] if s['instrument'].startswith('deck') else s['instrument']}.{s['action']}"
314
- arg_string = ""
315
- if s['args']:
316
- if type(s['args']) is dict:
317
- arg_string = "(" + ", ".join([f"{k} = {v}" for k, v in s['args'].items()]) + ")"
318
- else:
319
- arg_string = f"= {s['args']}"
392
+ def create_action_button(script, stype=None):
393
+ """
394
+ Creates action buttons for design route (design canvas)
395
+ :param script: Script object
396
+ :param stype: script type (script, prep, cleanup)
397
+ """
398
+ stype = stype or script.editing_type
399
+ variables = script.get_variables()
400
+ return [_action_button(i, variables) for i in script.get_script(stype)]
320
401
 
321
- text = f"{prefix}{action_text} {arg_string}"
402
+
403
+ def _action_button(action: dict, variables: dict):
404
+ """
405
+ Creates action button for one action
406
+ :param action: Action dict
407
+ :param variables: created variable dict
408
+ """
322
409
  style = {
323
410
  "repeat": "background-color: lightsteelblue",
324
411
  "if": "background-color: salmon",
325
412
  "while": "background-color: salmon",
413
+ }.get(action['instrument'], "")
326
414
 
327
- }.get(s['instrument'], "")
328
- return dict(label=text, style=style, uuid=s["uuid"], id=s["id"], instrument=s['instrument'])
415
+ if action['instrument'] in ['if', 'while', 'repeat']:
416
+ text = f"{action['action']} {action['args'].get('statement', '')}"
417
+ elif action['instrument'] == 'variable':
418
+ text = f"{action['action']} = {action['args'].get('statement')}"
419
+ else:
420
+ # regular action button
421
+ prefix = f"{action['return']} = " if action['return'] else ""
422
+ action_text = f"{action['instrument'].split('.')[-1] if action['instrument'].startswith('deck') else action['instrument']}.{action['action']}"
423
+ arg_string = ""
424
+ if action['args']:
425
+ if type(action['args']) is dict:
426
+ arg_list = []
427
+ for k, v in action['args'].items():
428
+ if isinstance(v, dict):
429
+ value = next(iter(v)) # Extract the first key if it's a dict
430
+ # show warning color for variable calling when there is no definition
431
+ style = "background-color: khaki" if value not in variables.keys() else ""
432
+ else:
433
+ value = v # Keep the original value if not a dict
434
+ arg_list.append(f"{k} = {value}") # Format the key-value pair
435
+ arg_string = "(" + ", ".join(arg_list) + ")"
436
+ else:
437
+ arg_string = f"= {action['args']}"
438
+ text = f"{prefix}{action_text} {arg_string}"
439
+ return dict(label=text, style=style, uuid=action["uuid"], id=action["id"], instrument=action['instrument'])
@@ -80,14 +80,17 @@ class ScriptRunner:
80
80
 
81
81
  def _run_actions(self, actions, section_name="", run_name=None, logger=None):
82
82
  logger.info(f'Executing {section_name} steps') if actions else logger.info(f'No {section_name} steps')
83
- for action in actions:
84
- if self.stop_event.is_set():
85
- logger.info(f"Stopping execution during {section_name} section.")
86
- break
87
- logger.info(f'Executing {action.get("action", "")} action')
88
- fname = f"{run_name}_{section_name}"
89
- function = self.globals_dict[fname]
90
- function()
83
+ if self.stop_event.is_set():
84
+ logger.info(f"Stopping execution during {section_name} section.")
85
+ return
86
+ # for action in actions:
87
+ # if self.stop_event.is_set():
88
+ # logger.info(f"Stopping execution during {section_name} section.")
89
+ # break
90
+ # logger.info(f'Executing {action.get("action", "")} action')
91
+ fname = f"{run_name}_{section_name}"
92
+ function = self.globals_dict[fname]
93
+ function()
91
94
 
92
95
  def _run_config_section(self, config, arg_type, output_list, return_list, run_name, logger, socketio):
93
96
  compiled = True
ivoryos/utils/utils.py CHANGED
@@ -7,7 +7,6 @@ import pickle
7
7
  import subprocess
8
8
  import sys
9
9
  from collections import Counter
10
- from typing import Optional, Dict, Tuple
11
10
 
12
11
  from flask import session
13
12
  from flask_socketio import SocketIO
@@ -84,7 +83,6 @@ def available_pseudo_deck(path):
84
83
  """
85
84
  load pseudo deck (snapshot) from connection history
86
85
  """
87
- import os
88
86
  return os.listdir(path)
89
87
 
90
88
 
@@ -103,20 +101,9 @@ def _inspect_class(class_object=None, debug=False):
103
101
  if not function.startswith(under_score) and not function.isupper():
104
102
  try:
105
103
  annotation = inspect.signature(method)
106
- # if doc_string:
107
104
  docstring = inspect.getdoc(method)
108
105
  functions[function] = dict(signature=annotation, docstring=docstring)
109
106
 
110
- # handle getter setters todo
111
- # if callable(att):
112
- # functions[function] = inspect.signature(att)
113
- # else:
114
- # att = getattr(class_object.__class__, function)
115
- # if isinstance(att, property) and att.fset is not None:
116
- # setter = att.fset.__annotations__
117
- # setter.pop('return', None)
118
- # if setter:
119
- # functions[function] = setter
120
107
  except Exception:
121
108
  pass
122
109
  return functions
@@ -132,36 +119,22 @@ def _get_type_from_parameters(arg, parameters):
132
119
  if annotation is not inspect._empty:
133
120
  # print(p[arg].annotation)
134
121
  if annotation.__module__ == 'typing':
135
- if hasattr(annotation, '_name') and annotation._name in ["Optional", "Union"]:
136
- # print(p[arg].annotation.__args__)
137
- arg_type = [i.__name__ for i in annotation.__args__]
138
- elif hasattr(annotation, '__origin__'):
139
- arg_type = annotation.__origin__.__name__
140
- else:
141
- # TODO
142
- pass
122
+
123
+ if hasattr(annotation, '__origin__'):
124
+ origin = annotation.__origin__
125
+ if hasattr(origin, '_name') and origin._name in ["Optional", "Union"]:
126
+ arg_type = [i.__name__ for i in annotation.__args__]
127
+ elif hasattr(origin, '__name__'):
128
+ arg_type = origin.__name__
129
+ # todo other types
130
+ elif annotation.__module__ == 'types':
131
+ arg_type = [i.__name__ for i in annotation.__args__]
132
+
143
133
  else:
144
134
  arg_type = annotation.__name__
145
135
  return arg_type
146
136
 
147
137
 
148
- def find_variable_in_script(script: Script, args: Dict[str, str]) -> Optional[Tuple[Dict[str, str], Dict[str, str]]]:
149
- # TODO: need to search for if the variable exists
150
- added_variables: list[Dict[str, str]] = [action for action in script.currently_editing_script if
151
- action["instrument"] == "variable"]
152
-
153
- possible_variable_arguments = {}
154
- possible_variable_types = {}
155
-
156
- for arg_name, arg_val in args.items():
157
- for added_variable in added_variables:
158
- if added_variable["action"] == arg_val:
159
- possible_variable_arguments[arg_name] = added_variable["action"]
160
- possible_variable_types[arg_name] = "variable"
161
-
162
- return possible_variable_arguments, possible_variable_types
163
-
164
-
165
138
  def _convert_by_str(args, arg_types):
166
139
  """
167
140
  Converts a value to type through eval(f'{type}("{args}")')
@@ -201,9 +174,6 @@ def convert_config_type(args, arg_types, is_class: bool = False):
201
174
  """
202
175
  Converts an argument from str to an arg type
203
176
  """
204
- bool_dict = {"True": True, "False": False}
205
- # print(args, arg_types)
206
- # print(globals())
207
177
  if args:
208
178
  for arg in args:
209
179
  if arg not in arg_types.keys():
@@ -338,8 +308,10 @@ def ax_initiation(data, arg_types):
338
308
 
339
309
 
340
310
  def get_arg_type(args, parameters):
311
+ """get argument type from signature"""
341
312
  arg_types = {}
342
313
  # print(args, parameters)
314
+ parameters = parameters.get("signature")
343
315
  if args:
344
316
  for arg in args:
345
317
  arg_types[arg] = _get_type_from_parameters(arg, parameters)
ivoryos/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.12"
1
+ __version__ = "0.1.18"
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ivoryos
3
- Version: 0.1.12
3
+ Version: 0.1.18
4
4
  Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
5
5
  Home-page: https://gitlab.com/heingroup/ivoryos
6
6
  Author: Ivory Zhang
7
7
  Author-email: ivoryzhang@chem.ubc.ca
8
8
  License: MIT
9
+ Platform: UNKNOWN
9
10
  Description-Content-Type: text/markdown
10
11
  License-File: LICENSE
11
12
  Requires-Dist: bcrypt
@@ -168,3 +169,5 @@ https://youtu.be/dFfJv9I2-1g
168
169
  Ivory Zhang, Lucy Hao
169
170
 
170
171
  Authors acknowledge all former and current Hein Lab members for their valuable suggestions.
172
+
173
+
@@ -1,6 +1,6 @@
1
- ivoryos/__init__.py,sha256=pKaEGt1aqh4U0ofAVm2jdhyoyrR1jYlEO-Qi2T7Sfp4,4743
1
+ ivoryos/__init__.py,sha256=F3KenDZX1zqei3PZ3tx1U77yXsbeytgMMhVJyJMkmJ0,6071
2
2
  ivoryos/config.py,sha256=3FPBYTIBhQTKDvsEoR8ZeTmg65D-CSFEdGmOuIL4pSI,1311
3
- ivoryos/version.py,sha256=LcIlFjHZFfiF9Rd4UHoakmombOFkxIYk00I181frGBM,23
3
+ ivoryos/version.py,sha256=6BiuMUkhwQp6bzUZSF8np8F1NwCltEtK0sPBF__tepU,23
4
4
  ivoryos/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  ivoryos/routes/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  ivoryos/routes/auth/auth.py,sha256=7CdXjGAr1B_xsmwweakTWOoROgsOJf0MNTzlMP_5Nus,3240
@@ -8,21 +8,20 @@ ivoryos/routes/auth/templates/auth/login.html,sha256=WSRrKbdM_oobqSXFRTo-j9UlOgp
8
8
  ivoryos/routes/auth/templates/auth/signup.html,sha256=b5LTXtpfTSkSS7X8u1ldwQbbgEFTk6UNMAediA5BwBY,1465
9
9
  ivoryos/routes/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  ivoryos/routes/control/control.py,sha256=MmrcKrkjSKS589XhDdvPc7kWO0ApCNVZCtrgfzTAAN8,14163
11
- ivoryos/routes/control/templates/control/controllers.html,sha256=QdZAieEA4ODC-3KlsgHmFO35q8KXjm0KT43ZNpcBgEs,4084
11
+ ivoryos/routes/control/templates/control/controllers.html,sha256=iIp0h6WA68gQj9OsoiB7dU1BqH8CGomTueR73F4C8eY,4274
12
12
  ivoryos/routes/control/templates/control/controllers_home.html,sha256=xFnBXTWMlyi2naMSsCEqFlX-Z1HJJDDtzITPvq-3nng,2733
13
13
  ivoryos/routes/control/templates/control/controllers_new.html,sha256=uOQo9kYmwX2jk3KZDkMUF_ylfNUIs_oIWb_kk_MMVDM,4921
14
14
  ivoryos/routes/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  ivoryos/routes/database/database.py,sha256=IOrdtdsZ28bV7R1ZQfcwAeS5JDCkX-QYsP9i8BseD38,5684
16
16
  ivoryos/routes/database/templates/database/experiment_database.html,sha256=ABchwHYDovzwECc7UD4Mh8C_9JUl0YZpAAF9sFjNCs0,3434
17
17
  ivoryos/routes/design/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- ivoryos/routes/design/design.py,sha256=ZAUh-XOMhePCmY7q-hfru-4X6fDR3aKKyktrD2NC6M4,20876
19
- ivoryos/routes/design/templates/design/experiment_builder.html,sha256=lF8fDMHtwQjVznbCL4klV3o1p0tkqMptPY5IXR7WSuE,27327
18
+ ivoryos/routes/design/design.py,sha256=489QCfjcCZuL7HKAvZVrxIL1wK4IhE0zUef_mmbNuMs,21003
19
+ ivoryos/routes/design/templates/design/experiment_builder.html,sha256=-C84nHcK1grC8b_B5Lgbg6StJcP8x1oj2XAjRPj1oU0,28239
20
20
  ivoryos/routes/design/templates/design/experiment_run.html,sha256=JxYEbJqeJH8vZaSVI25EtNYmI_W5GSFdc02Y8y3kZGc,22543
21
21
  ivoryos/routes/main/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  ivoryos/routes/main/main.py,sha256=yuVJzXAob1kc1dfflkTBIZQ0tdf6kChfuq-uQlN1e9Q,957
23
23
  ivoryos/routes/main/templates/main/help.html,sha256=IOktMEsOPk0SCiMBXZ4mpffClERAyX8W82fel71M3M0,9370
24
- ivoryos/routes/main/templates/main/home.html,sha256=D3DtJSpWtkMRZEsLOtLr0yJVD4qNYAWPytPeZuRP4yQ,3234
25
- ivoryos/static/.DS_Store,sha256=skh9ta8MJo1eOfvLDKqqVRNKQXFH2Wfse7ybGMLytNs,6148
24
+ ivoryos/routes/main/templates/main/home.html,sha256=ujM0YC0yrHhCfkuprNnZZZd8XEEguS_6NjrY5ktfctg,3356
26
25
  ivoryos/static/favicon.ico,sha256=RhlrPtfITOkzC9BjP1UB1V5L9Oyp6NwNtWeMcGOnpyc,15406
27
26
  ivoryos/static/logo.webp,sha256=lXgfQR-4mHTH83k7VV9iB54-oC2ipe6uZvbwdOnLETc,14974
28
27
  ivoryos/static/style.css,sha256=cbQ8T8h42smwuyF5qQ_pNhlptDXGcuyK2u4sUppqnyI,3717
@@ -32,16 +31,16 @@ ivoryos/static/js/overlay.js,sha256=dPxop19es0E0ZUSY3d_4exIk7CJuQEnlW5uTt5fZfzI,
32
31
  ivoryos/static/js/socket_handler.js,sha256=O7r33couafOE9QCvUK9mP0kJRiBFw2K-Qk1cjtMI5Vg,1415
33
32
  ivoryos/static/js/sortable_card.js,sha256=ifmlGe3yy0U_KzMphV4ClRhK2DLOvkELYMlq1vECuac,807
34
33
  ivoryos/static/js/sortable_design.js,sha256=1lI1I8FbL66tv6n-SX2FkbHNDYo36xVo2qDBKVLmxnQ,1120
35
- ivoryos/templates/base.html,sha256=OR04eHEgmq4Wj0en3z6J2l-CdcJjZryRBjLsWyKdnCo,7800
34
+ ivoryos/templates/base.html,sha256=8HDi7I74ugcCAV4c3ha4C__-7xopt4ZsC0OQ2E_AsQ8,8313
36
35
  ivoryos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- ivoryos/utils/db_models.py,sha256=XoReukuWiroDX4OTfyd9dHRpGIN2woWL017P7N-VZ0U,20918
38
- ivoryos/utils/form.py,sha256=zpEFUyx9nMZkkTYVL0DIT3kEWd1DQsDGSBu4UysXf4s,12338
36
+ ivoryos/utils/db_models.py,sha256=Y0KymXvb5uHwXwDrtUpc9DNxCBH9pHCmU39Hf4Hwlv4,24835
37
+ ivoryos/utils/form.py,sha256=1h6eytHz1tv5_CIc_C6KGYn5JEPYniIOxo49yzM37o0,17149
39
38
  ivoryos/utils/global_config.py,sha256=Ojcz6xKATSbMLnTT0kiKqSnu_bNqCMyIAnZyHaKxJns,1589
40
39
  ivoryos/utils/llm_agent.py,sha256=DTf-AF56vy1Em1fUKagl5NURKittmNoxTKIw1PlyC2o,6413
41
- ivoryos/utils/script_runner.py,sha256=sFAUGCcfsA8DEPgw7koqEAr9fnxxYNRuiOC3L3yOwwc,7079
42
- ivoryos/utils/utils.py,sha256=5pNF5QJMXmImxDR0IRqaMzIy9n0fD_M1SUY1v9koEc8,15368
43
- ivoryos-0.1.12.dist-info/LICENSE,sha256=p2c8S8i-8YqMpZCJnadLz1-ofxnRMILzz6NCMIypRag,1084
44
- ivoryos-0.1.12.dist-info/METADATA,sha256=-aWjCWBd57wVqDBrPxwJdUPW3picfwV-I47vgpo0xX8,6335
45
- ivoryos-0.1.12.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
46
- ivoryos-0.1.12.dist-info/top_level.txt,sha256=FRIWWdiEvRKqw-XfF_UK3XV0CrnNb6EmVbEgjaVazRM,8
47
- ivoryos-0.1.12.dist-info/RECORD,,
40
+ ivoryos/utils/script_runner.py,sha256=DImUy5jfv64lrF8CnQf0HGJjnesi7D8uqh4a939ihEQ,7231
41
+ ivoryos/utils/utils.py,sha256=nQbGSR_FmlZyBb9lwKy3ws4FDAWWfDyu96hZg2DVIeI,14081
42
+ ivoryos-0.1.18.dist-info/LICENSE,sha256=p2c8S8i-8YqMpZCJnadLz1-ofxnRMILzz6NCMIypRag,1084
43
+ ivoryos-0.1.18.dist-info/METADATA,sha256=ldWGQwTTe0M5hF4qi-kWrB0NJUCFvHjRL7F0cOwxq4g,6355
44
+ ivoryos-0.1.18.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
45
+ ivoryos-0.1.18.dist-info/top_level.txt,sha256=FRIWWdiEvRKqw-XfF_UK3XV0CrnNb6EmVbEgjaVazRM,8
46
+ ivoryos-0.1.18.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.38.4)
2
+ Generator: bdist_wheel (0.45.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
ivoryos/static/.DS_Store DELETED
Binary file