parsl 2024.10.21__py3-none-any.whl → 2024.10.28__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.
- parsl/channels/base.py +0 -11
- parsl/channels/errors.py +0 -17
- parsl/channels/local/local.py +3 -16
- parsl/channels/ssh/ssh.py +0 -11
- parsl/dataflow/dflow.py +1 -1
- parsl/executors/high_throughput/interchange.py +8 -5
- parsl/executors/high_throughput/process_worker_pool.py +0 -8
- parsl/monitoring/db_manager.py +1 -1
- parsl/monitoring/monitoring.py +5 -5
- parsl/monitoring/radios.py +2 -2
- parsl/monitoring/router.py +4 -7
- parsl/monitoring/types.py +3 -6
- parsl/providers/base.py +0 -16
- parsl/tests/{integration/test_channels → test_channels}/test_local_channel.py +4 -8
- parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py +92 -0
- parsl/tests/test_serialization/test_3495_deserialize_managerlost.py +1 -1
- parsl/version.py +1 -1
- {parsl-2024.10.21.data → parsl-2024.10.28.data}/scripts/interchange.py +8 -5
- {parsl-2024.10.21.data → parsl-2024.10.28.data}/scripts/process_worker_pool.py +0 -8
- {parsl-2024.10.21.dist-info → parsl-2024.10.28.dist-info}/METADATA +2 -2
- {parsl-2024.10.21.dist-info → parsl-2024.10.28.dist-info}/RECORD +27 -27
- parsl/tests/integration/test_channels/test_channels.py +0 -17
- {parsl-2024.10.21.data → parsl-2024.10.28.data}/scripts/exec_parsl_function.py +0 -0
- {parsl-2024.10.21.data → parsl-2024.10.28.data}/scripts/parsl_coprocess.py +0 -0
- {parsl-2024.10.21.dist-info → parsl-2024.10.28.dist-info}/LICENSE +0 -0
- {parsl-2024.10.21.dist-info → parsl-2024.10.28.dist-info}/WHEEL +0 -0
- {parsl-2024.10.21.dist-info → parsl-2024.10.28.dist-info}/entry_points.txt +0 -0
- {parsl-2024.10.21.dist-info → parsl-2024.10.28.dist-info}/top_level.txt +0 -0
parsl/channels/base.py
CHANGED
@@ -120,14 +120,3 @@ class Channel(metaclass=ABCMeta):
|
|
120
120
|
Path of directory to check.
|
121
121
|
"""
|
122
122
|
pass
|
123
|
-
|
124
|
-
@abstractmethod
|
125
|
-
def abspath(self, path: str) -> str:
|
126
|
-
"""Return the absolute path.
|
127
|
-
|
128
|
-
Parameters
|
129
|
-
----------
|
130
|
-
path : str
|
131
|
-
Path for which the absolute path will be returned.
|
132
|
-
"""
|
133
|
-
pass
|
parsl/channels/errors.py
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
''' Exceptions raise by Apps.
|
2
2
|
'''
|
3
|
-
from typing import Optional
|
4
|
-
|
5
3
|
from parsl.errors import ParslError
|
6
4
|
|
7
5
|
|
@@ -60,21 +58,6 @@ class BadPermsScriptPath(ChannelError):
|
|
60
58
|
super().__init__("User does not have permissions to access the script_dir", e, hostname)
|
61
59
|
|
62
60
|
|
63
|
-
class FileExists(ChannelError):
|
64
|
-
''' Push or pull of file over channel fails since a file of the name already
|
65
|
-
exists on the destination.
|
66
|
-
|
67
|
-
Contains:
|
68
|
-
reason(string)
|
69
|
-
e (paramiko exception object)
|
70
|
-
hostname (string)
|
71
|
-
'''
|
72
|
-
|
73
|
-
def __init__(self, e: Exception, hostname: str, filename: Optional[str] = None) -> None:
|
74
|
-
super().__init__("File name collision in channel transport phase: {}".format(filename),
|
75
|
-
e, hostname)
|
76
|
-
|
77
|
-
|
78
61
|
class AuthException(ChannelError):
|
79
62
|
''' An error raised during execution of an app.
|
80
63
|
What this exception contains depends entirely on context
|
parsl/channels/local/local.py
CHANGED
@@ -37,19 +37,16 @@ class LocalChannel(Channel, RepresentationMixin):
|
|
37
37
|
|
38
38
|
Args:
|
39
39
|
- cmd (string) : Commandline string to execute
|
40
|
-
- walltime (int) : walltime in seconds
|
40
|
+
- walltime (int) : walltime in seconds
|
41
41
|
|
42
42
|
Kwargs:
|
43
43
|
- envs (dict) : Dictionary of env variables. This will be used
|
44
44
|
to override the envs set at channel initialization.
|
45
45
|
|
46
46
|
Returns:
|
47
|
-
- retcode : Return code from the execution
|
47
|
+
- retcode : Return code from the execution
|
48
48
|
- stdout : stdout string
|
49
49
|
- stderr : stderr string
|
50
|
-
|
51
|
-
Raises:
|
52
|
-
None.
|
53
50
|
'''
|
54
51
|
current_env = copy.deepcopy(self._envs)
|
55
52
|
current_env.update(envs)
|
@@ -145,16 +142,6 @@ class LocalChannel(Channel, RepresentationMixin):
|
|
145
142
|
|
146
143
|
return os.makedirs(path, mode, exist_ok)
|
147
144
|
|
148
|
-
def abspath(self, path):
|
149
|
-
"""Return the absolute path.
|
150
|
-
|
151
|
-
Parameters
|
152
|
-
----------
|
153
|
-
path : str
|
154
|
-
Path for which the absolute path will be returned.
|
155
|
-
"""
|
156
|
-
return os.path.abspath(path)
|
157
|
-
|
158
145
|
@property
|
159
146
|
def script_dir(self):
|
160
147
|
return self._script_dir
|
@@ -162,5 +149,5 @@ class LocalChannel(Channel, RepresentationMixin):
|
|
162
149
|
@script_dir.setter
|
163
150
|
def script_dir(self, value):
|
164
151
|
if value is not None:
|
165
|
-
value =
|
152
|
+
value = os.path.abspath(value)
|
166
153
|
self._script_dir = value
|
parsl/channels/ssh/ssh.py
CHANGED
@@ -214,7 +214,6 @@ class DeprecatedSSHChannel(Channel, RepresentationMixin):
|
|
214
214
|
- str: Local path to file
|
215
215
|
|
216
216
|
Raises:
|
217
|
-
- FileExists : Name collision at local directory.
|
218
217
|
- FileCopyException : FileCopy failed.
|
219
218
|
'''
|
220
219
|
|
@@ -287,16 +286,6 @@ class DeprecatedSSHChannel(Channel, RepresentationMixin):
|
|
287
286
|
self.execute_wait('mkdir -p {}'.format(path))
|
288
287
|
self._valid_sftp_client().chmod(path, mode)
|
289
288
|
|
290
|
-
def abspath(self, path):
|
291
|
-
"""Return the absolute path on the remote side.
|
292
|
-
|
293
|
-
Parameters
|
294
|
-
----------
|
295
|
-
path : str
|
296
|
-
Path for which the absolute path will be returned.
|
297
|
-
"""
|
298
|
-
return self._valid_sftp_client().normalize(path)
|
299
|
-
|
300
289
|
@property
|
301
290
|
def script_dir(self):
|
302
291
|
return self._script_dir
|
parsl/dataflow/dflow.py
CHANGED
@@ -66,7 +66,7 @@ class Interchange:
|
|
66
66
|
If specified the interchange will only listen on this address for connections from workers
|
67
67
|
else, it binds to all addresses.
|
68
68
|
|
69
|
-
client_ports :
|
69
|
+
client_ports : tuple(int, int, int)
|
70
70
|
The ports at which the client can be reached
|
71
71
|
|
72
72
|
worker_ports : tuple(int, int)
|
@@ -104,7 +104,6 @@ class Interchange:
|
|
104
104
|
os.makedirs(self.logdir, exist_ok=True)
|
105
105
|
|
106
106
|
start_file_logger("{}/interchange.log".format(self.logdir), level=logging_level)
|
107
|
-
logger.propagate = False
|
108
107
|
logger.debug("Initializing Interchange process")
|
109
108
|
|
110
109
|
self.client_address = client_address
|
@@ -437,9 +436,13 @@ class Interchange:
|
|
437
436
|
logger.info(f"Manager {manager_id!r} has compatible Parsl version {msg['parsl_v']}")
|
438
437
|
logger.info(f"Manager {manager_id!r} has compatible Python version {msg['python_v'].rsplit('.', 1)[0]}")
|
439
438
|
elif msg['type'] == 'heartbeat':
|
440
|
-
|
441
|
-
|
442
|
-
|
439
|
+
manager = self._ready_managers.get(manager_id)
|
440
|
+
if manager:
|
441
|
+
manager['last_heartbeat'] = time.time()
|
442
|
+
logger.debug("Manager %r sent heartbeat via tasks connection", manager_id)
|
443
|
+
self.task_outgoing.send_multipart([manager_id, b'', PKL_HEARTBEAT_CODE])
|
444
|
+
else:
|
445
|
+
logger.warning("Received heartbeat via tasks connection for not-registered manager %r", manager_id)
|
443
446
|
elif msg['type'] == 'drain':
|
444
447
|
self._ready_managers[manager_id]['draining'] = True
|
445
448
|
logger.debug("Manager %r requested drain", manager_id)
|
@@ -650,14 +650,6 @@ def worker(
|
|
650
650
|
debug: bool,
|
651
651
|
mpi_launcher: str,
|
652
652
|
):
|
653
|
-
"""
|
654
|
-
|
655
|
-
Put request token into queue
|
656
|
-
Get task from task_queue
|
657
|
-
Pop request from queue
|
658
|
-
Put result into result_queue
|
659
|
-
"""
|
660
|
-
|
661
653
|
# override the global logger inherited from the __main__ process (which
|
662
654
|
# usually logs to manager.log) with one specific to this worker.
|
663
655
|
global logger
|
parsl/monitoring/db_manager.py
CHANGED
@@ -556,7 +556,7 @@ class DatabaseManager:
|
|
556
556
|
logger.debug("Checking STOP conditions: kill event: %s, queue has entries: %s",
|
557
557
|
kill_event.is_set(), logs_queue.qsize() != 0)
|
558
558
|
try:
|
559
|
-
x
|
559
|
+
x = logs_queue.get(timeout=0.1)
|
560
560
|
except queue.Empty:
|
561
561
|
continue
|
562
562
|
else:
|
parsl/monitoring/monitoring.py
CHANGED
@@ -16,7 +16,7 @@ from parsl.monitoring.errors import MonitoringHubStartError
|
|
16
16
|
from parsl.monitoring.message_type import MessageType
|
17
17
|
from parsl.monitoring.radios import MultiprocessingQueueRadioSender
|
18
18
|
from parsl.monitoring.router import router_starter
|
19
|
-
from parsl.monitoring.types import
|
19
|
+
from parsl.monitoring.types import TaggedMonitoringMessage
|
20
20
|
from parsl.multiprocessing import ForkProcess, SizedQueue
|
21
21
|
from parsl.process_loggers import wrap_with_logs
|
22
22
|
from parsl.serialize import deserialize
|
@@ -138,7 +138,7 @@ class MonitoringHub(RepresentationMixin):
|
|
138
138
|
self.exception_q: Queue[Tuple[str, str]]
|
139
139
|
self.exception_q = SizedQueue(maxsize=10)
|
140
140
|
|
141
|
-
self.resource_msgs: Queue[Union[
|
141
|
+
self.resource_msgs: Queue[Union[TaggedMonitoringMessage, Literal["STOP"]]]
|
142
142
|
self.resource_msgs = SizedQueue()
|
143
143
|
|
144
144
|
self.router_exit_event: ms.Event
|
@@ -237,7 +237,7 @@ class MonitoringHub(RepresentationMixin):
|
|
237
237
|
logger.debug("Finished waiting for router termination")
|
238
238
|
if len(exception_msgs) == 0:
|
239
239
|
logger.debug("Sending STOP to DBM")
|
240
|
-
self.resource_msgs.put(
|
240
|
+
self.resource_msgs.put("STOP")
|
241
241
|
else:
|
242
242
|
logger.debug("Not sending STOP to DBM, because there were DBM exceptions")
|
243
243
|
logger.debug("Waiting for DB termination")
|
@@ -261,7 +261,7 @@ class MonitoringHub(RepresentationMixin):
|
|
261
261
|
|
262
262
|
|
263
263
|
@wrap_with_logs
|
264
|
-
def filesystem_receiver(logdir: str, q: "queue.Queue[
|
264
|
+
def filesystem_receiver(logdir: str, q: "queue.Queue[TaggedMonitoringMessage]", run_dir: str) -> None:
|
265
265
|
logger = set_file_logger("{}/monitoring_filesystem_radio.log".format(logdir),
|
266
266
|
name="monitoring_filesystem_radio",
|
267
267
|
level=logging.INFO)
|
@@ -288,7 +288,7 @@ def filesystem_receiver(logdir: str, q: "queue.Queue[AddressedMonitoringMessage]
|
|
288
288
|
message = deserialize(f.read())
|
289
289
|
logger.debug(f"Message received is: {message}")
|
290
290
|
assert isinstance(message, tuple)
|
291
|
-
q.put(cast(
|
291
|
+
q.put(cast(TaggedMonitoringMessage, message))
|
292
292
|
os.remove(full_path_filename)
|
293
293
|
except Exception:
|
294
294
|
logger.exception(f"Exception processing {filename} - probably will be retried next iteration")
|
parsl/monitoring/radios.py
CHANGED
@@ -58,7 +58,7 @@ class FilesystemRadioSender(MonitoringRadioSender):
|
|
58
58
|
|
59
59
|
tmp_filename = f"{self.tmp_path}/{unique_id}"
|
60
60
|
new_filename = f"{self.new_path}/{unique_id}"
|
61
|
-
buffer =
|
61
|
+
buffer = message
|
62
62
|
|
63
63
|
# this will write the message out then atomically
|
64
64
|
# move it into new/, so that a partially written
|
@@ -187,7 +187,7 @@ class MultiprocessingQueueRadioSender(MonitoringRadioSender):
|
|
187
187
|
self.queue = queue
|
188
188
|
|
189
189
|
def send(self, message: object) -> None:
|
190
|
-
self.queue.put(
|
190
|
+
self.queue.put(message)
|
191
191
|
|
192
192
|
|
193
193
|
class ZMQRadioSender(MonitoringRadioSender):
|
parsl/monitoring/router.py
CHANGED
@@ -14,7 +14,7 @@ import typeguard
|
|
14
14
|
import zmq
|
15
15
|
|
16
16
|
from parsl.log_utils import set_file_logger
|
17
|
-
from parsl.monitoring.types import
|
17
|
+
from parsl.monitoring.types import TaggedMonitoringMessage
|
18
18
|
from parsl.process_loggers import wrap_with_logs
|
19
19
|
from parsl.utils import setproctitle
|
20
20
|
|
@@ -125,7 +125,7 @@ class MonitoringRouter:
|
|
125
125
|
data, addr = self.udp_sock.recvfrom(2048)
|
126
126
|
resource_msg = pickle.loads(data)
|
127
127
|
self.logger.debug("Got UDP Message from {}: {}".format(addr, resource_msg))
|
128
|
-
self.resource_msgs.put(
|
128
|
+
self.resource_msgs.put(resource_msg)
|
129
129
|
except socket.timeout:
|
130
130
|
pass
|
131
131
|
|
@@ -136,7 +136,7 @@ class MonitoringRouter:
|
|
136
136
|
data, addr = self.udp_sock.recvfrom(2048)
|
137
137
|
msg = pickle.loads(data)
|
138
138
|
self.logger.debug("Got UDP Message from {}: {}".format(addr, msg))
|
139
|
-
self.resource_msgs.put(
|
139
|
+
self.resource_msgs.put(msg)
|
140
140
|
last_msg_received_time = time.time()
|
141
141
|
except socket.timeout:
|
142
142
|
pass
|
@@ -160,10 +160,7 @@ class MonitoringRouter:
|
|
160
160
|
assert len(msg) >= 1, "ZMQ Receiver expects tuples of length at least 1, got {}".format(msg)
|
161
161
|
assert len(msg) == 2, "ZMQ Receiver expects message tuples of exactly length 2, got {}".format(msg)
|
162
162
|
|
163
|
-
|
164
|
-
msg_0 = (msg, 0)
|
165
|
-
|
166
|
-
self.resource_msgs.put(msg_0)
|
163
|
+
self.resource_msgs.put(msg)
|
167
164
|
except zmq.Again:
|
168
165
|
pass
|
169
166
|
except Exception:
|
parsl/monitoring/types.py
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
from typing import Any, Dict, Tuple
|
1
|
+
from typing import Any, Dict, Tuple
|
2
2
|
|
3
3
|
from typing_extensions import TypeAlias
|
4
4
|
|
5
5
|
from parsl.monitoring.message_type import MessageType
|
6
6
|
|
7
|
-
# A
|
8
|
-
#
|
9
|
-
# a TaggedMonitoringMessage, and then that can be further tagged with
|
10
|
-
# an often unused sender address, giving an AddressedMonitoringMessage.
|
7
|
+
# A MonitoringMessage dictionary can be tagged, giving a
|
8
|
+
# TaggedMonitoringMessage.
|
11
9
|
|
12
10
|
MonitoringMessage: TypeAlias = Dict[str, Any]
|
13
11
|
TaggedMonitoringMessage: TypeAlias = Tuple[MessageType, MonitoringMessage]
|
14
|
-
AddressedMonitoringMessage: TypeAlias = Tuple[TaggedMonitoringMessage, Union[str, int]]
|
parsl/providers/base.py
CHANGED
@@ -2,7 +2,6 @@ import logging
|
|
2
2
|
from abc import ABCMeta, abstractmethod, abstractproperty
|
3
3
|
from typing import Any, Dict, List, Optional
|
4
4
|
|
5
|
-
from parsl.channels.base import Channel
|
6
5
|
from parsl.jobs.states import JobStatus
|
7
6
|
|
8
7
|
logger = logging.getLogger(__name__)
|
@@ -154,18 +153,3 @@ class ExecutionProvider(metaclass=ABCMeta):
|
|
154
153
|
:return: the number of seconds to wait between calls to status()
|
155
154
|
"""
|
156
155
|
pass
|
157
|
-
|
158
|
-
|
159
|
-
class Channeled():
|
160
|
-
"""A marker type to indicate that parsl should manage a Channel for this provider"""
|
161
|
-
def __init__(self) -> None:
|
162
|
-
self.channel: Channel
|
163
|
-
pass
|
164
|
-
|
165
|
-
|
166
|
-
class MultiChanneled():
|
167
|
-
"""A marker type to indicate that parsl should manage multiple Channels for this provider"""
|
168
|
-
|
169
|
-
def __init__(self) -> None:
|
170
|
-
self.channels: List[Channel]
|
171
|
-
pass
|
@@ -1,6 +1,9 @@
|
|
1
|
+
import pytest
|
2
|
+
|
1
3
|
from parsl.channels.local.local import LocalChannel
|
2
4
|
|
3
5
|
|
6
|
+
@pytest.mark.local
|
4
7
|
def test_env():
|
5
8
|
''' Regression testing for issue #27
|
6
9
|
'''
|
@@ -15,9 +18,8 @@ def test_env():
|
|
15
18
|
x = [s for s in stdout if s.startswith("HOME=")]
|
16
19
|
assert x, "HOME not found"
|
17
20
|
|
18
|
-
print("RC:{} \nSTDOUT:{} \nSTDERR:{}".format(rc, stdout, stderr))
|
19
|
-
|
20
21
|
|
22
|
+
@pytest.mark.local
|
21
23
|
def test_env_mod():
|
22
24
|
''' Testing for env update at execute time.
|
23
25
|
'''
|
@@ -34,9 +36,3 @@ def test_env_mod():
|
|
34
36
|
|
35
37
|
x = [s for s in stdout if s.startswith("TEST_ENV=fooo")]
|
36
38
|
assert x, "User set env missing"
|
37
|
-
|
38
|
-
|
39
|
-
if __name__ == "__main__":
|
40
|
-
|
41
|
-
test_env()
|
42
|
-
test_env_mod()
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import os
|
2
|
+
import signal
|
3
|
+
import time
|
4
|
+
|
5
|
+
import pytest
|
6
|
+
import zmq
|
7
|
+
|
8
|
+
import parsl
|
9
|
+
from parsl.channels import LocalChannel
|
10
|
+
from parsl.config import Config
|
11
|
+
from parsl.executors import HighThroughputExecutor
|
12
|
+
from parsl.launchers import SimpleLauncher
|
13
|
+
from parsl.providers import LocalProvider
|
14
|
+
|
15
|
+
T_s = 1
|
16
|
+
|
17
|
+
|
18
|
+
def fresh_config():
|
19
|
+
htex = HighThroughputExecutor(
|
20
|
+
heartbeat_period=1 * T_s,
|
21
|
+
heartbeat_threshold=3 * T_s,
|
22
|
+
label="htex_local",
|
23
|
+
worker_debug=True,
|
24
|
+
cores_per_worker=1,
|
25
|
+
encrypted=False,
|
26
|
+
provider=LocalProvider(
|
27
|
+
channel=LocalChannel(),
|
28
|
+
init_blocks=0,
|
29
|
+
min_blocks=0,
|
30
|
+
max_blocks=0,
|
31
|
+
launcher=SimpleLauncher(),
|
32
|
+
),
|
33
|
+
)
|
34
|
+
c = Config(
|
35
|
+
executors=[htex],
|
36
|
+
strategy='none',
|
37
|
+
strategy_period=0.5,
|
38
|
+
)
|
39
|
+
return c, htex
|
40
|
+
|
41
|
+
|
42
|
+
@parsl.python_app
|
43
|
+
def app():
|
44
|
+
return 7
|
45
|
+
|
46
|
+
|
47
|
+
@pytest.mark.local
|
48
|
+
@pytest.mark.parametrize("msg",
|
49
|
+
(b'FuzzyByte\rSTREAM', # not JSON
|
50
|
+
b'{}', # missing fields
|
51
|
+
b'{"type":"heartbeat"}', # regression test #3262
|
52
|
+
)
|
53
|
+
)
|
54
|
+
def test_bad_messages(try_assert, msg):
|
55
|
+
"""This tests that the interchange is resilient to a few different bad
|
56
|
+
messages: malformed messages caused by implementation errors, and
|
57
|
+
heartbeat messages from managers that are not registered.
|
58
|
+
|
59
|
+
The heartbeat test is a regression test for issues #3262, #3632
|
60
|
+
"""
|
61
|
+
|
62
|
+
c, htex = fresh_config()
|
63
|
+
|
64
|
+
with parsl.load(c):
|
65
|
+
|
66
|
+
# send a bad message into the interchange on the task_outgoing worker
|
67
|
+
# channel, and then check that the interchange is still alive enough
|
68
|
+
# that we can scale out a block and run a task.
|
69
|
+
|
70
|
+
(task_port, result_port) = htex.command_client.run("WORKER_PORTS")
|
71
|
+
|
72
|
+
context = zmq.Context()
|
73
|
+
channel_timeout = 10000 # in milliseconds
|
74
|
+
task_channel = context.socket(zmq.DEALER)
|
75
|
+
task_channel.setsockopt(zmq.LINGER, 0)
|
76
|
+
task_channel.setsockopt(zmq.IDENTITY, b'testid')
|
77
|
+
|
78
|
+
task_channel.set_hwm(0)
|
79
|
+
task_channel.setsockopt(zmq.SNDTIMEO, channel_timeout)
|
80
|
+
task_channel.connect(f"tcp://localhost:{task_port}")
|
81
|
+
|
82
|
+
task_channel.send(msg)
|
83
|
+
|
84
|
+
# If the interchange exits, it's likely that this test will hang rather
|
85
|
+
# than raise an error, because the interchange interaction code
|
86
|
+
# assumes the interchange is always there.
|
87
|
+
# In the case of issue #3262, an exception message goes to stderr, and
|
88
|
+
# no error goes to the interchange log file.
|
89
|
+
htex.scale_out_facade(1)
|
90
|
+
try_assert(lambda: len(htex.connected_managers()) == 1, timeout_ms=10000)
|
91
|
+
|
92
|
+
assert app().result() == 7
|
@@ -32,7 +32,7 @@ def test_manager_lost_system_failure(tmpd_cwd):
|
|
32
32
|
cores_per_worker=1,
|
33
33
|
worker_logdir_root=str(tmpd_cwd),
|
34
34
|
heartbeat_period=1,
|
35
|
-
heartbeat_threshold=
|
35
|
+
heartbeat_threshold=3,
|
36
36
|
)
|
37
37
|
c = Config(executors=[hte], strategy='simple', strategy_period=0.1)
|
38
38
|
|
parsl/version.py
CHANGED
@@ -66,7 +66,7 @@ class Interchange:
|
|
66
66
|
If specified the interchange will only listen on this address for connections from workers
|
67
67
|
else, it binds to all addresses.
|
68
68
|
|
69
|
-
client_ports :
|
69
|
+
client_ports : tuple(int, int, int)
|
70
70
|
The ports at which the client can be reached
|
71
71
|
|
72
72
|
worker_ports : tuple(int, int)
|
@@ -104,7 +104,6 @@ class Interchange:
|
|
104
104
|
os.makedirs(self.logdir, exist_ok=True)
|
105
105
|
|
106
106
|
start_file_logger("{}/interchange.log".format(self.logdir), level=logging_level)
|
107
|
-
logger.propagate = False
|
108
107
|
logger.debug("Initializing Interchange process")
|
109
108
|
|
110
109
|
self.client_address = client_address
|
@@ -437,9 +436,13 @@ class Interchange:
|
|
437
436
|
logger.info(f"Manager {manager_id!r} has compatible Parsl version {msg['parsl_v']}")
|
438
437
|
logger.info(f"Manager {manager_id!r} has compatible Python version {msg['python_v'].rsplit('.', 1)[0]}")
|
439
438
|
elif msg['type'] == 'heartbeat':
|
440
|
-
|
441
|
-
|
442
|
-
|
439
|
+
manager = self._ready_managers.get(manager_id)
|
440
|
+
if manager:
|
441
|
+
manager['last_heartbeat'] = time.time()
|
442
|
+
logger.debug("Manager %r sent heartbeat via tasks connection", manager_id)
|
443
|
+
self.task_outgoing.send_multipart([manager_id, b'', PKL_HEARTBEAT_CODE])
|
444
|
+
else:
|
445
|
+
logger.warning("Received heartbeat via tasks connection for not-registered manager %r", manager_id)
|
443
446
|
elif msg['type'] == 'drain':
|
444
447
|
self._ready_managers[manager_id]['draining'] = True
|
445
448
|
logger.debug("Manager %r requested drain", manager_id)
|
@@ -650,14 +650,6 @@ def worker(
|
|
650
650
|
debug: bool,
|
651
651
|
mpi_launcher: str,
|
652
652
|
):
|
653
|
-
"""
|
654
|
-
|
655
|
-
Put request token into queue
|
656
|
-
Get task from task_queue
|
657
|
-
Pop request from queue
|
658
|
-
Put result into result_queue
|
659
|
-
"""
|
660
|
-
|
661
653
|
# override the global logger inherited from the __main__ process (which
|
662
654
|
# usually logs to manager.log) with one specific to this worker.
|
663
655
|
global logger
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: parsl
|
3
|
-
Version: 2024.10.
|
3
|
+
Version: 2024.10.28
|
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.10.
|
6
|
+
Download-URL: https://github.com/Parsl/parsl/archive/2024.10.28.tar.gz
|
7
7
|
Author: The Parsl Team
|
8
8
|
Author-email: parsl@googlegroups.com
|
9
9
|
License: Apache 2.0
|
@@ -8,7 +8,7 @@ parsl/multiprocessing.py,sha256=MyaEcEq-Qf860u7V98u-PZrPNdtzOZL_NW6EhIJnmfQ,1937
|
|
8
8
|
parsl/process_loggers.py,sha256=uQ7Gd0W72Jz7rrcYlOMfLsAEhkRltxXJL2MgdduJjEw,1136
|
9
9
|
parsl/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
parsl/utils.py,sha256=rMLKeadEsQ9jGwm4ogqiLIXPS3zOAyfznQJXVkJSY8E,13107
|
11
|
-
parsl/version.py,sha256=
|
11
|
+
parsl/version.py,sha256=_aB3gX1QHuC8JylX_fsIWJhUjbr-OtBk6u88PVGFMFQ,131
|
12
12
|
parsl/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
parsl/app/app.py,sha256=0gbM4AH2OtFOLsv07I5nglpElcwMSOi-FzdZZfrk7So,8532
|
14
14
|
parsl/app/bash.py,sha256=jm2AvePlCT9DZR7H_4ANDWxatp5dN_22FUlT_gWhZ-g,5528
|
@@ -18,14 +18,14 @@ parsl/app/python.py,sha256=0hrz2BppVOwwNfh5hnoP70Yv56gSRkIoT-fP9XNb4v4,2331
|
|
18
18
|
parsl/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
19
|
parsl/benchmark/perf.py,sha256=kKXefDozWXSJKSNA7qdfUgEoacA2-R9kSZcI2YvZ5uE,3096
|
20
20
|
parsl/channels/__init__.py,sha256=OEZcuNBOxUwmzrHMZOuPvkw4kUxrbJDA99crDk61O90,131
|
21
|
-
parsl/channels/base.py,sha256=
|
22
|
-
parsl/channels/errors.py,sha256=
|
21
|
+
parsl/channels/base.py,sha256=eJQQHBE_N0sAl41LH2UE6KBJomxjWw_B3ilQRYgpxHc,3948
|
22
|
+
parsl/channels/errors.py,sha256=x0ppJXY4Um0XIwO0oJ3x0biFaTxxv5Z4sP-FkowR72U,2782
|
23
23
|
parsl/channels/local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
-
parsl/channels/local/local.py,sha256=
|
24
|
+
parsl/channels/local/local.py,sha256=kAyO7byrjBX2heuhcG_Nr_DbZemdvKHw8GsH9XEUQ4A,5004
|
25
25
|
parsl/channels/oauth_ssh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
26
|
parsl/channels/oauth_ssh/oauth_ssh.py,sha256=6pj3LQAX89p5Lc8NL1Llq2_noi8GS8BItCuRtDp-iCA,3823
|
27
27
|
parsl/channels/ssh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
|
-
parsl/channels/ssh/ssh.py,sha256=
|
28
|
+
parsl/channels/ssh/ssh.py,sha256=y21at_99Cjo2YNC110bf5dbNsOvAsUA-843LyOPkJH8,10156
|
29
29
|
parsl/channels/ssh_il/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
30
|
parsl/channels/ssh_il/ssh_il.py,sha256=acOXJyqCmgC2nl7zrO_uEu3GpJZMN2l-Af5XfmNMLRs,2783
|
31
31
|
parsl/concurrent/__init__.py,sha256=TvIVceJYaJAsxedNBF3Vdo9lEQNHH_j3uxJv0zUjP7w,3288
|
@@ -62,7 +62,7 @@ parsl/data_provider/staging.py,sha256=ZDZuuFg38pjUStegKPcvPsfGp3iMeReMzfU6DSwtJj
|
|
62
62
|
parsl/data_provider/zip.py,sha256=S4kVuH9lxAegRURYbvIUR7EYYBOccyslaqyCrVWUBhw,4497
|
63
63
|
parsl/dataflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
64
64
|
parsl/dataflow/dependency_resolvers.py,sha256=Om8Dgh7a0ZwgXAc6TlhxLSzvxXHDlNNV1aBNiD3JTNY,3325
|
65
|
-
parsl/dataflow/dflow.py,sha256=
|
65
|
+
parsl/dataflow/dflow.py,sha256=g7il86TRBoulACyCZcDBkbFvFc7k1dV9cxoeb2wWngY,68230
|
66
66
|
parsl/dataflow/errors.py,sha256=9SxVhIJY_53FQx8x4OU8UA8nd7lvUbDllH7KfMXpYaY,2177
|
67
67
|
parsl/dataflow/futures.py,sha256=08LuP-HFiHBIZmeKCjlsazw_WpQ5fwevrU2_WbidkYw,6080
|
68
68
|
parsl/dataflow/memoization.py,sha256=l9uw1Bu50GucBF70M5relpGKFkE4dIM9T3R1KrxW0v0,9583
|
@@ -81,7 +81,7 @@ parsl/executors/flux/flux_instance_manager.py,sha256=5T3Rp7ZM-mlT0Pf0Gxgs5_YmnaP
|
|
81
81
|
parsl/executors/high_throughput/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
82
82
|
parsl/executors/high_throughput/errors.py,sha256=Sak8e8UpiEcXefUjMHbhyXc4Rn7kJtOoh7L8wreBQdk,1638
|
83
83
|
parsl/executors/high_throughput/executor.py,sha256=_dff5USFQq7V89kEXEWd2OqgYJQfq9i1b2e8FYA-zow,37511
|
84
|
-
parsl/executors/high_throughput/interchange.py,sha256=
|
84
|
+
parsl/executors/high_throughput/interchange.py,sha256=DQjIb7SpBAfHUFr5kY9f_9lJhH_ZX0CktoFu7yyTXBQ,30111
|
85
85
|
parsl/executors/high_throughput/manager_record.py,sha256=yn3L8TUJFkgm2lX1x0SeS9mkvJowC0s2VIMCFiU7ThM,455
|
86
86
|
parsl/executors/high_throughput/manager_selector.py,sha256=UKcUE6v0tO7PDMTThpKSKxVpOpOUilxDL7UbNgpZCxo,2116
|
87
87
|
parsl/executors/high_throughput/monitoring_info.py,sha256=HC0drp6nlXQpAop5PTUKNjdXMgtZVvrBL0JzZJebPP4,298
|
@@ -89,7 +89,7 @@ parsl/executors/high_throughput/mpi_executor.py,sha256=khvGz56A8zU8XAY-R4TtqqiJB
|
|
89
89
|
parsl/executors/high_throughput/mpi_prefix_composer.py,sha256=DmpKugANNa1bdYlqQBLHkrFc15fJpefPPhW9hkAlh1s,4308
|
90
90
|
parsl/executors/high_throughput/mpi_resource_management.py,sha256=LFBbJ3BnzTcY_v-jNu30uoIB2Enk4cleN4ygY3dncjY,8194
|
91
91
|
parsl/executors/high_throughput/probe.py,sha256=TNpGTXb4_DEeg_h-LHu4zEKi1-hffboxvKcZUl2OZGk,2751
|
92
|
-
parsl/executors/high_throughput/process_worker_pool.py,sha256=
|
92
|
+
parsl/executors/high_throughput/process_worker_pool.py,sha256=wpfKhA1hqbzfSnRfKn1WPFE_ZRd0LF07dBaK0YDXamg,42934
|
93
93
|
parsl/executors/high_throughput/zmq_pipes.py,sha256=tAjQB3aNVMuTXziN3dbJWre46YpXgliD55qMBbhYTLU,8581
|
94
94
|
parsl/executors/radical/__init__.py,sha256=CKbtV2numw5QvgIBq1htMUrt9TqDCIC2zifyf2svTNU,186
|
95
95
|
parsl/executors/radical/executor.py,sha256=426cMt6d8uJFZ_7Ub1kCslaND4OKtBX5WZdz-0RXjMk,22554
|
@@ -121,14 +121,14 @@ parsl/launchers/base.py,sha256=CblcvPTJiu-MNLWaRtFe29SZQ0BpTOlaY8CGcHdlHIE,538
|
|
121
121
|
parsl/launchers/errors.py,sha256=8YMV_CHpBNVa4eXkGE4x5DaFQlZkDCRCHmBktYcY6TA,467
|
122
122
|
parsl/launchers/launchers.py,sha256=cQsNsHuCOL_nQTjPXf0--YsgsDoMoJ77bO1Wt4ncLjs,15134
|
123
123
|
parsl/monitoring/__init__.py,sha256=0ywNz6i0lM1xo_7_BIxhETDGeVd2C_0wwD7qgeaMR4c,83
|
124
|
-
parsl/monitoring/db_manager.py,sha256=
|
124
|
+
parsl/monitoring/db_manager.py,sha256=G795Nme9di2AWT7zqFNNyOn8ZJd5i1I2hA6iDSorZD4,33330
|
125
125
|
parsl/monitoring/errors.py,sha256=D6jpYzEzp0d6FmVKGqhvjAxr4ztZfJX2s-aXemH9bBU,148
|
126
126
|
parsl/monitoring/message_type.py,sha256=Khn88afNxcOIciKiCK4GLnn90I5BlRTiOL3zK-P07yQ,401
|
127
|
-
parsl/monitoring/monitoring.py,sha256=
|
128
|
-
parsl/monitoring/radios.py,sha256=
|
127
|
+
parsl/monitoring/monitoring.py,sha256=9P9IcXFd6m9YVPZlc1cTUlrvdIt2MibCvE84rtNsHWw,13062
|
128
|
+
parsl/monitoring/radios.py,sha256=mK7DfpeLbXnbXybLI_yS6clDNDmCCrZVAMVNaUI9DQA,6424
|
129
129
|
parsl/monitoring/remote.py,sha256=avIWMvejN0LeIXpt_RCXJxGLbsXhapUab2rS5Tmjca4,13739
|
130
|
-
parsl/monitoring/router.py,sha256=
|
131
|
-
parsl/monitoring/types.py,sha256=
|
130
|
+
parsl/monitoring/router.py,sha256=5WrJ7YT2SV3T9BHCI8P0KqHm-4Y6NDgZkwmEcISmzGU,9110
|
131
|
+
parsl/monitoring/types.py,sha256=oOCrzv-ab-_rv4pb8o58Sdb8G_RGp1aZriRbdf9zBEk,339
|
132
132
|
parsl/monitoring/queries/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
133
133
|
parsl/monitoring/queries/pandas.py,sha256=0Z2r0rjTKCemf0eaDkF1irvVHn5g7KC5SYETvQPRxwU,2232
|
134
134
|
parsl/monitoring/visualization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -153,7 +153,7 @@ parsl/monitoring/visualization/templates/task.html,sha256=omDwp7zFXHVtuGsUCXcB7x
|
|
153
153
|
parsl/monitoring/visualization/templates/workflow.html,sha256=QCSHAPHK_2C3gNcZ3NmChLFG6xuchZEjT_iLQ3wwXmk,1871
|
154
154
|
parsl/monitoring/visualization/templates/workflows_summary.html,sha256=7brKKNsxcT4z-l10BKJlgTxQtGL033ZS5jEDdSmsPEE,891
|
155
155
|
parsl/providers/__init__.py,sha256=fvmVlu4aHw796K-fuUqxCHdK8KhrQviMARSmUQl1XXs,1077
|
156
|
-
parsl/providers/base.py,sha256=
|
156
|
+
parsl/providers/base.py,sha256=Kj8adE9SgIFwvbd61qvwEdtuI3gfkqYVJEbI4bGsaZQ,5271
|
157
157
|
parsl/providers/cluster_provider.py,sha256=o75wJHHyZkecjEBhGGBCMUQ1JlsecAhAKxX_Qd2pyg8,4668
|
158
158
|
parsl/providers/errors.py,sha256=_CbCmpguzcA81SC5dPLkDZs1AShzacGKttNhuzNBeiQ,2270
|
159
159
|
parsl/providers/ad_hoc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -251,8 +251,6 @@ parsl/tests/integration/latency.py,sha256=kWYkXsbnVnpwS6rHsdm7a1FsUOJWHhuXDsRPlA
|
|
251
251
|
parsl/tests/integration/test_parsl_load_default_config.py,sha256=wecDvbmblTgE3gErejGNLqQNaBigDyUpiqry9eoVUcw,395
|
252
252
|
parsl/tests/integration/test_apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
253
253
|
parsl/tests/integration/test_channels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
254
|
-
parsl/tests/integration/test_channels/test_channels.py,sha256=Nv_1ljrJ5Miqe4U5q9XPBqc0YZbJC90TIsH0p3203Gs,323
|
255
|
-
parsl/tests/integration/test_channels/test_local_channel.py,sha256=_j9z4LqdfawEQRlae6EHpMtrhMPMapbIlJwoHEibAuE,1009
|
256
254
|
parsl/tests/integration/test_stress/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
257
255
|
parsl/tests/integration/test_stress/test_python_simple.py,sha256=QZMhi6E0OmMsKi3QkHJZdNpALSrWshrLcKsstLANUWE,1007
|
258
256
|
parsl/tests/integration/test_stress/test_python_threads.py,sha256=-4dW-g69cu6uhSvk5HiH0fI6ceckQNqUXZGvNK6QGq4,897
|
@@ -303,6 +301,7 @@ parsl/tests/test_bash_apps/test_stdout.py,sha256=hrzHXLt308qH2Gg_r0-qy5nFBNXI56v
|
|
303
301
|
parsl/tests/test_channels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
304
302
|
parsl/tests/test_channels/test_dfk_close.py,sha256=n7IF3Ud_vejg0VNRnvEgxCLmwMvPVvLbXvJdw-Mz_lw,628
|
305
303
|
parsl/tests/test_channels/test_large_output.py,sha256=PGeNSW_sN5mR7KF1hVL2CPfktydYxo4oNz1wVQ-ENN0,595
|
304
|
+
parsl/tests/test_channels/test_local_channel.py,sha256=0TYjJRXBdeWbB60tCRQVZ4zZSXS4405eLzEIbcAWXy8,927
|
306
305
|
parsl/tests/test_checkpointing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
307
306
|
parsl/tests/test_checkpointing/test_periodic.py,sha256=nfMgrG7sZ8rkMu6iOHS6lp_iTU4IsOyQLQ2Gur_FMmE,1509
|
308
307
|
parsl/tests/test_checkpointing/test_python_checkpoint_1.py,sha256=k7_Zy4CV9OQt4ORYFCdyX53c4B0YPiwEIi35LhvLB2w,746
|
@@ -425,9 +424,10 @@ parsl/tests/test_scaling/test_scale_down.py,sha256=u8TbbVM2PXgy4Zg7bAkh0C-KQuF1k
|
|
425
424
|
parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py,sha256=PKfH18sA11oNhf2Ub8BJjxbxdIfzEeL1Lk2E0VhLJrs,4605
|
426
425
|
parsl/tests/test_scaling/test_scale_down_htex_unregistered.py,sha256=buNGB2wKG9omLf4d1R07zaxl1slVPuWtH8e1z4Hj70I,2038
|
427
426
|
parsl/tests/test_scaling/test_shutdown_scalein.py,sha256=Jzi0OH7UE6qvQ4ZpsfHu8lySpkMDgorn2elAzMNE6wI,2397
|
427
|
+
parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py,sha256=U4ZBx5HyjPmYZ2_Ti_gc0ZiChdDEC5BML5FnbpemmY4,2871
|
428
428
|
parsl/tests/test_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
429
429
|
parsl/tests/test_serialization/test_2555_caching_deserializer.py,sha256=jEXJvbriaLVI7frV5t-iJRKYyeQ7a9_-t3X9lhhBWQo,767
|
430
|
-
parsl/tests/test_serialization/test_3495_deserialize_managerlost.py,sha256=
|
430
|
+
parsl/tests/test_serialization/test_3495_deserialize_managerlost.py,sha256=GoMtK6BmARicawzYR2eQj5jUSL9RZ_tHV3g19BdQuQ8,1144
|
431
431
|
parsl/tests/test_serialization/test_basic.py,sha256=4_1Rkq5tNl9EC0nfneF8kHTws7I0E6ovE_0DE97BEfU,544
|
432
432
|
parsl/tests/test_serialization/test_htex_code_cache.py,sha256=dd0XwlNDn6Lgj6-nHHjYWzl1FnhFLY_8Buxj77dyZ28,1840
|
433
433
|
parsl/tests/test_serialization/test_pack_resource_spec.py,sha256=-Vtyh8KyezZw8e7M2Z4m3LawY1Au4U-H3KRmVKXSut0,641
|
@@ -466,13 +466,13 @@ parsl/usage_tracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
466
466
|
parsl/usage_tracking/api.py,sha256=iaCY58Dc5J4UM7_dJzEEs871P1p1HdxBMtNGyVdzc9g,1821
|
467
467
|
parsl/usage_tracking/levels.py,sha256=xbfzYEsd55KiZJ-mzNgPebvOH4rRHum04hROzEf41tU,291
|
468
468
|
parsl/usage_tracking/usage.py,sha256=tcoZ2OUjsQVakG8Uu9_HFuEdzpSHyt4JarSRcLGnSMw,8918
|
469
|
-
parsl-2024.10.
|
470
|
-
parsl-2024.10.
|
471
|
-
parsl-2024.10.
|
472
|
-
parsl-2024.10.
|
473
|
-
parsl-2024.10.
|
474
|
-
parsl-2024.10.
|
475
|
-
parsl-2024.10.
|
476
|
-
parsl-2024.10.
|
477
|
-
parsl-2024.10.
|
478
|
-
parsl-2024.10.
|
469
|
+
parsl-2024.10.28.data/scripts/exec_parsl_function.py,sha256=RUkJ4JSJAjr7YyRZ58zhMdg8cR5dVV9odUl3AuzNf3k,7802
|
470
|
+
parsl-2024.10.28.data/scripts/interchange.py,sha256=6jsxpVgtruFtE_0nMHAZYVF1gvoALBCkprEbUb_YQgg,30098
|
471
|
+
parsl-2024.10.28.data/scripts/parsl_coprocess.py,sha256=zrVjEqQvFOHxsLufPi00xzMONagjVwLZbavPM7bbjK4,5722
|
472
|
+
parsl-2024.10.28.data/scripts/process_worker_pool.py,sha256=Qed0dgUa6375UgWm5h196V0FBdeTdW6iowG9RYDNG9Y,42920
|
473
|
+
parsl-2024.10.28.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
474
|
+
parsl-2024.10.28.dist-info/METADATA,sha256=QrGvIyy6IrEP8lsBKtOKsOKAvgL3GeIyDUw29t81mAc,4072
|
475
|
+
parsl-2024.10.28.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
476
|
+
parsl-2024.10.28.dist-info/entry_points.txt,sha256=XqnsWDYoEcLbsMcpnYGKLEnSBmaIe1YoM5YsBdJG2tI,176
|
477
|
+
parsl-2024.10.28.dist-info/top_level.txt,sha256=PIheYoUFQtF2icLsgOykgU-Cjuwr2Oi6On2jo5RYgRM,6
|
478
|
+
parsl-2024.10.28.dist-info/RECORD,,
|
@@ -1,17 +0,0 @@
|
|
1
|
-
from parsl.channels.local.local import LocalChannel
|
2
|
-
|
3
|
-
|
4
|
-
def test_local():
|
5
|
-
|
6
|
-
channel = LocalChannel(None, None)
|
7
|
-
|
8
|
-
ec, out, err = channel.execute_wait('echo "pwd: $PWD"', 2)
|
9
|
-
|
10
|
-
assert ec == 0, "Channel execute failed"
|
11
|
-
print("Stdout: ", out)
|
12
|
-
print("Stderr: ", err)
|
13
|
-
|
14
|
-
|
15
|
-
if __name__ == "__main__":
|
16
|
-
|
17
|
-
test_local()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|