parsl 2025.9.8__py3-none-any.whl → 2025.9.15__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.

Potentially problematic release.


This version of parsl might be problematic. Click here for more details.

Files changed (28) hide show
  1. parsl/curvezmq.py +0 -16
  2. parsl/executors/high_throughput/executor.py +8 -0
  3. parsl/executors/high_throughput/interchange.py +10 -1
  4. parsl/executors/high_throughput/zmq_pipes.py +29 -43
  5. parsl/monitoring/monitoring.py +2 -2
  6. parsl/multiprocessing.py +0 -49
  7. parsl/tests/test_curvezmq.py +0 -42
  8. parsl/tests/test_htex/test_command_concurrency_regression_1321.py +54 -0
  9. parsl/tests/test_htex/test_interchange_exit_bad_registration.py +2 -1
  10. parsl/tests/test_htex/test_priority_queue.py +1 -0
  11. parsl/tests/test_htex/test_zmq_binding.py +2 -1
  12. parsl/version.py +1 -1
  13. {parsl-2025.9.8.data → parsl-2025.9.15.data}/scripts/interchange.py +10 -1
  14. {parsl-2025.9.8.dist-info → parsl-2025.9.15.dist-info}/METADATA +2 -2
  15. {parsl-2025.9.8.dist-info → parsl-2025.9.15.dist-info}/RECORD +22 -27
  16. parsl/tests/site_tests/test_provider.py +0 -88
  17. parsl/tests/site_tests/test_site.py +0 -70
  18. parsl/tests/test_aalst_patterns.py +0 -474
  19. parsl/tests/test_docs/test_workflow2.py +0 -42
  20. parsl/tests/test_error_handling/test_rand_fail.py +0 -171
  21. parsl/tests/test_regression/test_854.py +0 -62
  22. {parsl-2025.9.8.data → parsl-2025.9.15.data}/scripts/exec_parsl_function.py +0 -0
  23. {parsl-2025.9.8.data → parsl-2025.9.15.data}/scripts/parsl_coprocess.py +0 -0
  24. {parsl-2025.9.8.data → parsl-2025.9.15.data}/scripts/process_worker_pool.py +0 -0
  25. {parsl-2025.9.8.dist-info → parsl-2025.9.15.dist-info}/LICENSE +0 -0
  26. {parsl-2025.9.8.dist-info → parsl-2025.9.15.dist-info}/WHEEL +0 -0
  27. {parsl-2025.9.8.dist-info → parsl-2025.9.15.dist-info}/entry_points.txt +0 -0
  28. {parsl-2025.9.8.dist-info → parsl-2025.9.15.dist-info}/top_level.txt +0 -0
@@ -1,88 +0,0 @@
1
- import argparse
2
- import logging
3
- import time
4
-
5
- import pytest
6
-
7
- import parsl
8
- from parsl.app.app import python_app # , bash_app
9
- from parsl.jobs.states import JobState
10
- from parsl.tests.site_tests.site_config_selector import fresh_config
11
-
12
- logger = logging.getLogger(__name__)
13
-
14
-
15
- @python_app
16
- def platform(sleep=10, stdout=None):
17
- import time
18
- time.sleep(sleep)
19
- return True
20
-
21
-
22
- @pytest.mark.local
23
- @pytest.mark.skip("This test cannot run on sites which cannot be identified by site_config_selector")
24
- def test_provider():
25
- """ Provider scaling
26
- """
27
- logger.info("Starting test_provider")
28
- config = fresh_config()
29
- name = config.executors[0].label
30
- parsl.load(config)
31
-
32
- dfk = parsl.dfk()
33
- logger.info("Trying to get executor : {}".format(name))
34
-
35
- x = platform(sleep=0)
36
- logger.info("Result is {}".format(x.result()))
37
-
38
- executor = dfk.executors[name]
39
- provider = dfk.executors[name].provider
40
-
41
- # At this point we should have 1 job
42
- _, current_jobs = executor._get_block_and_job_ids()
43
- assert len(current_jobs) == 1, "Expected 1 job at init, got {}".format(len(current_jobs))
44
-
45
- logger.info("Getting provider status (1)")
46
- status = provider.status(current_jobs)
47
- logger.info("Got provider status")
48
- assert status[0].state == JobState.RUNNING, "Expected job to be in state RUNNING"
49
-
50
- # Scale down to 0
51
- scale_in_blocks = executor.scale_in(blocks=1)
52
- logger.info("Now sleeping 60 seconds")
53
- time.sleep(60)
54
- logger.info("Sleep finished")
55
- logger.info("Getting provider status (2)")
56
- status = executor.status()
57
- logger.info("Got executor status")
58
- logger.info("Block status: {}".format(status))
59
- assert status[scale_in_blocks[0]].terminal is True, "Terminal state"
60
- logger.info("Job in terminal state")
61
-
62
- _, current_jobs = executor._get_block_and_job_ids()
63
- # PR 1952 stoped removing scale_in blocks from self.blocks_to_job_id
64
- # A new PR will handle removing blocks from self.block
65
- # this includes failed/completed/canceled blocks
66
- assert len(current_jobs) == 1, "Expected current_jobs == 1"
67
- dfk.cleanup()
68
- parsl.clear()
69
- logger.info("Ended test_provider")
70
- return True
71
-
72
-
73
- if __name__ == '__main__':
74
-
75
- parser = argparse.ArgumentParser()
76
- parser.add_argument("-c", "--count", default="4",
77
- help="Count of apps to launch")
78
- parser.add_argument("-t", "--time", default="60",
79
- help="Sleep time for each app")
80
-
81
- parser.add_argument("-d", "--debug", action='store_true',
82
- help="Count of apps to launch")
83
- args = parser.parse_args()
84
-
85
- if args.debug:
86
- parsl.set_stream_logger()
87
-
88
- x = test_provider()
@@ -1,70 +0,0 @@
1
- import argparse
2
-
3
- import pytest
4
-
5
- import parsl
6
- from parsl.app.app import python_app
7
- from parsl.tests.site_tests.site_config_selector import fresh_config
8
-
9
-
10
- @python_app
11
- def platform(sleep=10, stdout=None):
12
- import platform
13
- import time
14
- time.sleep(sleep)
15
- return platform.uname()
16
-
17
-
18
- @pytest.mark.local
19
- @pytest.mark.skip("The behaviour this test is testing is unclear: there is no guarantee that tasks will go to different nodes")
20
- def test_platform(n=2, sleep_dur=10):
21
- """ This should sleep to make sure that concurrent apps will go to different workers
22
- on different nodes.
23
- """
24
- config = fresh_config()
25
- if config.executors[0].label == "htex_local":
26
- return
27
-
28
- parsl.load(fresh_config())
29
-
30
- dfk = parsl.dfk()
31
- name = list(dfk.executors.keys())[0]
32
- print("Trying to get executor : ", name)
33
-
34
- x = [platform(sleep=1) for i in range(2)]
35
- print([i.result() for i in x])
36
-
37
- print("Executor : ", dfk.executors[name])
38
- print("Connected : ", dfk.executors[name].connected_workers())
39
- print("Outstanding : ", dfk.executors[name].outstanding())
40
-
41
- d = []
42
- for i in range(0, n):
43
- x = platform(sleep=sleep_dur)
44
- d.append(x)
45
-
46
- pinfo = set([i.result()for i in d])
47
- assert len(pinfo) == 2, "Expected two nodes, instead got {}".format(pinfo)
48
-
49
- print("Test passed")
50
-
51
- dfk.cleanup()
52
- parsl.clear()
53
- return True
54
-
55
-
56
- if __name__ == '__main__':
57
-
58
- parser = argparse.ArgumentParser()
59
- parser.add_argument("-c", "--count", default="4",
60
- help="Count of apps to launch")
61
- parser.add_argument("-t", "--time", default="60",
62
- help="Sleep time for each app")
63
- parser.add_argument("-d", "--debug", action='store_true',
64
- help="Count of apps to launch")
65
- args = parser.parse_args()
66
-
67
- if args.debug:
68
- parsl.set_stream_logger()
69
-
70
- x = test_platform(n=int(args.count), sleep_dur=int(args.time))
@@ -1,474 +0,0 @@
1
- import random
2
- import time
3
-
4
- import pytest
5
-
6
- from parsl.app.app import python_app
7
- from parsl.tests.configs.local_threads import config
8
-
9
- pytestmark = pytest.mark.skip('not asserting anything')
10
-
11
-
12
- local_config = config
13
-
14
-
15
- @python_app
16
- def multiply_rand(x):
17
- return x * random.randint(1, 10)
18
-
19
-
20
- @python_app
21
- def square_sum(x, y):
22
- return (x + y) ** 2
23
-
24
-
25
- @python_app
26
- def double_sum(x, y):
27
- return 2 * (x + y)
28
-
29
-
30
- @python_app
31
- def subtract(x, y):
32
- return y - x
33
-
34
-
35
- @python_app
36
- def add_two(x):
37
- return x + 2
38
-
39
-
40
- @python_app
41
- def rand():
42
- x = random.randint(1, 100)
43
- return x
44
-
45
-
46
- @python_app
47
- def square(x):
48
- z = x ** 2
49
- return z
50
-
51
-
52
- @python_app
53
- def cubed(x):
54
- return x ** 3
55
-
56
-
57
- @python_app
58
- def sleep_cubed(x):
59
- if x < 5:
60
- time.sleep(7)
61
- return x ** 3
62
- else:
63
- return x ** 3
64
-
65
-
66
- @python_app
67
- def increment(x):
68
- return x + 1
69
-
70
-
71
- @python_app
72
- def slow_increment(x, dur=1):
73
- import time
74
- time.sleep(dur)
75
- return x + 1
76
-
77
-
78
- @python_app
79
- def join(inputs=[]):
80
- return sum(inputs)
81
-
82
-
83
- @python_app
84
- def join_three(x, y, z):
85
- return x + y + z
86
-
87
-
88
- @python_app
89
- def sleep_square(x):
90
- if x > 5:
91
- return x ** 2
92
- else:
93
- time.sleep(5)
94
- return x ** 2
95
-
96
-
97
- @python_app
98
- def sum_results(x=[]):
99
- total = 0
100
- for r in x:
101
- total += r.result()
102
- return total
103
-
104
-
105
- @python_app
106
- def add(x, y):
107
- return x + y
108
-
109
-
110
- @python_app
111
- def sum_list(x=[]):
112
- return sum(x)
113
-
114
-
115
- @python_app
116
- def sum_lists(x=[], y=[], z=[]):
117
- total = 0
118
- for i in range(len(x)):
119
- total += x[i].result()
120
- for j in range(len(y)):
121
- total += y[j].result()
122
- for k in range(len(z)):
123
- total += z[k].result()
124
- return total
125
-
126
-
127
- @python_app
128
- def sum_elements(x=[], y=[], z=[]):
129
- total = 0
130
- for i in range(len(x)):
131
- total += x[i].result()
132
- for j in range(len(y)):
133
- if y[j] is not None:
134
- total += y[j].result()
135
- for k in range(len(z)):
136
- total += z[k].result()
137
- return total
138
-
139
-
140
- @python_app
141
- def simple_sum_elements(x, y, z):
142
- return x + y + z
143
-
144
-
145
- @python_app
146
- def eval_number(x):
147
- if x > 5:
148
- print("Larger than 5")
149
- return return_one().result()
150
- else:
151
- print("Less than or equal to 5")
152
- return return_zero().result()
153
-
154
-
155
- @python_app
156
- def return_one():
157
- return 1
158
-
159
-
160
- @python_app
161
- def return_zero():
162
- return 0
163
-
164
-
165
- @python_app
166
- def xor_split():
167
- """Test XOR split. Do A if x else B
168
- """
169
- x = rand()
170
-
171
- if x.result() > 5:
172
- print("Result > 5")
173
- return 0
174
- else:
175
- print("Result < 5")
176
- return 1
177
-
178
-
179
- @python_app
180
- def arb_rand():
181
- x = random.randint(2, 10)
182
- print(x)
183
- print("random")
184
- return arb_square(x).result()
185
-
186
-
187
- @python_app
188
- def arb_square(x):
189
- y = x ** 2
190
- if y > 25:
191
- return increment(y).result()
192
- else:
193
- return arb_cubed(x).result()
194
-
195
-
196
- @python_app
197
- def arb_cubed(x):
198
- y = x ** 3
199
- return arb_square(y).result()
200
-
201
-
202
- def test_increment_p1a(depth=5):
203
- """Test simple pipeline A->B...->N
204
- """
205
- futs = {0: 0}
206
- for i in range(1, depth):
207
- futs[i] = increment(futs[i - 1])
208
-
209
- print([futs[i].result() for i in futs if not isinstance(futs[i], int)])
210
-
211
-
212
- def test_increment_slow_p1b(depth=4):
213
- """Test simple pipeline A->B...->N with delay
214
- """
215
- futs = {0: 0}
216
- for i in range(1, depth):
217
- futs[i] = slow_increment(futs[i - 1], 0.5)
218
-
219
- print(futs[i])
220
- print([futs[i].result() for i in futs if not isinstance(futs[i], int)])
221
-
222
-
223
- def test_sequence_p1c(x=5):
224
- flights = []
225
- miles = []
226
- for i in range(x):
227
- flights.append(rand())
228
- for j in range(len(flights)):
229
- miles.append(multiply_rand(flights[j].result()))
230
- for k in range(len(miles)):
231
- print(miles[k].result())
232
-
233
-
234
- def test_and_split_p2a(depth=5):
235
- """Test simple pipeline A->B...->N
236
- """
237
- futs = {}
238
- for i in range(depth):
239
- futs[i] = increment(i)
240
-
241
- print([futs[i].result() for i in futs])
242
-
243
-
244
- def test_parallel_split_p2b(x=4):
245
- for i in range(x):
246
- num = rand().result()
247
- y = square(num).result()
248
- z = cubed(num).result()
249
- print(y)
250
- print(z)
251
-
252
-
253
- def test_and_join_p3a(depth=5):
254
- """Test simple pipeline A->B...->N
255
- """
256
- futs = {}
257
- for i in range(depth):
258
- futs[i] = increment(i)
259
-
260
- x = join(inputs=futs.values())
261
- print("Final sum: ", x.result())
262
- assert x.result() == sum([i + 1 for i in range(depth)])
263
-
264
-
265
- def test_synchronization_p3b(x=5):
266
- i = []
267
- for j in range(x):
268
- a = increment(j).result()
269
- b = square(j).result()
270
- i.append(add(a, b).result())
271
- total = sum(i)
272
- print(total)
273
-
274
-
275
- def test_xor_split_p4a():
276
- """Test XOR split. Do A if x else B
277
- """
278
- x = rand()
279
-
280
- if x.result() > 5:
281
- print("Result > 5")
282
- else:
283
- print("Result < 5")
284
-
285
-
286
- def test_xor_split_p4b(x=4):
287
- num = []
288
- for i in range(x):
289
- num.append(eval_number(rand().result()))
290
- for i in range(len(num)):
291
- print(num[i].result())
292
-
293
-
294
- def test_xor_join_p5(x=2):
295
- print(join_three(square(x).result(), increment(
296
- x).result(), cubed(x).result()).result())
297
-
298
-
299
- def test_or_split_p6(x=4, y=5):
300
- if x < 5:
301
- print(add(x, y).result())
302
- if y > 7:
303
- print(subtract(x, y).result())
304
- if x >= 5:
305
- print(square_sum(x, y).result())
306
- if y <= 7:
307
- print(double_sum(x, y).result())
308
-
309
-
310
- def test_synchronizing_merge_p7(x=4, y=5):
311
- num = []
312
- if x < 5:
313
- num.append(add(x, y).result())
314
- if y > 7:
315
- num.append(subtract(x, y).result())
316
- if x >= 5:
317
- num.append(square_sum(x, y).result())
318
- if y <= 7:
319
- num.append(double_sum(x, y).result())
320
- print(sum_list(num).result())
321
-
322
-
323
- def test_multi_merge_p8():
324
- r = rand().result()
325
- num1 = cubed(add_two(square(r).result()).result())
326
- num2 = cubed(add_two(increment(r).result()).result())
327
- print(add(num1.result(), num2.result()).result())
328
-
329
-
330
- def test_discriminator_p9(x=4):
331
- squares = []
332
- cubes = []
333
- total = []
334
- for i in range(x):
335
- squares.append(square(rand().result()))
336
- cubes.append(cubed(rand().result()))
337
- while squares[i].done() is False and cubes[i].done() is False:
338
- pass
339
- total.append(squares[i].result() + cubes[i].result())
340
- for i in range(x):
341
- print(total[i])
342
-
343
-
344
- def test_arbitrary_cycles_p10(x=2):
345
- numbers = []
346
- for i in range(x):
347
- numbers.append(arb_rand())
348
- for i in range(x):
349
- print(numbers[i].result())
350
-
351
-
352
- def test_implicit_termination_p11(x=5):
353
- numbers = []
354
- numbers.append(slow_increment(rand().result()))
355
- for i in range(x):
356
- y = rand().result()
357
- numbers.append(square(increment(y).result()).result())
358
- print(numbers[0].result())
359
- return
360
-
361
-
362
- def test_multi_instances_p12(x=5):
363
- numbers = []
364
- for i in range(x):
365
- numbers.append(square(rand().result()))
366
- print(numbers[i])
367
- print([numbers[i].result() for i in range(len(numbers))])
368
-
369
-
370
- def test_multi_instances_priori_p13():
371
- x = increment(square(rand().result()).result()).result()
372
- y = increment(square(rand().result()).result()).result()
373
- z = increment(square(rand().result()).result()).result()
374
- total = simple_sum_elements(x, y, z).result()
375
- print(total)
376
-
377
-
378
- def test_multi_instances_without_runtime_p15():
379
- numbers = []
380
- while sum_list(numbers).result() < 20:
381
- numbers.append(increment(rand().result()).result())
382
- print(sum_list(numbers).result())
383
-
384
-
385
- def test_multi_instances_runtime_p14(x=5):
386
- numbers = []
387
- [numbers.append(increment(square(rand().result()).result()))
388
- for i in range(x)]
389
- total = sum_results(numbers)
390
- print(total.result())
391
-
392
-
393
- def test_deferred_choice_p16():
394
- r = rand().result()
395
- s = sleep_square(r)
396
- i = slow_increment(r)
397
- print(s.done())
398
- while s.done() is not True and i.done() is not True:
399
- pass
400
- if s.done() is True:
401
- print(s.result())
402
- elif i.done() is True:
403
- print(i.result())
404
-
405
-
406
- def test_unordered_sequence_p17():
407
- r = rand().result()
408
- s = sleep_square(r)
409
- i = slow_increment(r)
410
- print(s.done())
411
- while s.done() is not True and i.done() is not True:
412
- pass
413
- if i.done() is True:
414
- print(i.result())
415
- print(sleep_square(i.result()).result())
416
- elif s.done() is True:
417
- print(s.result())
418
- print(slow_increment(s.result()).result())
419
-
420
-
421
- def test_milestone_p18():
422
- r = rand().result()
423
- i = increment(r)
424
- s = sleep_square(r)
425
- while s.done() is not True:
426
- if i.done() is True:
427
- print(cubed(r).result())
428
- return
429
-
430
-
431
- def test_withdraw_activity_p19(x=3):
432
- cubes = []
433
- squares = []
434
- increments = []
435
- for i in range(x):
436
- r = rand().result()
437
- cubes.append(sleep_cubed(r))
438
- squares.append(square(r))
439
- if cubes[i].done() is True:
440
- print(True)
441
- squares[i] = None
442
- else:
443
- print(False)
444
- increments.append(increment(r))
445
- print(sum_elements(cubes, squares, increments).result())
446
-
447
-
448
- def test_cancel_case_p20(x=3):
449
- cubes = []
450
- squares = []
451
- increments = []
452
- for i in range(x):
453
- r = rand().result()
454
- cubes.append(cubed(r))
455
- squares.append(square(r))
456
- increments.append(increment(r))
457
- r = random.randint(1, 30)
458
- print(r)
459
- if r > 20:
460
- del cubes[:]
461
- if r < 20 and r > 10:
462
- del squares[:]
463
- if r < 10:
464
- del increments[:]
465
- print(sum_lists(cubes, squares, increments).result())
466
-
467
-
468
- def test_xor_parallel_split(width=2):
469
- futures = {}
470
-
471
- for i in range(width):
472
- futures[i] = xor_split()
473
-
474
- print([futures[key].result() for key in futures])
@@ -1,42 +0,0 @@
1
- import time
2
-
3
- import pytest
4
-
5
- from parsl.app.app import python_app
6
- from parsl.tests.configs.local_threads import config
7
-
8
- local_config = config
9
-
10
-
11
- @python_app
12
- def wait_sleep_double(x, fu_1, fu_2):
13
- import time
14
- time.sleep(2) # Sleep for 2 seconds
15
- return x * 2
16
-
17
-
18
- @pytest.mark.skip('fails with pytest+xdist')
19
- def test_parallel(N=2):
20
- """Parallel workflow example from docs on composing a workflow
21
- """
22
-
23
- # Launch two apps, which will execute in parallel, since they don't have to
24
- # wait on any futures
25
- start = time.time()
26
- doubled_x = wait_sleep_double(N, None, None)
27
- doubled_y = wait_sleep_double(N, None, None)
28
-
29
- # The third depends on the first two :
30
- # doubled_x doubled_y (2 s)
31
- # \ /
32
- # doublex_z (2 s)
33
- doubled_z = wait_sleep_double(N, doubled_x, doubled_y)
34
-
35
- # doubled_z will be done in ~4s
36
- print(doubled_z.result())
37
- time.time()
38
- delta = time.time() - start
39
-
40
- assert doubled_z.result() == N * \
41
- 2, "Expected doubled_z = N*2 = {0}".format(N * 2)
42
- assert delta > 4 and delta < 5, "Time delta exceeded expected 4 < duration < 5"