parsl 2024.8.5__py3-none-any.whl → 2024.8.19__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 (48) hide show
  1. parsl/channels/__init__.py +1 -4
  2. parsl/channels/oauth_ssh/oauth_ssh.py +12 -4
  3. parsl/channels/ssh/ssh.py +17 -7
  4. parsl/channels/ssh_il/ssh_il.py +13 -3
  5. parsl/dataflow/dflow.py +1 -1
  6. parsl/executors/high_throughput/executor.py +18 -27
  7. parsl/executors/high_throughput/interchange.py +4 -0
  8. parsl/executors/high_throughput/mpi_executor.py +23 -2
  9. parsl/executors/high_throughput/mpi_prefix_composer.py +5 -4
  10. parsl/executors/taskvine/executor.py +2 -0
  11. parsl/executors/workqueue/executor.py +2 -0
  12. parsl/monitoring/db_manager.py +36 -49
  13. parsl/monitoring/monitoring.py +9 -5
  14. parsl/monitoring/remote.py +4 -4
  15. parsl/monitoring/router.py +16 -18
  16. parsl/providers/__init__.py +0 -4
  17. parsl/providers/ad_hoc/ad_hoc.py +6 -2
  18. parsl/tests/configs/local_adhoc.py +2 -2
  19. parsl/tests/test_htex/test_resource_spec_validation.py +40 -0
  20. parsl/tests/test_htex/test_zmq_binding.py +2 -1
  21. parsl/tests/test_mpi_apps/test_bad_mpi_config.py +29 -14
  22. parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +16 -8
  23. parsl/tests/test_mpi_apps/test_mpiex.py +2 -3
  24. parsl/tests/test_mpi_apps/test_resource_spec.py +39 -41
  25. parsl/tests/test_providers/test_local_provider.py +6 -5
  26. parsl/version.py +1 -1
  27. {parsl-2024.8.5.data → parsl-2024.8.19.data}/scripts/interchange.py +4 -0
  28. {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/METADATA +5 -3
  29. {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/RECORD +36 -47
  30. parsl/configs/ad_hoc.py +0 -38
  31. parsl/tests/configs/ad_hoc_cluster_htex.py +0 -35
  32. parsl/tests/configs/htex_ad_hoc_cluster.py +0 -26
  33. parsl/tests/configs/swan_htex.py +0 -43
  34. parsl/tests/integration/test_channels/test_scp_1.py +0 -45
  35. parsl/tests/integration/test_channels/test_ssh_1.py +0 -40
  36. parsl/tests/integration/test_channels/test_ssh_errors.py +0 -46
  37. parsl/tests/integration/test_channels/test_ssh_file_transport.py +0 -41
  38. parsl/tests/integration/test_channels/test_ssh_interactive.py +0 -24
  39. parsl/tests/manual_tests/test_ad_hoc_htex.py +0 -49
  40. parsl/tests/manual_tests/test_oauth_ssh.py +0 -13
  41. parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +0 -47
  42. {parsl-2024.8.5.data → parsl-2024.8.19.data}/scripts/exec_parsl_function.py +0 -0
  43. {parsl-2024.8.5.data → parsl-2024.8.19.data}/scripts/parsl_coprocess.py +0 -0
  44. {parsl-2024.8.5.data → parsl-2024.8.19.data}/scripts/process_worker_pool.py +0 -0
  45. {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/LICENSE +0 -0
  46. {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/WHEEL +0 -0
  47. {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/entry_points.txt +0 -0
  48. {parsl-2024.8.5.dist-info → parsl-2024.8.19.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ import multiprocessing.queues as mpq
4
5
  import os
5
6
  import pickle
6
- import queue
7
7
  import socket
8
8
  import threading
9
9
  import time
10
10
  from multiprocessing.synchronize import Event
11
- from typing import Optional, Tuple, Union
11
+ from typing import Optional, Tuple
12
12
 
13
+ import typeguard
13
14
  import zmq
14
15
 
15
16
  from parsl.log_utils import set_file_logger
@@ -31,13 +32,12 @@ class MonitoringRouter:
31
32
 
32
33
  monitoring_hub_address: str = "127.0.0.1",
33
34
  logdir: str = ".",
34
- run_id: str,
35
35
  logging_level: int = logging.INFO,
36
36
  atexit_timeout: int = 3, # in seconds
37
- priority_msgs: "queue.Queue[AddressedMonitoringMessage]",
38
- node_msgs: "queue.Queue[AddressedMonitoringMessage]",
39
- block_msgs: "queue.Queue[AddressedMonitoringMessage]",
40
- resource_msgs: "queue.Queue[AddressedMonitoringMessage]",
37
+ priority_msgs: mpq.Queue,
38
+ node_msgs: mpq.Queue,
39
+ block_msgs: mpq.Queue,
40
+ resource_msgs: mpq.Queue,
41
41
  exit_event: Event,
42
42
  ):
43
43
  """ Initializes a monitoring configuration class.
@@ -71,7 +71,6 @@ class MonitoringRouter:
71
71
 
72
72
  self.hub_address = hub_address
73
73
  self.atexit_timeout = atexit_timeout
74
- self.run_id = run_id
75
74
 
76
75
  self.loop_freq = 10.0 # milliseconds
77
76
 
@@ -172,7 +171,6 @@ class MonitoringRouter:
172
171
  msg_0 = (msg, 0)
173
172
 
174
173
  if msg[0] == MessageType.NODE_INFO:
175
- msg[1]['run_id'] = self.run_id
176
174
  self.node_msgs.put(msg_0)
177
175
  elif msg[0] == MessageType.RESOURCE_INFO:
178
176
  self.resource_msgs.put(msg_0)
@@ -205,12 +203,14 @@ class MonitoringRouter:
205
203
 
206
204
 
207
205
  @wrap_with_logs
208
- def router_starter(comm_q: "queue.Queue[Union[Tuple[int, int], str]]",
209
- exception_q: "queue.Queue[Tuple[str, str]]",
210
- priority_msgs: "queue.Queue[AddressedMonitoringMessage]",
211
- node_msgs: "queue.Queue[AddressedMonitoringMessage]",
212
- block_msgs: "queue.Queue[AddressedMonitoringMessage]",
213
- resource_msgs: "queue.Queue[AddressedMonitoringMessage]",
206
+ @typeguard.typechecked
207
+ def router_starter(*,
208
+ comm_q: mpq.Queue,
209
+ exception_q: mpq.Queue,
210
+ priority_msgs: mpq.Queue,
211
+ node_msgs: mpq.Queue,
212
+ block_msgs: mpq.Queue,
213
+ resource_msgs: mpq.Queue,
214
214
  exit_event: Event,
215
215
 
216
216
  hub_address: str,
@@ -218,8 +218,7 @@ def router_starter(comm_q: "queue.Queue[Union[Tuple[int, int], str]]",
218
218
  zmq_port_range: Tuple[int, int],
219
219
 
220
220
  logdir: str,
221
- logging_level: int,
222
- run_id: str) -> None:
221
+ logging_level: int) -> None:
223
222
  setproctitle("parsl: monitoring router")
224
223
  try:
225
224
  router = MonitoringRouter(hub_address=hub_address,
@@ -227,7 +226,6 @@ def router_starter(comm_q: "queue.Queue[Union[Tuple[int, int], str]]",
227
226
  zmq_port_range=zmq_port_range,
228
227
  logdir=logdir,
229
228
  logging_level=logging_level,
230
- run_id=run_id,
231
229
  priority_msgs=priority_msgs,
232
230
  node_msgs=node_msgs,
233
231
  block_msgs=block_msgs,
@@ -1,6 +1,3 @@
1
- # Workstation Provider
2
- from parsl.providers.ad_hoc.ad_hoc import AdHocProvider
3
-
4
1
  # Cloud Providers
5
2
  from parsl.providers.aws.aws import AWSProvider
6
3
  from parsl.providers.azure.azure import AzureProvider
@@ -24,7 +21,6 @@ __all__ = ['LocalProvider',
24
21
  'SlurmProvider',
25
22
  'TorqueProvider',
26
23
  'LSFProvider',
27
- 'AdHocProvider',
28
24
  'PBSProProvider',
29
25
  'AWSProvider',
30
26
  'GoogleCloudProvider',
@@ -12,8 +12,12 @@ from parsl.utils import RepresentationMixin
12
12
  logger = logging.getLogger(__name__)
13
13
 
14
14
 
15
- class AdHocProvider(ExecutionProvider, RepresentationMixin):
16
- """ Ad-hoc execution provider
15
+ class DeprecatedAdHocProvider(ExecutionProvider, RepresentationMixin):
16
+ """ Deprecated ad-hoc execution provider
17
+
18
+ The (former) AdHocProvider is deprecated. See
19
+ `issue #3515 <https://github.com/Parsl/parsl/issues/3515>`_
20
+ for further discussion.
17
21
 
18
22
  This provider is used to provision execution resources over one or more ad hoc nodes
19
23
  that are each accessible over a Channel (say, ssh) but otherwise lack a cluster scheduler.
@@ -1,7 +1,7 @@
1
1
  from parsl.channels import LocalChannel
2
2
  from parsl.config import Config
3
3
  from parsl.executors import HighThroughputExecutor
4
- from parsl.providers import AdHocProvider
4
+ from parsl.providers.ad_hoc.ad_hoc import DeprecatedAdHocProvider
5
5
 
6
6
 
7
7
  def fresh_config():
@@ -10,7 +10,7 @@ def fresh_config():
10
10
  HighThroughputExecutor(
11
11
  label='AdHoc',
12
12
  encrypted=True,
13
- provider=AdHocProvider(
13
+ provider=DeprecatedAdHocProvider(
14
14
  channels=[LocalChannel(), LocalChannel()]
15
15
  )
16
16
  )
@@ -0,0 +1,40 @@
1
+ import queue
2
+ from unittest import mock
3
+
4
+ import pytest
5
+
6
+ from parsl.executors import HighThroughputExecutor
7
+ from parsl.executors.high_throughput.mpi_prefix_composer import (
8
+ InvalidResourceSpecification,
9
+ )
10
+
11
+
12
+ def double(x):
13
+ return x * 2
14
+
15
+
16
+ @pytest.mark.local
17
+ def test_submit_calls_validate():
18
+
19
+ htex = HighThroughputExecutor()
20
+ htex.outgoing_q = mock.Mock(spec=queue.Queue)
21
+ htex.validate_resource_spec = mock.Mock(spec=htex.validate_resource_spec)
22
+
23
+ res_spec = {}
24
+ htex.submit(double, res_spec, (5,), {})
25
+ htex.validate_resource_spec.assert_called()
26
+
27
+
28
+ @pytest.mark.local
29
+ def test_resource_spec_validation():
30
+ htex = HighThroughputExecutor()
31
+ ret_val = htex.validate_resource_spec({})
32
+ assert ret_val is None
33
+
34
+
35
+ @pytest.mark.local
36
+ def test_resource_spec_validation_bad_keys():
37
+ htex = HighThroughputExecutor()
38
+
39
+ with pytest.raises(InvalidResourceSpecification):
40
+ htex.validate_resource_spec({"num_nodes": 2})
@@ -25,7 +25,8 @@ def make_interchange(*, interchange_address: Optional[str], cert_dir: Optional[s
25
25
  logdir=".",
26
26
  logging_level=logging.INFO,
27
27
  manager_selector=RandomManagerSelector(),
28
- poll_period=10)
28
+ poll_period=10,
29
+ run_id="test_run_id")
29
30
 
30
31
 
31
32
  @pytest.fixture
@@ -1,33 +1,48 @@
1
1
  import pytest
2
2
 
3
3
  from parsl import Config
4
- from parsl.executors import HighThroughputExecutor
4
+ from parsl.executors import MPIExecutor
5
5
  from parsl.launchers import AprunLauncher, SimpleLauncher, SrunLauncher
6
6
  from parsl.providers import SlurmProvider
7
7
 
8
8
 
9
9
  @pytest.mark.local
10
- def test_bad_launcher_with_mpi_mode():
11
- """AssertionError if a launcher other than SimpleLauncher is supplied"""
10
+ def test_bad_launcher():
11
+ """TypeError if a launcher other than SimpleLauncher is supplied"""
12
12
 
13
13
  for launcher in [SrunLauncher(), AprunLauncher()]:
14
- with pytest.raises(AssertionError):
14
+ with pytest.raises(TypeError):
15
15
  Config(executors=[
16
- HighThroughputExecutor(
17
- enable_mpi_mode=True,
16
+ MPIExecutor(
18
17
  provider=SlurmProvider(launcher=launcher),
19
18
  )
20
19
  ])
21
20
 
22
21
 
23
22
  @pytest.mark.local
24
- def test_correct_launcher_with_mpi_mode():
23
+ def test_bad_mpi_launcher():
24
+ """ValueError if an unsupported mpi_launcher is specified"""
25
+
26
+ with pytest.raises(ValueError):
27
+ Config(executors=[
28
+ MPIExecutor(
29
+ mpi_launcher="bad_launcher",
30
+ provider=SlurmProvider(launcher=SimpleLauncher()),
31
+ )
32
+ ])
33
+
34
+
35
+ @pytest.mark.local
36
+ @pytest.mark.parametrize(
37
+ "mpi_launcher",
38
+ ["srun", "aprun", "mpiexec"]
39
+ )
40
+ def test_correct_launcher_with_mpi_mode(mpi_launcher: str):
25
41
  """Confirm that SimpleLauncher works with mpi_mode"""
26
42
 
27
- config = Config(executors=[
28
- HighThroughputExecutor(
29
- enable_mpi_mode=True,
30
- provider=SlurmProvider(launcher=SimpleLauncher()),
31
- )
32
- ])
33
- assert isinstance(config.executors[0].provider.launcher, SimpleLauncher)
43
+ executor = MPIExecutor(
44
+ mpi_launcher=mpi_launcher,
45
+ provider=SlurmProvider(launcher=SimpleLauncher()),
46
+ )
47
+
48
+ assert isinstance(executor.provider.launcher, SimpleLauncher)
@@ -6,26 +6,34 @@ from typing import Dict
6
6
  import pytest
7
7
 
8
8
  import parsl
9
- from parsl import bash_app, python_app
9
+ from parsl import Config, bash_app, python_app
10
+ from parsl.executors import MPIExecutor
10
11
  from parsl.executors.high_throughput.mpi_prefix_composer import (
11
12
  MissingResourceSpecification,
12
13
  )
13
- from parsl.tests.configs.htex_local import fresh_config
14
+ from parsl.launchers import SimpleLauncher
15
+ from parsl.providers import LocalProvider
14
16
 
15
17
  EXECUTOR_LABEL = "MPI_TEST"
16
18
 
17
19
 
18
20
  def local_setup():
19
- config = fresh_config()
20
- config.executors[0].label = EXECUTOR_LABEL
21
- config.executors[0].max_workers_per_node = 2
22
- config.executors[0].enable_mpi_mode = True
23
- config.executors[0].mpi_launcher = "mpiexec"
24
21
 
25
22
  cwd = os.path.abspath(os.path.dirname(__file__))
26
23
  pbs_nodefile = os.path.join(cwd, "mocks", "pbs_nodefile")
27
24
 
28
- config.executors[0].provider.worker_init = f"export PBS_NODEFILE={pbs_nodefile}"
25
+ config = Config(
26
+ executors=[
27
+ MPIExecutor(
28
+ label=EXECUTOR_LABEL,
29
+ max_workers_per_block=2,
30
+ mpi_launcher="mpiexec",
31
+ provider=LocalProvider(
32
+ worker_init=f"export PBS_NODEFILE={pbs_nodefile}",
33
+ launcher=SimpleLauncher()
34
+ )
35
+ )
36
+ ])
29
37
 
30
38
  parsl.load(config)
31
39
 
@@ -4,7 +4,6 @@ from pathlib import Path
4
4
 
5
5
  import pytest
6
6
 
7
- import parsl
8
7
  from parsl import Config, HighThroughputExecutor
9
8
  from parsl.executors.high_throughput.mpi_executor import MPIExecutor
10
9
  from parsl.launchers import SimpleLauncher
@@ -42,8 +41,8 @@ def test_docstring():
42
41
  def test_init():
43
42
  """Ensure all relevant kwargs are copied over from HTEx"""
44
43
 
45
- new_kwargs = {'max_workers_per_block'}
46
- excluded_kwargs = {'available_accelerators', 'enable_mpi_mode', 'cores_per_worker', 'max_workers_per_node',
44
+ new_kwargs = {'max_workers_per_block', 'mpi_launcher'}
45
+ excluded_kwargs = {'available_accelerators', 'cores_per_worker', 'max_workers_per_node',
47
46
  'mem_per_worker', 'cpu_affinity', 'max_workers', 'manager_selector'}
48
47
 
49
48
  # Get the kwargs from both HTEx and MPIEx
@@ -1,18 +1,20 @@
1
1
  import contextlib
2
2
  import logging
3
3
  import os
4
+ import queue
4
5
  import typing
5
6
  import unittest
6
7
  from typing import Dict
8
+ from unittest import mock
7
9
 
8
10
  import pytest
9
11
 
10
- import parsl
11
12
  from parsl.app.app import python_app
13
+ from parsl.executors.high_throughput.executor import HighThroughputExecutor
14
+ from parsl.executors.high_throughput.mpi_executor import MPIExecutor
12
15
  from parsl.executors.high_throughput.mpi_prefix_composer import (
13
16
  InvalidResourceSpecification,
14
17
  MissingResourceSpecification,
15
- validate_resource_spec,
16
18
  )
17
19
  from parsl.executors.high_throughput.mpi_resource_management import (
18
20
  get_nodes_in_batchjob,
@@ -20,6 +22,8 @@ from parsl.executors.high_throughput.mpi_resource_management import (
20
22
  get_slurm_hosts_list,
21
23
  identify_scheduler,
22
24
  )
25
+ from parsl.launchers import SimpleLauncher
26
+ from parsl.providers import LocalProvider
23
27
  from parsl.tests.configs.htex_local import fresh_config
24
28
 
25
29
  EXECUTOR_LABEL = "MPI_TEST"
@@ -48,23 +52,6 @@ def get_env_vars(parsl_resource_specification: Dict = {}) -> Dict:
48
52
  return parsl_vars
49
53
 
50
54
 
51
- @pytest.mark.local
52
- def test_resource_spec_env_vars():
53
- resource_spec = {
54
- "num_nodes": 4,
55
- "ranks_per_node": 2,
56
- }
57
-
58
- assert double(5).result() == 10
59
-
60
- future = get_env_vars(parsl_resource_specification=resource_spec)
61
-
62
- result = future.result()
63
- assert isinstance(result, Dict)
64
- assert result["PARSL_NUM_NODES"] == str(resource_spec["num_nodes"])
65
- assert result["PARSL_RANKS_PER_NODE"] == str(resource_spec["ranks_per_node"])
66
-
67
-
68
55
  @pytest.mark.local
69
56
  @unittest.mock.patch("subprocess.check_output", return_value=b"c203-031\nc203-032\n")
70
57
  def test_slurm_mocked_mpi_fetch(subprocess_check):
@@ -83,16 +70,6 @@ def add_to_path(path: os.PathLike) -> typing.Generator[None, None, None]:
83
70
  os.environ["PATH"] = old_path
84
71
 
85
72
 
86
- @pytest.mark.local
87
- @pytest.mark.skip
88
- def test_slurm_mpi_fetch():
89
- logging.warning(f"Current pwd : {os.path.dirname(__file__)}")
90
- with add_to_path(os.path.dirname(__file__)):
91
- logging.warning(f"PATH: {os.environ['PATH']}")
92
- nodeinfo = get_slurm_hosts_list()
93
- logging.warning(f"Got : {nodeinfo}")
94
-
95
-
96
73
  @contextlib.contextmanager
97
74
  def mock_pbs_nodefile(nodefile: str = "pbs_nodefile") -> typing.Generator[None, None, None]:
98
75
  cwd = os.path.abspath(os.path.dirname(__file__))
@@ -122,22 +99,43 @@ def test_top_level():
122
99
 
123
100
  @pytest.mark.local
124
101
  @pytest.mark.parametrize(
125
- "resource_spec, is_mpi_enabled, exception",
102
+ "resource_spec, exception",
126
103
  (
127
- ({"num_nodes": 2, "ranks_per_node": 1}, False, None),
128
- ({"launcher_options": "--debug_foo"}, False, None),
129
- ({"num_nodes": 2, "BAD_OPT": 1}, False, InvalidResourceSpecification),
130
- ({}, False, None),
131
- ({"num_nodes": 2, "ranks_per_node": 1}, True, None),
132
- ({"launcher_options": "--debug_foo"}, True, None),
133
- ({"num_nodes": 2, "BAD_OPT": 1}, True, InvalidResourceSpecification),
134
- ({}, True, MissingResourceSpecification),
104
+
105
+ ({"num_nodes": 2, "ranks_per_node": 1}, None),
106
+ ({"launcher_options": "--debug_foo"}, None),
107
+ ({"num_nodes": 2, "BAD_OPT": 1}, InvalidResourceSpecification),
108
+ ({}, MissingResourceSpecification),
135
109
  )
136
110
  )
137
- def test_resource_spec(resource_spec: Dict, is_mpi_enabled: bool, exception):
111
+ def test_mpi_resource_spec(resource_spec: Dict, exception):
112
+ """Test validation of resource_specification in MPIExecutor"""
113
+
114
+ mpi_ex = MPIExecutor(provider=LocalProvider(launcher=SimpleLauncher()))
115
+ mpi_ex.outgoing_q = mock.Mock(spec=queue.Queue)
116
+
138
117
  if exception:
139
118
  with pytest.raises(exception):
140
- validate_resource_spec(resource_spec, is_mpi_enabled)
119
+ mpi_ex.validate_resource_spec(resource_spec)
141
120
  else:
142
- result = validate_resource_spec(resource_spec, is_mpi_enabled)
121
+ result = mpi_ex.validate_resource_spec(resource_spec)
143
122
  assert result is None
123
+
124
+
125
+ @pytest.mark.local
126
+ @pytest.mark.parametrize(
127
+ "resource_spec",
128
+ (
129
+ {"num_nodes": 2, "ranks_per_node": 1},
130
+ {"launcher_options": "--debug_foo"},
131
+ {"BAD_OPT": 1},
132
+ )
133
+ )
134
+ def test_mpi_resource_spec_passed_to_htex(resource_spec: dict):
135
+ """HTEX should reject every resource_spec"""
136
+
137
+ htex = HighThroughputExecutor()
138
+ htex.outgoing_q = mock.Mock(spec=queue.Queue)
139
+
140
+ with pytest.raises(InvalidResourceSpecification):
141
+ htex.validate_resource_spec(resource_spec)
@@ -11,7 +11,8 @@ import time
11
11
 
12
12
  import pytest
13
13
 
14
- from parsl.channels import LocalChannel, SSHChannel
14
+ from parsl.channels import LocalChannel
15
+ from parsl.channels.ssh.ssh import DeprecatedSSHChannel
15
16
  from parsl.jobs.states import JobState
16
17
  from parsl.launchers import SingleNodeLauncher
17
18
  from parsl.providers import LocalProvider
@@ -92,10 +93,10 @@ def test_ssh_channel():
92
93
  # already exist, so create it here.
93
94
  pathlib.Path('{}/known.hosts'.format(config_dir)).touch(mode=0o600)
94
95
  script_dir = tempfile.mkdtemp()
95
- channel = SSHChannel('127.0.0.1', port=server_port,
96
- script_dir=remote_script_dir,
97
- host_keys_filename='{}/known.hosts'.format(config_dir),
98
- key_filename=priv_key)
96
+ channel = DeprecatedSSHChannel('127.0.0.1', port=server_port,
97
+ script_dir=remote_script_dir,
98
+ host_keys_filename='{}/known.hosts'.format(config_dir),
99
+ key_filename=priv_key)
99
100
  try:
100
101
  p = LocalProvider(channel=channel,
101
102
  launcher=SingleNodeLauncher(debug=False))
parsl/version.py CHANGED
@@ -3,4 +3,4 @@
3
3
  Year.Month.Day[alpha/beta/..]
4
4
  Alphas will be numbered like this -> 2024.12.10a0
5
5
  """
6
- VERSION = '2024.08.05'
6
+ VERSION = '2024.08.19'
@@ -55,6 +55,7 @@ class Interchange:
55
55
  poll_period: int,
56
56
  cert_dir: Optional[str],
57
57
  manager_selector: ManagerSelector,
58
+ run_id: str,
58
59
  ) -> None:
59
60
  """
60
61
  Parameters
@@ -125,6 +126,8 @@ class Interchange:
125
126
  self.command_channel.connect("tcp://{}:{}".format(client_address, client_ports[2]))
126
127
  logger.info("Connected to client")
127
128
 
129
+ self.run_id = run_id
130
+
128
131
  self.hub_address = hub_address
129
132
  self.hub_zmq_port = hub_zmq_port
130
133
 
@@ -227,6 +230,7 @@ class Interchange:
227
230
  d: Dict = cast(Dict, manager.copy())
228
231
  d['timestamp'] = datetime.datetime.now()
229
232
  d['last_heartbeat'] = datetime.datetime.fromtimestamp(d['last_heartbeat'])
233
+ d['run_id'] = self.run_id
230
234
 
231
235
  monitoring_radio.send((MessageType.NODE_INFO, d))
232
236
 
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: parsl
3
- Version: 2024.8.5
3
+ Version: 2024.8.19
4
4
  Summary: Simple data dependent workflows in Python
5
5
  Home-page: https://github.com/Parsl/parsl
6
- Download-URL: https://github.com/Parsl/parsl/archive/2024.08.05.tar.gz
6
+ Download-URL: https://github.com/Parsl/parsl/archive/2024.08.19.tar.gz
7
7
  Author: The Parsl Team
8
8
  Author-email: parsl@googlegroups.com
9
9
  License: Apache 2.0
@@ -25,7 +25,6 @@ Requires-Dist: globus-sdk
25
25
  Requires-Dist: dill
26
26
  Requires-Dist: tblib
27
27
  Requires-Dist: requests
28
- Requires-Dist: paramiko
29
28
  Requires-Dist: psutil>=5.5.1
30
29
  Requires-Dist: setproctitle
31
30
  Requires-Dist: filelock<4,>=3.13
@@ -57,6 +56,7 @@ Requires-Dist: jsonschema; extra == "all"
57
56
  Requires-Dist: proxystore; extra == "all"
58
57
  Requires-Dist: radical.pilot==1.60; extra == "all"
59
58
  Requires-Dist: radical.utils==1.60; extra == "all"
59
+ Requires-Dist: paramiko; extra == "all"
60
60
  Provides-Extra: aws
61
61
  Requires-Dist: boto3; extra == "aws"
62
62
  Provides-Extra: azure
@@ -87,6 +87,8 @@ Requires-Dist: proxystore; extra == "proxystore"
87
87
  Provides-Extra: radical-pilot
88
88
  Requires-Dist: radical.pilot==1.60; extra == "radical-pilot"
89
89
  Requires-Dist: radical.utils==1.60; extra == "radical-pilot"
90
+ Provides-Extra: ssh
91
+ Requires-Dist: paramiko; extra == "ssh"
90
92
  Provides-Extra: visualization
91
93
  Requires-Dist: pydot; extra == "visualization"
92
94
  Requires-Dist: networkx<2.6,>=2.5; extra == "visualization"