ivoryos 0.1.24__tar.gz → 1.0.0__tar.gz
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-0.1.24/ivoryos.egg-info → ivoryos-1.0.0}/PKG-INFO +5 -6
- {ivoryos-0.1.24 → ivoryos-1.0.0}/README.md +4 -5
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/__init__.py +15 -5
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/design/design.py +5 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/utils/script_runner.py +11 -1
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/utils/utils.py +53 -8
- ivoryos-1.0.0/ivoryos/version.py +1 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0/ivoryos.egg-info}/PKG-INFO +5 -6
- ivoryos-0.1.24/ivoryos/version.py +0 -1
- {ivoryos-0.1.24 → ivoryos-1.0.0}/LICENSE +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/MANIFEST.in +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/config.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/__init__.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/auth/__init__.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/auth/auth.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/auth/templates/auth/login.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/auth/templates/auth/signup.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/control/__init__.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/control/control.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/control/templates/control/controllers.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/control/templates/control/controllers_home.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/control/templates/control/controllers_new.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/database/__init__.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/database/database.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/database/templates/database/experiment_database.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/database/templates/database/experiment_step_view.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/database/templates/database/step_card.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/database/templates/database/workflow_run_database.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/design/__init__.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/design/templates/design/experiment_builder.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/design/templates/design/experiment_run.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/main/__init__.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/main/main.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/main/templates/main/help.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/main/templates/main/home.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/favicon.ico +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/gui_annotation/Slide1.png +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/gui_annotation/Slide2.PNG +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/js/overlay.js +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/js/socket_handler.js +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/js/sortable_card.js +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/js/sortable_design.js +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/logo.webp +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/static/style.css +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/templates/base.html +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/utils/__init__.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/utils/client_proxy.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/utils/db_models.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/utils/form.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/utils/global_config.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/utils/llm_agent.py +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos.egg-info/SOURCES.txt +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos.egg-info/dependency_links.txt +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos.egg-info/requires.txt +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos.egg-info/top_level.txt +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/setup.cfg +0 -0
- {ivoryos-0.1.24 → ivoryos-1.0.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ivoryos
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.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
|
|
@@ -14,7 +14,7 @@ License-File: LICENSE
|
|
|
14
14
|
[](https://pypi.org/project/ivoryos/)
|
|
15
15
|

|
|
16
16
|
[](https://youtu.be/dFfJv9I2-1g)
|
|
17
|
-
[](https://www.nature.com/articles/s41467-025-60514-w)
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|

|
|
@@ -163,11 +163,10 @@ When you run the application for the first time, it will automatically create th
|
|
|
163
163
|
## Roadmap
|
|
164
164
|
|
|
165
165
|
- [x] Allow plugin pages ✅
|
|
166
|
-
- [x] pause, resume, abort current and pending workflows ✅
|
|
166
|
+
- [x] pause, resume, abort current and pending workflows ✅
|
|
167
|
+
- [x] dropdown input ✅
|
|
168
|
+
- [x] show line number option ✅
|
|
167
169
|
- [ ] snapshot version control
|
|
168
|
-
- [ ] dropdown input
|
|
169
|
-
- [ ] show line number option
|
|
170
|
-
|
|
171
170
|
|
|
172
171
|
## Authors and Acknowledgement
|
|
173
172
|
Ivory Zhang, Lucy Hao
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://pypi.org/project/ivoryos/)
|
|
3
3
|

|
|
4
4
|
[](https://youtu.be/dFfJv9I2-1g)
|
|
5
|
-
[](https://www.nature.com/articles/s41467-025-60514-w)
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|

|
|
@@ -151,11 +151,10 @@ When you run the application for the first time, it will automatically create th
|
|
|
151
151
|
## Roadmap
|
|
152
152
|
|
|
153
153
|
- [x] Allow plugin pages ✅
|
|
154
|
-
- [x] pause, resume, abort current and pending workflows ✅
|
|
154
|
+
- [x] pause, resume, abort current and pending workflows ✅
|
|
155
|
+
- [x] dropdown input ✅
|
|
156
|
+
- [x] show line number option ✅
|
|
155
157
|
- [ ] snapshot version control
|
|
156
|
-
- [ ] dropdown input
|
|
157
|
-
- [ ] show line number option
|
|
158
|
-
|
|
159
158
|
|
|
160
159
|
## Authors and Acknowledgement
|
|
161
160
|
Ivory Zhang, Lucy Hao
|
|
@@ -17,11 +17,13 @@ from ivoryos.utils.global_config import GlobalConfig
|
|
|
17
17
|
from ivoryos.utils.script_runner import ScriptRunner
|
|
18
18
|
from ivoryos.version import __version__ as ivoryos_version
|
|
19
19
|
from importlib.metadata import entry_points
|
|
20
|
+
|
|
20
21
|
global_config = GlobalConfig()
|
|
21
22
|
from sqlalchemy import event
|
|
22
23
|
from sqlalchemy.engine import Engine
|
|
23
24
|
import sqlite3
|
|
24
25
|
|
|
26
|
+
|
|
25
27
|
@event.listens_for(Engine, "connect")
|
|
26
28
|
def enforce_sqlite_foreign_keys(dbapi_connection, connection_record):
|
|
27
29
|
if isinstance(dbapi_connection, sqlite3.Connection):
|
|
@@ -29,6 +31,7 @@ def enforce_sqlite_foreign_keys(dbapi_connection, connection_record):
|
|
|
29
31
|
cursor.execute("PRAGMA foreign_keys=ON")
|
|
30
32
|
cursor.close()
|
|
31
33
|
|
|
34
|
+
|
|
32
35
|
url_prefix = os.getenv('URL_PREFIX', "/ivoryos")
|
|
33
36
|
app = Flask(__name__, static_url_path=f'{url_prefix}/static', static_folder='static')
|
|
34
37
|
app.register_blueprint(main, url_prefix=url_prefix)
|
|
@@ -81,8 +84,9 @@ def run(module=None, host="0.0.0.0", port=None, debug=None, llm_server=None, mod
|
|
|
81
84
|
config: Config = None,
|
|
82
85
|
logger: Union[str, list] = None,
|
|
83
86
|
logger_output_name: str = None,
|
|
84
|
-
enable_design=True,
|
|
85
|
-
blueprint_plugins=
|
|
87
|
+
enable_design: bool = True,
|
|
88
|
+
blueprint_plugins: Union[list[Blueprint], Blueprint] = [],
|
|
89
|
+
exclude_names: list[str] = [],
|
|
86
90
|
):
|
|
87
91
|
"""
|
|
88
92
|
Start ivoryOS app server.
|
|
@@ -97,11 +101,13 @@ def run(module=None, host="0.0.0.0", port=None, debug=None, llm_server=None, mod
|
|
|
97
101
|
:param logger: logger name of list of logger names, defaults to None
|
|
98
102
|
:param logger_output_name: log file save name of logger, defaults to None, and will use "default.log"
|
|
99
103
|
:param enable_design: enable design canvas, database and workflow execution
|
|
104
|
+
:param blueprint_plugins: custom Blueprint pages
|
|
105
|
+
:param exclude_names: module names to exclude from parsing
|
|
100
106
|
"""
|
|
101
107
|
app = create_app(config_class=config or get_config()) # Create app instance using factory function
|
|
102
108
|
|
|
103
109
|
# plugins = load_installed_plugins(app, socketio)
|
|
104
|
-
plugins =
|
|
110
|
+
plugins = []
|
|
105
111
|
if blueprint_plugins:
|
|
106
112
|
config_plugins = load_plugins(blueprint_plugins, app, socketio)
|
|
107
113
|
plugins.extend(config_plugins)
|
|
@@ -126,7 +132,10 @@ def run(module=None, host="0.0.0.0", port=None, debug=None, llm_server=None, mod
|
|
|
126
132
|
app.config["OFF_LINE"] = False
|
|
127
133
|
global_config.deck = sys.modules[module]
|
|
128
134
|
global_config.deck_snapshot = utils.create_deck_snapshot(global_config.deck,
|
|
129
|
-
output_path=app.config["DUMMY_DECK"],
|
|
135
|
+
output_path=app.config["DUMMY_DECK"],
|
|
136
|
+
save=True,
|
|
137
|
+
exclude_names=exclude_names
|
|
138
|
+
)
|
|
130
139
|
else:
|
|
131
140
|
app.config["OFF_LINE"] = True
|
|
132
141
|
if model:
|
|
@@ -165,7 +174,8 @@ def load_installed_plugins(app, socketio):
|
|
|
165
174
|
|
|
166
175
|
return plugin_names
|
|
167
176
|
|
|
168
|
-
|
|
177
|
+
|
|
178
|
+
def load_plugins(blueprints: Union[list[Blueprint], Blueprint], app, socketio):
|
|
169
179
|
"""
|
|
170
180
|
Dynamically load installed plugins and attach Flask-SocketIO.
|
|
171
181
|
"""
|
|
@@ -307,4 +307,14 @@ class ScriptRunner:
|
|
|
307
307
|
while time.time() < end_time:
|
|
308
308
|
if self.stop_current_event.is_set():
|
|
309
309
|
return # Exit early if stop is requested
|
|
310
|
-
time.sleep(min(interval, end_time - time.time()))
|
|
310
|
+
time.sleep(min(interval, end_time - time.time()))
|
|
311
|
+
|
|
312
|
+
def get_status(self):
|
|
313
|
+
"""Returns current status of the script runner."""
|
|
314
|
+
with self.lock:
|
|
315
|
+
return {
|
|
316
|
+
"is_running": self.is_running,
|
|
317
|
+
"paused": self.paused,
|
|
318
|
+
"stop_pending": self.stop_pending_event.is_set(),
|
|
319
|
+
"stop_current": self.stop_current_event.is_set(),
|
|
320
|
+
}
|
|
@@ -8,6 +8,7 @@ import subprocess
|
|
|
8
8
|
import sys
|
|
9
9
|
from collections import Counter
|
|
10
10
|
|
|
11
|
+
import flask
|
|
11
12
|
from flask import session
|
|
12
13
|
from flask_socketio import SocketIO
|
|
13
14
|
|
|
@@ -239,7 +240,7 @@ def start_logger(socketio: SocketIO, logger_name: str, log_filename: str = None)
|
|
|
239
240
|
return logger
|
|
240
241
|
|
|
241
242
|
|
|
242
|
-
def ax_wrapper(data: dict, arg_types:list):
|
|
243
|
+
def ax_wrapper(data: dict, arg_types: list):
|
|
243
244
|
"""
|
|
244
245
|
Ax platform wrapper function for creating optimization campaign parameters and objective from the web form input
|
|
245
246
|
:param data: e.g.,
|
|
@@ -363,17 +364,62 @@ def web_config_entry_wrapper(data: dict, config_type: list):
|
|
|
363
364
|
return filtered_rows
|
|
364
365
|
|
|
365
366
|
|
|
366
|
-
def create_deck_snapshot(deck, save: bool = False, output_path: str = ''):
|
|
367
|
+
def create_deck_snapshot(deck, save: bool = False, output_path: str = '', exclude_names: list[str] = []):
|
|
367
368
|
"""
|
|
368
369
|
Create a deck snapshot of the given script
|
|
369
370
|
:param deck: python module name to create the deck snapshot from e.g. __main__
|
|
370
371
|
:param save: save the deck snapshot into pickle file
|
|
371
372
|
:param output_path: path to save the pickle file
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
373
|
+
:param exclude_names: module names to exclude from deck snapshot
|
|
374
|
+
"""
|
|
375
|
+
exclude_classes = (flask.Blueprint, logging.Logger)
|
|
376
|
+
|
|
377
|
+
deck_snapshot = {}
|
|
378
|
+
included = {}
|
|
379
|
+
excluded = {}
|
|
380
|
+
failed = {}
|
|
381
|
+
|
|
382
|
+
for name, val in vars(deck).items():
|
|
383
|
+
qualified_name = f"deck.{name}"
|
|
384
|
+
|
|
385
|
+
# Exclusion checks
|
|
386
|
+
if (
|
|
387
|
+
type(val).__module__ == 'builtins'
|
|
388
|
+
or name[0].isupper()
|
|
389
|
+
or name.startswith("_")
|
|
390
|
+
or isinstance(val, exclude_classes)
|
|
391
|
+
or name in exclude_names
|
|
392
|
+
):
|
|
393
|
+
excluded[qualified_name] = type(val).__name__
|
|
394
|
+
continue
|
|
395
|
+
|
|
396
|
+
try:
|
|
397
|
+
deck_snapshot[qualified_name] = _inspect_class(val)
|
|
398
|
+
included[qualified_name] = type(val).__name__
|
|
399
|
+
except Exception as e:
|
|
400
|
+
failed[qualified_name] = str(e)
|
|
401
|
+
|
|
402
|
+
# Final result
|
|
403
|
+
deck_summary = {
|
|
404
|
+
"included": included,
|
|
405
|
+
# "excluded": excluded,
|
|
406
|
+
"failed": failed
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
def print_deck_snapshot(deck_summary):
|
|
410
|
+
def print_section(title, items):
|
|
411
|
+
print(f"\n=== {title} ({len(items)}) ===")
|
|
412
|
+
if not items:
|
|
413
|
+
return
|
|
414
|
+
for name, class_type in items.items():
|
|
415
|
+
print(f" {name}: {class_type}")
|
|
416
|
+
|
|
417
|
+
print_section("✅ INCLUDED", deck_summary["included"])
|
|
418
|
+
print_section("❌ FAILED", deck_summary["failed"])
|
|
419
|
+
print("\n")
|
|
420
|
+
|
|
421
|
+
print_deck_snapshot(deck_summary)
|
|
422
|
+
|
|
377
423
|
if deck_snapshot and save:
|
|
378
424
|
# pseudo_deck = parse_dict
|
|
379
425
|
parse_dict = deck_snapshot.copy()
|
|
@@ -418,7 +464,6 @@ def get_method_from_workflow(function_string, func_name="workflow"):
|
|
|
418
464
|
# Get the function name dynamically
|
|
419
465
|
return namespace[func_name]
|
|
420
466
|
|
|
421
|
-
|
|
422
467
|
# def load_workflows(script):
|
|
423
468
|
#
|
|
424
469
|
# class RegisteredWorkflows:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ivoryos
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.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
|
|
@@ -14,7 +14,7 @@ License-File: LICENSE
|
|
|
14
14
|
[](https://pypi.org/project/ivoryos/)
|
|
15
15
|

|
|
16
16
|
[](https://youtu.be/dFfJv9I2-1g)
|
|
17
|
-
[](https://www.nature.com/articles/s41467-025-60514-w)
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|

|
|
@@ -163,11 +163,10 @@ When you run the application for the first time, it will automatically create th
|
|
|
163
163
|
## Roadmap
|
|
164
164
|
|
|
165
165
|
- [x] Allow plugin pages ✅
|
|
166
|
-
- [x] pause, resume, abort current and pending workflows ✅
|
|
166
|
+
- [x] pause, resume, abort current and pending workflows ✅
|
|
167
|
+
- [x] dropdown input ✅
|
|
168
|
+
- [x] show line number option ✅
|
|
167
169
|
- [ ] snapshot version control
|
|
168
|
-
- [ ] dropdown input
|
|
169
|
-
- [ ] show line number option
|
|
170
|
-
|
|
171
170
|
|
|
172
171
|
## Authors and Acknowledgement
|
|
173
172
|
Ivory Zhang, Lucy Hao
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.24"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/control/templates/control/controllers_home.html
RENAMED
|
File without changes
|
{ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/control/templates/control/controllers_new.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/database/templates/database/experiment_database.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ivoryos-0.1.24 → ivoryos-1.0.0}/ivoryos/routes/design/templates/design/experiment_builder.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|