ivoryos 1.0.9__py3-none-any.whl → 1.2.0__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 +26 -7
- ivoryos/routes/api/api.py +56 -0
- ivoryos/routes/auth/auth.py +5 -5
- ivoryos/routes/control/control.py +77 -372
- ivoryos/routes/control/control_file.py +36 -0
- ivoryos/routes/control/control_new_device.py +142 -0
- ivoryos/routes/control/templates/controllers.html +166 -0
- ivoryos/routes/control/templates/controllers_new.html +112 -0
- ivoryos/routes/control/utils.py +38 -0
- ivoryos/routes/data/data.py +129 -0
- ivoryos/routes/data/templates/components/step_card.html +13 -0
- ivoryos/routes/{database/templates/database → data/templates}/workflow_database.html +14 -8
- ivoryos/routes/{database/templates/database → data/templates}/workflow_view.html +3 -3
- ivoryos/routes/design/__init__.py +4 -0
- ivoryos/routes/design/design.py +298 -656
- ivoryos/routes/design/design_file.py +68 -0
- ivoryos/routes/design/design_step.py +145 -0
- ivoryos/routes/design/templates/components/action_form.html +53 -0
- ivoryos/routes/design/templates/components/actions_panel.html +25 -0
- ivoryos/routes/design/templates/components/autofill_toggle.html +10 -0
- ivoryos/routes/design/templates/components/canvas.html +5 -0
- ivoryos/routes/design/templates/components/canvas_footer.html +9 -0
- ivoryos/routes/design/templates/components/canvas_header.html +75 -0
- ivoryos/routes/design/templates/components/canvas_main.html +34 -0
- ivoryos/routes/design/templates/components/deck_selector.html +10 -0
- ivoryos/routes/design/templates/components/edit_action_form.html +38 -0
- ivoryos/routes/design/templates/components/instruments_panel.html +66 -0
- ivoryos/routes/design/templates/components/modals/drop_modal.html +17 -0
- ivoryos/routes/design/templates/components/modals/json_modal.html +22 -0
- ivoryos/routes/design/templates/components/modals/new_script_modal.html +17 -0
- ivoryos/routes/design/templates/components/modals/rename_modal.html +23 -0
- ivoryos/routes/design/templates/components/modals/saveas_modal.html +27 -0
- ivoryos/routes/design/templates/components/modals.html +6 -0
- ivoryos/routes/design/templates/components/python_code_overlay.html +39 -0
- ivoryos/routes/design/templates/components/sidebar.html +15 -0
- ivoryos/routes/design/templates/components/text_to_code_panel.html +20 -0
- ivoryos/routes/design/templates/experiment_builder.html +41 -0
- ivoryos/routes/execute/__init__.py +0 -0
- ivoryos/routes/execute/execute.py +317 -0
- ivoryos/routes/execute/execute_file.py +78 -0
- ivoryos/routes/execute/templates/components/error_modal.html +20 -0
- ivoryos/routes/execute/templates/components/logging_panel.html +31 -0
- ivoryos/routes/execute/templates/components/progress_panel.html +27 -0
- ivoryos/routes/execute/templates/components/run_panel.html +9 -0
- ivoryos/routes/execute/templates/components/run_tabs.html +17 -0
- ivoryos/routes/execute/templates/components/tab_bayesian.html +398 -0
- ivoryos/routes/execute/templates/components/tab_configuration.html +98 -0
- ivoryos/routes/execute/templates/components/tab_repeat.html +14 -0
- ivoryos/routes/execute/templates/experiment_run.html +294 -0
- ivoryos/routes/library/__init__.py +0 -0
- ivoryos/routes/library/library.py +159 -0
- ivoryos/routes/{database/templates/database/scripts_database.html → library/templates/library.html} +30 -22
- ivoryos/routes/main/main.py +1 -1
- ivoryos/routes/main/templates/{main/home.html → home.html} +4 -4
- ivoryos/socket_handlers.py +52 -0
- ivoryos/static/js/action_handlers.js +213 -0
- ivoryos/static/js/db_delete.js +23 -0
- ivoryos/static/js/script_metadata.js +39 -0
- ivoryos/static/js/sortable_design.js +89 -56
- ivoryos/static/js/ui_state.js +113 -0
- ivoryos/templates/base.html +4 -4
- ivoryos/utils/bo_campaign.py +179 -3
- ivoryos/utils/db_models.py +14 -5
- ivoryos/utils/form.py +5 -9
- ivoryos/utils/global_config.py +13 -1
- ivoryos/utils/py_to_json.py +225 -0
- ivoryos/utils/script_runner.py +49 -7
- ivoryos/utils/serilize.py +203 -0
- ivoryos/utils/task_runner.py +4 -1
- ivoryos/version.py +1 -1
- {ivoryos-1.0.9.dist-info → ivoryos-1.2.0.dist-info}/METADATA +5 -8
- ivoryos-1.2.0.dist-info/RECORD +105 -0
- ivoryos/routes/control/templates/control/controllers.html +0 -78
- ivoryos/routes/control/templates/control/controllers_home.html +0 -55
- ivoryos/routes/control/templates/control/controllers_new.html +0 -89
- ivoryos/routes/database/database.py +0 -306
- ivoryos/routes/database/templates/database/step_card.html +0 -7
- ivoryos/routes/design/templates/design/experiment_builder.html +0 -521
- ivoryos/routes/design/templates/design/experiment_run.html +0 -558
- ivoryos-1.0.9.dist-info/RECORD +0 -61
- /ivoryos/routes/auth/templates/{auth/login.html → login.html} +0 -0
- /ivoryos/routes/auth/templates/{auth/signup.html → signup.html} +0 -0
- /ivoryos/routes/{database → data}/__init__.py +0 -0
- /ivoryos/routes/main/templates/{main/help.html → help.html} +0 -0
- {ivoryos-1.0.9.dist-info → ivoryos-1.2.0.dist-info}/LICENSE +0 -0
- {ivoryos-1.0.9.dist-info → ivoryos-1.2.0.dist-info}/WHEEL +0 -0
- {ivoryos-1.0.9.dist-info → ivoryos-1.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import json
|
|
3
|
+
import inspect
|
|
4
|
+
import logging
|
|
5
|
+
from typing import get_type_hints, Union, Optional, get_origin, get_args
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
import flask
|
|
9
|
+
|
|
10
|
+
from example.abstract_sdl_example.abstract_balance import AbstractBalance
|
|
11
|
+
from example.abstract_sdl_example.abstract_pump import AbstractPump
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ScriptAnalyzer:
|
|
15
|
+
def __init__(self):
|
|
16
|
+
self.primitive_types = {
|
|
17
|
+
'int', 'float', 'str', 'bool', 'tuple', 'list'
|
|
18
|
+
}
|
|
19
|
+
self.type_mapping = {
|
|
20
|
+
int: 'int',
|
|
21
|
+
float: 'float',
|
|
22
|
+
str: 'str',
|
|
23
|
+
bool: 'bool',
|
|
24
|
+
tuple: 'tuple',
|
|
25
|
+
list: 'list'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def extract_type_from_hint(self, type_hint):
|
|
29
|
+
"""Extract primitive types from type hints, handling Union and Optional"""
|
|
30
|
+
if type_hint is None:
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
# Handle Union types (including Optional which is Union[T, None])
|
|
34
|
+
origin = get_origin(type_hint)
|
|
35
|
+
if origin is Union:
|
|
36
|
+
args = get_args(type_hint)
|
|
37
|
+
types = []
|
|
38
|
+
for arg in args:
|
|
39
|
+
if arg is type(None): # Skip None type
|
|
40
|
+
continue
|
|
41
|
+
if arg in self.type_mapping:
|
|
42
|
+
types.append(self.type_mapping[arg])
|
|
43
|
+
elif hasattr(arg, '__name__') and arg.__name__ in self.primitive_types:
|
|
44
|
+
types.append(arg.__name__)
|
|
45
|
+
else:
|
|
46
|
+
return None # Non-primitive type found
|
|
47
|
+
return types if types else None
|
|
48
|
+
|
|
49
|
+
# Handle direct primitive types
|
|
50
|
+
if type_hint in self.type_mapping:
|
|
51
|
+
return [self.type_mapping[type_hint]]
|
|
52
|
+
elif hasattr(type_hint, '__name__') and type_hint.__name__ in self.primitive_types:
|
|
53
|
+
return [type_hint.__name__]
|
|
54
|
+
else:
|
|
55
|
+
return None # Non-primitive type
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def analyze_method(self, method):
|
|
59
|
+
"""Analyze a single method and extract its signature"""
|
|
60
|
+
try:
|
|
61
|
+
sig = inspect.signature(method)
|
|
62
|
+
type_hints = get_type_hints(method)
|
|
63
|
+
|
|
64
|
+
parameters = []
|
|
65
|
+
type_hint_warning = False
|
|
66
|
+
user_input_params = []
|
|
67
|
+
|
|
68
|
+
for param_name, param in sig.parameters.items():
|
|
69
|
+
if param_name == 'self':
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
param_info = {"name": param_name}
|
|
73
|
+
|
|
74
|
+
# Get type hint
|
|
75
|
+
if param_name in type_hints:
|
|
76
|
+
type_list = self.extract_type_from_hint(type_hints[param_name])
|
|
77
|
+
if type_list is None:
|
|
78
|
+
type_hint_warning = True
|
|
79
|
+
user_input_params.append(param_name)
|
|
80
|
+
param_info["type"] = ""
|
|
81
|
+
else:
|
|
82
|
+
param_info["type"] = type_list[0] if len(type_list) == 1 else type_list
|
|
83
|
+
else:
|
|
84
|
+
type_hint_warning = True
|
|
85
|
+
user_input_params.append(param_name)
|
|
86
|
+
param_info["type"] = ""
|
|
87
|
+
|
|
88
|
+
# Get default value
|
|
89
|
+
if param.default != inspect.Parameter.empty:
|
|
90
|
+
param_info["default"] = param.default
|
|
91
|
+
|
|
92
|
+
parameters.append(param_info)
|
|
93
|
+
|
|
94
|
+
# Get docstring
|
|
95
|
+
docstring = inspect.getdoc(method)
|
|
96
|
+
|
|
97
|
+
method_info = {
|
|
98
|
+
"docstring": docstring or "",
|
|
99
|
+
"parameters": parameters
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return method_info, type_hint_warning
|
|
103
|
+
|
|
104
|
+
except Exception as e:
|
|
105
|
+
print(f"Error analyzing method {method.__name__}: {e}")
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def analyze_module(self, module, exclude_names=[]):
|
|
110
|
+
"""Analyze module from sys.modules and extract class instances and methods"""
|
|
111
|
+
exclude_classes = (flask.Blueprint, logging.Logger)
|
|
112
|
+
# Get all variables in the module that are class instances
|
|
113
|
+
included = {}
|
|
114
|
+
excluded = {}
|
|
115
|
+
failed = {}
|
|
116
|
+
included_with_warnings = {}
|
|
117
|
+
for name, obj in vars(module).items():
|
|
118
|
+
if (
|
|
119
|
+
type(obj).__module__ == 'builtins'
|
|
120
|
+
or name[0].isupper()
|
|
121
|
+
or name.startswith("_")
|
|
122
|
+
or isinstance(obj, exclude_classes)
|
|
123
|
+
or name in exclude_names
|
|
124
|
+
or not hasattr(obj, '__class__')
|
|
125
|
+
):
|
|
126
|
+
excluded[name] = type(obj).__name__
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
cls = obj.__class__
|
|
130
|
+
|
|
131
|
+
try:
|
|
132
|
+
class_methods, type_hint_warning = self.analyze_class(cls)
|
|
133
|
+
if class_methods:
|
|
134
|
+
if type_hint_warning:
|
|
135
|
+
included_with_warnings[name] = class_methods
|
|
136
|
+
included[name] = class_methods
|
|
137
|
+
except Exception as e:
|
|
138
|
+
failed[name] = str(e)
|
|
139
|
+
continue
|
|
140
|
+
return included, included_with_warnings, failed, excluded
|
|
141
|
+
|
|
142
|
+
def save_to_json(self, data, output_path):
|
|
143
|
+
"""Save analysis result to JSON file"""
|
|
144
|
+
with open(output_path, 'w') as f:
|
|
145
|
+
json.dump(data, f, indent=2)
|
|
146
|
+
|
|
147
|
+
def analyze_class(self, cls):
|
|
148
|
+
class_methods = {}
|
|
149
|
+
type_hint_flag = False
|
|
150
|
+
for method_name, method in inspect.getmembers(cls, predicate=callable):
|
|
151
|
+
if method_name.startswith("_") or method_name.isupper():
|
|
152
|
+
continue
|
|
153
|
+
method_info, type_hint_warning = self.analyze_method(method)
|
|
154
|
+
if type_hint_warning:
|
|
155
|
+
type_hint_flag = True
|
|
156
|
+
if method_info:
|
|
157
|
+
class_methods[method_name] = method_info
|
|
158
|
+
return class_methods, type_hint_flag
|
|
159
|
+
|
|
160
|
+
@staticmethod
|
|
161
|
+
def print_deck_snapshot(result, with_warnings, failed):
|
|
162
|
+
print("\nDeck Snapshot:")
|
|
163
|
+
print("Included Classes:")
|
|
164
|
+
for name, methods in result.items():
|
|
165
|
+
print(f" {name}:")
|
|
166
|
+
for method_name, method_info in methods.items():
|
|
167
|
+
print(f" {method_name}: {method_info}")
|
|
168
|
+
|
|
169
|
+
if with_warnings:
|
|
170
|
+
print("\nClasses with Type Hint Warnings:")
|
|
171
|
+
for name, methods in with_warnings.items():
|
|
172
|
+
print(f" {name}:")
|
|
173
|
+
for method_name, method_info in methods.items():
|
|
174
|
+
print(f" {method_name}: {method_info}")
|
|
175
|
+
|
|
176
|
+
if failed:
|
|
177
|
+
print("\nFailed Classes:")
|
|
178
|
+
for name, error in failed.items():
|
|
179
|
+
print(f" {name}: {error}")
|
|
180
|
+
|
|
181
|
+
if __name__ == "__main__":
|
|
182
|
+
balance = AbstractBalance("re")
|
|
183
|
+
pump = AbstractPump("re")
|
|
184
|
+
|
|
185
|
+
_analyzer = ScriptAnalyzer()
|
|
186
|
+
module = sys.modules[__name__]
|
|
187
|
+
try:
|
|
188
|
+
|
|
189
|
+
result, with_warnings, failed, _ = _analyzer.analyze_module(module)
|
|
190
|
+
|
|
191
|
+
output_path = f"analysis.json"
|
|
192
|
+
_analyzer.save_to_json(result, output_path)
|
|
193
|
+
|
|
194
|
+
print(f"\nAnalysis complete! Results saved to: {output_path}")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
_analyzer.print_deck_snapshot(result, with_warnings, failed)
|
|
200
|
+
|
|
201
|
+
except Exception as e:
|
|
202
|
+
print(f"Error: {e}")
|
|
203
|
+
|
ivoryos/utils/task_runner.py
CHANGED
|
@@ -72,10 +72,13 @@ class TaskRunner:
|
|
|
72
72
|
output = function_executable(**kwargs)
|
|
73
73
|
step.output = output
|
|
74
74
|
step.end_time = datetime.now()
|
|
75
|
+
success = True
|
|
75
76
|
except Exception as e:
|
|
76
77
|
step.run_error = e.__str__()
|
|
77
78
|
step.end_time = datetime.now()
|
|
79
|
+
success = False
|
|
80
|
+
output = e.__str__()
|
|
78
81
|
finally:
|
|
79
82
|
db.session.commit()
|
|
80
83
|
self.lock.release()
|
|
81
|
-
return output
|
|
84
|
+
return dict(success=success, output=output)
|
ivoryos/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.0
|
|
1
|
+
__version__ = "1.2.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ivoryos
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.0
|
|
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
|
|
@@ -48,7 +48,7 @@ With the least modification of the current workflow, user can design, manage and
|
|
|
48
48
|
This software is developed and tested using Windows. This software and its dependencies are compatible across major platforms: Linux, macOS, and Windows. Some dependencies (Flask-SQLAlchemy) may require additional setup.
|
|
49
49
|
|
|
50
50
|
### Python Version
|
|
51
|
-
Python >=3.
|
|
51
|
+
Python >=3.10 for best compatibility. Python >=3.7 without Ax.
|
|
52
52
|
### Python dependencies
|
|
53
53
|
This software is compatible with the latest versions of all dependencies.
|
|
54
54
|
- bcrypt~=4.0
|
|
@@ -59,8 +59,7 @@ This software is compatible with the latest versions of all dependencies.
|
|
|
59
59
|
- SQLAlchemy-Utils~=0.41
|
|
60
60
|
- Flask-WTF~=1.2
|
|
61
61
|
- python-dotenv==1.0.1
|
|
62
|
-
-
|
|
63
|
-
- ax-platform (optional ~=0.3 or ~=0.4 for Python>=3.9)
|
|
62
|
+
- ax-platform (optional ~=0.4 for Python>=3.9)
|
|
64
63
|
|
|
65
64
|
## Installation
|
|
66
65
|
```bash
|
|
@@ -70,7 +69,7 @@ or
|
|
|
70
69
|
```bash
|
|
71
70
|
git clone https://gitlab.com/heingroup/ivoryos.git
|
|
72
71
|
cd ivoryos
|
|
73
|
-
pip install
|
|
72
|
+
pip install .
|
|
74
73
|
```
|
|
75
74
|
|
|
76
75
|
The installation may take 10 to 30 seconds to install. The installation time may vary and take up to several minutes, depending on the network speed, computer performance, and virtual environment settings.
|
|
@@ -98,7 +97,7 @@ Create an account and login (local database)
|
|
|
98
97
|
[//]: # ()
|
|
99
98
|
|
|
100
99
|
|
|
101
|
-
### Additional settings
|
|
100
|
+
### Additional settings (not actively maintained)
|
|
102
101
|
#### AI assistant
|
|
103
102
|
To streamline the experimental design on SDLs, we also integrate Large Language Models (LLMs) to interpret the inspected functions and generate code according to task descriptions.
|
|
104
103
|
|
|
@@ -150,8 +149,6 @@ ivoryos.run(__name__)
|
|
|
150
149
|
### Deck function and web form
|
|
151
150
|

|
|
152
151
|
|
|
153
|
-
### Text-to-code demo
|
|
154
|
-

|
|
155
152
|
|
|
156
153
|
### Directory structure
|
|
157
154
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
ivoryos/__init__.py,sha256=p9m5csEeKgE7VJ_PPf-d50G5Q4A9aN2vRfJRJdi9Z4c,9149
|
|
2
|
+
ivoryos/config.py,sha256=sk4dskm-K_Nv4uaA3QuE6xtew8wL6q3HmIoLgRm7p8U,2153
|
|
3
|
+
ivoryos/socket_handlers.py,sha256=VWVWiIdm4jYAutwGu6R0t1nK5MuMyOCL0xAnFn06jWQ,1302
|
|
4
|
+
ivoryos/version.py,sha256=MpAT5hgNoHnTtG1XRD_GV_A7QrHVU6vJjGSw_8qMGA4,22
|
|
5
|
+
ivoryos/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
ivoryos/routes/api/api.py,sha256=X_aZMB_nCxW41pqZpJOiEEwGmlqLqJUArruevuy41v0,2284
|
|
7
|
+
ivoryos/routes/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
ivoryos/routes/auth/auth.py,sha256=SbtiMc1kFHDXIauvT1o3_8rJ-jVVz2C6hfKeSCmoXSE,3231
|
|
9
|
+
ivoryos/routes/auth/templates/login.html,sha256=WSRrKbdM_oobqSXFRTo-j9UlOgp6sYzS9tm7TqqPULI,1207
|
|
10
|
+
ivoryos/routes/auth/templates/signup.html,sha256=b5LTXtpfTSkSS7X8u1ldwQbbgEFTk6UNMAediA5BwBY,1465
|
|
11
|
+
ivoryos/routes/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
ivoryos/routes/control/control.py,sha256=Vmy3GRZz8EbKmV9qslR8gsaYaYzb5HQTpukp42HfMow,5236
|
|
13
|
+
ivoryos/routes/control/control_file.py,sha256=NIAzwhswvpl3u0mansy1ku-rPDybS5hVbmbnymOikWk,1548
|
|
14
|
+
ivoryos/routes/control/control_new_device.py,sha256=mfJKg5JAOagIpUKbp2b5nRwvd2V3bzT3M0zIhIsEaFM,5456
|
|
15
|
+
ivoryos/routes/control/utils.py,sha256=at11wA5HPAZN4BfMaymj1GKEvRTrqi4Wg6cTqUZJDjU,1155
|
|
16
|
+
ivoryos/routes/control/templates/controllers.html,sha256=tgtTuns8S2Pf6XKeojinQZ1bz112ieRGLPF5-1cElfE,8030
|
|
17
|
+
ivoryos/routes/control/templates/controllers_new.html,sha256=eVeLABT39DWOIYrwWClw7sAD3lCoAGCznygPgFbQoRc,5945
|
|
18
|
+
ivoryos/routes/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
ivoryos/routes/data/data.py,sha256=PhuTNlQptpqBZ_9cVCYN_PbM7LBma5BjvsDlZ5gpPxM,4186
|
|
20
|
+
ivoryos/routes/data/templates/workflow_database.html,sha256=ofvHcovpwmJXo1SFiSrL8I9kLU_3U1UxsJUUrQ2CJUU,4878
|
|
21
|
+
ivoryos/routes/data/templates/workflow_view.html,sha256=72xKreX9WhYx-0n0cFf-CL-fJIWXPCIaTi_Aa8Tq3xg,3651
|
|
22
|
+
ivoryos/routes/data/templates/components/step_card.html,sha256=9lKR4NCgU2v5Nbdv2uaJ-9aKibtiB_2-Y_kyHX6Ka1k,730
|
|
23
|
+
ivoryos/routes/design/__init__.py,sha256=zS3HXKaw0ALL5n6t_W1rUz5Uj5_tTQ-Y1VMXyzewvR0,113
|
|
24
|
+
ivoryos/routes/design/design.py,sha256=9xP6uOro4ZRzvVNJ0oVv9cc27LrQw06lLsxhgYTym9c,17711
|
|
25
|
+
ivoryos/routes/design/design_file.py,sha256=m4yku8fkpLUs4XvLJBqR5V-kyaGKbGB6ZoRxGbjEU5Q,2140
|
|
26
|
+
ivoryos/routes/design/design_step.py,sha256=l8U3-FuXmap__sYm51AueKdbTaLCFaKjAz-j02b4g-E,5200
|
|
27
|
+
ivoryos/routes/design/templates/experiment_builder.html,sha256=hh-d2tOc_40gww5WfUYIf8sM3qBaALZnR8Sx7Ja4tpU,1623
|
|
28
|
+
ivoryos/routes/design/templates/components/action_form.html,sha256=ktnmXVwe2WFLM6Sg_VbBfDrPXrnongSUxjpYhZGamPY,3058
|
|
29
|
+
ivoryos/routes/design/templates/components/actions_panel.html,sha256=jHTR58saTUIZInBdC-vLc1ZTbStLiULeWbupjB4hQzo,977
|
|
30
|
+
ivoryos/routes/design/templates/components/autofill_toggle.html,sha256=CRVQUHoQT7sOSO5-Vax54ImHdT4G_mEgqR5OQkeUwK8,617
|
|
31
|
+
ivoryos/routes/design/templates/components/canvas.html,sha256=bKLCJaG1B36Yy9Vsnz4P5qiX4BPdfaGe9JeQQzu9rsI,268
|
|
32
|
+
ivoryos/routes/design/templates/components/canvas_footer.html,sha256=5VRRacMZbzx0hUej0NPP-PmXM_AtUqduHzDS7a60cQY,435
|
|
33
|
+
ivoryos/routes/design/templates/components/canvas_header.html,sha256=7iIzLDGHX7MnmBbf98nWtLDprbeIgoNV4dJUO1zE4Tc,3598
|
|
34
|
+
ivoryos/routes/design/templates/components/canvas_main.html,sha256=9inYO700zRa09lfQI2NY4FJGGeTh-9rvX4ltjj0LK3k,1432
|
|
35
|
+
ivoryos/routes/design/templates/components/deck_selector.html,sha256=ryTRpljYezo0AzGLCJu_qOMokjjnft3GIxddmNGtBA0,657
|
|
36
|
+
ivoryos/routes/design/templates/components/edit_action_form.html,sha256=Dz7FnnOK4PYptAHNy9_WFCU1RZTSV61-1lNHHOSRJNs,1876
|
|
37
|
+
ivoryos/routes/design/templates/components/instruments_panel.html,sha256=r1jnScVRAknrRPRbAnIVApfnx9f4yavgf9ZlNhNpjW4,3135
|
|
38
|
+
ivoryos/routes/design/templates/components/modals.html,sha256=6Dl8I8oD4ln7kK8C5e92pFVVH5KDte-vVTL0U_6NSTg,306
|
|
39
|
+
ivoryos/routes/design/templates/components/python_code_overlay.html,sha256=GUHgsmUWQf0P1Fbg5W0OJC34TXCUIMQVUkS7KDoauyI,1264
|
|
40
|
+
ivoryos/routes/design/templates/components/sidebar.html,sha256=A6dRo53zIB6QJVrRLJcBZHUNJ3qpYPnR3kWxM8gTkjw,501
|
|
41
|
+
ivoryos/routes/design/templates/components/text_to_code_panel.html,sha256=d-omdXk-PXAR5AyWPr4Rc4pqsebZOiTiMrnz3pPCnUY,1197
|
|
42
|
+
ivoryos/routes/design/templates/components/modals/drop_modal.html,sha256=LPxcycSiBjdQbajYOegjMQEi7ValcaczGoWmW8Sz3Ms,779
|
|
43
|
+
ivoryos/routes/design/templates/components/modals/json_modal.html,sha256=R-SeEdhtuDVbwOWYYH_hCdpul7y4ybCWoNwVIO5j49s,1122
|
|
44
|
+
ivoryos/routes/design/templates/components/modals/new_script_modal.html,sha256=pxZdWWDgI52VsTFzz6pIM9m_dTwR6jARcvCYQ6fV3Lc,937
|
|
45
|
+
ivoryos/routes/design/templates/components/modals/rename_modal.html,sha256=40rLNF9JprdXekB3mv_S3OdqVuQYOe-BZSCgOnIkxJQ,1202
|
|
46
|
+
ivoryos/routes/design/templates/components/modals/saveas_modal.html,sha256=N5PEqUuK3qxDFbtDKFnzHwhLarQLPHiX-XQAdQPL1AU,1555
|
|
47
|
+
ivoryos/routes/execute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
+
ivoryos/routes/execute/execute.py,sha256=hFnCvzO1OzR0XckCRzHfP_RZV70DtbH_p7kw1YhIe3o,12250
|
|
49
|
+
ivoryos/routes/execute/execute_file.py,sha256=TelWYV295p4ZPhkUDJSVxfYROfVaKodEmDPTS2plQHI,2816
|
|
50
|
+
ivoryos/routes/execute/templates/experiment_run.html,sha256=D-ek7ISQrIQXy4PH37TnsURihbGNdpCgdTC8w79cwQc,10355
|
|
51
|
+
ivoryos/routes/execute/templates/components/error_modal.html,sha256=5Dmp9V0Ys6781Y-pKn_mc4N9J46c8EwIkjkHX22xCsw,1025
|
|
52
|
+
ivoryos/routes/execute/templates/components/logging_panel.html,sha256=FllozlPd6o7uBd8eflGjRktPV435J3XgiEeLZugoUi0,1623
|
|
53
|
+
ivoryos/routes/execute/templates/components/progress_panel.html,sha256=-nX76aFLxSOiYgI1xMjznC9rDYF-Vb92TmfjXYpBtps,1323
|
|
54
|
+
ivoryos/routes/execute/templates/components/run_panel.html,sha256=CmK-LYJ4K6RonHn6l9eJkqRw0XQizThOugxiXZonSDs,373
|
|
55
|
+
ivoryos/routes/execute/templates/components/run_tabs.html,sha256=u-msoTQPBGvyE_5_UczRtR9bh7zD3EvsgJhT77rTzOI,1145
|
|
56
|
+
ivoryos/routes/execute/templates/components/tab_bayesian.html,sha256=5XTMHZzbGxcCZ2M0LSRqqmVh4qmu0R1MjCkT_FQ0ag0,21314
|
|
57
|
+
ivoryos/routes/execute/templates/components/tab_configuration.html,sha256=JIHsYvwcYQZmJJz503NXnhcceKxd9B3JKFUSvGNWe_0,5131
|
|
58
|
+
ivoryos/routes/execute/templates/components/tab_repeat.html,sha256=X-r7p78tVRrfwmAbhhZGBZbm78C4nTJS6O2A4dvzGEg,760
|
|
59
|
+
ivoryos/routes/library/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
|
+
ivoryos/routes/library/library.py,sha256=jook_OZRIO1nr3nBxU_X9yrDw5PSLqa0wrInI7GY6sg,5457
|
|
61
|
+
ivoryos/routes/library/templates/library.html,sha256=8pyKTc0TmrSSrwSVAYrh6cuPRHutg_yAA8mqzLFyZIg,3968
|
|
62
|
+
ivoryos/routes/main/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
|
+
ivoryos/routes/main/main.py,sha256=1AcSouCocHWjlpEED-ECn5OFiu0-3u0N-0st5RtKCVY,952
|
|
64
|
+
ivoryos/routes/main/templates/help.html,sha256=IOktMEsOPk0SCiMBXZ4mpffClERAyX8W82fel71M3M0,9370
|
|
65
|
+
ivoryos/routes/main/templates/home.html,sha256=BDvwkVthxniQ157H6E2hgYHT1Vv1GVBwu6dQejtzwoo,4633
|
|
66
|
+
ivoryos/static/favicon.ico,sha256=RhlrPtfITOkzC9BjP1UB1V5L9Oyp6NwNtWeMcGOnpyc,15406
|
|
67
|
+
ivoryos/static/logo.webp,sha256=lXgfQR-4mHTH83k7VV9iB54-oC2ipe6uZvbwdOnLETc,14974
|
|
68
|
+
ivoryos/static/style.css,sha256=zQVx35A5g6JMJ-K84-6fSKtzXGjp_p5ZVG6KLHPM2IE,4021
|
|
69
|
+
ivoryos/static/gui_annotation/Slide1.png,sha256=Lm4gdOkUF5HIUFaB94tl6koQVkzpitKj43GXV_XYMMc,121727
|
|
70
|
+
ivoryos/static/gui_annotation/Slide2.PNG,sha256=z3wQ9oVgg4JTWVLQGKK_KhtepRHUYP1e05XUWGT2A0I,118761
|
|
71
|
+
ivoryos/static/js/action_handlers.js,sha256=VEDox3gQvg0YXJ6WW6IthOsFqZKmvUGJ8pmQdfzHQFw,5122
|
|
72
|
+
ivoryos/static/js/db_delete.js,sha256=l67fqUaN_FVDaL7v91Hd7LyRbxnqXx9nyjF34-7aewY,561
|
|
73
|
+
ivoryos/static/js/overlay.js,sha256=dPxop19es0E0ZUSY3d_4exIk7CJuQEnlW5uTt5fZfzI,483
|
|
74
|
+
ivoryos/static/js/script_metadata.js,sha256=m8VYZ8OGT2oTx1kXMXq60bKQI9WCbJNkzcFDzLvRuGc,1188
|
|
75
|
+
ivoryos/static/js/socket_handler.js,sha256=2Iyv_3METjhSlSavs_L9FE3PKY4xDEpfzJpd2FywY9o,5300
|
|
76
|
+
ivoryos/static/js/sortable_card.js,sha256=ifmlGe3yy0U_KzMphV4ClRhK2DLOvkELYMlq1vECuac,807
|
|
77
|
+
ivoryos/static/js/sortable_design.js,sha256=QqYyk385JNm6zCgZK_Oa-cJEP1uPtZ_tVz27x4hyx5A,4790
|
|
78
|
+
ivoryos/static/js/ui_state.js,sha256=5EuqwIDndjZTqj9dsAR_IA91iGMcodY_TuQo17LLL1w,3331
|
|
79
|
+
ivoryos/templates/base.html,sha256=SdZswZmfLWehorMsoGkm-FjLFtB1ivLkdUJFbpDRqp4,8519
|
|
80
|
+
ivoryos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
|
+
ivoryos/utils/bo_campaign.py,sha256=Fil-zT7JexL_p9XqyWByjAk42XB1R9XUKN8CdV5bi6c,9714
|
|
82
|
+
ivoryos/utils/client_proxy.py,sha256=0OT2xTMkqh_2ybgCxMV_71ZVUThWwrsnAhTIBY5vDR8,2095
|
|
83
|
+
ivoryos/utils/db_models.py,sha256=baE4LJcSGUj10Tj6imfINXi4JQX_4oLv_kb9bd0rp-M,27920
|
|
84
|
+
ivoryos/utils/form.py,sha256=eIk1N77Ynxc4Omww5ZYlmpOIJfQPWto2qfiU6nzIIeQ,21755
|
|
85
|
+
ivoryos/utils/global_config.py,sha256=zNO9GYhGn7El3msWoxJIm3S4Mzb3VMh2i5ZEsVtvb2Q,2463
|
|
86
|
+
ivoryos/utils/llm_agent.py,sha256=-lVCkjPlpLues9sNTmaT7bT4sdhWvV2DiojNwzB2Lcw,6422
|
|
87
|
+
ivoryos/utils/py_to_json.py,sha256=fyqjaxDHPh-sahgT6IHSn34ktwf6y51_x1qvhbNlH-U,7314
|
|
88
|
+
ivoryos/utils/script_runner.py,sha256=W4UL2iMt9bTBlb47pu2kc7SJyL9hlKzdtPudVZ9FvIM,16723
|
|
89
|
+
ivoryos/utils/serilize.py,sha256=Ded3Vbicl4KYN8GJ_gY7HJMuInAeFZEPk5ZtuEtHPns,6933
|
|
90
|
+
ivoryos/utils/task_runner.py,sha256=cDIcmDaqYh0vXoYaL_kO877pluAo2tyfsHl9OgZqJJE,3029
|
|
91
|
+
ivoryos/utils/utils.py,sha256=BzgKIMMb7vyUIwYMhGDsWtwJEy5vNKtEHRJHHSiTSnM,13881
|
|
92
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
93
|
+
tests/conftest.py,sha256=u2sQ6U-Lghyl7et1Oz6J2E5VZ47VINKcjRM_2leAE2s,3627
|
|
94
|
+
tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
95
|
+
tests/integration/test_route_auth.py,sha256=l3ZDqr0oiCWS3yYSXGK5yMP6qI2t7Sv5I9zoYTkiyQU,2754
|
|
96
|
+
tests/integration/test_route_control.py,sha256=YYIll84bTUEKiAxFiFSz6LF3fTldPNfCtHs0IR3mSdM,3935
|
|
97
|
+
tests/integration/test_route_database.py,sha256=mS026W_hEuCTMpSkdRWvM-f4MYykK_6nRDJ4K5a7QA0,2342
|
|
98
|
+
tests/integration/test_route_design.py,sha256=PJAvGRiCY6B53Pu1v5vPAVHHsuaqRmRKk2eesSNshLU,1157
|
|
99
|
+
tests/integration/test_route_main.py,sha256=bmuf8Y_9CRWhiLLf4up11ltEd5YCdsLx6I-o26VGDEw,1228
|
|
100
|
+
tests/integration/test_sockets.py,sha256=4ZyFyExm7a-DYzVqpzEONpWeb1a0IT68wyFaQu0rY_Y,925
|
|
101
|
+
ivoryos-1.2.0.dist-info/LICENSE,sha256=p2c8S8i-8YqMpZCJnadLz1-ofxnRMILzz6NCMIypRag,1084
|
|
102
|
+
ivoryos-1.2.0.dist-info/METADATA,sha256=EjG1H1CEgd3eiOshrWhkp2nw8SeoGQ7qB2SZiuxqf9Q,8834
|
|
103
|
+
ivoryos-1.2.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
104
|
+
ivoryos-1.2.0.dist-info/top_level.txt,sha256=mIOiZkdpSwxFJt1R5fsyOff8mNprXHq1nMGNKNULIyE,14
|
|
105
|
+
ivoryos-1.2.0.dist-info/RECORD,,
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
{% extends 'base.html' %}
|
|
2
|
-
{% block title %}IvoryOS | Controller for {{instrument}}{% endblock %}
|
|
3
|
-
{% block body %}
|
|
4
|
-
<div id="overlay" class="overlay">
|
|
5
|
-
<div>
|
|
6
|
-
<h3 id="overlay-text"></h3>
|
|
7
|
-
<div class="spinner-border" role="status"></div>
|
|
8
|
-
</div>
|
|
9
|
-
</div>
|
|
10
|
-
<h1>{{instrument}} controller</h1>
|
|
11
|
-
{% set hidden = session.get('hidden_functions', {}) %}
|
|
12
|
-
<div class="grid-container" id="sortable-grid">
|
|
13
|
-
{% for function, form in forms.items() %}
|
|
14
|
-
|
|
15
|
-
{% set hidden_instrument = hidden.get(instrument, []) %}
|
|
16
|
-
{% if function not in hidden_instrument %}
|
|
17
|
-
<div class="card" id="{{function}}">
|
|
18
|
-
<div class="bg-white rounded shadow-sm flex-fill">
|
|
19
|
-
<i class="bi bi-info-circle ms-2" data-bs-toggle="tooltip" data-bs-placement="top" title='{{ form.hidden_name.description or "Docstring is not available" }}' ></i>
|
|
20
|
-
<a style="float: right" aria-label="Close" href="{{ url_for('control.hide_function', instrument=instrument, function=function) }}"><i class="bi bi-eye-slash-fill"></i></a>
|
|
21
|
-
<div class="form-control" style="border: none">
|
|
22
|
-
<form role="form" method='POST' name="{{function}}" id="{{function}}">
|
|
23
|
-
<div class="form-group">
|
|
24
|
-
{{ form.hidden_tag() }}
|
|
25
|
-
{% for field in form %}
|
|
26
|
-
{% if field.type not in ['CSRFTokenField', 'HiddenField'] %}
|
|
27
|
-
<div class="input-group mb-3">
|
|
28
|
-
<label class="input-group-text">{{ field.label.text }}</label>
|
|
29
|
-
{% if field.type == "SubmitField" %}
|
|
30
|
-
{{ field(class="btn btn-dark") }}
|
|
31
|
-
{% elif field.type == "BooleanField" %}
|
|
32
|
-
{{ field(class="form-check-input") }}
|
|
33
|
-
{% else %}
|
|
34
|
-
{{ field(class="form-control") }}
|
|
35
|
-
{% endif %}
|
|
36
|
-
</div>
|
|
37
|
-
{% endif %}
|
|
38
|
-
{% endfor %}
|
|
39
|
-
</div>
|
|
40
|
-
<div class="input-group mb-3">
|
|
41
|
-
<button type="submit" name="{{ function }}" id="{{ function }}" class="form-control" style="background-color: #a5cece;">{{format_name(function)}} </button>
|
|
42
|
-
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
</form>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
{% endif %}
|
|
50
|
-
{% endfor %}
|
|
51
|
-
</div>
|
|
52
|
-
<div class="accordion accordion-flush" id="accordionActions" >
|
|
53
|
-
<div class="accordion-item">
|
|
54
|
-
<h4 class="accordion-header">
|
|
55
|
-
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#hidden">
|
|
56
|
-
Hidden functions
|
|
57
|
-
</button>
|
|
58
|
-
</h4>
|
|
59
|
-
</div>
|
|
60
|
-
<div id="hidden" class="accordion-collapse collapse" data-bs-parent="#accordionActions">
|
|
61
|
-
<div class="accordion-body">
|
|
62
|
-
{% set hidden_instrument = hidden.get(instrument, []) %}
|
|
63
|
-
{% for function in hidden_instrument %}
|
|
64
|
-
<div>
|
|
65
|
-
{{ function }} <a href="{{ url_for('control.remove_hidden', instrument=instrument, function=function) }}"><i class="bi bi-eye-fill"></i></a>
|
|
66
|
-
</div>
|
|
67
|
-
{% endfor %}
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<script>
|
|
73
|
-
const saveOrderUrl = `{{ url_for('control.save_order', instrument=instrument) }}`;
|
|
74
|
-
const buttonIds = {{ session['card_order'][instrument] | tojson }};
|
|
75
|
-
</script>
|
|
76
|
-
<script src="{{ url_for('static', filename='js/sortable_card.js') }}"></script>
|
|
77
|
-
<script src="{{ url_for('static', filename='js/overlay.js') }}"></script>
|
|
78
|
-
{% endblock %}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
{% extends 'base.html' %}
|
|
2
|
-
{% block title %}IvoryOS | Devices{% endblock %}
|
|
3
|
-
{% block body %}
|
|
4
|
-
<div class="row">
|
|
5
|
-
{% if defined_variables %}
|
|
6
|
-
{% for instrument in defined_variables %}
|
|
7
|
-
<div class="col-xl-3 col-lg-4 col-md-6 mb-4 ">
|
|
8
|
-
<div class="bg-white rounded shadow-sm position-relative">
|
|
9
|
-
{% if deck %}
|
|
10
|
-
{# <a href="{{ url_for('control.disconnect', instrument=instrument) }}" class="stretched-link controller-card" style="float: right;color: red; position: relative;">Disconnect <i class="bi bi-x-square"></i></a>#}
|
|
11
|
-
<div class="p-4 controller-card">
|
|
12
|
-
<h5 class=""><a href="{{ url_for('control.controllers', instrument=instrument) }}" class="text-dark stretched-link">{{instrument.split(".")[1]}}</a></h5>
|
|
13
|
-
</div>
|
|
14
|
-
{% else %}
|
|
15
|
-
<div class="p-4 controller-card">
|
|
16
|
-
<h5 class=""><a href="{{ url_for('control.controllers', instrument=instrument) }}" class="text-dark stretched-link">{{instrument}}</a></h5>
|
|
17
|
-
</div>
|
|
18
|
-
{% endif %}
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
{% endfor %}
|
|
22
|
-
<div class="d-flex mb-3">
|
|
23
|
-
<a href="{{ url_for('control.download_proxy', filetype='proxy') }}" class="btn btn-outline-primary">
|
|
24
|
-
<i class="bi bi-download"></i> Download remote control script
|
|
25
|
-
</a>
|
|
26
|
-
</div>
|
|
27
|
-
{% if not deck %}
|
|
28
|
-
<div class="col-xl-3 col-lg-4 col-md-6 mb-4 ">
|
|
29
|
-
<div class="bg-white rounded shadow-sm position-relative">
|
|
30
|
-
<div class="p-4 controller-card" >
|
|
31
|
-
{% if deck %}
|
|
32
|
-
{# todo disconnect for imported deck #}
|
|
33
|
-
{# <h5> <a href="{{ url_for("disconnect") }}" class="stretched-link" style="color: orangered">Disconnect deck</a></h5>#}
|
|
34
|
-
{% else %}
|
|
35
|
-
<h5><a href="{{ url_for('control.new_controller') }}" style="color: orange" class="stretched-link">New connection</a></h5>
|
|
36
|
-
{% endif %}
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
{% endif %}
|
|
41
|
-
{% else %}
|
|
42
|
-
<div class="col-xl-3 col-lg-4 col-md-6 mb-4 ">
|
|
43
|
-
<div class="bg-white rounded shadow-sm position-relative">
|
|
44
|
-
<div class="p-4 controller-card" >
|
|
45
|
-
{% if deck %}
|
|
46
|
-
<h5><a data-bs-toggle="modal" href="#importModal" class="stretched-link"><i class="bi bi-folder-plus"></i> Import deck </a></h5>
|
|
47
|
-
{% else %}
|
|
48
|
-
<h5><a href="{{ url_for('control.new_controller') }}" style="color: orange" class="stretched-link">New connection</a></h5>
|
|
49
|
-
{% endif %}
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
{% endif %}
|
|
54
|
-
</div>
|
|
55
|
-
{% endblock %}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
{% extends 'base.html' %}
|
|
2
|
-
{% block title %}IvoryOS | New devices{% endblock %}
|
|
3
|
-
|
|
4
|
-
{% block body %}
|
|
5
|
-
<div class="row">
|
|
6
|
-
<div class="col-xl-4 col-lg-4 col-md-6 mb-4 ">
|
|
7
|
-
<h5>Available Python API</h5>
|
|
8
|
-
<hr>
|
|
9
|
-
{% for instrument in api_variables %}
|
|
10
|
-
<div class="bg-white rounded shadow-sm position-relative">
|
|
11
|
-
<h5 class="p-3 controller-card">
|
|
12
|
-
<a href="{{ url_for('control.new_controller', instrument=instrument) }}" class="text-dark stretched-link">{{instrument}}</a>
|
|
13
|
-
</h5>
|
|
14
|
-
</div>
|
|
15
|
-
{% endfor %}
|
|
16
|
-
<div class="bg-white rounded shadow-sm position-relative">
|
|
17
|
-
<h5 class="p-3 controller-card">
|
|
18
|
-
<a data-bs-toggle="modal" href="#importAPI" class="stretched-link"><i class="bi bi-folder-plus"></i> Import API</a>
|
|
19
|
-
</h5>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
|
-
<div class="col-xl-5 col-lg-5 col-md-6 mb-4 ">
|
|
23
|
-
{% if device %}
|
|
24
|
-
<h5>Connecting</h5><hr>
|
|
25
|
-
<form role="form" method='POST' name="init" action="{{ url_for('control.new_controller', instrument=instrument) }}">
|
|
26
|
-
<div class="form-group">
|
|
27
|
-
<div class="input-group mb-3">
|
|
28
|
-
<span class="input-group-text" >Name this device</span>
|
|
29
|
-
<input class="form-control" type="text" id="device_name" name="device_name" aria-labelledby="nameHelpBlock" placeholder="e.g. {{device.__name__}}_1" >
|
|
30
|
-
<div id="nameHelpBlock" class="form-text">
|
|
31
|
-
Name your instrument, avoid names that are defined on the right
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
{% for arg in device.__init__.__annotations__ %}
|
|
35
|
-
{% if not arg == "return" %}
|
|
36
|
-
<div class="input-group mb-3">
|
|
37
|
-
<span class="input-group-text" >{{arg}}</span>
|
|
38
|
-
<input class="form-control" type="text" id="{{arg}}" name="{{arg}}"
|
|
39
|
-
placeholder="{{device.__init__.__annotations__[arg].__name__}}"
|
|
40
|
-
value="{{args.parameters[arg].default if not args.parameters[arg].default.__name__ == '_empty' else ''}}">
|
|
41
|
-
{% if device.__init__.__annotations__[arg].__module__ is not in ["builtins", "typing"] %}
|
|
42
|
-
<a role="button" href="{{ url_for('control.new_controller', instrument=device.__init__.__annotations__[arg].__name__) }}" class="btn btn-secondary">initialize {{device.__init__.__annotations__[arg].__name__}} first</a>
|
|
43
|
-
{% endif %}
|
|
44
|
-
</div>
|
|
45
|
-
{% endif %}
|
|
46
|
-
{% endfor %}
|
|
47
|
-
<button type="submit" class="btn btn-dark">Connect</button>
|
|
48
|
-
</div>
|
|
49
|
-
</form>
|
|
50
|
-
{% endif %}
|
|
51
|
-
</div>
|
|
52
|
-
<div class="col-xl-3 col-lg-3 col-md-6 mb-4">
|
|
53
|
-
<h5>Defined Instruments</h5><hr>
|
|
54
|
-
{% if defined_variables %}
|
|
55
|
-
<ul class="list-group">
|
|
56
|
-
{% for instrument in defined_variables %}
|
|
57
|
-
<li class="list-group-item">{{instrument}}</li>
|
|
58
|
-
{% endfor %}
|
|
59
|
-
</ul>
|
|
60
|
-
{% endif %}
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<div class="modal fade" id="importAPI" tabindex="-1" aria-labelledby="importModal" aria-hidden="true" >
|
|
66
|
-
<div class="modal-dialog">
|
|
67
|
-
<div class="modal-content">
|
|
68
|
-
<div class="modal-header">
|
|
69
|
-
<h1 class="modal-title fs-5" id="importModal">Import API by file path</h1>
|
|
70
|
-
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
71
|
-
</div>
|
|
72
|
-
<form method="POST" action="{{ url_for('control.import_api') }}" enctype="multipart/form-data">
|
|
73
|
-
<div class="modal-body">
|
|
74
|
-
<h5>input manually</h5>
|
|
75
|
-
<div class="input-group mb-3">
|
|
76
|
-
<label class="input-group-text" for="filepath">File Path:</label>
|
|
77
|
-
<input type="text" class="form-control" name="filepath" id="filepath">
|
|
78
|
-
</div>
|
|
79
|
-
<div class="modal-footer">
|
|
80
|
-
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> Close </button>
|
|
81
|
-
<button type="submit" class="btn btn-primary"> Save </button>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
</form>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
{% endblock %}
|