OpenOrchestrator 1.1.0__py3-none-any.whl → 1.3.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.
Files changed (27) hide show
  1. OpenOrchestrator/common/crypto_util.py +21 -9
  2. OpenOrchestrator/common/datetime_util.py +1 -1
  3. OpenOrchestrator/database/db_util.py +167 -131
  4. OpenOrchestrator/database/queues.py +1 -0
  5. OpenOrchestrator/database/triggers.py +1 -0
  6. OpenOrchestrator/database/truncated_string.py +18 -0
  7. OpenOrchestrator/orchestrator/application.py +18 -1
  8. OpenOrchestrator/orchestrator/datetime_input.py +16 -2
  9. OpenOrchestrator/orchestrator/popups/constant_popup.py +8 -7
  10. OpenOrchestrator/orchestrator/popups/credential_popup.py +8 -7
  11. OpenOrchestrator/orchestrator/popups/trigger_popup.py +27 -15
  12. OpenOrchestrator/orchestrator/tabs/constants_tab.py +1 -1
  13. OpenOrchestrator/orchestrator/tabs/logging_tab.py +4 -3
  14. OpenOrchestrator/orchestrator/tabs/queue_tab.py +19 -11
  15. OpenOrchestrator/orchestrator/tabs/settings_tab.py +2 -2
  16. OpenOrchestrator/orchestrator/tabs/trigger_tab.py +4 -7
  17. OpenOrchestrator/orchestrator_connection/connection.py +11 -9
  18. OpenOrchestrator/scheduler/application.py +1 -1
  19. OpenOrchestrator/scheduler/connection_frame.py +1 -1
  20. OpenOrchestrator/scheduler/run_tab.py +85 -87
  21. OpenOrchestrator/scheduler/runner.py +34 -23
  22. {OpenOrchestrator-1.1.0.dist-info → OpenOrchestrator-1.3.0.dist-info}/METADATA +1 -1
  23. OpenOrchestrator-1.3.0.dist-info/RECORD +39 -0
  24. {OpenOrchestrator-1.1.0.dist-info → OpenOrchestrator-1.3.0.dist-info}/WHEEL +1 -1
  25. OpenOrchestrator-1.1.0.dist-info/RECORD +0 -38
  26. {OpenOrchestrator-1.1.0.dist-info → OpenOrchestrator-1.3.0.dist-info}/LICENSE +0 -0
  27. {OpenOrchestrator-1.1.0.dist-info → OpenOrchestrator-1.3.0.dist-info}/top_level.txt +0 -0
@@ -1,124 +1,123 @@
1
1
  """This module is responsible for the layout and functionality of the run tab
2
2
  in Scheduler."""
3
3
 
4
+ from __future__ import annotations
5
+ from typing import TYPE_CHECKING
6
+
4
7
  import tkinter
5
8
  from tkinter import ttk
6
9
  import sys
7
10
 
11
+ from sqlalchemy import exc as alc_exc
12
+
8
13
  from OpenOrchestrator.common import crypto_util
9
14
  from OpenOrchestrator.database import db_util
10
15
  from OpenOrchestrator.scheduler import runner
11
16
 
17
+ if TYPE_CHECKING:
18
+ from OpenOrchestrator.scheduler.application import Application
12
19
 
13
- def create_tab(parent: ttk.Notebook, app) -> ttk.Frame:
14
- """Create a new Run tab object.
15
-
16
- Args:
17
- parent: The ttk.Notebook object that this tab is a child of.
18
- app: The Scheduler application object.
19
-
20
- Returns:
21
- ttk.Frame: The created tab object as a ttk.Frame.
22
- """
23
- tab = ttk.Frame(parent)
24
- tab.pack(fill='both', expand=True)
25
-
26
- status_label = ttk.Label(tab, text="State: Paused")
27
- status_label.pack()
28
-
29
- ttk.Button(tab, text="Run", command=lambda: run(app, status_label)).pack()
30
- ttk.Button(tab, text="Pause", command=lambda: pause(app, status_label)).pack()
31
-
32
- # Text area
33
- text_frame = tkinter.Frame(tab)
34
- text_frame.pack()
35
20
 
36
- text_area = tkinter.Text(text_frame, state='disabled', wrap='none')
37
- sys.stdout.write = lambda s: print_text(text_area, s)
21
+ # pylint: disable-next=too-many-ancestors
22
+ class RunTab(ttk.Frame):
23
+ """A ttk.frame object containing the functionality of the run tab in Scheduler."""
24
+ def __init__(self, parent: ttk.Notebook, app: Application):
25
+ super().__init__(parent)
26
+ self.pack(fill='both', expand=True)
38
27
 
39
- text_yscroll = ttk.Scrollbar(text_frame, orient='vertical', command=text_area.yview)
40
- text_yscroll.pack(side='right', fill='y')
41
- text_area.configure(yscrollcommand=text_yscroll.set)
28
+ self.app = app
42
29
 
43
- text_xscroll = ttk.Scrollbar(text_frame, orient='horizontal', command=text_area.xview)
44
- text_xscroll.pack(side='bottom', fill='x')
45
- text_area.configure(xscrollcommand=text_xscroll.set)
30
+ s = ttk.Style()
31
+ s.configure('my.TButton', font=('Helvetica Bold', 24))
32
+ self.button = ttk.Button(self, text="Run", command=self.button_click, style='my.TButton')
33
+ self.button.pack()
46
34
 
47
- text_area.pack()
35
+ # Text area
36
+ text_frame = tkinter.Frame(self)
37
+ text_frame.pack()
48
38
 
49
- return tab
39
+ self.text_area = tkinter.Text(text_frame, state='disabled', wrap='none')
50
40
 
41
+ # Redirect stdout to the text area instead of console
42
+ sys.stdout.write = self.print_text
51
43
 
52
- def run(app, status_label: ttk.Label) -> None:
53
- """Starts the Scheduler and sets the app's status to 'running'.
44
+ # Add scroll bars to text area
45
+ text_yscroll = ttk.Scrollbar(text_frame, orient='vertical', command=self.text_area.yview)
46
+ text_yscroll.pack(side='right', fill='y')
47
+ self.text_area.configure(yscrollcommand=text_yscroll.set)
54
48
 
55
- Args:
56
- app: The Scheduler application object.
57
- status_label: The label showing the current status.
58
- """
59
- if db_util.get_conn_string() is None:
60
- print("Can't start without a valid connection string. Go to the settings tab to configure the connection string")
61
- return
62
- if crypto_util.get_key() is None:
63
- print("Can't start without a valid encryption key. Go to the settings tab to configure the encryption key")
64
- return
65
-
66
- if not app.running:
67
- status_label.configure(text='State: Running')
68
- print('Running...\n')
69
- app.running = True
49
+ text_xscroll = ttk.Scrollbar(text_frame, orient='horizontal', command=self.text_area.xview)
50
+ text_xscroll.pack(side='bottom', fill='x')
51
+ self.text_area.configure(xscrollcommand=text_xscroll.set)
70
52
 
71
- # Only start loop if it's not already running
72
- if app.tk.call('after', 'info') == '':
73
- app.after(0, loop, app)
53
+ self.text_area.pack()
74
54
 
55
+ def button_click(self):
56
+ """Callback for when the run/pause button is clicked."""
57
+ if self.app.running:
58
+ self.pause()
59
+ else:
60
+ self.run()
75
61
 
76
- def pause(app, status_label: ttk.Label):
77
- """Stops the Scheduler and sets the app's status to 'paused'.
78
-
79
- Args:
80
- app: The Scheduler application object.
81
- status_label: The label showing the current status.
82
- """
83
- if app.running:
84
- status_label.configure(text="State: Paused")
62
+ def pause(self):
63
+ """Stops the Scheduler and sets the app's status to 'paused'."""
64
+ self.button.configure(text="Run")
85
65
  print('Paused... Please wait for all processes to stop before closing the application\n')
86
- app.running = False
66
+ self.app.running = False
67
+
68
+ def run(self):
69
+ """Starts the Scheduler and sets the app's status to 'running'."""
70
+ if db_util.get_conn_string() is None:
71
+ print("Can't start without a valid connection string. Go to the settings tab to configure the connection string")
72
+ return
73
+ if crypto_util.get_key() is None:
74
+ print("Can't start without a valid encryption key. Go to the settings tab to configure the encryption key")
75
+ return
76
+
77
+ self.button.configure(text="Pause")
78
+ print('Running...\n')
79
+ self.app.running = True
87
80
 
81
+ # Only start a new loop if it's not already running
82
+ if self.app.tk.call('after', 'info') == '':
83
+ self.app.after(0, loop, self.app)
88
84
 
89
- def print_text(text_widget: tkinter.Text, text: str) -> None:
90
- """Appends text to the text area.
91
- Is used to replace the functionality of sys.stdout.write (print).
85
+ def print_text(self, text: str) -> None:
86
+ """Appends text to the text area.
87
+ Is used to replace the functionality of sys.stdout.write (print).
92
88
 
93
- Args:
94
- print_text: The text area object.
95
- string: The string to append.
96
- """
97
- # Insert text at the end
98
- text_widget.configure(state='normal')
99
- text_widget.insert('end', text)
89
+ Args:
90
+ string: The string to append.
91
+ """
92
+ # Insert text at the end
93
+ self.text_area.configure(state='normal')
94
+ self.text_area.insert('end', text)
100
95
 
101
- # If the number of lines are above 1000 delete 10 lines from the top
102
- num_lines = int(text_widget.index('end').split('.')[0])
103
- if num_lines > 1000:
104
- text_widget.delete("1.0", "10.0")
96
+ # If the number of lines are above 1000 delete 10 lines from the top
97
+ num_lines = int(self.text_area.index('end').split('.', maxsplit=1)[0])
98
+ if num_lines > 1000:
99
+ self.text_area.delete("1.0", "10.0")
105
100
 
106
- # Scroll to end
107
- text_widget.see('end')
108
- text_widget.configure(state='disabled')
101
+ # Scroll to end
102
+ self.text_area.see('end')
103
+ self.text_area.configure(state='disabled')
109
104
 
110
105
 
111
- def loop(app) -> None:
106
+ def loop(app: Application) -> None:
112
107
  """The main loop function of the Scheduler.
113
108
  Checks heartbeats, check triggers, and schedules the next loop.
114
109
 
115
110
  Args:
116
111
  app: The Scheduler Application object.
117
112
  """
118
- check_heartbeats(app)
113
+ try:
114
+ check_heartbeats(app)
115
+
116
+ if app.running:
117
+ check_triggers(app)
119
118
 
120
- if app.running:
121
- check_triggers(app)
119
+ except alc_exc.OperationalError:
120
+ print("Couldn't connect to database.")
122
121
 
123
122
  if len(app.running_jobs) == 0:
124
123
  print("Doing cleanup...")
@@ -132,7 +131,7 @@ def loop(app) -> None:
132
131
  print("Scheduler is paused and no more processes are running.")
133
132
 
134
133
 
135
- def check_heartbeats(app) -> None:
134
+ def check_heartbeats(app: Application) -> None:
136
135
  """Check if any running jobs are still running, failed or done.
137
136
 
138
137
  Args:
@@ -141,8 +140,6 @@ def check_heartbeats(app) -> None:
141
140
  print('Checking heartbeats...')
142
141
  for job in app.running_jobs:
143
142
  if job.process.poll() is not None:
144
- app.running_jobs.remove(job)
145
-
146
143
  if job.process.returncode == 0:
147
144
  print(f"Process '{job.trigger.process_name}' is done")
148
145
  runner.end_job(job)
@@ -150,11 +147,12 @@ def check_heartbeats(app) -> None:
150
147
  print(f"Process '{job.trigger.process_name}' failed. Check process log for more info.")
151
148
  runner.fail_job(job)
152
149
 
150
+ app.running_jobs.remove(job)
153
151
  else:
154
152
  print(f"Process '{job.trigger.process_name}' is still running")
155
153
 
156
154
 
157
- def check_triggers(app) -> None:
155
+ def check_triggers(app: Application) -> None:
158
156
  """Checks any process is blocking
159
157
  and if not checks if any trigger should be run.
160
158
 
@@ -16,6 +16,7 @@ class Job():
16
16
  """An object that holds information about a running job."""
17
17
  process: subprocess.Popen
18
18
  trigger: Trigger
19
+ process_folder: str | None
19
20
 
20
21
 
21
22
  def poll_triggers(app) -> Job | None:
@@ -66,10 +67,7 @@ def run_single_trigger(trigger: SingleTrigger) -> Job | None:
66
67
  print('Running trigger: ', trigger.trigger_name)
67
68
 
68
69
  if db_util.begin_single_trigger(trigger.id):
69
- process = run_process(trigger)
70
-
71
- if process is not None:
72
- return Job(process, trigger)
70
+ return run_process(trigger)
73
71
 
74
72
  return None
75
73
 
@@ -88,10 +86,7 @@ def run_scheduled_trigger(trigger: ScheduledTrigger) -> Job | None:
88
86
  print('Running trigger: ', trigger.trigger_name)
89
87
 
90
88
  if db_util.begin_scheduled_trigger(trigger.id):
91
- process = run_process(trigger)
92
-
93
- if process is not None:
94
- return Job(process, trigger)
89
+ return run_process(trigger)
95
90
 
96
91
  return None
97
92
 
@@ -109,10 +104,7 @@ def run_queue_trigger(trigger: QueueTrigger) -> Job | None:
109
104
  print('Running trigger: ', trigger.trigger_name)
110
105
 
111
106
  if db_util.begin_queue_trigger(trigger.id):
112
- process = run_process(trigger)
113
-
114
- if process is not None:
115
- return Job(process, trigger)
107
+ return run_process(trigger)
116
108
 
117
109
  return None
118
110
 
@@ -142,7 +134,7 @@ def clone_git_repo(repo_url: str) -> str:
142
134
  def clear_repo_folder() -> None:
143
135
  """Completely remove the repos folder."""
144
136
  repo_folder = get_repo_folder_path()
145
- subprocess.run(['rmdir', '/s', '/q', repo_folder], check=False, shell=True, capture_output=True)
137
+ clear_folder(repo_folder)
146
138
 
147
139
 
148
140
  def get_repo_folder_path() -> str:
@@ -156,6 +148,15 @@ def get_repo_folder_path() -> str:
156
148
  return repo_path
157
149
 
158
150
 
151
+ def clear_folder(folder_path: str) -> None:
152
+ """Clear a folder on the system.
153
+
154
+ Args:
155
+ folder_path: The folder to remove.
156
+ """
157
+ subprocess.run(['rmdir', '/s', '/q', folder_path], check=False, shell=True, capture_output=True)
158
+
159
+
159
160
  def find_main_file(folder_path: str) -> str:
160
161
  """Finds the file in the given folder with the name 'main.py'.
161
162
  The search checks subfolders recursively.
@@ -179,7 +180,7 @@ def end_job(job: Job) -> None:
179
180
  """Mark a job as ended in the triggers table
180
181
  in the database.
181
182
  If it's a single trigger it's marked as 'Done'
182
- else it's marked as 'Idle'.
183
+ else it's marked as 'Idle' or 'Paused'.
183
184
 
184
185
  Args:
185
186
  job: The job whose trigger to mark as ended.
@@ -187,11 +188,15 @@ def end_job(job: Job) -> None:
187
188
  if isinstance(job.trigger, SingleTrigger):
188
189
  db_util.set_trigger_status(job.trigger.id, TriggerStatus.DONE)
189
190
 
190
- elif isinstance(job.trigger, ScheduledTrigger):
191
- db_util.set_trigger_status(job.trigger.id, TriggerStatus.IDLE)
191
+ elif isinstance(job.trigger, (ScheduledTrigger, QueueTrigger)):
192
+ current_status = db_util.get_trigger(job.trigger.id).process_status
193
+ if current_status == TriggerStatus.PAUSING:
194
+ db_util.set_trigger_status(job.trigger.id, TriggerStatus.PAUSED)
195
+ elif current_status == TriggerStatus.RUNNING:
196
+ db_util.set_trigger_status(job.trigger.id, TriggerStatus.IDLE)
192
197
 
193
- elif isinstance(job.trigger, QueueTrigger):
194
- db_util.set_trigger_status(job.trigger.id, TriggerStatus.IDLE)
198
+ if job.process_folder:
199
+ clear_folder(job.process_folder)
195
200
 
196
201
 
197
202
  def fail_job(job: Job) -> None:
@@ -205,8 +210,11 @@ def fail_job(job: Job) -> None:
205
210
  error_msg = f"An uncaught error ocurred during the process:\n{error}"
206
211
  db_util.create_log(job.trigger.process_name, LogLevel.ERROR, error_msg)
207
212
 
213
+ if job.process_folder:
214
+ clear_folder(job.process_folder)
208
215
 
209
- def run_process(trigger: Trigger) -> subprocess.Popen | None:
216
+
217
+ def run_process(trigger: Trigger) -> Job | None:
210
218
  """Runs the process of the given trigger with the necessary inputs:
211
219
  Process name
212
220
  Connection string
@@ -224,14 +232,15 @@ def run_process(trigger: Trigger) -> subprocess.Popen | None:
224
232
  trigger: The trigger whose process to run.
225
233
 
226
234
  Returns:
227
- subprocess.Popen: The Popen instance of the process if successful.
235
+ Job: A Job object referencing the process if succesful.
228
236
  """
229
237
  process_path = trigger.process_path
238
+ folder_path = None
230
239
 
231
240
  try:
232
241
  if trigger.is_git_repo:
233
- git_folder_path = clone_git_repo(process_path)
234
- process_path = find_main_file(git_folder_path)
242
+ folder_path = clone_git_repo(process_path)
243
+ process_path = find_main_file(folder_path)
235
244
 
236
245
  if not os.path.isfile(process_path):
237
246
  raise ValueError(f"The process path didn't point to a file on the system. Path: '{process_path}'")
@@ -244,7 +253,9 @@ def run_process(trigger: Trigger) -> subprocess.Popen | None:
244
253
 
245
254
  command_args = ['python', process_path, trigger.process_name, conn_string, crypto_key, trigger.process_args]
246
255
 
247
- return subprocess.Popen(command_args, stderr=subprocess.PIPE, text=True)
256
+ process = subprocess.Popen(command_args, stderr=subprocess.PIPE, text=True) # pylint: disable=consider-using-with
257
+
258
+ return Job(process, trigger, folder_path)
248
259
 
249
260
  # We actually want to catch any exception here
250
261
  # pylint: disable=broad-exception-caught
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: OpenOrchestrator
3
- Version: 1.1.0
3
+ Version: 1.3.0
4
4
  Summary: A package containing OpenOrchestrator and OpenOrchestrator Scheduler
5
5
  Author-email: ITK Development <itk-rpa@mkb.aarhus.dk>
6
6
  Project-URL: Homepage, https://github.com/itk-dev-rpa/OpenOrchestrator
@@ -0,0 +1,39 @@
1
+ OpenOrchestrator/__init__.py,sha256=i4Ir68mBu7rrqhlEE6Qh_uyble599jaEWCEMf8g58tI,179
2
+ OpenOrchestrator/__main__.py,sha256=Oe3SbWqw3zUhpQpspUaS6mMddXxVvvV-pJbuBU_1GgA,518
3
+ OpenOrchestrator/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ OpenOrchestrator/common/connection_frame.py,sha256=NuRwbEZviOExszhspbETvHcMi7pS4cgOnwQBvAqAZc4,2838
5
+ OpenOrchestrator/common/crypto_util.py,sha256=VJ7fgxyjrW-bGQmsGVKXLUk98pcZGXG4faHtwxCWDDk,2440
6
+ OpenOrchestrator/common/datetime_util.py,sha256=4I70tz6WZGZ3xdxodJhdHJID14Y9myJTShFArOWCSpA,534
7
+ OpenOrchestrator/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ OpenOrchestrator/database/constants.py,sha256=ik6lY6IR8EOyKEg-N70X-0U654i3nFb3u-XWhqbUbJU,2404
9
+ OpenOrchestrator/database/db_util.py,sha256=2M2j47LLj6OymS1J3Zw4q6b7xfgUzEhlcoVQbTpFuiE,28768
10
+ OpenOrchestrator/database/logs.py,sha256=h2BztjmDRhj8TACYN3LK5c9hIqn5xCs9m_LDUdYYHEk,1623
11
+ OpenOrchestrator/database/queues.py,sha256=GYrTktg-RiHef-nFAXGAR9Ne0MIiRipxkAXv-CGc0_Q,2292
12
+ OpenOrchestrator/database/triggers.py,sha256=cO3-dq5-Ib4P_F6p5EgU02XgaRaiIgs6CKqsY0SnDBk,4028
13
+ OpenOrchestrator/database/truncated_string.py,sha256=v5TvMn3Sof9sG3RzHZx5_wRGBZ5IcJTsiyIO20MjehA,521
14
+ OpenOrchestrator/orchestrator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ OpenOrchestrator/orchestrator/application.py,sha256=Sb0rMrlFsvwkXuTLvBLqTUNqFSYjvdrAz3keiQYiUvY,3224
16
+ OpenOrchestrator/orchestrator/datetime_input.py,sha256=GmQ7kVe_QgOsFF7okJJshjaTQ7P-Epe3lxOJ1u21Z0k,3011
17
+ OpenOrchestrator/orchestrator/popups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ OpenOrchestrator/orchestrator/popups/constant_popup.py,sha256=58Yhyz7dW0I_1Vly0U54NEpwWHhEmwLr34z2nUpQAgs,3435
19
+ OpenOrchestrator/orchestrator/popups/credential_popup.py,sha256=4uY4mhD-EGOnOCu9GN4JPecoCbKj067kdSs1kMutpv8,3909
20
+ OpenOrchestrator/orchestrator/popups/generic_popups.py,sha256=wV5isJrwFGUBpDhDpuOzzURwU4NTp4l5mzMDg-KebKw,1061
21
+ OpenOrchestrator/orchestrator/popups/trigger_popup.py,sha256=adCKg-nnUYq_1WWdJK0SI6mZhekYuUD-0VaaQZMgK1E,10063
22
+ OpenOrchestrator/orchestrator/tabs/constants_tab.py,sha256=dSnfWbZeCndsd8vzVEyRJFEyEUPnP-RAY2YwCCi7Omw,2485
23
+ OpenOrchestrator/orchestrator/tabs/logging_tab.py,sha256=kLl2QplqGEkvWwmXlr3wfZEFf-XXqctOeQN8hcpMBQw,3589
24
+ OpenOrchestrator/orchestrator/tabs/queue_tab.py,sha256=ZjN_rWUZ99alunztxEMMI-OYIYvzMlulwmzuMoO2wlU,5820
25
+ OpenOrchestrator/orchestrator/tabs/settings_tab.py,sha256=9_B5K__GtUVWFxBD4XQ1KiGOx5a7VxiMz4WjJHoWuVE,852
26
+ OpenOrchestrator/orchestrator/tabs/trigger_tab.py,sha256=bBIyQSbfL6zBEiA8ZlhzVR3u6AdsAOlp-L5MVW4rz08,4035
27
+ OpenOrchestrator/orchestrator_connection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ OpenOrchestrator/orchestrator_connection/connection.py,sha256=whw3pbCiTwVoy4bmgdkaxBjPOpsHhGmpz7dHGlsYZjY,8923
29
+ OpenOrchestrator/scheduler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ OpenOrchestrator/scheduler/application.py,sha256=vjDzW8x0MwS9giFI6UOlhtFqUPHKbsRnrb6-HY8jWOI,1620
31
+ OpenOrchestrator/scheduler/connection_frame.py,sha256=Ufltek3jyX0Fm20A5JxSGQPuftqtY5BvodfLFOkmm8U,3378
32
+ OpenOrchestrator/scheduler/run_tab.py,sha256=QP-hoZEJAI5A-T7kV1lFCftpTm_e_R3T8I2Fg9BHxnA,5779
33
+ OpenOrchestrator/scheduler/runner.py,sha256=5F9eGlo8AsUx8WgeGxCe4k33NBPUzpsqTnVRS7_NaGQ,8348
34
+ OpenOrchestrator/scheduler/settings_tab.py,sha256=AQxt5HxPn4sLfj-6GwyAQ8ffJ35D0PHLBVoi8W3tu2A,613
35
+ OpenOrchestrator-1.3.0.dist-info/LICENSE,sha256=4-Kjm-gkbiOLCBYMzsVJZEepdsm2vk8QesNOASvi9mg,1068
36
+ OpenOrchestrator-1.3.0.dist-info/METADATA,sha256=esgDD3fPQSnTXFRZMfDlg1kq18WpFr5ihCJtjVG-bhY,1938
37
+ OpenOrchestrator-1.3.0.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
38
+ OpenOrchestrator-1.3.0.dist-info/top_level.txt,sha256=2btKMQESHuRC_ICbCjHTHH_-us2G7CyeskeaSTTL07Y,17
39
+ OpenOrchestrator-1.3.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (70.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,38 +0,0 @@
1
- OpenOrchestrator/__init__.py,sha256=i4Ir68mBu7rrqhlEE6Qh_uyble599jaEWCEMf8g58tI,179
2
- OpenOrchestrator/__main__.py,sha256=Oe3SbWqw3zUhpQpspUaS6mMddXxVvvV-pJbuBU_1GgA,518
3
- OpenOrchestrator/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- OpenOrchestrator/common/connection_frame.py,sha256=NuRwbEZviOExszhspbETvHcMi7pS4cgOnwQBvAqAZc4,2838
5
- OpenOrchestrator/common/crypto_util.py,sha256=Yo3WvIJnWtBJvlbvkDRu-HaReUUdaW747PcamCJUHzw,2029
6
- OpenOrchestrator/common/datetime_util.py,sha256=xNf_LORb67ohR3KfWE_owY15RqAOLJ8DfDPQlMBfsGc,527
7
- OpenOrchestrator/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- OpenOrchestrator/database/constants.py,sha256=ik6lY6IR8EOyKEg-N70X-0U654i3nFb3u-XWhqbUbJU,2404
9
- OpenOrchestrator/database/db_util.py,sha256=wqIK01ODOnmG5dfz5doPLDTVJTKTMuaWibk87fGr7T4,27599
10
- OpenOrchestrator/database/logs.py,sha256=h2BztjmDRhj8TACYN3LK5c9hIqn5xCs9m_LDUdYYHEk,1623
11
- OpenOrchestrator/database/queues.py,sha256=BFCbUUbo_OOCPNCzRRxDcgoxos_LI__Ypg7t9e3qdUk,2264
12
- OpenOrchestrator/database/triggers.py,sha256=Qq1lsSNrOYBKXnKhaD5s71YVmviaTxiD8j8kMBc76sg,4004
13
- OpenOrchestrator/orchestrator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- OpenOrchestrator/orchestrator/application.py,sha256=RgAyc-O79AtrgqOgUoKA5dcusBtIVBxjGpf-jCqAkdE,2804
15
- OpenOrchestrator/orchestrator/datetime_input.py,sha256=1EEkmKxYOQSIE6e-anbjACgbo7SL4wyuhqerdiBIg5w,2571
16
- OpenOrchestrator/orchestrator/popups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- OpenOrchestrator/orchestrator/popups/constant_popup.py,sha256=B6-xfEYRNNkf4dwbPgjGRuDqfKDL5pa6wUoZJ-A2l4g,3367
18
- OpenOrchestrator/orchestrator/popups/credential_popup.py,sha256=dIDro77ogBCZEZ8jUXMkenpSBANIfYX-PqVgKvVVbvU,3839
19
- OpenOrchestrator/orchestrator/popups/generic_popups.py,sha256=wV5isJrwFGUBpDhDpuOzzURwU4NTp4l5mzMDg-KebKw,1061
20
- OpenOrchestrator/orchestrator/popups/trigger_popup.py,sha256=Ir8Hx-DHtvCu3qm5BkG0uSRTObM9G4fpk-VOfeajelA,9684
21
- OpenOrchestrator/orchestrator/tabs/constants_tab.py,sha256=JcRIyntrzZBh5Ugkb0QrkBrjI-g9xl2VpbeKhdT6bFM,2478
22
- OpenOrchestrator/orchestrator/tabs/logging_tab.py,sha256=7HdXAnAMDHGC6Au8FaQ58M8i88oalBBtBAvGvdiRD_0,3527
23
- OpenOrchestrator/orchestrator/tabs/queue_tab.py,sha256=Yl_THeka0ykM-IlbsRpktxiGxZwhKGx0T-XC4S50aQI,5169
24
- OpenOrchestrator/orchestrator/tabs/settings_tab.py,sha256=xBMBdgrTxehmbuAk-H3QfEP_zdILzJ3sIgMCii7qlQg,845
25
- OpenOrchestrator/orchestrator/tabs/trigger_tab.py,sha256=qIEI3BEuKaknuV7EcH1fNTbGULVR4zAtHdADx5W-26c,4047
26
- OpenOrchestrator/orchestrator_connection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- OpenOrchestrator/orchestrator_connection/connection.py,sha256=DU552EigOu2xzM3SjY4766BXrDEnDC2jC4Jjy0-9OrU,8706
28
- OpenOrchestrator/scheduler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- OpenOrchestrator/scheduler/application.py,sha256=W2nkI6q6BCkgzmIMp3P_OHY-uZN5clACCa9rLtZg5-U,1624
30
- OpenOrchestrator/scheduler/connection_frame.py,sha256=I1Qooso_iqkNhvztQvFgjlC89Lvfqx0s5B6olATqa98,3369
31
- OpenOrchestrator/scheduler/run_tab.py,sha256=huwx5pQ5DhPCXgpDtK7b49BwyxuDdfZ9Dwh_P5kfWBY,5456
32
- OpenOrchestrator/scheduler/runner.py,sha256=2oC-WvfFcdyCWnbLCYh-jybA4t6cnayN__mSii7bW3U,7980
33
- OpenOrchestrator/scheduler/settings_tab.py,sha256=AQxt5HxPn4sLfj-6GwyAQ8ffJ35D0PHLBVoi8W3tu2A,613
34
- OpenOrchestrator-1.1.0.dist-info/LICENSE,sha256=4-Kjm-gkbiOLCBYMzsVJZEepdsm2vk8QesNOASvi9mg,1068
35
- OpenOrchestrator-1.1.0.dist-info/METADATA,sha256=6COV_ps1Vx9CEOvt-Nj5D7fCGv7lyf943QPTaRRGQbk,1938
36
- OpenOrchestrator-1.1.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
37
- OpenOrchestrator-1.1.0.dist-info/top_level.txt,sha256=2btKMQESHuRC_ICbCjHTHH_-us2G7CyeskeaSTTL07Y,17
38
- OpenOrchestrator-1.1.0.dist-info/RECORD,,