ivoryos 0.1.6__py3-none-any.whl → 0.1.8__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.
ivoryos/__init__.py CHANGED
@@ -2,7 +2,7 @@ import os
2
2
  import sys
3
3
  from typing import Union
4
4
 
5
- from flask import Flask
5
+ from flask import Flask, redirect, url_for
6
6
 
7
7
  from ivoryos.config import Config, get_config
8
8
  from ivoryos.routes.auth.auth import auth, login_manager
@@ -19,7 +19,8 @@ global_config = GlobalConfig()
19
19
 
20
20
 
21
21
  def create_app(config_class=None):
22
- app = Flask(__name__)
22
+ url_prefix = os.getenv('URL_PREFIX', "/ivoryos")
23
+ app = Flask(__name__, static_url_path=f'{url_prefix}/static', static_folder='static')
23
24
  app.config.from_object(config_class or 'config.get_config()')
24
25
 
25
26
  # Initialize extensions
@@ -45,11 +46,15 @@ def create_app(config_class=None):
45
46
  g.logger = logger
46
47
  g.socketio = socketio
47
48
 
48
- app.register_blueprint(main)
49
- app.register_blueprint(auth)
50
- app.register_blueprint(design)
51
- app.register_blueprint(database)
52
- app.register_blueprint(control)
49
+ app.register_blueprint(main, url_prefix=url_prefix)
50
+ app.register_blueprint(auth, url_prefix=url_prefix)
51
+ app.register_blueprint(design, url_prefix=url_prefix)
52
+ app.register_blueprint(database, url_prefix=url_prefix)
53
+ app.register_blueprint(control, url_prefix=url_prefix)
54
+
55
+ @app.route('/')
56
+ def redirect_to_prefix():
57
+ return redirect(url_for('main.index')) # Assuming 'index' is a route in your blueprint
53
58
 
54
59
  return app
55
60
 
@@ -37,7 +37,7 @@
37
37
  {% endfor %}
38
38
  </div>
39
39
  <div class="input-group mb-3">
40
- <button type="submit" name="{{ function }}" id="{{ function }}" class="form-control" style="background-color: #a5cece;">{{function}} </button>
40
+ <button type="submit" name="{{ function }}" id="{{ function }}" class="form-control" style="background-color: #a5cece;">{{format_name(function)}} </button>
41
41
  </div>
42
42
  </form>
43
43
  </div>
@@ -7,15 +7,6 @@ from ivoryos.utils.utils import get_script_file, post_script_file
7
7
  database = Blueprint('database', __name__, template_folder='templates/database')
8
8
 
9
9
 
10
- @database.route("/delete/<id>")
11
- @login_required
12
- def delete_action(id):
13
- back = request.referrer
14
- script = get_script_file()
15
- script.delete_action(id)
16
- post_script_file(script)
17
- return redirect(back)
18
-
19
10
 
20
11
  @database.route("/edit_workflow/<workflow_name>")
21
12
  @login_required
@@ -13,10 +13,10 @@ from werkzeug.utils import secure_filename
13
13
  from ivoryos.utils import utils
14
14
  from ivoryos.utils.global_config import GlobalConfig
15
15
  from ivoryos.utils.form import create_builtin_form, create_action_button, format_name, create_form_from_pseudo
16
+ from ivoryos.utils.llm_agent import LlmAgent
16
17
  from ivoryos.utils.db_models import Script
17
18
  from ivoryos.utils.script_runner import ScriptRunner
18
19
 
19
-
20
20
  socketio = SocketIO()
21
21
  design = Blueprint('design', __name__, template_folder='templates/design')
22
22
 
@@ -165,7 +165,6 @@ def generate_code():
165
165
  model = current_app.config["LLM_MODEL"]
166
166
  server = current_app.config["LLM_SERVER"]
167
167
  module = current_app.config["MODULE"]
168
- from ivoryos.utils.llm_agent import LlmAgent
169
168
  agent = LlmAgent(host=server, model=model, output_path=os.path.dirname(os.path.abspath(module)))
170
169
  except Exception as e:
171
170
  flash(e.__str__())
@@ -395,3 +394,13 @@ def edit_action(uuid):
395
394
  flash(e.__str__())
396
395
  session.pop('edit_action')
397
396
  return redirect(url_for('design.experiment_builder'))
397
+
398
+
399
+ @design.route("/delete/<id>", methods=['GET', 'POST'])
400
+ @login_required
401
+ def delete_action(id):
402
+ back = request.referrer
403
+ script = utils.get_script_file()
404
+ script.delete_action(id)
405
+ utils.post_script_file(script)
406
+ return redirect(back)
@@ -302,7 +302,7 @@
302
302
  {% for button in buttons %}
303
303
  <li id="{{ button['id'] }}" style="list-style-type: none;">
304
304
  <a href="{{ url_for('design.edit_action', uuid=button['uuid']) }}" type="button" class="btn btn-light" style="{{ button['style'] }}">{{ button['label'] }}</a>
305
- <a href="/delete/{{ button['id'] }}" type="button" class="btn btn-light"><span class="bi bi-trash"></span></a>
305
+ <a href="{{ url_for('design.delete_action', id=button['id']) }}" type="button" class="btn btn-light"><span class="bi bi-trash"></span></a>
306
306
  </li>
307
307
  {% endfor %}
308
308
  </ul>
@@ -6,7 +6,16 @@ document.addEventListener("DOMContentLoaded", function() {
6
6
  socket.on('progress', function(data) {
7
7
  var progress = data.progress;
8
8
  console.log(progress);
9
- $('#progress-bar-inner').css('width', progress + '%')
9
+ // Update the progress bar's width and appearance
10
+ var progressBar = document.getElementById('progress-bar-inner');
11
+ progressBar.style.width = progress + '%';
12
+ progressBar.setAttribute('aria-valuenow', progress);
13
+
14
+ if (progress === 100) {
15
+ // Remove animation and set green color when 100% is reached
16
+ progressBar.classList.remove('progress-bar-animated');
17
+ progressBar.classList.add('bg-success'); // Bootstrap class for green color
18
+ }
10
19
  });
11
20
  socket.on('log', function(data) {
12
21
  var logMessage = data.message;
Binary file
@@ -25,7 +25,7 @@
25
25
  <div class= "container">
26
26
 
27
27
  <a class="navbar-brand" href="{{ url_for('main.index') }}">
28
- <img src="{{url_for('static', filename='logo.png')}}" alt="Logo" height="60" class="d-inline-block align-text-bottom">
28
+ <img src="{{url_for('static', filename='logo.webp')}}" alt="Logo" height="60" class="d-inline-block align-text-bottom">
29
29
  </a>
30
30
  <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
31
31
  <span class="navbar-toggler-icon"></span>
@@ -33,6 +33,9 @@
33
33
 
34
34
  <div class="collapse navbar-collapse" id="navbarSupportedContent">
35
35
  <ul class="navbar-nav mr-auto">
36
+ <li class="nav-item">
37
+ <a class="nav-link" href="{{ url_for('main.index') }}" aria-current="page">Home</a>
38
+ </li>
36
39
  <li class="nav-item">
37
40
  <a class="nav-link" href="{{ url_for('database.load_from_database') }}" aria-current="page">Library</a>
38
41
  </li>
ivoryos/utils/form.py CHANGED
@@ -220,7 +220,8 @@ def create_form_for_method(method, method_name, autofill, script=None, design=Tr
220
220
  formatted_param_name = format_name(param.name)
221
221
  field_kwargs = {
222
222
  "label": formatted_param_name,
223
- "default": f'#{param.name}' if autofill else (param.default if param.default is not param.empty else ""),
223
+ "default": f'#{param.name}' if autofill else (param.default if param.default is not param.empty else None),
224
+ "validators": [InputRequired()] if param.default is param.empty else None,
224
225
  **({"script": script} if (autofill or design) else {})
225
226
  }
226
227
  field_class, placeholder_text = annotation_mapping.get(
@@ -3,7 +3,7 @@ import json
3
3
  import os
4
4
  import re
5
5
 
6
- from openai import OpenAI, BaseModel
6
+ from openai import OpenAI
7
7
 
8
8
 
9
9
  # from dotenv import load_dotenv
@@ -53,6 +53,7 @@ class ScriptRunner:
53
53
  def _run_with_stop_check(self, script: Script, repeat_count, run_name, logger, socketio, config, bo_args,
54
54
  output_path):
55
55
  time.sleep(1)
56
+ self._emit_progress(socketio, 1)
56
57
  try:
57
58
  # Run "prep" section once
58
59
  script_dict = script.script_dict
@@ -75,6 +76,7 @@ class ScriptRunner:
75
76
  finally:
76
77
  with self.lock:
77
78
  self.is_running = False # Reset the running flag when done
79
+ self._emit_progress(socketio, 100)
78
80
 
79
81
  def _run_actions(self, actions, section_name="", run_name=None, logger=None):
80
82
  logger.info(f'Executing {section_name} steps') if actions else logger.info(f'No {section_name} steps')
@@ -104,7 +106,7 @@ class ScriptRunner:
104
106
  break
105
107
  logger.info(f'Executing {i + 1} of {len(config)} with kwargs = {kwargs}')
106
108
  progress = (i + 1) * 100 / len(config)
107
- socketio.emit('progress', {'progress': progress})
109
+ self._emit_progress(socketio, progress)
108
110
  fname = f"{run_name}_script"
109
111
  function = self.globals_dict[fname]
110
112
  output = function(**kwargs)
@@ -121,8 +123,8 @@ class ScriptRunner:
121
123
  logger.info(f'Stopping execution during {run_name}: {i + 1}/{int(repeat_count)}')
122
124
  break
123
125
  logger.info(f'Executing {run_name} experiment: {i + 1}/{int(repeat_count)}')
124
- progress = (i + 1) * 100 / int(repeat_count)
125
- socketio.emit('progress', {'progress': progress})
126
+ progress = (i + 1) * 100 / int(repeat_count) - 0.1
127
+ self._emit_progress(socketio, progress)
126
128
  if bo_args:
127
129
  try:
128
130
  parameters, trial_index = ax_client.get_next_trial()
@@ -156,3 +158,7 @@ class ScriptRunner:
156
158
  writer.writeheader()
157
159
  writer.writerows(output_list)
158
160
  logger.info(f'Results saved to {file_path}')
161
+
162
+ @staticmethod
163
+ def _emit_progress(socketio, progress):
164
+ socketio.emit('progress', {'progress': progress})
ivoryos/utils/utils.py CHANGED
@@ -1,3 +1,4 @@
1
+ import ast
1
2
  import importlib
2
3
  import inspect
3
4
  import logging
@@ -124,23 +125,22 @@ def _get_type_from_parameters(arg, parameters):
124
125
  """get argument types from inspection"""
125
126
  arg_type = ''
126
127
  if type(parameters) is inspect.Signature:
127
- p = parameters.parameters
128
+ annotation = parameters.parameters[arg].annotation
129
+ elif type(parameters) is dict:
130
+ annotation = parameters[arg]
131
+ if annotation is not inspect._empty:
128
132
  # print(p[arg].annotation)
129
- if p[arg].annotation is not inspect._empty:
130
- # print(p[arg].annotation)
131
- if p[arg].annotation.__module__ == 'typing':
133
+ if annotation.__module__ == 'typing':
134
+ if hasattr(annotation, '_name') and annotation._name in ["Optional", "Union"]:
132
135
  # print(p[arg].annotation.__args__)
133
- arg_type = [i.__name__ for i in p[arg].annotation.__args__]
134
- else:
135
- arg_type = p[arg].annotation.__name__
136
- # print(arg_type)
137
- elif type(parameters) is dict:
138
- if parameters[arg]:
139
-
140
- if parameters[arg].__module__ == 'typing':
141
- arg_type = [i.__name__ for i in parameters[arg].__args__]
136
+ arg_type = [i.__name__ for i in annotation.__args__]
137
+ elif hasattr(annotation, '__origin__'):
138
+ arg_type = annotation.__origin__.__name__
142
139
  else:
143
- arg_type = parameters[arg].__name__
140
+ # TODO
141
+ pass
142
+ else:
143
+ arg_type = annotation.__name__
144
144
  return arg_type
145
145
 
146
146
 
@@ -168,17 +168,12 @@ def _convert_by_str(args, arg_types):
168
168
  if type(arg_types) is not list:
169
169
  arg_types = [arg_types]
170
170
  for arg_type in arg_types:
171
- if arg_type == "any":
171
+ if not arg_type == "any":
172
172
  try:
173
- args = eval(args)
173
+ args = eval(f'{arg_type}("{args}")') if type(args) is str else eval(f'{arg_type}({args})')
174
+ return args
174
175
  except Exception:
175
- pass
176
- return args
177
- try:
178
- args = eval(f'{arg_type}("{args}")')
179
- return args
180
- except Exception:
181
- raise TypeError(f"Input type error: cannot convert '{args}' to {arg_type}.")
176
+ raise TypeError(f"Input type error: cannot convert '{args}' to {arg_type}.")
182
177
 
183
178
 
184
179
  def _convert_by_class(args, arg_types):
@@ -214,16 +209,20 @@ def convert_config_type(args, arg_types, is_class: bool = False):
214
209
  raise ValueError("config file format not supported.")
215
210
  if args[arg] == '' or args[arg] == "None":
216
211
  args[arg] = None
217
- elif args[arg] == "True" or args[arg] == "False":
218
- args[arg] = bool_dict[args[arg]]
212
+ # elif args[arg] == "True" or args[arg] == "False":
213
+ # args[arg] = bool_dict[args[arg]]
219
214
  else:
220
215
  arg_type = arg_types[arg]
221
-
222
- if is_class:
223
- # if arg_type.__module__ == 'builtins':
224
- args[arg] = _convert_by_class(args[arg], arg_type)
225
- else:
226
- args[arg] = _convert_by_str(args[arg], arg_type)
216
+ try:
217
+ args[arg] = ast.literal_eval(args[arg])
218
+ except ValueError:
219
+ pass
220
+ if type(args[arg]) is not arg_type and not type(args[arg]).__name__ == arg_type:
221
+ if is_class:
222
+ # if arg_type.__module__ == 'builtins':
223
+ args[arg] = _convert_by_class(args[arg], arg_type)
224
+ else:
225
+ args[arg] = _convert_by_str(args[arg], arg_type)
227
226
  return args
228
227
 
229
228
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ivoryos
3
- Version: 0.1.6
3
+ Version: 0.1.8
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
@@ -1,4 +1,4 @@
1
- ivoryos/__init__.py,sha256=prqANp0lD5gqHOsvVEhnuAgaCvKg2BcC3zWiXZbJS_U,3535
1
+ ivoryos/__init__.py,sha256=0bjHffTf3m8NWU3zwLz7sZMDqhwNP9FpNXJhxFRliEQ,3938
2
2
  ivoryos/config.py,sha256=K03jdGmbUfJ9o4kK6NOtDGJtydGHFq8-oU8nvCyq5zQ,1358
3
3
  ivoryos/routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  ivoryos/routes/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -7,40 +7,39 @@ ivoryos/routes/auth/templates/auth/login.html,sha256=1uxYU7NpxVaA4sfwkC6CuzZXJdy
7
7
  ivoryos/routes/auth/templates/auth/signup.html,sha256=QQ7n4OBnF8TNFS5_4s11n4BCqSePn429rZfA6vO8qw8,1497
8
8
  ivoryos/routes/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  ivoryos/routes/control/control.py,sha256=YKM1T_bDIggbW_NF6Ld6-rb3d0KbAjyikJztN-ka_XM,11305
10
- ivoryos/routes/control/templates/control/controllers.html,sha256=CD1DEm9DuBBlKg_ltrEWgNxWhTIR9C2_a0-AkxwGre0,4146
10
+ ivoryos/routes/control/templates/control/controllers.html,sha256=5LKKlhiGdg2fxs-akAAxtm1AMF5HAiuSlputDBMeTc0,4159
11
11
  ivoryos/routes/control/templates/control/controllers_home.html,sha256=IND1T3_mPZd-MzfuyodbedMnmsTowiTVdRp5ez6NoZM,2783
12
12
  ivoryos/routes/control/templates/control/controllers_new.html,sha256=Wqn9x9D6K7RWHkLFxvZkzbIJxHJR1zywQ6WDgySXOig,5010
13
13
  ivoryos/routes/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- ivoryos/routes/database/database.py,sha256=e1OpmQayM0KYUTPiYQzXHo-zLVd5yHtS0EYNce7vcmQ,4357
14
+ ivoryos/routes/database/database.py,sha256=W7axqxlRyIwqdLCuzYzER33obz6PCkevk6NTy-sCOLw,4133
15
15
  ivoryos/routes/database/templates/database/experiment_database.html,sha256=x9zf4u4KbG6BEICnH_TOVNNUkp5oAmGBB12OUX0PPl4,3506
16
16
  ivoryos/routes/design/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- ivoryos/routes/design/design.py,sha256=g1V4HYLldD7O6K5brtdxV8uoyOVGTpM3rC1lOmw91AA,16913
18
- ivoryos/routes/design/templates/design/experiment_builder.html,sha256=IAU9XvtbcEWDlnCqf2Z81gcBB7bNDFOfod3xLJfRbQc,27371
17
+ ivoryos/routes/design/design.py,sha256=sbGkd9GztrNsY0vvvC4wZ9O1_rRS1f5dqkAYCATgvdM,17156
18
+ ivoryos/routes/design/templates/design/experiment_builder.html,sha256=HIkb-llvEy57agHuaiSN95tKj4Oh0T88GBfHxEsz8bI,27399
19
19
  ivoryos/routes/design/templates/design/experiment_run.html,sha256=xoEHH8CC83KCWTPavwP9JWUI8SE5HX9bkEfJN6vMg5s,22845
20
20
  ivoryos/routes/main/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  ivoryos/routes/main/main.py,sha256=Zkagtw0E67FaspNJ87jkYpc-wqqoTq99dyyB7qdnOVM,655
22
22
  ivoryos/routes/main/templates/main/help.html,sha256=TY6uD-v8MXpiZlGucchko1Bas5jHRzARIgCgneBZ_ok,9511
23
23
  ivoryos/routes/main/templates/main/home.html,sha256=fjeSSXkuVDr2y-CQmskNHf1yYFFdrPPI4wn6_XPb6AY,3252
24
24
  ivoryos/static/favicon.ico,sha256=RhlrPtfITOkzC9BjP1UB1V5L9Oyp6NwNtWeMcGOnpyc,15406
25
- ivoryos/static/logo.png,sha256=7lNyToDllflGPUK2sj7IBR8FkHLC-6gi-OVSL9o4jrs,63464
25
+ ivoryos/static/logo.webp,sha256=lXgfQR-4mHTH83k7VV9iB54-oC2ipe6uZvbwdOnLETc,14974
26
26
  ivoryos/static/style.css,sha256=rY6n2mbP_xNavtVin_yUqtcvNm6uqAF82t7ONE2Sx9E,3918
27
27
  ivoryos/static/gui_annotation/Slide1.png,sha256=Lm4gdOkUF5HIUFaB94tl6koQVkzpitKj43GXV_XYMMc,121727
28
28
  ivoryos/static/gui_annotation/Slide2.PNG,sha256=z3wQ9oVgg4JTWVLQGKK_KhtepRHUYP1e05XUWGT2A0I,118761
29
29
  ivoryos/static/js/overlay.js,sha256=44l9THVKYZfa7HX6siyqY7EdFWKBk5pyyKgN0_7ZnrM,495
30
- ivoryos/static/js/socket_handler.js,sha256=HduGphUyyZq8GE1-5ZmDgHGTzcWDRa6oXBNrWWMnxwM,989
30
+ ivoryos/static/js/socket_handler.js,sha256=2936CldW6Po_saWh1aL_EV-VydJVIvikrNfTaSfU1sE,1449
31
31
  ivoryos/static/js/sortable_card.js,sha256=mDVd2YjhusLokUw3xL6YOZLXIzty9yKDsC1U5yR8aC8,831
32
32
  ivoryos/static/js/sortable_design.js,sha256=BxNXzqET_yY0xpS1Fc0iwPCnkkDwYMiuVqkgOPMb6JY,1156
33
- ivoryos/templates/base.html,sha256=cu6MZMlfOR0IhuNrMin_pWYtm1_TpJLHI6KH5NomopI,7763
33
+ ivoryos/templates/base.html,sha256=KcKMjITaaC23yzIRN535uMhzv5x96nJl245Y2GaqdsM,7943
34
34
  ivoryos/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  ivoryos/utils/db_models.py,sha256=umEATdxDP-sR_AMaLrOW2PBUcmBf1w38DLeFkBvVjJE,19280
36
- ivoryos/utils/form.py,sha256=W8fSGybeWSCfPqySEfH1mKJbdoYmRb3vwpy15w2rj_Q,12226
36
+ ivoryos/utils/form.py,sha256=FcrexHxcykoQke2J78mDQf1PRAcXlMHwi-JZMgGBpOU,12316
37
37
  ivoryos/utils/global_config.py,sha256=JCQvmZB0pNC-EjveRu48Tp4uvcNwn9DP3Ema6Xd9fJY,1656
38
- ivoryos/utils/llm_agent.py,sha256=pxiaiIVHzbGA_Tq4yOZY3iyIDikx6-_chIvPEjlywLg,6607
39
- ivoryos/utils/script_runner.py,sha256=jlJMCFLmcS6GOlOfEmLXAzG47sU18nNtRPtojjdN018,6919
40
- ivoryos/utils/task_manager.py,sha256=xfQ1s9ywWDrCYYpdgliVvoWED0s2xARmo3LXvAy6fgY,2517
41
- ivoryos/utils/utils.py,sha256=8GMuMwKUKKMjz8hvilavNlV4RANcQWsJy8hZpbXanRg,15042
42
- ivoryos-0.1.6.dist-info/LICENSE,sha256=psyqat4GJkzi42551i0kH-bXLbEzrQEnjPDwy2TVhv8,1105
43
- ivoryos-0.1.6.dist-info/METADATA,sha256=QTek7bK8bAPqXCo0RIY6w_YTUeisTWFcg2ythkjqYc4,6101
44
- ivoryos-0.1.6.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
45
- ivoryos-0.1.6.dist-info/top_level.txt,sha256=FRIWWdiEvRKqw-XfF_UK3XV0CrnNb6EmVbEgjaVazRM,8
46
- ivoryos-0.1.6.dist-info/RECORD,,
38
+ ivoryos/utils/llm_agent.py,sha256=z0DIpZzc-z09p-diUZIOE5L9zfFW8RwseFjbfUvEqoQ,6596
39
+ ivoryos/utils/script_runner.py,sha256=gtqiHy4-40j5FMERXrmGb4jb9RAPzjCR345PMPduDno,7120
40
+ ivoryos/utils/utils.py,sha256=BMmvyBNo8PYs-MiBiiHjYPvSwrHORofbNwhPYpaVnfI,15249
41
+ ivoryos-0.1.8.dist-info/LICENSE,sha256=psyqat4GJkzi42551i0kH-bXLbEzrQEnjPDwy2TVhv8,1105
42
+ ivoryos-0.1.8.dist-info/METADATA,sha256=8t3dDdrj62BKNKuOMKS1FOwlPur9rox_4F9_x9haIYk,6101
43
+ ivoryos-0.1.8.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
44
+ ivoryos-0.1.8.dist-info/top_level.txt,sha256=FRIWWdiEvRKqw-XfF_UK3XV0CrnNb6EmVbEgjaVazRM,8
45
+ ivoryos-0.1.8.dist-info/RECORD,,
ivoryos/static/logo.png DELETED
Binary file
@@ -1,80 +0,0 @@
1
- import threading
2
- import queue
3
- import time
4
-
5
-
6
- # A task manager class to manage the queue and tasks
7
- class TaskManager:
8
- def __init__(self):
9
- self.task_queue = queue.Queue()
10
- self.current_task = None
11
- self.stop_event = threading.Event()
12
-
13
- def add_task(self, func, **kwargs):
14
- # Add the function and its kwargs to the task queue
15
- self.task_queue.put((func, kwargs))
16
-
17
- def run_tasks(self):
18
- # Run the tasks from the queue
19
- while not self.task_queue.empty():
20
- func, kwargs = self.task_queue.get()
21
- thread = threading.Thread(target=self.run_task, args=(func, kwargs))
22
- self.current_task = thread
23
- thread.start()
24
- thread.join() # Wait for the task to finish
25
-
26
- def run_task(self, func, kwargs):
27
- # Run the task function with control to stop in the middle
28
- self.stop_event.clear() # Reset the stop flag
29
- func(**kwargs)
30
- if self.stop_event.is_set():
31
- print("Current task was stopped.")
32
-
33
- def stop_current_task(self):
34
- # Stop the current task by setting the stop flag
35
- if self.current_task and self.current_task.is_alive():
36
- print("Stopping current task...")
37
- self.stop_event.set() # Signal to stop the current task
38
- self.current_task.join() # Wait for the task to stop
39
-
40
-
41
- # Wrapping tasks to allow stopping between them
42
- def function_to_call(stop_event, **kwargs):
43
- if stop_event.is_set():
44
- return
45
- task1(kwargs['arg1'])
46
- if stop_event.is_set():
47
- return
48
- task2(kwargs['arg2'])
49
-
50
-
51
- # Dummy task functions as provided
52
- def task1(arg1):
53
- for i in range(arg1):
54
- print(f"Task 1 running: {i}")
55
- time.sleep(1)
56
-
57
-
58
- def task2(arg2):
59
- for i in range(arg2):
60
- print(f"Task 2 running: {i}")
61
- time.sleep(1)
62
-
63
-
64
- if __name__ == "__main__":
65
- manager = TaskManager()
66
-
67
- # Add tasks to the manager
68
- manager.add_task(function_to_call, stop_event=manager.stop_event, arg1=3, arg2=5)
69
- manager.add_task(function_to_call, stop_event=manager.stop_event, arg1=2, arg2=4)
70
-
71
- # Run tasks in a separate thread
72
- manager_thread = threading.Thread(target=manager.run_tasks)
73
- manager_thread.start()
74
-
75
- # Example: Stop the current workflow while task1 is running
76
- time.sleep(2) # Let task1 run for a bit
77
- manager.stop_current_task()
78
-
79
- # Wait for all tasks to finish
80
- manager_thread.join()