executorlib 1.9.0__tar.gz → 1.9.2__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.
Files changed (51) hide show
  1. {executorlib-1.9.0 → executorlib-1.9.2}/PKG-INFO +1 -1
  2. {executorlib-1.9.0 → executorlib-1.9.2}/pyproject.toml +1 -1
  3. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/_version.py +2 -2
  4. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/executor/flux.py +8 -3
  5. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/executor/single.py +5 -0
  6. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/executor/slurm.py +7 -2
  7. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/validate.py +2 -0
  8. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/blockallocation.py +57 -5
  9. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/spawner_pysqa.py +2 -0
  10. {executorlib-1.9.0 → executorlib-1.9.2}/.gitignore +0 -0
  11. {executorlib-1.9.0 → executorlib-1.9.2}/LICENSE +0 -0
  12. {executorlib-1.9.0 → executorlib-1.9.2}/README.md +0 -0
  13. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/__init__.py +0 -0
  14. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/api.py +0 -0
  15. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/backend/__init__.py +0 -0
  16. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/backend/cache_parallel.py +0 -0
  17. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/backend/cache_serial.py +0 -0
  18. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/backend/interactive_parallel.py +0 -0
  19. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/backend/interactive_serial.py +0 -0
  20. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/executor/__init__.py +0 -0
  21. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/executor/base.py +0 -0
  22. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/__init__.py +0 -0
  23. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/batched.py +0 -0
  24. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/command.py +0 -0
  25. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/error.py +0 -0
  26. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/hdf.py +0 -0
  27. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/inputcheck.py +0 -0
  28. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/interactive/__init__.py +0 -0
  29. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/interactive/arguments.py +0 -0
  30. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/interactive/backend.py +0 -0
  31. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/interactive/communication.py +0 -0
  32. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/interactive/spawner.py +0 -0
  33. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/queue.py +0 -0
  34. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/scheduler.py +0 -0
  35. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/select.py +0 -0
  36. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/standalone/serialize.py +0 -0
  37. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/__init__.py +0 -0
  38. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/base.py +0 -0
  39. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/file/__init__.py +0 -0
  40. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/file/backend.py +0 -0
  41. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/file/shared.py +0 -0
  42. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/file/spawner_pysqa.py +0 -0
  43. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/file/spawner_subprocess.py +0 -0
  44. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/file/task_scheduler.py +0 -0
  45. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/__init__.py +0 -0
  46. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/dependency.py +0 -0
  47. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/dependency_plot.py +0 -0
  48. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/onetoone.py +0 -0
  49. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/shared.py +0 -0
  50. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/spawner_flux.py +0 -0
  51. {executorlib-1.9.0 → executorlib-1.9.2}/src/executorlib/task_scheduler/interactive/spawner_slurm.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: executorlib
3
- Version: 1.9.0
3
+ Version: 1.9.2
4
4
  Summary: Up-scale python functions for high performance computing (HPC) with executorlib.
5
5
  Project-URL: Homepage, https://github.com/pyiron/executorlib
6
6
  Project-URL: Documentation, https://executorlib.readthedocs.io
@@ -1,6 +1,6 @@
1
1
  [build-system]
2
2
  requires = [
3
- "hatchling>=1.27.0,<=1.28.0",
3
+ "hatchling>=1.27.0,<=1.29.0",
4
4
  "hatch-vcs==0.5.0",
5
5
  "cloudpickle>=2.0.0,<=3.1.2",
6
6
  "pyzmq>=25.0.0,<=27.1.0",
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.9.0'
32
- __version_tuple__ = version_tuple = (1, 9, 0)
31
+ __version__ = version = '1.9.2'
32
+ __version_tuple__ = version_tuple = (1, 9, 2)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -45,6 +45,7 @@ class FluxJobExecutor(BaseExecutor):
45
45
  * cwd (str): current working directory where the parallel python task is executed
46
46
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
47
47
  provide an external cache_key to identify tasks on the file system.
48
+ * cache_directory (str): The directory to store cache files.
48
49
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
49
50
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
50
51
  do not allow other tasks to use the same compute node.
@@ -54,7 +55,7 @@ class FluxJobExecutor(BaseExecutor):
54
55
  allowed to take in seconds.
55
56
  * priority (int): the queuing system priority assigned to a given Python function to
56
57
  influence the scheduling.
57
- *`slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
58
+ * slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
58
59
  pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None
59
60
  flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
60
61
  flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
@@ -146,6 +147,7 @@ class FluxJobExecutor(BaseExecutor):
146
147
  * cwd (str): current working directory where the parallel python task is executed
147
148
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
148
149
  provide an external cache_key to identify tasks on the file system.
150
+ * cache_directory (str): The directory to store cache files.
149
151
  * num_nodes (int): number of compute nodes used for the evaluation of the Python
150
152
  function.
151
153
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes
@@ -275,6 +277,7 @@ class FluxClusterExecutor(BaseExecutor):
275
277
  * cwd (str): current working directory where the parallel python task is executed
276
278
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
277
279
  provide an external cache_key to identify tasks on the file system.
280
+ * cache_directory (str): The directory to store cache files.
278
281
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
279
282
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
280
283
  do not allow other tasks to use the same compute node.
@@ -284,7 +287,7 @@ class FluxClusterExecutor(BaseExecutor):
284
287
  allowed to take in seconds.
285
288
  * priority (int): the queuing system priority assigned to a given Python function to
286
289
  influence the scheduling.
287
- *`slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
290
+ * slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
288
291
  pysqa_config_directory (str, optional): path to the pysqa config directory (only for pysqa based backend).
289
292
  pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None
290
293
  hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
@@ -370,6 +373,7 @@ class FluxClusterExecutor(BaseExecutor):
370
373
  * cwd (str): current working directory where the parallel python task is executed
371
374
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
372
375
  provide an external cache_key to identify tasks on the file system.
376
+ * cache_directory (str): The directory to store cache files.
373
377
  * num_nodes (int): number of compute nodes used for the evaluation of the Python
374
378
  function.
375
379
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes
@@ -530,6 +534,7 @@ def create_flux_executor(
530
534
  * cwd (str): current working directory where the parallel python task is executed
531
535
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
532
536
  provide an external cache_key to identify tasks on the file system.
537
+ * cache_directory (str): The directory to store cache files.
533
538
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
534
539
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
535
540
  do not allow other tasks to use the same compute node.
@@ -539,7 +544,7 @@ def create_flux_executor(
539
544
  allowed to take in seconds.
540
545
  * priority (int): the queuing system priority assigned to a given Python function to
541
546
  influence the scheduling.
542
- *`slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
547
+ * slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
543
548
  pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None
544
549
  flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
545
550
  flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
@@ -44,6 +44,7 @@ class SingleNodeExecutor(BaseExecutor):
44
44
  * cwd (str): current working directory where the parallel python task is executed
45
45
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
46
46
  provide an external cache_key to identify tasks on the file system.
47
+ * cache_directory (str): The directory to store cache files.
47
48
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
48
49
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
49
50
  do not allow other tasks to use the same compute node.
@@ -137,6 +138,7 @@ class SingleNodeExecutor(BaseExecutor):
137
138
  * cwd (str): current working directory where the parallel python task is executed
138
139
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
139
140
  provide an external cache_key to identify tasks on the file system.
141
+ * cache_directory (str): The directory to store cache files.
140
142
  * num_nodes (int): number of compute nodes used for the evaluation of the Python
141
143
  function.
142
144
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes
@@ -251,6 +253,7 @@ class TestClusterExecutor(BaseExecutor):
251
253
  * cwd (str): current working directory where the parallel python task is executed
252
254
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
253
255
  provide an external cache_key to identify tasks on the file system.
256
+ * cache_directory (str): The directory to store cache files.
254
257
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
255
258
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
256
259
  do not allow other tasks to use the same compute node.
@@ -340,6 +343,7 @@ class TestClusterExecutor(BaseExecutor):
340
343
  * cwd (str): current working directory where the parallel python task is executed
341
344
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
342
345
  provide an external cache_key to identify tasks on the file system.
346
+ * cache_directory (str): The directory to store cache files.
343
347
  * num_nodes (int): number of compute nodes used for the evaluation of the Python
344
348
  function.
345
349
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes
@@ -469,6 +473,7 @@ def create_single_node_executor(
469
473
  * cwd (str): current working directory where the parallel python task is executed
470
474
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
471
475
  provide an external cache_key to identify tasks on the file system.
476
+ * cache_directory (str): The directory to store cache files.
472
477
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
473
478
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
474
479
  do not allow other tasks to use the same compute node.
@@ -46,6 +46,7 @@ class SlurmClusterExecutor(BaseExecutor):
46
46
  * cwd (str): current working directory where the parallel python task is executed
47
47
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
48
48
  provide an external cache_key to identify tasks on the file system.
49
+ * cache_directory (str): The directory to store cache files.
49
50
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
50
51
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
51
52
  do not allow other tasks to use the same compute node.
@@ -55,7 +56,7 @@ class SlurmClusterExecutor(BaseExecutor):
55
56
  allowed to take in seconds.
56
57
  * priority (int): the queuing system priority assigned to a given Python function to
57
58
  influence the scheduling.
58
- *`slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
59
+ * slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
59
60
  pysqa_config_directory (str, optional): path to the pysqa config directory (only for pysqa based backend).
60
61
  pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None
61
62
  hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
@@ -141,6 +142,7 @@ class SlurmClusterExecutor(BaseExecutor):
141
142
  * cwd (str): current working directory where the parallel python task is executed
142
143
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
143
144
  provide an external cache_key to identify tasks on the file system.
145
+ * cache_directory (str): The directory to store cache files.
144
146
  * num_nodes (int): number of compute nodes used for the evaluation of the Python
145
147
  function.
146
148
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes
@@ -285,6 +287,7 @@ class SlurmJobExecutor(BaseExecutor):
285
287
  * cwd (str): current working directory where the parallel python task is executed
286
288
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
287
289
  provide an external cache_key to identify tasks on the file system.
290
+ * cache_directory (str): The directory to store cache files.
288
291
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
289
292
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
290
293
  do not allow other tasks to use the same compute node.
@@ -294,7 +297,7 @@ class SlurmJobExecutor(BaseExecutor):
294
297
  allowed to take in seconds.
295
298
  * priority (int): the queuing system priority assigned to a given Python function to
296
299
  influence the scheduling.
297
- *`slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
300
+ * slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
298
301
  pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None
299
302
  hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
300
303
  context of an HPC cluster this essential to be able to communicate to an
@@ -380,6 +383,7 @@ class SlurmJobExecutor(BaseExecutor):
380
383
  * cwd (str): current working directory where the parallel python task is executed
381
384
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
382
385
  provide an external cache_key to identify tasks on the file system.
386
+ * cache_directory (str): The directory to store cache files.
383
387
  * num_nodes (int): number of compute nodes used for the evaluation of the Python
384
388
  function.
385
389
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes
@@ -508,6 +512,7 @@ def create_slurm_executor(
508
512
  * cwd (str): current working directory where the parallel python task is executed
509
513
  * cache_key (str): Rather than using the internal hashing of executorlib the user can
510
514
  provide an external cache_key to identify tasks on the file system.
515
+ * cache_directory (str): The directory to store cache files.
511
516
  * num_nodes (int): number of compute nodes used for the evaluation of the Python function.
512
517
  * exclusive (bool): boolean flag to reserve exclusive access to selected compute nodes -
513
518
  do not allow other tasks to use the same compute node.
@@ -19,12 +19,14 @@ class ResourceDictValidation(BaseModel):
19
19
  gpus_per_core: Optional[int] = None
20
20
  cwd: Optional[str] = None
21
21
  cache_key: Optional[str] = None
22
+ cache_directory: Optional[str] = None
22
23
  num_nodes: Optional[int] = None
23
24
  exclusive: Optional[bool] = None
24
25
  error_log_file: Optional[str] = None
25
26
  run_time_limit: Optional[int] = None
26
27
  priority: Optional[int] = None
27
28
  slurm_cmd_args: Optional[list[str]] = None
29
+ submission_template: Optional[str] = None
28
30
 
29
31
  if HAS_PYDANTIC:
30
32
 
@@ -1,7 +1,7 @@
1
1
  import queue
2
2
  import random
3
3
  from concurrent.futures import Future
4
- from threading import Event, Thread
4
+ from threading import Event, Lock, Thread
5
5
  from typing import Callable, Optional
6
6
 
7
7
  from executorlib.standalone.command import get_interactive_execute_command
@@ -83,6 +83,8 @@ class BlockAllocationTaskScheduler(TaskSchedulerBase):
83
83
  self_id = random.getrandbits(128)
84
84
  self._self_id = self_id
85
85
  _interrupt_bootup_dict[self._self_id] = False
86
+ alive_workers = [max_workers]
87
+ alive_workers_lock = Lock()
86
88
  bootup_events = [Event() for _ in range(self._max_workers)]
87
89
  bootup_events[0].set()
88
90
  self._set_process(
@@ -99,6 +101,8 @@ class BlockAllocationTaskScheduler(TaskSchedulerBase):
99
101
  if worker_id + 1 < self._max_workers
100
102
  else None
101
103
  ),
104
+ "alive_workers": alive_workers,
105
+ "alive_workers_lock": alive_workers_lock,
102
106
  },
103
107
  )
104
108
  for worker_id in range(self._max_workers)
@@ -227,6 +231,8 @@ def _execute_multiple_tasks(
227
231
  restart_limit: int = 0,
228
232
  bootup_event: Optional[Event] = None,
229
233
  next_bootup_event: Optional[Event] = None,
234
+ alive_workers: Optional[list] = None,
235
+ alive_workers_lock: Optional[Lock] = None,
230
236
  **kwargs,
231
237
  ) -> None:
232
238
  """
@@ -258,6 +264,9 @@ def _execute_multiple_tasks(
258
264
  bootup_event (Event): Event to wait on before submitting the job to the scheduler, ensuring workers are
259
265
  submitted in worker_id order.
260
266
  next_bootup_event (Event): Event to signal after job submission, unblocking the next worker.
267
+ alive_workers (list): Single-element list [N] tracking how many worker threads are still alive. Shared across
268
+ all worker threads; decremented when a worker is permanently dead.
269
+ alive_workers_lock (Lock): Lock protecting alive_workers from concurrent modification.
261
270
  """
262
271
  if bootup_event is not None:
263
272
  bootup_event.wait()
@@ -279,11 +288,13 @@ def _execute_multiple_tasks(
279
288
  )
280
289
  restart_counter = 0
281
290
  while True:
282
- if not interface.status and restart_counter > restart_limit:
283
- interface.status = True # no more restarts
284
- interface_initialization_exception = ExecutorlibSocketError(
285
- "SocketInterface crashed during execution."
291
+ if not interface.status and restart_counter >= restart_limit:
292
+ _drain_dead_worker(
293
+ future_queue=future_queue,
294
+ alive_workers=alive_workers,
295
+ alive_workers_lock=alive_workers_lock,
286
296
  )
297
+ break
287
298
  elif not interface.status:
288
299
  interface.bootup()
289
300
  interface_initialization_exception = _set_init_function(
@@ -321,6 +332,47 @@ def _execute_multiple_tasks(
321
332
  task_done(future_queue=future_queue)
322
333
 
323
334
 
335
+ def _drain_dead_worker(
336
+ future_queue: queue.Queue,
337
+ alive_workers: Optional[list] = None,
338
+ alive_workers_lock: Optional[Lock] = None,
339
+ ) -> None:
340
+ """Handle a permanently dead worker by recycling or failing its tasks.
341
+
342
+ If healthy workers remain, tasks are recycled back into the shared queue
343
+ so they can be picked up. If all workers are dead, tasks are failed
344
+ immediately with ExecutorlibSocketError. In both cases, the worker's
345
+ shutdown message is consumed to prevent hangs in shutdown().
346
+ """
347
+ if alive_workers is not None and alive_workers_lock is not None:
348
+ with alive_workers_lock:
349
+ if alive_workers[0] > 0:
350
+ alive_workers[0] -= 1
351
+ while True:
352
+ try:
353
+ task_dict = future_queue.get(timeout=1)
354
+ except queue.Empty:
355
+ continue
356
+ if "shutdown" in task_dict and task_dict["shutdown"]:
357
+ task_done(future_queue=future_queue)
358
+ break
359
+ elif "fn" in task_dict and "future" in task_dict:
360
+ if alive_workers is not None and alive_workers_lock is not None:
361
+ with alive_workers_lock:
362
+ has_healthy_workers = alive_workers[0] > 0
363
+ else:
364
+ has_healthy_workers = False
365
+ if has_healthy_workers:
366
+ future_queue.put(task_dict)
367
+ task_done(future_queue=future_queue)
368
+ else:
369
+ f = task_dict.pop("future")
370
+ f.set_exception(
371
+ ExecutorlibSocketError("SocketInterface crashed during execution.")
372
+ )
373
+ task_done(future_queue=future_queue)
374
+
375
+
324
376
  def _set_init_function(
325
377
  interface: SocketInterface,
326
378
  init_function: Optional[Callable] = None,
@@ -238,6 +238,8 @@ def create_pysqa_block_allocation_scheduler(
238
238
  cores_per_worker = executor_kwargs.get("cores", 1)
239
239
  if "cwd" in executor_kwargs and executor_kwargs["cwd"] is not None:
240
240
  executor_kwargs["cwd"] = os.path.abspath(executor_kwargs["cwd"])
241
+ elif cache_directory is not None:
242
+ executor_kwargs["cwd"] = os.path.abspath(cache_directory)
241
243
  if cache_directory is not None:
242
244
  executor_kwargs["cache_directory"] = os.path.abspath(cache_directory)
243
245
  else:
File without changes
File without changes
File without changes