parsl 2023.12.25__py3-none-any.whl → 2024.1.8__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/addresses.py CHANGED
@@ -72,8 +72,9 @@ def address_by_hostname() -> str:
72
72
  """
73
73
  logger.debug("Finding address by using local hostname")
74
74
  addr = platform.node()
75
- logger.debug("Address found: {}".format(addr))
76
- return addr
75
+ ip_addr = socket.gethostbyname(addr)
76
+ logger.debug("Address found: {}".format(ip_addr))
77
+ return ip_addr
77
78
 
78
79
 
79
80
  @typeguard.typechecked
parsl/dataflow/dflow.py CHANGED
@@ -262,9 +262,8 @@ class DataFlowKernel:
262
262
  """
263
263
  count = 0
264
264
  for dep in depends:
265
- if isinstance(dep, Future):
266
- if not dep.done():
267
- count += 1
265
+ if not dep.done():
266
+ count += 1
268
267
 
269
268
  return count
270
269
 
@@ -527,9 +526,7 @@ class DataFlowKernel:
527
526
  # or do nothing?
528
527
  if self.checkpoint_mode == 'task_exit':
529
528
  self.checkpoint(tasks=[task_record])
530
- elif self.checkpoint_mode == 'manual' or \
531
- self.checkpoint_mode == 'periodic' or \
532
- self.checkpoint_mode == 'dfk_exit':
529
+ elif self.checkpoint_mode in ('manual', 'periodic', 'dfk_exit'):
533
530
  with self.checkpoint_lock:
534
531
  self.checkpointable_tasks.append(task_record)
535
532
  elif self.checkpoint_mode is None:
@@ -1299,11 +1296,7 @@ class DataFlowKernel:
1299
1296
  hashsum = task_record['hashsum']
1300
1297
  if not hashsum:
1301
1298
  continue
1302
- t = {'hash': hashsum,
1303
- 'exception': None,
1304
- 'result': None}
1305
-
1306
- t['result'] = app_fu.result()
1299
+ t = {'hash': hashsum, 'exception': None, 'result': app_fu.result()}
1307
1300
 
1308
1301
  # We are using pickle here since pickle dumps to a file in 'ab'
1309
1302
  # mode behave like a incremental log.
@@ -53,12 +53,13 @@ class RadicalPilotExecutor(ParslExecutor, RepresentationMixin):
53
53
  """Executor is designed for executing heterogeneous tasks
54
54
  in terms of type/resource.
55
55
 
56
- The RadicalPilotExecutor system has the following components:
56
+ The RadicalPilotExecutor system has the following main components:
57
57
 
58
- 1. "start" :creating the RADICAL-executor session and pilot.
59
- 2. "translate":unwrap/identify/ out of parsl task and construct RP task.
60
- 3. "submit" :translating and submitting Parsl tasks to Radical Pilot.
61
- 4. "shut_down":shutting down the RADICAL-executor components.
58
+ 1. "start": Create and start the RADICAL-Pilot runtime components ``rp.Session``,
59
+ ``rp.PilotManager`` and ``rp.TaskManager``.
60
+ 2. "translate": Unwrap, identify, and parse Parsl ``apps`` into ``rp.TaskDescription``.
61
+ 3. "submit": Submit Parsl apps to ``rp.TaskManager``.
62
+ 4. "shut_down": Shut down the RADICAL-Pilot runtime and all associated components.
62
63
 
63
64
  Here is a diagram
64
65
 
@@ -75,7 +76,7 @@ class RadicalPilotExecutor(ParslExecutor, RepresentationMixin):
75
76
  ----------------------------------------------------------------------------
76
77
 
77
78
  The RadicalPilotExecutor creates a ``rp.Session``, ``rp.TaskManager``,
78
- and ``rp.PilotManager``. The executor receives the parsl apps from the
79
+ and ``rp.PilotManager``. The executor receives the Parsl apps from the
79
80
  DFK and translates these apps (in-memory) into ``rp.TaskDescription``
80
81
  object to be passed to the ``rp.TaskManager``. This executor has two
81
82
  submission mechanisms:
@@ -146,7 +147,7 @@ class RadicalPilotExecutor(ParslExecutor, RepresentationMixin):
146
147
 
147
148
  def task_state_cb(self, task, state):
148
149
  """
149
- Update the state of Parsl Future tasks
150
+ Update the state of Parsl Future apps
150
151
  Based on RP task state callbacks.
151
152
  """
152
153
  if not task.uid.startswith('master'):
@@ -275,7 +276,7 @@ class RadicalPilotExecutor(ParslExecutor, RepresentationMixin):
275
276
 
276
277
  def unwrap(self, func, args):
277
278
  """
278
- Unwrap a parsl app and its args for further processing.
279
+ Unwrap a Parsl app and its args for further processing.
279
280
 
280
281
  Parameters
281
282
  ----------
@@ -325,14 +326,14 @@ class RadicalPilotExecutor(ParslExecutor, RepresentationMixin):
325
326
 
326
327
  def task_translate(self, tid, func, parsl_resource_specification, args, kwargs):
327
328
  """
328
- Convert parsl function to RADICAL-Pilot rp.TaskDescription
329
+ Convert Parsl function to RADICAL-Pilot rp.TaskDescription
329
330
  """
330
331
 
331
332
  task = rp.TaskDescription()
332
333
  task.name = func.__name__
333
334
 
334
335
  if parsl_resource_specification and isinstance(parsl_resource_specification, dict):
335
- logger.debug('mapping parsl resource specifications >> rp resource specifications')
336
+ logger.debug('mapping Parsl resource specifications >> RP resource specifications')
336
337
  for key, val in parsl_resource_specification.items():
337
338
  if key not in task.as_dict():
338
339
  key = PARSL_RP_RESOURCE_MAP.get(key, None)
@@ -523,7 +524,7 @@ class RadicalPilotExecutor(ParslExecutor, RepresentationMixin):
523
524
  ns=self.session.uid)
524
525
  parsl_tid = int(rp_tid.split('task.')[1])
525
526
 
526
- logger.debug("got Task {0} from parsl-dfk".format(parsl_tid))
527
+ logger.debug("got Task {0} from Parsl-dfk".format(parsl_tid))
527
528
  task = self.task_translate(parsl_tid, func, resource_specification, args, kwargs)
528
529
 
529
530
  # assign task id for rp task
@@ -959,43 +959,42 @@ def _work_queue_submit_wait(*,
959
959
 
960
960
  # If the queue is not empty wait on the WorkQueue queue for a task
961
961
  task_found = True
962
- if not q.empty():
963
- while task_found and not should_stop.value:
964
- # Obtain the task from the queue
965
- t = q.wait(1)
966
- if t is None:
967
- task_found = False
968
- continue
969
- # When a task is found:
970
- executor_task_id = t.tag
971
- logger.debug("Completed Work Queue task {}, executor task {}".format(t.id, t.tag))
972
- result_file = result_file_of_task_id.pop(t.tag)
973
-
974
- # A tasks completes 'succesfully' if it has result file.
975
- # The check whether this file can load a serialized Python object
976
- # happens later in the collector thread of the executor process.
977
- logger.debug("Looking for result in {}".format(result_file))
978
- if os.path.exists(result_file):
979
- logger.debug("Found result in {}".format(result_file))
980
- collector_queue.put_nowait(WqTaskToParsl(id=executor_task_id,
981
- result_received=True,
982
- result_file=result_file,
983
- reason=None,
984
- status=t.return_status))
985
- # If a result file could not be generated, explain the
986
- # failure according to work queue error codes.
987
- else:
988
- reason = _explain_work_queue_result(t)
989
- logger.debug("Did not find result in {}".format(result_file))
990
- logger.debug("Wrapper Script status: {}\nWorkQueue Status: {}"
991
- .format(t.return_status, t.result))
992
- logger.debug("Task with executor id {} / Work Queue id {} failed because:\n{}"
993
- .format(executor_task_id, t.id, reason))
994
- collector_queue.put_nowait(WqTaskToParsl(id=executor_task_id,
995
- result_received=False,
996
- result_file=None,
997
- reason=reason,
998
- status=t.return_status))
962
+ while not q.empty() and task_found and not should_stop.value:
963
+ # Obtain the task from the queue
964
+ t = q.wait(1)
965
+ if t is None:
966
+ task_found = False
967
+ continue
968
+ # When a task is found:
969
+ executor_task_id = t.tag
970
+ logger.debug("Completed Work Queue task {}, executor task {}".format(t.id, t.tag))
971
+ result_file = result_file_of_task_id.pop(t.tag)
972
+
973
+ # A tasks completes 'succesfully' if it has result file.
974
+ # The check whether this file can load a serialized Python object
975
+ # happens later in the collector thread of the executor process.
976
+ logger.debug("Looking for result in {}".format(result_file))
977
+ if os.path.exists(result_file):
978
+ logger.debug("Found result in {}".format(result_file))
979
+ collector_queue.put_nowait(WqTaskToParsl(id=executor_task_id,
980
+ result_received=True,
981
+ result_file=result_file,
982
+ reason=None,
983
+ status=t.return_status))
984
+ # If a result file could not be generated, explain the
985
+ # failure according to work queue error codes.
986
+ else:
987
+ reason = _explain_work_queue_result(t)
988
+ logger.debug("Did not find result in {}".format(result_file))
989
+ logger.debug("Wrapper Script status: {}\nWorkQueue Status: {}"
990
+ .format(t.return_status, t.result))
991
+ logger.debug("Task with executor id {} / Work Queue id {} failed because:\n{}"
992
+ .format(executor_task_id, t.id, reason))
993
+ collector_queue.put_nowait(WqTaskToParsl(id=executor_task_id,
994
+ result_received=False,
995
+ result_file=None,
996
+ reason=reason,
997
+ status=t.return_status))
999
998
  logger.debug("Exiting WorkQueue Monitoring Process")
1000
999
  return 0
1001
1000
 
@@ -15,6 +15,5 @@ def fresh_config():
15
15
  RadicalPilotExecutor(
16
16
  label='RPEXBulk',
17
17
  rpex_cfg=rpex_cfg,
18
- bulk_mode=True,
19
18
  resource='local.localhost',
20
19
  runtime=30, cores=4)])
parsl/tests/conftest.py CHANGED
@@ -3,6 +3,8 @@ import itertools
3
3
  import logging
4
4
  import os
5
5
  import pathlib
6
+ import re
7
+ import shutil
6
8
  import time
7
9
  import types
8
10
  import signal
@@ -44,17 +46,46 @@ def pytest_sessionstart(session):
44
46
 
45
47
 
46
48
  @pytest.fixture(scope="session")
47
- def tmpd_cwd_session():
48
- n = datetime.now().strftime('%Y%m%d.%H%I%S')
49
- with tempfile.TemporaryDirectory(dir=os.getcwd(), prefix=f".pytest-{n}-") as tmpd:
50
- yield pathlib.Path(tmpd)
49
+ def tmpd_cwd_session(pytestconfig):
50
+ config = re.sub(r"[^A-z0-9_-]+", "_", pytestconfig.getoption('config')[0])
51
+ cwd = pathlib.Path(os.getcwd())
52
+ pytest_dir = cwd / ".pytest"
53
+ pytest_dir.mkdir(mode=0o700, parents=True, exist_ok=True)
54
+
55
+ test_dir_prefix = "parsltest-"
56
+ link = pytest_dir / f"{test_dir_prefix}current"
57
+ link.unlink(missing_ok=True)
58
+ n = datetime.now().strftime('%Y%m%d.%H%M%S')
59
+ tmpd = tempfile.mkdtemp(dir=pytest_dir, prefix=f"{test_dir_prefix}{n}-{config}-")
60
+ tmpd = pathlib.Path(tmpd)
61
+ link.symlink_to(tmpd.name)
62
+ yield link
63
+
64
+ try:
65
+ preserve = int(os.getenv("PARSL_TEST_PRESERVE_NUM_RUNS", "3"))
66
+ except Exception:
67
+ preserve = 3
68
+
69
+ test_runs = sorted(
70
+ d for d in pytest_dir.glob(f"{test_dir_prefix}*")
71
+ if d.is_dir() and not d.is_symlink()
72
+ )
73
+ for run_to_remove in test_runs[:-preserve]:
74
+ run_to_remove.chmod(0o700)
75
+ for root, subdirnames, fnames in os.walk(run_to_remove):
76
+ rpath = pathlib.Path(root)
77
+ for d in subdirnames:
78
+ (rpath / d).lchmod(0o700)
79
+ for f in fnames:
80
+ (rpath / f).lchmod(0o600)
81
+ shutil.rmtree(run_to_remove)
51
82
 
52
83
 
53
84
  @pytest.fixture
54
85
  def tmpd_cwd(tmpd_cwd_session, request):
55
86
  prefix = f"{request.node.name}-"
56
- with tempfile.TemporaryDirectory(dir=tmpd_cwd_session, prefix=prefix) as tmpd:
57
- yield pathlib.Path(tmpd)
87
+ tmpd = tempfile.mkdtemp(dir=tmpd_cwd_session, prefix=prefix)
88
+ yield pathlib.Path(tmpd)
58
89
 
59
90
 
60
91
  def pytest_addoption(parser):
@@ -118,7 +149,7 @@ def pytest_configure(config):
118
149
 
119
150
 
120
151
  @pytest.fixture(autouse=True, scope='session')
121
- def load_dfk_session(request, pytestconfig):
152
+ def load_dfk_session(request, pytestconfig, tmpd_cwd_session):
122
153
  """Load a dfk around entire test suite, except in local mode.
123
154
 
124
155
  The special path `local` indicates that configuration will not come
@@ -137,12 +168,19 @@ def load_dfk_session(request, pytestconfig):
137
168
  raise RuntimeError("DFK didn't start as None - there was a DFK from somewhere already")
138
169
 
139
170
  if hasattr(module, 'config'):
140
- dfk = parsl.load(module.config)
171
+ parsl_conf = module.config
141
172
  elif hasattr(module, 'fresh_config'):
142
- dfk = parsl.load(module.fresh_config())
173
+ parsl_conf = module.fresh_config()
143
174
  else:
144
175
  raise RuntimeError("Config module does not define config or fresh_config")
145
176
 
177
+ if parsl_conf.run_dir == "runinfo": # the default
178
+ parsl_conf.run_dir = tmpd_cwd_session / parsl_conf.run_dir
179
+ dfk = parsl.load(parsl_conf)
180
+
181
+ for ex in dfk.executors.values():
182
+ ex.working_dir = tmpd_cwd_session
183
+
146
184
  yield
147
185
 
148
186
  if parsl.dfk() != dfk:
@@ -154,7 +192,7 @@ def load_dfk_session(request, pytestconfig):
154
192
 
155
193
 
156
194
  @pytest.fixture(autouse=True, scope='module')
157
- def load_dfk_local_module(request, pytestconfig):
195
+ def load_dfk_local_module(request, pytestconfig, tmpd_cwd_session):
158
196
  """Load the dfk around test modules, in local mode.
159
197
 
160
198
  If local_config is specified in the test module, it will be loaded using
@@ -177,8 +215,15 @@ def load_dfk_local_module(request, pytestconfig):
177
215
  assert callable(local_config)
178
216
  c = local_config()
179
217
  assert isinstance(c, parsl.Config)
218
+
219
+ if c.run_dir == "runinfo": # the default
220
+ c.run_dir = tmpd_cwd_session / c.run_dir
221
+
180
222
  dfk = parsl.load(c)
181
223
 
224
+ for ex in dfk.executors.values():
225
+ ex.working_dir = tmpd_cwd_session
226
+
182
227
  if callable(local_setup):
183
228
  local_setup()
184
229
 
@@ -1,4 +1,3 @@
1
- import argparse
2
1
  import os
3
2
  import pytest
4
3
 
@@ -7,47 +6,28 @@ from parsl import python_app
7
6
  from parsl.tests.configs.local_threads import fresh_config
8
7
 
9
8
 
10
- @python_app(cache=True)
11
- def random_app(i):
12
- import random
13
- return random.randint(i, 100000)
14
-
15
-
16
- def launch_n_random(n=2):
17
- """1. Launch a few apps and write the checkpoint once a few have completed
18
- """
9
+ def local_config():
10
+ config = fresh_config()
11
+ config.checkpoint_mode = "manual"
12
+ return config
19
13
 
20
- d = [random_app(i) for i in range(0, n)]
21
- print("Done launching")
22
14
 
23
- # Block till done
24
- return [i.result() for i in d]
15
+ @python_app(cache=True)
16
+ def uuid_app():
17
+ import uuid
18
+ return uuid.uuid4()
25
19
 
26
20
 
27
21
  @pytest.mark.local
28
- def test_initial_checkpoint_write(n=2):
22
+ def test_initial_checkpoint_write():
29
23
  """1. Launch a few apps and write the checkpoint once a few have completed
30
24
  """
31
- config = fresh_config()
32
- config.checkpoint_mode = 'manual'
33
- parsl.load(config)
34
- results = launch_n_random(n)
25
+ uuid_app().result()
35
26
 
36
27
  cpt_dir = parsl.dfk().checkpoint()
37
28
 
38
29
  cptpath = cpt_dir + '/dfk.pkl'
39
- print("Path exists : ", os.path.exists(cptpath))
40
- assert os.path.exists(
41
- cptpath), "DFK checkpoint missing: {0}".format(cptpath)
30
+ assert os.path.exists(cptpath), f"DFK checkpoint missing: {cptpath}"
42
31
 
43
32
  cptpath = cpt_dir + '/tasks.pkl'
44
- print("Path exists : ", os.path.exists(cptpath))
45
- assert os.path.exists(
46
- cptpath), "Tasks checkpoint missing: {0}".format(cptpath)
47
-
48
- run_dir = parsl.dfk().run_dir
49
-
50
- parsl.dfk().cleanup()
51
- parsl.clear()
52
-
53
- return run_dir, results
33
+ assert os.path.exists(cptpath), f"Tasks checkpoint missing: {cptpath}"
@@ -1,45 +1,42 @@
1
- import argparse
1
+ import contextlib
2
2
  import os
3
3
  import pytest
4
4
  import parsl
5
5
  from parsl import python_app
6
6
 
7
- from parsl.tests.configs.local_threads import config
8
7
  from parsl.tests.configs.local_threads_checkpoint import fresh_config
9
8
 
10
9
 
11
- @python_app(cache=True)
12
- def random_app(i):
13
- import random
14
- return random.randint(i, 100000)
10
+ @contextlib.contextmanager
11
+ def parsl_configured(run_dir, **kw):
12
+ c = fresh_config()
13
+ c.run_dir = run_dir
14
+ for config_attr, config_val in kw.items():
15
+ setattr(c, config_attr, config_val)
16
+ dfk = parsl.load(c)
17
+ for ex in dfk.executors.values():
18
+ ex.working_dir = run_dir
19
+ yield dfk
20
+
21
+ parsl.dfk().cleanup()
22
+ parsl.clear()
15
23
 
16
24
 
17
- def launch_n_random(n=2):
18
- """1. Launch a few apps and write the checkpoint once a few have completed
19
- """
20
- d = [random_app(i) for i in range(0, n)]
21
- return [i.result() for i in d]
25
+ @python_app(cache=True)
26
+ def uuid_app():
27
+ import uuid
28
+ return uuid.uuid4()
22
29
 
23
30
 
24
31
  @pytest.mark.local
25
- def test_loading_checkpoint(n=2):
32
+ def test_loading_checkpoint(tmpd_cwd):
26
33
  """Load memoization table from previous checkpoint
27
34
  """
28
- config.checkpoint_mode = 'task_exit'
29
- parsl.load(config)
30
- results = launch_n_random(n)
31
- rundir = parsl.dfk().run_dir
32
- parsl.dfk().cleanup()
33
- parsl.clear()
34
-
35
- local_config = fresh_config()
36
- local_config.checkpoint_files = [os.path.join(rundir, 'checkpoint')]
37
- parsl.load(local_config)
35
+ with parsl_configured(tmpd_cwd, checkpoint_mode="task_exit"):
36
+ checkpoint_files = [os.path.join(parsl.dfk().run_dir, "checkpoint")]
37
+ result = uuid_app().result()
38
38
 
39
- relaunched = launch_n_random(n)
40
- assert len(relaunched) == len(results) == n, "Expected all results to have n items"
39
+ with parsl_configured(tmpd_cwd, checkpoint_files=checkpoint_files):
40
+ relaunched = uuid_app().result()
41
41
 
42
- for i in range(n):
43
- assert relaunched[i] == results[i], "Expected relaunched to contain cached results from first run"
44
- parsl.dfk().cleanup()
45
- parsl.clear()
42
+ assert result == relaunched, "Expected following call to uuid_app to return cached uuid"
@@ -0,0 +1,16 @@
1
+ import pytest
2
+
3
+ from parsl.providers import SlurmProvider
4
+
5
+
6
+ @pytest.mark.local
7
+ def test_slurm_instantiate_regression_2994():
8
+ """This test checks that repr can be executed on SlurmProvider.
9
+ This does not need a SLURM installation around.
10
+
11
+ Because of the behaviour of RepresentationMixin, it's a relatively
12
+ common problem to break repr when adding new parameters to the
13
+ SlurmProvider, and this tests that repr does not raise an exception.
14
+ """
15
+ p = SlurmProvider()
16
+ repr(p)
@@ -5,7 +5,7 @@ from parsl.tests.configs.local_radical_mpi import fresh_config as local_config
5
5
 
6
6
 
7
7
  @parsl.python_app
8
- def test_mpi_func(msg, sleep, comm=None, parsl_resource_specification={}):
8
+ def some_mpi_func(msg, sleep, comm=None, parsl_resource_specification={}):
9
9
  import time
10
10
  msg = 'hello %d/%d: %s' % (comm.rank, comm.size, msg)
11
11
  time.sleep(sleep)
@@ -17,11 +17,12 @@ apps = []
17
17
 
18
18
 
19
19
  @pytest.mark.local
20
+ @pytest.mark.radical
20
21
  def test_radical_mpi(n=7):
21
22
  # rank size should be > 1 for the
22
23
  # radical runtime system to run this function in MPI env
23
24
  for i in range(2, n):
24
25
  spec = {'ranks': i}
25
- t = test_mpi_func(msg='mpi.func.%06d' % i, sleep=1, comm=None, parsl_resource_specification=spec)
26
+ t = some_mpi_func(msg='mpi.func.%06d' % i, sleep=1, comm=None, parsl_resource_specification=spec)
26
27
  apps.append(t)
27
28
  assert [len(app.result()) for app in apps] == list(range(2, n))
@@ -0,0 +1,7 @@
1
+ def read_sort_write(in_path, out_path):
2
+ with open(in_path) as u:
3
+ strs = u.read().split()
4
+ strs.sort()
5
+ with open(out_path, 'w') as s:
6
+ for e in strs:
7
+ print(e, file=s)
@@ -20,8 +20,8 @@ logger = logging.getLogger(__name__)
20
20
 
21
21
 
22
22
  @bash_app
23
- def touch(filename, inputs=[], outputs=[]):
24
- return "touch {}".format(filename)
23
+ def touch(filename, outputs=()):
24
+ return f"touch {filename}"
25
25
 
26
26
 
27
27
  @python_app
@@ -31,52 +31,47 @@ def app_test_in(file):
31
31
  pass
32
32
 
33
33
 
34
+ @pytest.fixture
35
+ def storage_access_parsl():
36
+ def _setup_config(*args, **kwargs):
37
+ tpe = ThreadPoolExecutor(
38
+ label='local_threads',
39
+ storage_access=[NoOpTestingFileStaging(*args, **kwargs)]
40
+ )
41
+ config = Config(executors=[tpe])
42
+ parsl.load(config)
43
+
44
+ yield _setup_config
45
+
46
+ parsl.dfk().cleanup()
47
+ parsl.clear()
48
+
49
+
34
50
  @pytest.mark.local
35
- def test_regression_stage_out_does_not_stage_in():
36
- no_stageout_config = Config(
37
- executors=[
38
- ThreadPoolExecutor(
39
- label='local_threads',
40
- storage_access=[NoOpTestingFileStaging(allow_stage_in=False)]
41
- )
42
- ]
43
- )
44
-
45
- parsl.load(no_stageout_config)
51
+ def test_regression_stage_out_does_not_stage_in(storage_access_parsl, tmpd_cwd):
52
+ storage_access_parsl(allow_stage_in=False)
46
53
 
47
54
  # Test that the helper app runs with no staging
48
- touch("test.1", outputs=[]).result()
55
+ touch(str(tmpd_cwd / "test.1"), outputs=[]).result()
49
56
 
50
- # Test with stage-out, checking that provider stage in is never
51
- # invoked. If stage-in is invoked, the the NoOpTestingFileStaging
57
+ # Test with stage-out, checking that provider stage-in is never
58
+ # invoked. If stage-in is invoked, then the NoOpTestingFileStaging
52
59
  # provider will raise an exception, which should propagate to
53
60
  # .result() here.
54
- touch("test.2", outputs=[File("test.2")]).result()
61
+ fpath = tmpd_cwd / "test.2"
62
+ touch(str(fpath), outputs=[File(fpath)]).result()
55
63
 
56
64
  # Test that stage-in exceptions propagate out to user code.
57
65
  with pytest.raises(NoOpError):
58
66
  touch("test.3", inputs=[File("test.3")]).result()
59
67
 
60
- parsl.dfk().cleanup()
61
- parsl.clear()
62
-
63
68
 
64
69
  @pytest.mark.local
65
- def test_regression_stage_in_does_not_stage_out():
66
- no_stageout_config = Config(
67
- executors=[
68
- ThreadPoolExecutor(
69
- label='local_threads',
70
- storage_access=[NoOpTestingFileStaging(allow_stage_out=False)]
71
- )
72
- ],
73
- )
74
-
75
- parsl.load(no_stageout_config)
76
-
77
- f = open("test.4", "a")
78
- f.write("test")
79
- f.close()
70
+ def test_regression_stage_in_does_not_stage_out(storage_access_parsl, tmpd_cwd):
71
+ storage_access_parsl(allow_stage_out=False)
72
+
73
+ fpath = tmpd_cwd / "test.4"
74
+ fpath.write_text("test")
80
75
 
81
76
  # Test that stage in does not invoke stage out. If stage out is
82
77
  # attempted, then the NoOpTestingFileStaging provider will raise
@@ -86,6 +81,3 @@ def test_regression_stage_in_does_not_stage_out():
86
81
  # Test that stage out exceptions propagate to user code.
87
82
  with pytest.raises(NoOpError):
88
83
  touch("test.5", outputs=[File("test.5")]).result()
89
-
90
- parsl.dfk().cleanup()
91
- parsl.clear()
@@ -9,111 +9,95 @@ import pytest
9
9
  # specificed with --config, not this one.
10
10
  from parsl.tests.configs.htex_local import fresh_config as local_config
11
11
 
12
+ """
13
+ Test staging for an http file
12
14
 
13
- @python_app
14
- def sort_strings(inputs=[], outputs=[]):
15
- with open(inputs[0].filepath, 'r') as u:
16
- strs = u.readlines()
17
- strs.sort()
18
- with open(outputs[0].filepath, 'w') as s:
19
- for e in strs:
20
- s.write(e)
21
-
15
+ Create a remote input file (https) that points to unsorted.txt, then
16
+ a local file for output data (sorted.txt).
17
+ """
22
18
 
23
- @pytest.mark.cleannet
24
- def test_staging_https():
25
- """Test staging for an https file
19
+ _unsorted_url = (
20
+ 'https://gist.githubusercontent.com/yadudoc/7f21dd15e64a421990a46766bfa5359c/'
21
+ 'raw/7fe04978ea44f807088c349f6ecb0f6ee350ec49/unsorted.txt'
22
+ )
23
+ _exp_sorted = sorted(f"{i}\n" for i in range(1, 101))[:20]
26
24
 
27
- Create a remote input file (https) that points to unsorted.txt.
28
- """
29
25
 
30
- # unsorted_file = File('https://testbed.petrel.host/test/public/unsorted.txt')
31
- unsorted_file = File('https://gist.githubusercontent.com/yadudoc/7f21dd15e64a421990a46766bfa5359c/'
32
- 'raw/7fe04978ea44f807088c349f6ecb0f6ee350ec49/unsorted.txt')
26
+ @python_app
27
+ def sort_strings(inputs=(), outputs=()):
28
+ from parsl.tests.test_staging import read_sort_write
29
+ read_sort_write(inputs[0].filepath, outputs[0].filepath)
33
30
 
34
- # Create a local file for output data
35
- sorted_file = File('sorted.txt')
36
31
 
37
- f = sort_strings(inputs=[unsorted_file], outputs=[sorted_file])
38
- f.result()
32
+ @python_app
33
+ def sort_strings_kw(*, x=None, outputs=()):
34
+ from parsl.tests.test_staging import read_sort_write
35
+ read_sort_write(x.filepath, outputs[0].filepath)
39
36
 
40
37
 
41
38
  @python_app
42
- def sort_strings_kw(x=None, outputs=[]):
43
- with open(x.filepath, 'r') as u:
44
- strs = u.readlines()
45
- strs.sort()
46
- with open(outputs[0].filepath, 'w') as s:
47
- for e in strs:
48
- s.write(e)
39
+ def sort_strings_arg(x, /, outputs=()):
40
+ from parsl.tests.test_staging import read_sort_write
41
+ read_sort_write(x.filepath, outputs[0].filepath)
49
42
 
50
43
 
51
- @pytest.mark.cleannet
52
- def test_staging_https_kwargs():
44
+ @python_app(executors=['other'])
45
+ def sort_strings_additional_executor(inputs=(), outputs=()):
46
+ from parsl.tests.test_staging import read_sort_write
47
+ read_sort_write(inputs[0].filepath, outputs[0].filepath)
53
48
 
54
- # unsorted_file = File('https://testbed.petrel.host/test/public/unsorted.txt')
55
- unsorted_file = File('https://gist.githubusercontent.com/yadudoc/7f21dd15e64a421990a46766bfa5359c/'
56
- 'raw/7fe04978ea44f807088c349f6ecb0f6ee350ec49/unsorted.txt')
57
49
 
58
- # Create a local file for output data
59
- sorted_file = File('sorted.txt')
50
+ @pytest.mark.cleannet
51
+ def test_staging_https_cleannet(tmpd_cwd):
52
+ unsorted_file = File(_unsorted_url)
53
+ sorted_file = File(tmpd_cwd / 'sorted.txt')
60
54
 
61
- f = sort_strings_kw(x=unsorted_file, outputs=[sorted_file])
62
- f.result()
55
+ sort_strings(inputs=[unsorted_file], outputs=[sorted_file]).result()
56
+ with open(sorted_file) as f:
57
+ assert all(a == b for a, b in zip(f.readlines(), _exp_sorted))
63
58
 
64
59
 
65
- @python_app
66
- def sort_strings_arg(x, outputs=[]):
67
- with open(x.filepath, 'r') as u:
68
- strs = u.readlines()
69
- strs.sort()
70
- with open(outputs[0].filepath, 'w') as s:
71
- for e in strs:
72
- s.write(e)
60
+ @pytest.mark.local
61
+ def test_staging_https_local(tmpd_cwd):
62
+ unsorted_file = File(_unsorted_url)
63
+ sorted_file = File(tmpd_cwd / 'sorted.txt')
73
64
 
65
+ sort_strings(inputs=[unsorted_file], outputs=[sorted_file]).result()
66
+ with open(sorted_file) as f:
67
+ assert all(a == b for a, b in zip(f.readlines(), _exp_sorted))
74
68
 
75
- @pytest.mark.cleannet
76
- def test_staging_https_args():
77
69
 
78
- # unsorted_file = File('https://testbed.petrel.host/test/public/unsorted.txt')
79
- unsorted_file = File('https://gist.githubusercontent.com/yadudoc/7f21dd15e64a421990a46766bfa5359c/'
80
- 'raw/7fe04978ea44f807088c349f6ecb0f6ee350ec49/unsorted.txt')
70
+ @pytest.mark.cleannet
71
+ def test_staging_https_kwargs(tmpd_cwd):
72
+ unsorted_file = File(_unsorted_url)
73
+ sorted_file = File(tmpd_cwd / 'sorted.txt')
81
74
 
82
- # Create a local file for output data
83
- sorted_file = File('sorted.txt')
75
+ sort_strings_kw(x=unsorted_file, outputs=[sorted_file]).result()
76
+ with open(sorted_file) as f:
77
+ assert all(a == b for a, b in zip(f.readlines(), _exp_sorted))
84
78
 
85
- f = sort_strings_arg(unsorted_file, outputs=[sorted_file])
86
- f.result()
87
79
 
80
+ @pytest.mark.cleannet
81
+ def test_staging_https_args(tmpd_cwd):
82
+ unsorted_file = File(_unsorted_url)
83
+ sorted_file = File(tmpd_cwd / 'sorted.txt')
88
84
 
89
- @python_app(executors=['other'])
90
- def sort_strings_additional_executor(inputs=[], outputs=[]):
91
- with open(inputs[0].filepath, 'r') as u:
92
- strs = u.readlines()
93
- strs.sort()
94
- with open(outputs[0].filepath, 'w') as s:
95
- for e in strs:
96
- s.write(e)
85
+ sort_strings_arg(unsorted_file, outputs=[sorted_file]).result()
86
+ with open(sorted_file) as f:
87
+ assert all(a == b for a, b in zip(f.readlines(), _exp_sorted))
97
88
 
98
89
 
99
90
  @pytest.mark.cleannet
100
91
  @pytest.mark.local
101
- def test_staging_https_additional_executor():
102
- """Test staging for an https file
103
-
104
- Create a remote input file (https) that points to unsorted.txt.
105
- """
106
-
107
- # unsorted_file = File('https://testbed.petrel.host/test/public/unsorted.txt')
108
- unsorted_file = File('https://gist.githubusercontent.com/yadudoc/7f21dd15e64a421990a46766bfa5359c/'
109
- 'raw/7fe04978ea44f807088c349f6ecb0f6ee350ec49/unsorted.txt')
110
-
111
- # Create a local file for output data
112
- sorted_file = File('sorted.txt')
92
+ def test_staging_https_additional_executor(tmpd_cwd):
93
+ unsorted_file = File(_unsorted_url)
94
+ sorted_file = File(tmpd_cwd / 'sorted.txt')
113
95
 
114
96
  other_executor = parsl.ThreadPoolExecutor(label='other')
97
+ other_executor.working_dir = tmpd_cwd
115
98
 
116
99
  parsl.dfk().add_executors([other_executor])
117
100
 
118
- f = sort_strings_additional_executor(inputs=[unsorted_file], outputs=[sorted_file])
119
- f.result()
101
+ sort_strings_additional_executor(inputs=[unsorted_file], outputs=[sorted_file]).result()
102
+ with open(sorted_file) as f:
103
+ assert all(a == b for a, b in zip(f.readlines(), _exp_sorted))
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 = '2023.12.25'
6
+ VERSION = '2024.01.08'
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: parsl
3
- Version: 2023.12.25
3
+ Version: 2024.1.8
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/2023.12.25.tar.gz
6
+ Download-URL: https://github.com/Parsl/parsl/archive/2024.01.08.tar.gz
7
7
  Author: The Parsl Team
8
8
  Author-email: parsl@googlegroups.com
9
9
  License: Apache 2.0
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.8
15
15
  Classifier: Programming Language :: Python :: 3.9
16
16
  Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
18
19
  Requires-Python: >=3.8.0
19
20
  License-File: LICENSE
20
21
  Requires-Dist: pyzmq >=17.1.2
@@ -34,7 +35,7 @@ Requires-Dist: pydot ; extra == 'all'
34
35
  Requires-Dist: networkx <2.6,>=2.5 ; extra == 'all'
35
36
  Requires-Dist: Flask >=1.0.2 ; extra == 'all'
36
37
  Requires-Dist: flask-sqlalchemy ; extra == 'all'
37
- Requires-Dist: pandas <2 ; extra == 'all'
38
+ Requires-Dist: pandas <3 ; extra == 'all'
38
39
  Requires-Dist: plotly ; extra == 'all'
39
40
  Requires-Dist: python-daemon ; extra == 'all'
40
41
  Requires-Dist: boto3 ; extra == 'all'
@@ -87,7 +88,7 @@ Requires-Dist: pydot ; extra == 'visualization'
87
88
  Requires-Dist: networkx <2.6,>=2.5 ; extra == 'visualization'
88
89
  Requires-Dist: Flask >=1.0.2 ; extra == 'visualization'
89
90
  Requires-Dist: flask-sqlalchemy ; extra == 'visualization'
90
- Requires-Dist: pandas <2 ; extra == 'visualization'
91
+ Requires-Dist: pandas <3 ; extra == 'visualization'
91
92
  Requires-Dist: plotly ; extra == 'visualization'
92
93
  Requires-Dist: python-daemon ; extra == 'visualization'
93
94
  Provides-Extra: workqueue
@@ -1,5 +1,5 @@
1
1
  parsl/__init__.py,sha256=hq8rJmP59wzd9-yxaGcmq5gPpshOopH-Y1K0BkUBNY0,1843
2
- parsl/addresses.py,sha256=L4RjQ-jGY9RfT-hBpsGw1uCzWaIdrEKxcPWV-TkGJes,4767
2
+ parsl/addresses.py,sha256=bkaRhM4IZ4iZzh6ZkRXPvCLKFkbJ6HX2AOjYyujCiO8,4814
3
3
  parsl/config.py,sha256=ysUWBfm9bygayHHdItaJbP4oozkHJJmVQVnWCt5igjE,6808
4
4
  parsl/errors.py,sha256=SzINzQFZDBDbj9l-DPQznD0TbGkNhHIRAPkcBCogf_A,1019
5
5
  parsl/log_utils.py,sha256=AGem-dhQs5TYUyJg6GKkRuHxAw8FHhYlWB_0s7_ROw4,3175
@@ -7,7 +7,7 @@ parsl/multiprocessing.py,sha256=w3t1pFkHo4oZpznc2KF6Ff-Jj8MvXqvjm-hoiRqZDDQ,1984
7
7
  parsl/process_loggers.py,sha256=1G3Rfrh5wuZNo2X03grG4kTYPGOxz7hHCyG6L_A3b0A,1137
8
8
  parsl/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  parsl/utils.py,sha256=_flbNpTu6IXHbzIyE5JkUbOBIK4poc1R1bjBtwJUVdo,11622
10
- parsl/version.py,sha256=72YSwmW-MS_RN7eW_oxX5vVjFjXLm9v5J1JePWhtnv4,131
10
+ parsl/version.py,sha256=NPMIiVrjuhjcfwCqoynKBV23jjy9LiRRIEHG07H7QPM,131
11
11
  parsl/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  parsl/app/app.py,sha256=wAHchJetgnicT1pn0NJKDeDX0lV3vDFlG8cQd_Ciax4,8522
13
13
  parsl/app/bash.py,sha256=bx9x1XFwkOTpZZD3CPwnVL9SyNRDjbUGtOnuGLvxN_8,5396
@@ -62,7 +62,7 @@ parsl/data_provider/http.py,sha256=nDHTW7XmJqAukWJjPRQjyhUXt8r6GsQ36mX9mv_wOig,2
62
62
  parsl/data_provider/rsync.py,sha256=2-ZxqrT-hBj39x082NusJaBqsGW4Jd2qCW6JkVPpEl0,4254
63
63
  parsl/data_provider/staging.py,sha256=l-mAXFburs3BWPjkSmiQKuAgJpsxCG62yATPDbrafYI,4523
64
64
  parsl/dataflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
- parsl/dataflow/dflow.py,sha256=uuXY9pURFDBpL0w52J0DWGCOtorTQ5wFy5V0WwHS9L8,63909
65
+ parsl/dataflow/dflow.py,sha256=J8ic2tEE5bX6IUAjhlATJefY7NSs_QrSjZz0Y9K-JbE,63673
66
66
  parsl/dataflow/errors.py,sha256=w2vOt_ymzG2dOqJUO4IDcmTlrCIHlMZL8nBVyVq0O_8,2176
67
67
  parsl/dataflow/futures.py,sha256=aVfEUTzp4-EdunDAtNcqVQf8l_A7ArDi2c82KZMwxfY,5256
68
68
  parsl/dataflow/memoization.py,sha256=AsJO6c6cRp2ac6H8uGn2USlEi78_nX3QWvpxYt4XdYE,9583
@@ -88,7 +88,7 @@ parsl/executors/high_throughput/probe.py,sha256=lvnuf-vBv57tHvFh-J51F9sDYBES7jCg
88
88
  parsl/executors/high_throughput/process_worker_pool.py,sha256=l0l5F3mpJ60idMCN-d1AbdaogmOtO5eO3uGWogspNXg,34070
89
89
  parsl/executors/high_throughput/zmq_pipes.py,sha256=88VJz9QejOCQ_yyhaO5C1uQuDYZTovYEcnKn15WxHSU,6103
90
90
  parsl/executors/radical/__init__.py,sha256=CKbtV2numw5QvgIBq1htMUrt9TqDCIC2zifyf2svTNU,186
91
- parsl/executors/radical/executor.py,sha256=ZYycq58jXlBlhmIO1355JCK1xIJHkspiy62NN1XiMYQ,20729
91
+ parsl/executors/radical/executor.py,sha256=u0GhRk4dzAX8lmTGjBYmztg1yT02AsEmsSnUg84MnwU,20823
92
92
  parsl/executors/radical/rpex_master.py,sha256=nMGxYWw3r-8_vZVnEwfB5eCfdTqXkeQDP5yvU0jXgc8,1368
93
93
  parsl/executors/radical/rpex_resources.py,sha256=d7QlJYBkWE-lPauetroEGIbA8RyVILA699LG0uNviws,4960
94
94
  parsl/executors/radical/rpex_worker.py,sha256=xPkjYdlXc3kjN-95NTMiQ5s-yU3JFDCA3sruPTxF3XU,1834
@@ -104,7 +104,7 @@ parsl/executors/taskvine/utils.py,sha256=iSrIogeiauL3UNy_9tiZp1cBSNn6fIJkMYQRVi1
104
104
  parsl/executors/workqueue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
105
  parsl/executors/workqueue/errors.py,sha256=ghB93Ptb_QbOAvgLe7siV_snRRkU_T-cFHv3AR6Ziwo,541
106
106
  parsl/executors/workqueue/exec_parsl_function.py,sha256=NtWNeBvRqksej38eRPw8zPBJ1CeW6vgaitve0tfz_qc,7801
107
- parsl/executors/workqueue/executor.py,sha256=niRuvBhspJjP6ghBKmYwkOLAjyGK1x1iuxBVCFSu6t8,49166
107
+ parsl/executors/workqueue/executor.py,sha256=fjcbln8cxs6AIffbJOtYFjUZHtTxcAecTzl3zGYPYUE,49018
108
108
  parsl/executors/workqueue/parsl_coprocess.py,sha256=6nmNqv7GT472J5smGFKm_TUjeFHy44i5Fl8pUovRoug,6046
109
109
  parsl/executors/workqueue/parsl_coprocess_stub.py,sha256=_bJmpPIgL42qM6bVzeEKt1Mn1trSP41rtJguXxPGfHI,735
110
110
  parsl/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -195,7 +195,7 @@ parsl/serialize/facade.py,sha256=0A--_bB_8e5RRT-weYu5Ak33zN_lqZeaJU1x7JXaoBQ,563
195
195
  parsl/serialize/proxystore.py,sha256=Yo-38odKlSKSuQfXU4cB5YM9sYV_302uPn1z_en19SU,1623
196
196
  parsl/tests/__init__.py,sha256=s_zoz7Ipgykh-QTQvctdpxENrMnmpXY8oe1bJbUmpqY,204
197
197
  parsl/tests/callables_helper.py,sha256=ceP1YYsNtrZgKT6MAIvpgdccEjQ_CpFEOnZBGHKGOx0,30
198
- parsl/tests/conftest.py,sha256=8JLS8HG4JxqTtEry4U2QSybDU69pHnGexCgTY9AWgVs,12246
198
+ parsl/tests/conftest.py,sha256=JrzruCQugpr7sUFRjsIz89PGYJM0H7G2S8FoQVdpd8k,13755
199
199
  parsl/tests/test_aalst_patterns.py,sha256=fi6JHKidV7vMJLv2nnu_-Q0ngGLc89mRm8rFrGIwiUM,9615
200
200
  parsl/tests/test_callables.py,sha256=_QsdS8v2nGgOj4_X69NFHZOGUnqbOrOMCA9pCJColZw,1974
201
201
  parsl/tests/test_flux.py,sha256=st9v55o5ZajK_LQUXh1saLwFh2gpaQFGG5mzdnJMNu0,5098
@@ -219,7 +219,7 @@ parsl/tests/configs/htex_local_alternate.py,sha256=6FsizxGFamcY_GhvJL4dHEXkchAAe
219
219
  parsl/tests/configs/htex_local_intask_staging.py,sha256=RZfHQbSN_GcAKssxZgMG6uD_VE9l2X1VMZ5eyqpU-d4,860
220
220
  parsl/tests/configs/htex_local_rsync_staging.py,sha256=KL76K8gEgbdf5S9RGDStBWrKteEY3B_2HuXVHF2b5xI,914
221
221
  parsl/tests/configs/local_adhoc.py,sha256=y91RPFcKFcH--9oljkRywxwy5KgEo6JwxRkFt97YDqM,443
222
- parsl/tests/configs/local_radical.py,sha256=-fk0vRUsYETBirm_PHSxBxu8qMwUwqidV_HarDxUZpQ,489
222
+ parsl/tests/configs/local_radical.py,sha256=V6mb3poummdeV67_Bw919TJh0cTLvShBAoWic9997LY,453
223
223
  parsl/tests/configs/local_radical_mpi.py,sha256=K6V2HbARujaow5DBAUYSIWt1RaYbt898FCVe7UJ5Ckw,570
224
224
  parsl/tests/configs/local_threads.py,sha256=oEnQSlom_JMLFX9_Ln49JAfOP3nSMbw8gTaDJo_NYfo,202
225
225
  parsl/tests/configs/local_threads_checkpoint.py,sha256=Ex7CI1Eo6wVRsem9uXTtbVJrkKc_vOYlVvCNa2RLpIo,286
@@ -304,8 +304,8 @@ parsl/tests/test_channels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
304
304
  parsl/tests/test_channels/test_large_output.py,sha256=PGeNSW_sN5mR7KF1hVL2CPfktydYxo4oNz1wVQ-ENN0,595
305
305
  parsl/tests/test_checkpointing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
306
306
  parsl/tests/test_checkpointing/test_periodic.py,sha256=Nb_3_eHYnMUJxYvI3y2Tum6cU07ZUtEawAtYsEsXPd0,1662
307
- parsl/tests/test_checkpointing/test_python_checkpoint_1.py,sha256=uAybnNRnk5YguvNc-5PsZ0HpYkGlTTeDQ3L-E9NLTF0,1272
308
- parsl/tests/test_checkpointing/test_python_checkpoint_2.py,sha256=i5TJWTvvM20u_M446bzsyL3Li9AXV8_Ymsc0XSevZck,1230
307
+ parsl/tests/test_checkpointing/test_python_checkpoint_1.py,sha256=7p_q5aFYYoRQpYmkFekuLOsPgTaILbj5-MMVCDP3Bsg,745
308
+ parsl/tests/test_checkpointing/test_python_checkpoint_2.py,sha256=f1s-qRzIzaCFJauEGU08fhFw6od3yGrMelk792WQuYI,1106
309
309
  parsl/tests/test_checkpointing/test_python_checkpoint_3.py,sha256=8Np2OpDeQ8sE1Hmd5rYZo1qgt2xOuR4t-d-41JyLCHI,823
310
310
  parsl/tests/test_checkpointing/test_regression_232.py,sha256=AsI6AJ0DcFaefAbEY9qWa41ER0VX-4yLuIdlgvBw360,2637
311
311
  parsl/tests/test_checkpointing/test_regression_233.py,sha256=jii7BKuygK6KMIGtg4IeBjix7Z28cYhv57rE9ixoXMU,1774
@@ -348,6 +348,7 @@ parsl/tests/test_monitoring/test_memoization_representation.py,sha256=tErT7zseSM
348
348
  parsl/tests/test_monitoring/test_viz_colouring.py,sha256=k8SiELxPtnGYZ4r02VQt46RC61fGDVC4nmY768snX1U,591
349
349
  parsl/tests/test_providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
350
350
  parsl/tests/test_providers/test_local_provider.py,sha256=G6Fuko22SvAtD7xhfQv8k_8HtJuFhZ8aHYcWQt073Pg,6968
351
+ parsl/tests/test_providers/test_slurm_instantiate.py,sha256=eW3pEZRIzZO1-eKFrBc7N5uoN5otwghgbqut74Kyqoc,500
351
352
  parsl/tests/test_python_apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
352
353
  parsl/tests/test_python_apps/test_arg_input_types.py,sha256=JXpfHiu8lr9BN6u1OzqFvGwBhxzsGTPMewHx6Wdo-HI,670
353
354
  parsl/tests/test_python_apps/test_basic.py,sha256=lFqh4ugePbp_FRiHGUXxzV34iS7l8C5UkxTHuLcpnYs,855
@@ -376,7 +377,7 @@ parsl/tests/test_python_apps/test_simple.py,sha256=LYGjdHvRizTpYzZePPvwKSPwrr2MP
376
377
  parsl/tests/test_python_apps/test_timeout.py,sha256=uENfT-1DharQkqkeG7a89E-gU1gjE7ATJrBZGUKvZSA,998
377
378
  parsl/tests/test_python_apps/test_type5.py,sha256=kUyA1NuFu-DDXsJNNvJLZVyewZBt7QAOhcGm2DWFTQw,777
378
379
  parsl/tests/test_radical/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
379
- parsl/tests/test_radical/test_mpi_funcs.py,sha256=vCb5u6fjafEhrPgxwOzUjGXC3O6Yjf3lSYaxUE98pKg,744
380
+ parsl/tests/test_radical/test_mpi_funcs.py,sha256=rLC01pdq6354pzHHm4PHMtePg0xOcQO2_2DwivoHvFg,765
380
381
  parsl/tests/test_regression/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
381
382
  parsl/tests/test_regression/test_1480.py,sha256=HNhuw7OYkBGMhN--XgKIl2JPHUj_hXlgL74oS3FqWk4,545
382
383
  parsl/tests/test_regression/test_1606_wait_for_current_tasks.py,sha256=frqPtaiVysevj9nCWoQlAeh9K1jQO5zaahr9ev_Mx_0,1134
@@ -397,28 +398,27 @@ parsl/tests/test_serialization/test_2555_caching_deserializer.py,sha256=J8__b4dj
397
398
  parsl/tests/test_serialization/test_basic.py,sha256=51KshqIk2RNr7S2iSkl5tZo40CJBb0h6uby8YPgOGlg,543
398
399
  parsl/tests/test_serialization/test_proxystore_configured.py,sha256=_JbMzeUgcR-1Ss2hGAb2v0LBA0fzKpNpfO-HaUCR7Yo,2293
399
400
  parsl/tests/test_serialization/test_proxystore_impl.py,sha256=Pn_4ulwCd7Tc6Qlmypq2ImT4DtErGDIfqHHmPTr7aOI,1226
400
- parsl/tests/test_staging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
401
+ parsl/tests/test_staging/__init__.py,sha256=WZl9EHSkfYiSoE3Gbulcq2ifmn7IFGUkasJIobL5T5A,208
401
402
  parsl/tests/test_staging/staging_provider.py,sha256=DEONOOGrYgDZimE3rkrbzFl_4KxhzmNJledh8Hho9fo,3242
402
403
  parsl/tests/test_staging/test_1316.py,sha256=pj1QbmOJSRES1R4Ov380MmVe6xXvPUXh4FB48nE6vjI,2687
403
404
  parsl/tests/test_staging/test_docs_1.py,sha256=SIGIYo9w2vwkQ-i9Io38sYYj8ns7uFrD1uziR_0Ae2w,628
404
405
  parsl/tests/test_staging/test_docs_2.py,sha256=zy6P6aanR27_U6ASDrB0YyG8udyRvA8r2HRDX5RcslU,463
405
- parsl/tests/test_staging/test_elaborate_noop_file.py,sha256=D1K5mu-meNQL8hieasdqktJ2ZDY5aSWBGNgvqRyV_Tg,2539
406
+ parsl/tests/test_staging/test_elaborate_noop_file.py,sha256=d694K2jKhyBM0bIY9j3w_huVjTU2CVFPgIRfYFpIQQM,2466
406
407
  parsl/tests/test_staging/test_staging_ftp.py,sha256=EkRoTcQ00FZGh8lDVYBdKb-pQ-ybW2Sx5vqGltoMGJ4,778
407
408
  parsl/tests/test_staging/test_staging_ftp_in_task.py,sha256=kR2XrGvbvVFDpHg53NnjO04kqEksTJjQAMQwYqBdb2M,884
408
409
  parsl/tests/test_staging/test_staging_globus.py,sha256=ds8nDH5dNbI10FV_GxMHyVaY6GPnuPPzkX9IiqROLF0,2339
409
- parsl/tests/test_staging/test_staging_https.py,sha256=alpbk-3Q025yZT26lg8-m1K4bsydLXysnRNMdub3elA,3750
410
- parsl/tests/test_staging/test_staging_https_in_task.py,sha256=Ezqcsr_wUXCYXv2sd9yR-zB-NJvxDDizfdvuptH6zBs,1036
410
+ parsl/tests/test_staging/test_staging_https.py,sha256=ESNuvdc_P5JoPaMjBM3ofi1mNJM0U6vahi9JgbCsrPw,3307
411
411
  parsl/tests/test_threads/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
412
412
  parsl/tests/test_threads/test_configs.py,sha256=QA9YjIMAtZ2jmkfOWqBzEfzQQcFVCDizH7Qwiy2HIMQ,909
413
413
  parsl/tests/test_threads/test_lazy_errors.py,sha256=nGhYfCMHFZYSy6YJ4gnAmiLl9SfYs0WVnuvj8DXQ9bw,560
414
414
  parsl/usage_tracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
415
415
  parsl/usage_tracking/usage.py,sha256=TEuAIm_U_G2ojZxvd0bbVa6gZlU61_mVRa2yJC9mGiI,7555
416
- parsl-2023.12.25.data/scripts/exec_parsl_function.py,sha256=NtWNeBvRqksej38eRPw8zPBJ1CeW6vgaitve0tfz_qc,7801
417
- parsl-2023.12.25.data/scripts/parsl_coprocess.py,sha256=kzX_1RI3V2KMKs6L-il4I1qkLNVodDKFXN_1FHB9fmM,6031
418
- parsl-2023.12.25.data/scripts/process_worker_pool.py,sha256=ytz3F8ZYeBr8tFqSRv2O9eZGdsID7oZRulBmmQmZaV8,34056
419
- parsl-2023.12.25.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
420
- parsl-2023.12.25.dist-info/METADATA,sha256=vri9mnQiuUfyLPY1aPnU1F6V12aehbagmSqm6wEdi1s,3818
421
- parsl-2023.12.25.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
422
- parsl-2023.12.25.dist-info/entry_points.txt,sha256=XqnsWDYoEcLbsMcpnYGKLEnSBmaIe1YoM5YsBdJG2tI,176
423
- parsl-2023.12.25.dist-info/top_level.txt,sha256=PIheYoUFQtF2icLsgOykgU-Cjuwr2Oi6On2jo5RYgRM,6
424
- parsl-2023.12.25.dist-info/RECORD,,
416
+ parsl-2024.1.8.data/scripts/exec_parsl_function.py,sha256=NtWNeBvRqksej38eRPw8zPBJ1CeW6vgaitve0tfz_qc,7801
417
+ parsl-2024.1.8.data/scripts/parsl_coprocess.py,sha256=kzX_1RI3V2KMKs6L-il4I1qkLNVodDKFXN_1FHB9fmM,6031
418
+ parsl-2024.1.8.data/scripts/process_worker_pool.py,sha256=ytz3F8ZYeBr8tFqSRv2O9eZGdsID7oZRulBmmQmZaV8,34056
419
+ parsl-2024.1.8.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
420
+ parsl-2024.1.8.dist-info/METADATA,sha256=hlXXmccniTKvGJcEsjbwqYV83HAExcoSG6_3lmSIBjM,3867
421
+ parsl-2024.1.8.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
422
+ parsl-2024.1.8.dist-info/entry_points.txt,sha256=XqnsWDYoEcLbsMcpnYGKLEnSBmaIe1YoM5YsBdJG2tI,176
423
+ parsl-2024.1.8.dist-info/top_level.txt,sha256=PIheYoUFQtF2icLsgOykgU-Cjuwr2Oi6On2jo5RYgRM,6
424
+ parsl-2024.1.8.dist-info/RECORD,,
@@ -1,34 +0,0 @@
1
- import pytest
2
-
3
- from parsl.app.app import python_app
4
- from parsl.data_provider.files import File
5
-
6
- from parsl.tests.configs.local_threads_http_in_task import fresh_config as local_config
7
-
8
-
9
- @python_app
10
- def sort_strings(inputs=[], outputs=[]):
11
- with open(inputs[0].filepath, 'r') as u:
12
- strs = u.readlines()
13
- strs.sort()
14
- with open(outputs[0].filepath, 'w') as s:
15
- for e in strs:
16
- s.write(e)
17
-
18
-
19
- @pytest.mark.local
20
- def test_staging_https():
21
- """Test staging for an http file
22
-
23
- Create a remote input file (https) that points to unsorted.txt.
24
- """
25
-
26
- # unsorted_file = File('https://testbed.petrel.host/test/public/unsorted.txt')
27
- unsorted_file = File('https://gist.githubusercontent.com/yadudoc/7f21dd15e64a421990a46766bfa5359c/'
28
- 'raw/7fe04978ea44f807088c349f6ecb0f6ee350ec49/unsorted.txt')
29
-
30
- # Create a local file for output data
31
- sorted_file = File('sorted.txt')
32
-
33
- f = sort_strings(inputs=[unsorted_file], outputs=[sorted_file])
34
- f.result()