pybiolib 1.2.334.dev1__py3-none-any.whl → 1.2.339__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.
@@ -84,8 +84,6 @@ def fasta_batch_records(records, work_per_batch_min, work_per_residue=1, verbose
84
84
  n_seqs, n_res = batch_dict['records'], batch_dict['residues']
85
85
  print(f'Batch {i+1}: {n_res} residues from {n_seqs} sequences')
86
86
 
87
- # records = SeqUtil.parse_fasta(fasta_file)
88
-
89
87
  batches = []
90
88
  batch = []
91
89
  current_work_units = 0
@@ -27,7 +27,7 @@ from biolib.compute_node import utils as compute_node_utils
27
27
  from biolib.compute_node.cloud_utils import CloudUtils
28
28
  from biolib.compute_node.job_worker.docker_image_cache import DockerImageCache
29
29
  from biolib.compute_node.job_worker.executors.docker_types import DockerDiffKind
30
- from biolib.compute_node.job_worker.executors.types import LocalExecutorOptions, StatusUpdate, MetadataToSaveOutput
30
+ from biolib.compute_node.job_worker.executors.types import LocalExecutorOptions, StatusUpdate
31
31
  from biolib.compute_node.job_worker.mappings import Mappings, path_without_first_folder
32
32
  from biolib.compute_node.job_worker.utilization_reporter_thread import UtilizationReporterThread
33
33
  from biolib.compute_node.job_worker.utils import ComputeProcessException
@@ -61,12 +61,9 @@ class DockerExecutor:
61
61
  os.makedirs(user_data_tar_dir, exist_ok=True)
62
62
 
63
63
  self._docker_container: Optional[Container] = None
64
- self._docker_api_client = BiolibDockerClient.get_docker_client().api
65
64
  self._runtime_tar_path = f'{user_data_tar_dir}/runtime_{self._random_docker_id}.tar'
66
65
  self._input_tar_path = f'{user_data_tar_dir}/input_{self._random_docker_id}.tar'
67
66
 
68
- self._metadata_for_save_output_on_cancel: Optional[MetadataToSaveOutput] = None
69
-
70
67
  if utils.IS_RUNNING_IN_CLOUD and not utils.BIOLIB_SECRETS_TMPFS_PATH:
71
68
  error_message = 'Running in cloud but no TMPFS path has been set for secrets'
72
69
  logger_no_user_data.error(error_message)
@@ -84,12 +81,12 @@ class DockerExecutor:
84
81
  raise Exception('Docker container was None')
85
82
  return self._docker_container
86
83
 
87
- def execute_module(self) -> None:
84
+ def execute_module(self, module_input_path: str, module_output_path: str) -> None:
88
85
  try:
89
86
  job_uuid = self._options['job']['public_id']
90
87
  send_status_update = self._options['send_status_update']
91
88
  logger_no_user_data.debug(f'Reading module input of {job_uuid}.')
92
- with open(self._options['module_input_path'], 'rb') as fp:
89
+ with open(module_input_path, 'rb') as fp:
93
90
  module_input_tmp = ModuleInput(fp.read())
94
91
  logger_no_user_data.debug(f'Deserialing module input of {job_uuid}...')
95
92
  module_input = module_input_tmp.deserialize()
@@ -103,7 +100,7 @@ class DockerExecutor:
103
100
 
104
101
  logger_no_user_data.debug(f'Starting execution of {job_uuid}.')
105
102
  try:
106
- self._execute_helper(module_input)
103
+ self._execute_helper(module_input, module_output_path)
107
104
  except docker.errors.NotFound as docker_error:
108
105
  raise DockerContainerNotFoundDuringExecutionException from docker_error
109
106
  except Exception as exception:
@@ -164,8 +161,7 @@ class DockerExecutor:
164
161
  may_contain_user_data=False,
165
162
  )
166
163
 
167
-
168
- def _execute_helper(self, module_input) -> None:
164
+ def _execute_helper(self, module_input, module_output_path: str) -> None:
169
165
  job_uuid = self._options['job']['public_id']
170
166
  logger_no_user_data.debug(f'Initializing container for {job_uuid}.')
171
167
  self._initialize_docker_container(module_input)
@@ -191,9 +187,10 @@ class DockerExecutor:
191
187
  logger_no_user_data.debug(f'_map_and_copy_input_files_to_container for {job_uuid}.')
192
188
  self._map_and_copy_input_files_to_container(module_input['files'], module_input['arguments'])
193
189
 
190
+ docker_api_client = BiolibDockerClient.get_docker_client().api
194
191
  logger_no_user_data.debug(f'Attaching Docker container for {job_uuid}')
195
192
 
196
- stdout_and_stderr_stream = self._docker_api_client.attach(
193
+ stdout_and_stderr_stream = docker_api_client.attach(
197
194
  container=self._container.id,
198
195
  stderr=True,
199
196
  stdout=True,
@@ -214,12 +211,6 @@ class DockerExecutor:
214
211
  logger.debug(f'Warning: Job "{job_uuid}" failed to start container. Hit error: {startup_error_string}')
215
212
  # even though the container start failed we should still be able to call logs() and wait() on it, so we pass
216
213
 
217
- self._metadata_for_save_output_on_cancel = MetadataToSaveOutput(
218
- arguments=module_input['arguments'],
219
- startup_error_string=startup_error_string,
220
- pre_start_diff=pre_start_diff,
221
- )
222
-
223
214
  if self._options['job']['app_version'].get('stdout_render_type') != 'markdown':
224
215
  logger_no_user_data.debug(f'Streaming stdout for {job_uuid}')
225
216
  for stdout_and_stderr in stdout_and_stderr_stream:
@@ -229,14 +220,7 @@ class DockerExecutor:
229
220
  self._send_stdout_and_stderr(stdout_and_stderr)
230
221
 
231
222
  logger_no_user_data.debug(f'Waiting on docker for {job_uuid}')
232
- try:
233
- docker_result = self._docker_api_client.wait(self._container.id)
234
- except docker.errors.NotFound as error:
235
- if self._is_cleaning_up:
236
- return
237
- else:
238
- raise error
239
-
223
+ docker_result = docker_api_client.wait(self._container.id)
240
224
  logger_no_user_data.debug(f'Got result from docker for {job_uuid}')
241
225
  exit_code = docker_result['StatusCode']
242
226
  # 137 is the error code from linux OOM killer (Should catch 90% of OOM errors)
@@ -248,26 +232,22 @@ class DockerExecutor:
248
232
  )
249
233
 
250
234
  logger_no_user_data.debug(f'Docker container exited with code {exit_code} for {job_uuid}')
251
- self._save_module_output_from_container(exit_code, self._metadata_for_save_output_on_cancel)
252
-
253
235
 
254
- def _save_module_output_from_container(self, exit_code: int, metadata: MetadataToSaveOutput) -> None:
255
- full_stdout = self._docker_api_client.logs(self._container.id, stdout=True, stderr=False)
256
- full_stderr = self._docker_api_client.logs(self._container.id, stdout=False, stderr=True)
236
+ full_stdout = docker_api_client.logs(self._container.id, stdout=True, stderr=False)
237
+ full_stderr = docker_api_client.logs(self._container.id, stdout=False, stderr=True)
257
238
 
258
- if metadata['startup_error_string']:
259
- full_stderr = full_stderr + metadata['startup_error_string'].encode()
239
+ if startup_error_string:
240
+ full_stderr = full_stderr + startup_error_string.encode()
260
241
 
261
242
  self._write_module_output_to_file(
262
- arguments=metadata['arguments'],
243
+ arguments=module_input['arguments'],
263
244
  exit_code=exit_code,
264
- module_output_path=self._options['module_output_path'],
245
+ module_output_path=module_output_path,
265
246
  stderr=full_stderr,
266
247
  stdout=full_stdout,
267
- pre_start_diff=metadata['pre_start_diff'],
248
+ pre_start_diff=pre_start_diff,
268
249
  )
269
250
 
270
-
271
251
  def cleanup(self):
272
252
  # Don't clean up if already in the process of doing so, or done doing so
273
253
  if self._is_cleaning_up:
@@ -275,22 +255,6 @@ class DockerExecutor:
275
255
  else:
276
256
  self._is_cleaning_up = True
277
257
 
278
- if self._metadata_for_save_output_on_cancel is not None:
279
- try:
280
- logger_no_user_data.debug('Attempting to save results')
281
- self._docker_container.stop()
282
- self._docker_container.reload()
283
- logger_no_user_data.debug(f'Container state {self._docker_container.status}')
284
- self._save_module_output_from_container(
285
- exit_code=self._docker_container.attrs['State']['ExitCode'],
286
- metadata=self._metadata_for_save_output_on_cancel
287
- )
288
- logger_no_user_data.debug('Saved results')
289
- except BaseException as error:
290
- logger_no_user_data.error(f'Failed to save results on cancel with error: {error}')
291
- else:
292
- logger_no_user_data.debug('Missing metadata, cannot save results')
293
-
294
258
  tar_time = time.time()
295
259
  for path_to_delete in [self._input_tar_path, self._runtime_tar_path]:
296
260
  if os.path.exists(path_to_delete):
@@ -34,16 +34,9 @@ class LocalExecutorOptions(TypedDict):
34
34
  cloud_job: Optional[CloudJob]
35
35
  large_file_systems: Dict[str, LargeFileSystem]
36
36
  module: Module
37
- module_input_path: str
38
- module_output_path: str
39
37
  remote_host_proxies: List[RemoteHostProxy]
40
38
  root_job_id: str
41
39
  runtime_zip_bytes: Optional[bytes] # TODO: replace this with a module_source_serialized
42
40
  send_status_update: SendStatusUpdateType
43
41
  send_system_exception: SendSystemExceptionType
44
42
  send_stdout_and_stderr: SendStdoutAndStderrType
45
-
46
- class MetadataToSaveOutput(TypedDict):
47
- arguments: List[str]
48
- startup_error_string: Optional[str]
49
- pre_start_diff: List[Dict]
@@ -400,15 +400,15 @@ class JobWorker:
400
400
  cloud_job=self._root_job_wrapper['cloud_job'],
401
401
  large_file_systems=lfs_dict,
402
402
  module=main_module,
403
- module_input_path=module_input_path,
404
- module_output_path=main_module_output_path,
405
403
  remote_host_proxies=self._remote_host_proxies,
406
404
  root_job_id=root_job_id,
407
405
  runtime_zip_bytes=runtime_zip_bytes,
408
406
  send_status_update=self._send_status_update,
409
407
  send_system_exception=self.send_system_exception,
410
408
  send_stdout_and_stderr=self.send_stdout_and_stderr,
411
- )
409
+ ),
410
+ module_input_path,
411
+ main_module_output_path,
412
412
  )
413
413
 
414
414
  if utils.IS_RUNNING_IN_CLOUD:
@@ -418,11 +418,11 @@ class JobWorker:
418
418
  def _run_module(
419
419
  self,
420
420
  options: LocalExecutorOptions,
421
+ module_input_path: str,
422
+ module_output_path: str,
421
423
  ) -> None:
422
424
  module = options['module']
423
425
  job_id = options['job']['public_id']
424
- module_output_path = options['module_output_path']
425
- module_input_path = options['module_input_path']
426
426
  logger_no_user_data.debug(f'Job "{job_id}" running module "{module["name"]}"...')
427
427
 
428
428
  executor_instance: DockerExecutor
@@ -469,7 +469,7 @@ class JobWorker:
469
469
  # Log memory and disk before pulling and executing module
470
470
  log_disk_and_memory_usage_info()
471
471
 
472
- executor_instance.execute_module()
472
+ executor_instance.execute_module(module_input_path, module_output_path)
473
473
 
474
474
  def _connect_to_parent(self):
475
475
  try:
@@ -7,7 +7,6 @@ import sys
7
7
  import threading
8
8
  import time
9
9
  from queue import Queue
10
- from typing import Optional
11
10
 
12
11
  from biolib import api, utils
13
12
  from biolib.biolib_binary_format import ModuleOutputV2, SystemException, SystemStatusUpdate
@@ -56,26 +55,6 @@ class WorkerThread(threading.Thread):
56
55
  def _job_temporary_dir(self):
57
56
  return self.compute_state['job_temporary_dir']
58
57
 
59
- def _upload_module_output_and_get_exit_code(self) -> Optional[int]:
60
- exit_code = None
61
- try:
62
- module_output_path = os.path.join(
63
- self._job_temporary_dir,
64
- JobStorage.module_output_file_name,
65
- )
66
- if os.path.exists(module_output_path):
67
- module_output = ModuleOutputV2(buffer=LocalFileIndexableBuffer(filename=module_output_path))
68
- exit_code = module_output.get_exit_code()
69
- logger_no_user_data.debug(f'Got exit code: {exit_code}')
70
- if utils.IS_RUNNING_IN_CLOUD:
71
- JobStorage.upload_module_output(
72
- job_temporary_dir=self._job_temporary_dir,
73
- job_uuid=self._job_uuid,
74
- )
75
- except Exception as error:
76
- logger_no_user_data.error(f'Could not upload module output or get exit code: {error}')
77
- return exit_code
78
-
79
58
  def run(self):
80
59
  try:
81
60
  while True:
@@ -98,7 +77,25 @@ class WorkerThread(threading.Thread):
98
77
 
99
78
  # If 'Computation Finished'
100
79
  if progress == 94:
101
- self.compute_state['exit_code'] = self._upload_module_output_and_get_exit_code()
80
+ # Get Job exit code
81
+ try:
82
+ module_output_path = os.path.join(
83
+ self._job_temporary_dir,
84
+ JobStorage.module_output_file_name,
85
+ )
86
+ module_output = ModuleOutputV2(buffer=LocalFileIndexableBuffer(filename=module_output_path))
87
+ self.compute_state['exit_code'] = module_output.get_exit_code()
88
+ logger_no_user_data.debug(f"Got exit code: {self.compute_state['exit_code']}")
89
+
90
+ except Exception as error: # pylint: disable=broad-except
91
+ logger_no_user_data.error(f'Could not get exit_code from module output due to: {error}')
92
+
93
+ if utils.IS_RUNNING_IN_CLOUD:
94
+ JobStorage.upload_module_output(
95
+ job_temporary_dir=self._job_temporary_dir,
96
+ job_uuid=self._job_uuid,
97
+ )
98
+
102
99
  self._set_status_update(progress=95, log_message='Result Ready')
103
100
  self.compute_state['is_completed'] = True
104
101
  self.terminate()
@@ -177,16 +174,13 @@ class WorkerThread(threading.Thread):
177
174
 
178
175
  def terminate(self) -> None:
179
176
  cloud_job_uuid = self.compute_state['cloud_job_id']
177
+ exit_code = self.compute_state.get('exit_code')
180
178
  system_exception_code = self.compute_state['status'].get('error_code')
181
-
182
179
  if utils.IS_RUNNING_IN_CLOUD:
183
- if system_exception_code == SystemExceptionCodes.CANCELLED_BY_USER.value:
184
- self.compute_state['exit_code'] = self._upload_module_output_and_get_exit_code()
185
-
186
180
  CloudUtils.finish_cloud_job(
187
181
  cloud_job_id=cloud_job_uuid,
188
182
  system_exception_code=system_exception_code,
189
- exit_code=self.compute_state.get('exit_code', None),
183
+ exit_code=exit_code,
190
184
  )
191
185
 
192
186
  deregistered_due_to_error = False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pybiolib
3
- Version: 1.2.334.dev1
3
+ Version: 1.2.339
4
4
  Summary: BioLib Python Client
5
5
  License: MIT
6
6
  Keywords: biolib
@@ -24,7 +24,7 @@ biolib/_internal/types/resource.py,sha256=G-vPkZoe4Um6FPxsQZtRzAlbSW5sDW4NFkbjn2
24
24
  biolib/_internal/types/resource_version.py,sha256=sLxViYXloDDUhTDFgjegiQCj097OM1Ih1-uqlC_4ULA,174
25
25
  biolib/_internal/types/typing.py,sha256=D4EKKEe7kDx0K6lJi-H_XLtk-8w6nu2fdqn9bvzI-Xo,288
26
26
  biolib/_internal/utils/__init__.py,sha256=p5vsIFyu-zYqBgdSMfwW9NC_jk7rXvvCbV4Bzd3As7c,630
27
- biolib/_internal/utils/multinode.py,sha256=G0t7dkHtoxIfdCD0vjG8eyQwRxQ0zWazOWZUFQ3hQxw,8278
27
+ biolib/_internal/utils/multinode.py,sha256=-J3PEAK3NaOwCn--5T7vWHkA3yu5w9QhmuhkQcH-2wY,8229
28
28
  biolib/_runtime/runtime.py,sha256=bZQ0m39R9jOBVAtlyvzDnOobKueOAQUCwMUZjDQnO7E,4439
29
29
  biolib/api/__init__.py,sha256=mQ4u8FijqyLzjYMezMUUbbBGNB3iFmkNdjXnWPZ7Jlw,138
30
30
  biolib/api/client.py,sha256=_kmwaGI_-u7kOeWVCYmo-pD2K1imwEv9n2gNZRb5F-I,3790
@@ -76,14 +76,14 @@ biolib/compute_node/job_worker/cache_state.py,sha256=MwjSRzcJJ_4jybqvBL4xdgnDYSI
76
76
  biolib/compute_node/job_worker/cache_types.py,sha256=ajpLy8i09QeQS9dEqTn3T6NVNMY_YsHQkSD5nvIHccQ,818
77
77
  biolib/compute_node/job_worker/docker_image_cache.py,sha256=ansHIkJIq_EMW1nZNlW-RRLVVeKWTbzNICYaOHpKiRE,7460
78
78
  biolib/compute_node/job_worker/executors/__init__.py,sha256=bW6t1qi3PZTlHM4quaTLa8EI4ALTCk83cqcVJfJfJfE,145
79
- biolib/compute_node/job_worker/executors/docker_executor.py,sha256=NpDSgNWbnC0Qr6aFaQMEfhib3O9BMOPsia-YqeTMhpU,30966
79
+ biolib/compute_node/job_worker/executors/docker_executor.py,sha256=J-wv7FTb_HJnfRdIByiOdtj18Fw5nYvVm-n0D1mrqwA,29377
80
80
  biolib/compute_node/job_worker/executors/docker_types.py,sha256=VhsU1DKtJjx_BbCkVmiPZPH4ROiL1ygW1Y_s1Kbpa2o,216
81
81
  biolib/compute_node/job_worker/executors/tars/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
- biolib/compute_node/job_worker/executors/types.py,sha256=gw_T-oq0lty8Hg8WsTrqhtV-kyOF_l5nr9Xe8-kzetc,1657
82
+ biolib/compute_node/job_worker/executors/types.py,sha256=yP5gG39hr-DLnw9bOE--VHi-1arDbIYiGuV1rlTbbHI,1466
83
83
  biolib/compute_node/job_worker/job_legacy_input_wait_timeout_thread.py,sha256=_cvEiZbOwfkv6fYmfrvdi_FVviIEYr_dSClQcOQaUWM,1198
84
84
  biolib/compute_node/job_worker/job_max_runtime_timer_thread.py,sha256=K_xgz7IhiIjpLlXRk8sqaMyLoApcidJkgu29sJX0gb8,1174
85
85
  biolib/compute_node/job_worker/job_storage.py,sha256=lScHI3ubcHKagSEW243tgbIWXUfbWDHDjEOPMvXxJE8,4603
86
- biolib/compute_node/job_worker/job_worker.py,sha256=xp1laEWUhUsKzF4ITdsTWcQlSn133pAjkeiPMAG5jqQ,28892
86
+ biolib/compute_node/job_worker/job_worker.py,sha256=fuWoYJo9HOqLmWl8yeCXh0mhT4ebbkrWac-BVb58khs,28842
87
87
  biolib/compute_node/job_worker/large_file_system.py,sha256=XXqRlVtYhs-Ji9zQGIk5KQPXFO_Q5jJH0nnlw4GkeMY,10461
88
88
  biolib/compute_node/job_worker/mappings.py,sha256=Z48Kg4nbcOvsT2-9o3RRikBkqflgO4XeaWxTGz-CNvI,2499
89
89
  biolib/compute_node/job_worker/utilization_reporter_thread.py,sha256=7tm5Yk9coqJ9VbEdnO86tSXI0iM0omwIyKENxdxiVXk,8575
@@ -97,7 +97,7 @@ biolib/compute_node/webserver/gunicorn_flask_application.py,sha256=jPfR_YvNBekLU
97
97
  biolib/compute_node/webserver/webserver.py,sha256=o4kOAStsqThUtKlnRE-U5TP0JIYntuySDjU7PH310xg,6620
98
98
  biolib/compute_node/webserver/webserver_types.py,sha256=2t8EaFKESnves3BA_NBdnS2yAdo1qwamCFHiSt888nE,380
99
99
  biolib/compute_node/webserver/webserver_utils.py,sha256=XWvwYPbWNR3qS0FYbLLp-MDDfVk0QdaAmg3xPrT0H2s,4234
100
- biolib/compute_node/webserver/worker_thread.py,sha256=jakGi-libQJfD7rcB525XbTVIAmI4uZ-xwvzvqFSWgw,11961
100
+ biolib/compute_node/webserver/worker_thread.py,sha256=GRRBUqXdMKvbjyLQhYlqGIbFKeU2iiEXIe5IXi9wgdg,11806
101
101
  biolib/experiments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
102
102
  biolib/experiments/experiment.py,sha256=m7FB7hot8CMOVrNyWGPB6FTkWQJwI0ytpIvtPxfoPME,7684
103
103
  biolib/jobs/__init__.py,sha256=aIb2H2DHjQbM2Bs-dysFijhwFcL58Blp0Co0gimED3w,32
@@ -118,8 +118,8 @@ biolib/utils/cache_state.py,sha256=u256F37QSRIVwqKlbnCyzAX4EMI-kl6Dwu6qwj-Qmag,3
118
118
  biolib/utils/multipart_uploader.py,sha256=XvGP1I8tQuKhAH-QugPRoEsCi9qvbRk-DVBs5PNwwJo,8452
119
119
  biolib/utils/seq_util.py,sha256=Ozk0blGtPur_D9MwShD02r_mphyQmgZkx-lOHOwnlIM,6730
120
120
  biolib/utils/zip/remote_zip.py,sha256=0wErYlxir5921agfFeV1xVjf29l9VNgGQvNlWOlj2Yc,23232
121
- pybiolib-1.2.334.dev1.dist-info/LICENSE,sha256=F2h7gf8i0agDIeWoBPXDMYScvQOz02pAWkKhTGOHaaw,1067
122
- pybiolib-1.2.334.dev1.dist-info/METADATA,sha256=AXuQRU7aU2ktbCRoVoprdenRGFhL6B5pJ4zQhVH3lu4,1575
123
- pybiolib-1.2.334.dev1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
124
- pybiolib-1.2.334.dev1.dist-info/entry_points.txt,sha256=p6DyaP_2kctxegTX23WBznnrDi4mz6gx04O5uKtRDXg,42
125
- pybiolib-1.2.334.dev1.dist-info/RECORD,,
121
+ pybiolib-1.2.339.dist-info/LICENSE,sha256=F2h7gf8i0agDIeWoBPXDMYScvQOz02pAWkKhTGOHaaw,1067
122
+ pybiolib-1.2.339.dist-info/METADATA,sha256=7w5znJtkMyO9KQ_CD0PdX2Hz1pBuTjnEOeSnfaOMrsk,1570
123
+ pybiolib-1.2.339.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
124
+ pybiolib-1.2.339.dist-info/entry_points.txt,sha256=p6DyaP_2kctxegTX23WBznnrDi4mz6gx04O5uKtRDXg,42
125
+ pybiolib-1.2.339.dist-info/RECORD,,