modal 0.62.115__py3-none-any.whl → 0.72.13__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.
- modal/__init__.py +13 -9
- modal/__main__.py +41 -3
- modal/_clustered_functions.py +80 -0
- modal/_clustered_functions.pyi +22 -0
- modal/_container_entrypoint.py +402 -398
- modal/_ipython.py +3 -13
- modal/_location.py +17 -10
- modal/_output.py +243 -99
- modal/_pty.py +2 -2
- modal/_resolver.py +55 -60
- modal/_resources.py +26 -7
- modal/_runtime/__init__.py +1 -0
- modal/_runtime/asgi.py +519 -0
- modal/_runtime/container_io_manager.py +1025 -0
- modal/{execution_context.py → _runtime/execution_context.py} +11 -2
- modal/_runtime/telemetry.py +169 -0
- modal/_runtime/user_code_imports.py +356 -0
- modal/_serialization.py +123 -6
- modal/_traceback.py +47 -187
- modal/_tunnel.py +50 -14
- modal/_tunnel.pyi +19 -36
- modal/_utils/app_utils.py +3 -17
- modal/_utils/async_utils.py +386 -104
- modal/_utils/blob_utils.py +157 -186
- modal/_utils/bytes_io_segment_payload.py +97 -0
- modal/_utils/deprecation.py +89 -0
- modal/_utils/docker_utils.py +98 -0
- modal/_utils/function_utils.py +299 -98
- modal/_utils/grpc_testing.py +47 -34
- modal/_utils/grpc_utils.py +54 -21
- modal/_utils/hash_utils.py +51 -10
- modal/_utils/http_utils.py +39 -9
- modal/_utils/logger.py +2 -1
- modal/_utils/mount_utils.py +34 -16
- modal/_utils/name_utils.py +58 -0
- modal/_utils/package_utils.py +14 -1
- modal/_utils/pattern_utils.py +205 -0
- modal/_utils/rand_pb_testing.py +3 -3
- modal/_utils/shell_utils.py +15 -49
- modal/_vendor/a2wsgi_wsgi.py +62 -72
- modal/_vendor/cloudpickle.py +1 -1
- modal/_watcher.py +12 -10
- modal/app.py +561 -323
- modal/app.pyi +474 -262
- modal/call_graph.py +7 -6
- modal/cli/_download.py +22 -6
- modal/cli/_traceback.py +200 -0
- modal/cli/app.py +203 -42
- modal/cli/config.py +12 -5
- modal/cli/container.py +61 -13
- modal/cli/dict.py +128 -0
- modal/cli/entry_point.py +26 -13
- modal/cli/environment.py +40 -9
- modal/cli/import_refs.py +21 -48
- modal/cli/launch.py +28 -14
- modal/cli/network_file_system.py +57 -21
- modal/cli/profile.py +1 -1
- modal/cli/programs/run_jupyter.py +34 -9
- modal/cli/programs/vscode.py +58 -8
- modal/cli/queues.py +131 -0
- modal/cli/run.py +199 -96
- modal/cli/secret.py +5 -4
- modal/cli/token.py +7 -2
- modal/cli/utils.py +74 -8
- modal/cli/volume.py +97 -56
- modal/client.py +248 -144
- modal/client.pyi +156 -124
- modal/cloud_bucket_mount.py +43 -30
- modal/cloud_bucket_mount.pyi +32 -25
- modal/cls.py +528 -141
- modal/cls.pyi +189 -145
- modal/config.py +32 -15
- modal/container_process.py +177 -0
- modal/container_process.pyi +82 -0
- modal/dict.py +50 -54
- modal/dict.pyi +120 -164
- modal/environments.py +106 -5
- modal/environments.pyi +77 -25
- modal/exception.py +30 -43
- modal/experimental.py +62 -2
- modal/file_io.py +537 -0
- modal/file_io.pyi +235 -0
- modal/file_pattern_matcher.py +196 -0
- modal/functions.py +846 -428
- modal/functions.pyi +446 -387
- modal/gpu.py +57 -44
- modal/image.py +943 -417
- modal/image.pyi +584 -245
- modal/io_streams.py +434 -0
- modal/io_streams.pyi +122 -0
- modal/mount.py +223 -90
- modal/mount.pyi +241 -243
- modal/network_file_system.py +85 -86
- modal/network_file_system.pyi +151 -110
- modal/object.py +66 -36
- modal/object.pyi +166 -143
- modal/output.py +63 -0
- modal/parallel_map.py +73 -47
- modal/parallel_map.pyi +51 -63
- modal/partial_function.py +272 -107
- modal/partial_function.pyi +219 -120
- modal/proxy.py +15 -12
- modal/proxy.pyi +3 -8
- modal/queue.py +96 -72
- modal/queue.pyi +210 -135
- modal/requirements/2024.04.txt +2 -1
- modal/requirements/2024.10.txt +16 -0
- modal/requirements/README.md +21 -0
- modal/requirements/base-images.json +22 -0
- modal/retries.py +45 -4
- modal/runner.py +325 -203
- modal/runner.pyi +124 -110
- modal/running_app.py +27 -4
- modal/sandbox.py +509 -231
- modal/sandbox.pyi +396 -169
- modal/schedule.py +2 -2
- modal/scheduler_placement.py +20 -3
- modal/secret.py +41 -25
- modal/secret.pyi +62 -42
- modal/serving.py +39 -49
- modal/serving.pyi +37 -43
- modal/stream_type.py +15 -0
- modal/token_flow.py +5 -3
- modal/token_flow.pyi +37 -32
- modal/volume.py +123 -137
- modal/volume.pyi +228 -221
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/METADATA +5 -5
- modal-0.72.13.dist-info/RECORD +174 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/top_level.txt +0 -1
- modal_docs/gen_reference_docs.py +3 -1
- modal_docs/mdmd/mdmd.py +0 -1
- modal_docs/mdmd/signatures.py +1 -2
- modal_global_objects/images/base_images.py +28 -0
- modal_global_objects/mounts/python_standalone.py +2 -2
- modal_proto/__init__.py +1 -1
- modal_proto/api.proto +1231 -531
- modal_proto/api_grpc.py +750 -430
- modal_proto/api_pb2.py +2102 -1176
- modal_proto/api_pb2.pyi +8859 -0
- modal_proto/api_pb2_grpc.py +1329 -675
- modal_proto/api_pb2_grpc.pyi +1416 -0
- modal_proto/modal_api_grpc.py +149 -0
- modal_proto/modal_options_grpc.py +3 -0
- modal_proto/options_pb2.pyi +20 -0
- modal_proto/options_pb2_grpc.pyi +7 -0
- modal_proto/py.typed +0 -0
- modal_version/__init__.py +1 -1
- modal_version/_version_generated.py +2 -2
- modal/_asgi.py +0 -370
- modal/_container_exec.py +0 -128
- modal/_container_io_manager.py +0 -646
- modal/_container_io_manager.pyi +0 -412
- modal/_sandbox_shell.py +0 -49
- modal/app_utils.py +0 -20
- modal/app_utils.pyi +0 -17
- modal/execution_context.pyi +0 -37
- modal/shared_volume.py +0 -23
- modal/shared_volume.pyi +0 -24
- modal-0.62.115.dist-info/RECORD +0 -207
- modal_global_objects/images/conda.py +0 -15
- modal_global_objects/images/debian_slim.py +0 -15
- modal_global_objects/images/micromamba.py +0 -15
- test/__init__.py +0 -1
- test/aio_test.py +0 -12
- test/async_utils_test.py +0 -279
- test/blob_test.py +0 -67
- test/cli_imports_test.py +0 -149
- test/cli_test.py +0 -674
- test/client_test.py +0 -203
- test/cloud_bucket_mount_test.py +0 -22
- test/cls_test.py +0 -636
- test/config_test.py +0 -149
- test/conftest.py +0 -1485
- test/container_app_test.py +0 -50
- test/container_test.py +0 -1405
- test/cpu_test.py +0 -23
- test/decorator_test.py +0 -85
- test/deprecation_test.py +0 -34
- test/dict_test.py +0 -51
- test/e2e_test.py +0 -68
- test/error_test.py +0 -7
- test/function_serialization_test.py +0 -32
- test/function_test.py +0 -791
- test/function_utils_test.py +0 -101
- test/gpu_test.py +0 -159
- test/grpc_utils_test.py +0 -82
- test/helpers.py +0 -47
- test/image_test.py +0 -814
- test/live_reload_test.py +0 -80
- test/lookup_test.py +0 -70
- test/mdmd_test.py +0 -329
- test/mount_test.py +0 -162
- test/mounted_files_test.py +0 -327
- test/network_file_system_test.py +0 -188
- test/notebook_test.py +0 -66
- test/object_test.py +0 -41
- test/package_utils_test.py +0 -25
- test/queue_test.py +0 -115
- test/resolver_test.py +0 -59
- test/retries_test.py +0 -67
- test/runner_test.py +0 -85
- test/sandbox_test.py +0 -191
- test/schedule_test.py +0 -15
- test/scheduler_placement_test.py +0 -57
- test/secret_test.py +0 -89
- test/serialization_test.py +0 -50
- test/stub_composition_test.py +0 -10
- test/stub_test.py +0 -361
- test/test_asgi_wrapper.py +0 -234
- test/token_flow_test.py +0 -18
- test/traceback_test.py +0 -135
- test/tunnel_test.py +0 -29
- test/utils_test.py +0 -88
- test/version_test.py +0 -14
- test/volume_test.py +0 -397
- test/watcher_test.py +0 -58
- test/webhook_test.py +0 -145
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/LICENSE +0 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/WHEEL +0 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/entry_points.txt +0 -0
modal-0.62.115.dist-info/RECORD
DELETED
@@ -1,207 +0,0 @@
|
|
1
|
-
modal/__init__.py,sha256=NBneFs9SID4d9fX3Q9FLdr1-pburBBP1mFXlRauxmRo,2095
|
2
|
-
modal/__main__.py,sha256=EKalcwy_6N0L5iqIvlYpXihi3zxy9HNuUMvnbraoTrk,1141
|
3
|
-
modal/_asgi.py,sha256=pumwIq8Sk5bXpaZpNRmo5QLykRwH0yCqPzlMkB9eCfs,15484
|
4
|
-
modal/_container_entrypoint.py,sha256=pNwBSY3piJ1kwTNbxJXm5oSlHqaCU4UdjdTpp7vIPpE,28456
|
5
|
-
modal/_container_exec.py,sha256=FiaSBUD0UkQRF8hW0AFf0rbqC8lb87f3EGeg7Mr5dx4,4349
|
6
|
-
modal/_container_io_manager.py,sha256=W2CSjRcvDGL4oePRvLx0Ymogy8-M5qJcitwkIHw_FwA,28110
|
7
|
-
modal/_container_io_manager.pyi,sha256=G5qC3Vy2Sh7Z_q1zlRvCxH-Cw06lGLBcTRl__I90UXY,12406
|
8
|
-
modal/_ipython.py,sha256=HF_DYy0e0qM9WnGDmTY30s1RxzGya9GeORCauCEpRaE,450
|
9
|
-
modal/_location.py,sha256=_SdCPzVOl7HRwLWIxzTJjhdpOo1sIl4flfEJ-bAbiDE,929
|
10
|
-
modal/_output.py,sha256=1GXKp-Qr-C5oe0e4A5epTgcIFhcp5Cko3HG_ircLFWg,20565
|
11
|
-
modal/_proxy_tunnel.py,sha256=gnKyCfmVB7x2d1A6c-JDysNIP3kEFxmXzhcXhPrzPn0,1906
|
12
|
-
modal/_pty.py,sha256=GhzrHKZpoI-YHMDN7LoySlSYLpoJ4yGPSF-fqiNsFrM,1336
|
13
|
-
modal/_resolver.py,sha256=FAkA_3_VK74MEiNOmYH9s2mThD38Z7QNWhNNY3r7qcI,7077
|
14
|
-
modal/_resources.py,sha256=4pOUFIgF2nwiKm744Q49fU4ZBZABywOAScttxUhGAgs,1142
|
15
|
-
modal/_sandbox_shell.py,sha256=OtkeMqOymFVqDBWt3kmT6_4mslPu0ZCfjqYjwUb6cGE,1658
|
16
|
-
modal/_serialization.py,sha256=sDVn7q1YMmTyNW-LKRoYmDs3Cyq8pQ0nbfuT0LqbTHo,12833
|
17
|
-
modal/_traceback.py,sha256=l6y-flU7rQK3YelSthHv4Paurw3rA5q9KofBRRVHCVM,10029
|
18
|
-
modal/_tunnel.py,sha256=L3ojxnKMMslYXN5_HFclCLGjOEIxKif8UUa0nAjrnYM,5171
|
19
|
-
modal/_tunnel.pyi,sha256=MhcFhkpt-Fo9dA59qhXtoNA9ktyJzwtmGj0vWaUdFiM,1337
|
20
|
-
modal/_watcher.py,sha256=WFnaF5npnkFb-gGG9X4Tc5DZDVqXDU-STSvfJKg7SOs,3605
|
21
|
-
modal/app.py,sha256=JF-_Bf4bc6fVVQtZd1o-54C1lqupF4pE0V4fjV8YeJc,36315
|
22
|
-
modal/app.pyi,sha256=3kCxWzHat6__uZzkjJ44X_NfKySfVy-TfldmR0BnvFg,19403
|
23
|
-
modal/app_utils.py,sha256=EuRot0Xhrq5m7bQgM8yVZkRxiKfnBMJSFguu-lsJ5Vs,748
|
24
|
-
modal/app_utils.pyi,sha256=9u0YQMoIt158Uh-HxUGrnuBeMFdBLdi_DLHHZNSGU-M,613
|
25
|
-
modal/call_graph.py,sha256=KhqmbJPlcpL-PO0N_lrK8VHoXK_xAHq5IhZ9A9rW9Zk,2524
|
26
|
-
modal/client.py,sha256=MdXWbQla4hIQFyB9pqgS5Nonq6r9NxyOx6covnvHepQ,10930
|
27
|
-
modal/client.pyi,sha256=zC7j10hwLcFqc27m14IK00LSxKjxRh8fOSdPZ3nOpOs,4048
|
28
|
-
modal/cloud_bucket_mount.py,sha256=5BXwNCF51V2EX0rbVAltRoPaBsTqdjJPC_IkUI0uRPs,5700
|
29
|
-
modal/cloud_bucket_mount.pyi,sha256=HQy0m3uXIziIrTbftNY_tja5m0tlYro1Q5vQ2fQq2lM,1217
|
30
|
-
modal/cls.py,sha256=6WXC5lvxFJi1QVAYMMAOq7cLAia0nP-Tp1ljhDQPUdo,12734
|
31
|
-
modal/cls.pyi,sha256=2gjM9x08Hs9wsdxWmFGdAt4W_hB_jBzqyBAecQ31mNo,6521
|
32
|
-
modal/config.py,sha256=_5PGiL2HsxDAL1THv1-FpZXvaiFIaNnT0xd1vGjBhTI,9980
|
33
|
-
modal/dict.py,sha256=91zpSn7O1ofrEyHBy8_yqD727C3oAnUx2ACwlSg4q0Y,12642
|
34
|
-
modal/dict.pyi,sha256=FvyO-otgDFPmYD3b-u09ROkP4Fw4bBFhZy79Q_r0M4s,7268
|
35
|
-
modal/environments.py,sha256=xOsBpVpjyBwA-0PVYAQAV_qUtEMxnYzu3Qpmkcqsbeo,2452
|
36
|
-
modal/environments.pyi,sha256=HMSB6AeWCXeQcrsEyNiWwSzou3lD0G6h6R_4-AFU3gg,1439
|
37
|
-
modal/exception.py,sha256=4AdUkT0uya5c4QDkO9mlpwfvu9C2SfpmjsbUNlfJH2k,5999
|
38
|
-
modal/execution_context.py,sha256=Rt_nJ6jI0nGtK_6hO7r_78OzlC1fnfwuOX3OhAqr9k4,2324
|
39
|
-
modal/execution_context.pyi,sha256=PZ-qh_AkmksTC7vJOA1HEzVsP1B9GI3yP2novHu1dUA,653
|
40
|
-
modal/experimental.py,sha256=-nXs5bQoFlQHsJWf6YfIO41BrMoYJuVKr1Pil-EUOOU,316
|
41
|
-
modal/functions.py,sha256=0ye39wcnKUTOF3KeVGM5-HHnm2G65BD4eoK_J-jUTaA,47804
|
42
|
-
modal/functions.pyi,sha256=84BhAt_MIE2yShcGj8BJO4FWpHb50Mo5S6oeV6Jjy_4,19891
|
43
|
-
modal/gpu.py,sha256=hZc8qWwp1iDsUwuilNjDWwL1ci4NINhMlUxPfKgn7Zs,8037
|
44
|
-
modal/image.py,sha256=nSn-kCY9SocWiauGrXbK4kPa8GBeDFmwecHcpe4tHcg,68296
|
45
|
-
modal/image.pyi,sha256=hA0O-YEJKOyyUo3ie9AaNpCgnkjUBXhTIfx0xcfSlMo,18339
|
46
|
-
modal/mount.py,sha256=kVOnSODWbGmCuxOKkoDX9Jt5Y4oQHXutgRQJWauYzlc,26212
|
47
|
-
modal/mount.pyi,sha256=Rwxg6Mxml1jXOLz9Kl8b-SQeJqM73gdHkzAgx_1LrBA,9710
|
48
|
-
modal/network_file_system.py,sha256=hc14g2eYejkfIDDmR-i00EMNVxpxGMpXbYkqheCb0N0,14428
|
49
|
-
modal/network_file_system.pyi,sha256=TI04zO5AUG58HwPIGCD0aB3G53DjUx-XdZy3EkbxvDo,6280
|
50
|
-
modal/object.py,sha256=Ja5F9kJlATJvJM7WGBG26cQwW--DICSq8N0aSJL2oTA,8329
|
51
|
-
modal/object.pyi,sha256=NVYTuTldnB5j8724Qx-dd0R8tWeuXBfh9IGSBMaw2aw,7573
|
52
|
-
modal/parallel_map.py,sha256=3Jvm-SfAeKyqfi_2081UQWB1InVrKHcVz7E-nL7IXjA,15151
|
53
|
-
modal/parallel_map.pyi,sha256=dYuVV0z1dniz9gt4iksCAkVKTggoml4Y5xjSloqIYE8,2400
|
54
|
-
modal/partial_function.py,sha256=yErY8Mh9O0OLlJKrV2bsTpRtSG9VuQGdZJE80wjwKM8,19975
|
55
|
-
modal/partial_function.pyi,sha256=1nfByULFi2rNIiCaFQR3YTv-FwD76aHpN_7iiO1o30E,6172
|
56
|
-
modal/proxy.py,sha256=ey5IlDkPfb0zHGSsIQjgtFsLZwdjCoCp-ecIJlbDo5w,1307
|
57
|
-
modal/proxy.pyi,sha256=Db8boRetc0K7sAUuKw-mg4eoRAX0GB7vyHOHlwuCEs8,428
|
58
|
-
modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
59
|
-
modal/queue.py,sha256=t8FuWHIxYzQKIn_kHPgCoMaa2mTx70AS3R2WGwv26vo,17461
|
60
|
-
modal/queue.pyi,sha256=JP4sUI9HZYlqZCG0aLBggVSMXbjyBfwBPGbMXCZxwlM,7881
|
61
|
-
modal/retries.py,sha256=n0tCmWPzOhKCXlTZn4gFaD4UWLbB3sbLzERXJsKUCY4,3768
|
62
|
-
modal/runner.py,sha256=eDn9r9jiAr3BS43MkiLpUZcbllCCz2e2J3kr0_WA34o,19436
|
63
|
-
modal/runner.pyi,sha256=YnCe8B4rvRb4CSK1EleZXaGTy3aLszp1SlFz4MQ8Kf8,5791
|
64
|
-
modal/running_app.py,sha256=MRLSMzdAryNbDTI9ox0KbY4X8WBsCxZnhdYje9PP6Ts,461
|
65
|
-
modal/sandbox.py,sha256=VFWn3MpTHcOqNey5tc7n3aqTgCABkeBxHw0y33EO5Ds,15449
|
66
|
-
modal/sandbox.pyi,sha256=eCuMVSakb8NIpA10NC_Eq0HtCU319MnJBQIK2P9efWE,6841
|
67
|
-
modal/schedule.py,sha256=_XVhLzsJXsqNs4uDO9E5P6HQsf2DF4DakjbRJnHUJ34,2721
|
68
|
-
modal/scheduler_placement.py,sha256=15NhfoI1W6qklc8BabM5t19oVNhx9ZbPByaQO7YWSYw,662
|
69
|
-
modal/secret.py,sha256=Xg3r6fRX3kjUDik-uGM0T_Pu4QeRfwjWWsLZbwp2ZDQ,9212
|
70
|
-
modal/secret.pyi,sha256=1oh_skH9R-PmM7XqI6udQny75f1FmNNyZwrsgtrxPmM,2265
|
71
|
-
modal/serving.py,sha256=p7QbGicoPVigCdBdqK52WPJ71TaRPsPabD9-FZDUUwc,4799
|
72
|
-
modal/serving.pyi,sha256=Sr_7eADe4cCg3cZqnKj0HsDgeytsWqh9KJk2XXMtt9c,2977
|
73
|
-
modal/shared_volume.py,sha256=vB-QLl7EMeusFWT91bVxsmYhzlBNYYYJukLmbF_5Rgk,888
|
74
|
-
modal/shared_volume.pyi,sha256=JSrQyY3M0nn6cbhEV_Xd8AqN7VdzWr2_jsHEGH7HYOQ,405
|
75
|
-
modal/token_flow.py,sha256=M28JpcN2KCeIaXmlGqtj6NBPcb8qvjEd59_ojR3tMDo,6742
|
76
|
-
modal/token_flow.pyi,sha256=F5_ty7M18ulmLG9I-DJoqcg7CrbEgLDndEWvL_p9708,1890
|
77
|
-
modal/volume.py,sha256=6NPxfsTURzozVJH-jXCS33mEF8B4WVdRTYSdJGraRNw,30272
|
78
|
-
modal/volume.pyi,sha256=RsaoCzk7SUiGvW0MeDOV964h67dpDZUcumJSCV4Q7hk,10361
|
79
|
-
modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
80
|
-
modal/_utils/app_utils.py,sha256=Uf9oNKcC6wJg3wcHNygWxMlkXuIMVRYIE5nutDSafkQ,465
|
81
|
-
modal/_utils/async_utils.py,sha256=xV63AKgDUc0gahAD8RIZj5oH1Oq27H2ClC3NT5PjNtU,16336
|
82
|
-
modal/_utils/blob_utils.py,sha256=oHWcx13W9NNXx0Das_x50jvVbA29jpGnLJM7c74WfxQ,15054
|
83
|
-
modal/_utils/function_utils.py,sha256=Kz8P8wIH5R1cYiQ3ruPIkoiBDMEqdoVGyUIXmOJZgqg,17084
|
84
|
-
modal/_utils/grpc_testing.py,sha256=n_HsO6pkTx2CStvGvLCl2-Rrj25X35wQ8Jln83QUySM,7927
|
85
|
-
modal/_utils/grpc_utils.py,sha256=udeRxwUVLGKwLdrWdItQ8BxxFn0JFmjp6kChB2U9Djk,6422
|
86
|
-
modal/_utils/hash_utils.py,sha256=HefF7zPQPxFxyx3fpz-AdSm4QsHZNNvgL9-iQHY-_F4,1790
|
87
|
-
modal/_utils/http_utils.py,sha256=DGKvrSQxAHjP_LNdM6EaL-TIQPGDX5vt3gcMGg2xkz4,1426
|
88
|
-
modal/_utils/logger.py,sha256=0QvxZpyhhZwKZ5xOcMC9btS_XBE1wAKhtQmISU3gdd0,1311
|
89
|
-
modal/_utils/mount_utils.py,sha256=f2q_tlDLVHcttJBkuoGfy99G-krZ-s5vZARi-bYzv-E,2341
|
90
|
-
modal/_utils/package_utils.py,sha256=mh5zRXmY9wSmvqaCqFBAdPntLP1EmSkDWJt3GB4ey4s,1640
|
91
|
-
modal/_utils/rand_pb_testing.py,sha256=_dRz09XhVoY9ZO7SN7xqi0MDVT22sY_ONnS0ts_3sUg,3857
|
92
|
-
modal/_utils/shell_utils.py,sha256=_nQIZb4jbwcfjg-qCLgtlXEx2I9TCsmY1G0IQY8fFg4,3633
|
93
|
-
modal/_vendor/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
94
|
-
modal/_vendor/a2wsgi_wsgi.py,sha256=2AnQcS5VhLZxod0trVNxnIYGH1SRbzT3dmJ4owVXzxA,22144
|
95
|
-
modal/_vendor/cloudpickle.py,sha256=CcpkVlNqP3rtFiPK1Ffpub_i0bc7EThN8kU7nC0WXlc,55225
|
96
|
-
modal/_vendor/tblib.py,sha256=g1O7QUDd3sDoLd8YPFltkXkih7r_fyZOjgmGuligv3s,9722
|
97
|
-
modal/cli/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
98
|
-
modal/cli/_download.py,sha256=sZL19eungg6P9ytUMivn16-dk-kVaIOi3rbr6Rszgwc,3007
|
99
|
-
modal/cli/app.py,sha256=GIdFVSFMS5T4blraH9As5JeIANR5rU4tNpSVOvOsVbc,3053
|
100
|
-
modal/cli/config.py,sha256=cSTH2oy0HTT-8GgH0tMvjqMKk_zYi_UcRGqRXkqCH3w,1294
|
101
|
-
modal/cli/container.py,sha256=6OObgXtCF1WsEVQYTqPvzbCP8NiMMTx8Dux9bJCfzVg,1771
|
102
|
-
modal/cli/entry_point.py,sha256=aUB_UYJeqbapCBN0bX4SyCagk1PIm94-oPan2PIsAwk,3538
|
103
|
-
modal/cli/environment.py,sha256=Jgen64Wu6MUdvX8iDoqE3aJtiCD8PiHVjd3dfDOjT_U,3414
|
104
|
-
modal/cli/import_refs.py,sha256=hmkMHywgBKoEfexUrmd9V32dw0GFMsgmG6YwP_KRoCk,10363
|
105
|
-
modal/cli/launch.py,sha256=uySnUipRpEWzN5nITAXM63_xmtKanpyLvN3VcKrBPAA,2135
|
106
|
-
modal/cli/network_file_system.py,sha256=y5UrCsXvcA1guD1KuywZ-xn45DljR12DKzrjjFlU-HU,6879
|
107
|
-
modal/cli/profile.py,sha256=s4jCYHwriOorEFCKxeGZoSWX8rXTR_hDTNFZhOA565s,3109
|
108
|
-
modal/cli/run.py,sha256=4MW1KN_U63rV0VS3Gp3FWFwqlicHUtrL7xmoX0VYmwo,13760
|
109
|
-
modal/cli/secret.py,sha256=4qcrCd-3alNPzzoNWTtM5ZQY4SDBkL5weD5gvx8wMWU,4192
|
110
|
-
modal/cli/token.py,sha256=Vsxy1ViEfuauWgPnpV8R3mRtKFQUtNmmTc2FYOY82Tg,1875
|
111
|
-
modal/cli/utils.py,sha256=UI8dfKlzbWaKPr0nz2H-SvrhbV7IKV7uIwAt_aiQIbU,1473
|
112
|
-
modal/cli/volume.py,sha256=ckvf6AsG8LpUZRBtNl7disKrcvRB3MlaIVUVWZY2VZM,9493
|
113
|
-
modal/cli/programs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
114
|
-
modal/cli/programs/run_jupyter.py,sha256=gYqMUBxi837XRSCtxfUSZYWi_0eIQhH2ES_g8AeMddE,2137
|
115
|
-
modal/cli/programs/vscode.py,sha256=OwiYwpuBSa6FcUkiRKv5dVNyuApTdtu0IPdpbIBnraM,1892
|
116
|
-
modal/extensions/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
117
|
-
modal/extensions/ipython.py,sha256=Xvzy-A7cvwMSDa9p4c4CEMLOX2_Xsg9DkM1J9uyu7jc,983
|
118
|
-
modal/requirements/2023.12.312.txt,sha256=zWWUVgVQ92GXBKNYYr2-5vn9rlnXcmkqlwlX5u1eTYw,400
|
119
|
-
modal/requirements/2023.12.txt,sha256=OjsbXFkCSdkzzryZP82Q73osr5wxQ6EUzmGcK7twfkA,502
|
120
|
-
modal/requirements/2024.04.txt,sha256=ahcvUgDTsw7slMDPneAX6rZdeIc6fsW00ZzODccAC4A,520
|
121
|
-
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
122
|
-
modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
|
123
|
-
modal_docs/gen_reference_docs.py,sha256=g37KpE5P5ZxZl-vj0ie3Ewx1waTRMKCGIXQ_iYSy0e0,6555
|
124
|
-
modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
125
|
-
modal_docs/mdmd/mdmd.py,sha256=F9J0KdYVz8WmdLDnInTIlm8SmNZJLAiu3ZAZcxVIZ0k,6268
|
126
|
-
modal_docs/mdmd/signatures.py,sha256=Jqy5AosHsQLAQJJe5cgYbciyFvb8xVwPIYwyBn-6RzU,3243
|
127
|
-
modal_global_objects/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
128
|
-
modal_global_objects/images/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
129
|
-
modal_global_objects/images/conda.py,sha256=5Tqd_62p7zGwVezJj1Qp2Vcxtt2WHWVBMzMNbjuNW-M,324
|
130
|
-
modal_global_objects/images/debian_slim.py,sha256=9iB8L0tuEDWas3Mge1jyGvfBXiKsJpcjqJT5M1fWRos,330
|
131
|
-
modal_global_objects/images/micromamba.py,sha256=k5m5P4xSBzliiTrdMITHx6iLhdQGIBuhPnP65JlBdG0,329
|
132
|
-
modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
133
|
-
modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
|
134
|
-
modal_global_objects/mounts/python_standalone.py,sha256=_vTEX3PECUsatzhDs8lyJmDK0LbFetT1sJB6MIDfFAo,1870
|
135
|
-
modal_proto/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
136
|
-
modal_proto/api.proto,sha256=3tZrpYTIoXjWR3X7b5R8ZW7SMPWIflQd9BIS_SYRYwg,57567
|
137
|
-
modal_proto/api_grpc.py,sha256=scZIz8gmSRXULKpVxwo2NIaOq0C9-WV5qCw_wMG6_QY,88101
|
138
|
-
modal_proto/api_pb2.py,sha256=t1EqYn71_RjRfDZqdLIu3tK_oULrnrphxDRDr_qOfiw,222646
|
139
|
-
modal_proto/api_pb2_grpc.py,sha256=2gvpCJ8T0WEsTkWwXv85fixrmFgJ63M5tQm_9aM0pgk,190583
|
140
|
-
modal_proto/options.proto,sha256=a-siq4swVbZPfaFRXAipRZzGP2bq8OsdUvjlyzAeodQ,488
|
141
|
-
modal_proto/options_grpc.py,sha256=M18X3d-8F_cNYSVM3I25dUTO5rZ0rd-vCCfynfh13Nc,125
|
142
|
-
modal_proto/options_pb2.py,sha256=OC2Oob8Yz_3Gs58hwpS_jSFWpGsWMcxlgXbJCyw3gMk,1827
|
143
|
-
modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
144
|
-
modal_version/__init__.py,sha256=HTM4O90gT-ndgKJIFiD8JRMsdauRAWxc9TDGhBuhkYI,470
|
145
|
-
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
146
|
-
modal_version/_version_generated.py,sha256=Rt-8vRt_Cfl6-FGpFfOVotOVbFQbZXC9eWbH8vu5x30,150
|
147
|
-
test/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
148
|
-
test/aio_test.py,sha256=u8nTraWcjAxPU7mV5w3m5hI2Xi9U1rXEEYyBnXTIEVs,199
|
149
|
-
test/async_utils_test.py,sha256=T4HJlfMNe1cL5cEzFxv2e4rJoaJkqygvZYSgS75FAo4,7247
|
150
|
-
test/blob_test.py,sha256=72LpqPJreb0mtLlkS14IN6rsvsQUWr1yrM97uTANUQo,2539
|
151
|
-
test/cli_imports_test.py,sha256=U2JGz759LUSA-k1sbUmx3ALD6DPmVFthfodpeg9bXPM,4635
|
152
|
-
test/cli_test.py,sha256=giu2W4yWLtrRu6rGFgsOrrOZeNZCjw27ZobggGlkka0,27254
|
153
|
-
test/client_test.py,sha256=BFt0JCaCRjqt-xtGnSOdta4uFrWlGcXTL2293DVy6Qk,6887
|
154
|
-
test/cloud_bucket_mount_test.py,sha256=5BwaEZbiWaDQ-9rzifhB7Uq6vzaqgTI6sL17SnAZqHA,530
|
155
|
-
test/cls_test.py,sha256=TdRZJ614LWw8-5B08GAON0H8_GiBWNDsDLicsEUmbFE,16132
|
156
|
-
test/config_test.py,sha256=oQgLnKLMZYTLxz_LNvE_Re99gYrAjR0DcfivI-U1btc,5121
|
157
|
-
test/conftest.py,sha256=kdUio4X_Oo5_4S-1piy0YtOGeHnkdL27bGYVz29gXng,62804
|
158
|
-
test/container_app_test.py,sha256=MDFTc_J9R1i4nXWD-k2Rk9SRiyGhxaBLFB6SwbG2GGs,1506
|
159
|
-
test/container_test.py,sha256=5GUaYgofWbcr8JFrlNepsefxeMmBEJCYONtA86dQNBM,50375
|
160
|
-
test/cpu_test.py,sha256=36StHgZlfblNGYxzwRvqL137x1Dk6C7oEb6y6cDWQi0,398
|
161
|
-
test/decorator_test.py,sha256=ec0oAO-oBE0fMVehr83Gj7gnRtqL4pz8jN6vwMDYXaw,1850
|
162
|
-
test/deprecation_test.py,sha256=IS_pracoNgt0vuEdLThukZpBkPBX4LUCQP5sAUMhjiY,1055
|
163
|
-
test/dict_test.py,sha256=MmPaR1fzsN0lR-c3piPL4ylkBcSnfdjRIZ6ICUViTF4,1622
|
164
|
-
test/e2e_test.py,sha256=OBBTB8p422PBD0iCoOfNTQQsIs_sX6_SkT1dNv3DiY4,2152
|
165
|
-
test/error_test.py,sha256=bDxKUwE4WJ1qwAfm0Jlzqkb3WetF0YLxplrgjevAv4U,165
|
166
|
-
test/function_serialization_test.py,sha256=4SJM8EdH9YXJ1woBla5L2VdnxWqSkOiL_EzDUU85KKY,966
|
167
|
-
test/function_test.py,sha256=kVY5dxup6dR2Ictak_1loOT7aexSdnfSHawF8O5LkM8,23769
|
168
|
-
test/function_utils_test.py,sha256=AZr8ZPh2h152epv-kn0rWZXwhM8MbPcaVSsOa5thzhY,1892
|
169
|
-
test/gpu_test.py,sha256=lwL0nvQfcMHzS1tld9Pj3ElsujI6GaZTRA09Ik85lWA,4571
|
170
|
-
test/grpc_utils_test.py,sha256=idjbD9XFiR4Tike8iiu_60nUX5iSv731_F40HXg8Jrs,2959
|
171
|
-
test/helpers.py,sha256=2yL3YNC6xAa4kOiZeRX8yz1z4EbkLJuNfPvgZ9xvmu8,1716
|
172
|
-
test/image_test.py,sha256=NUTBREVJlohusHCpwZBqtiNGiceYwbCRC1cwOvF9P1M,32798
|
173
|
-
test/live_reload_test.py,sha256=iP3TdMu4JjkS6rI7oaIPfgNqDBRpkg2v9OQD9iae5mA,2722
|
174
|
-
test/lookup_test.py,sha256=uGauFaxUBNJPl3unMgqM8lHhQMWDAGM8W_r_aBotZgQ,2160
|
175
|
-
test/mdmd_test.py,sha256=G3B0986QneKtIrui34hu95h09No9mM06O7mPp2sTm50,5118
|
176
|
-
test/mount_test.py,sha256=n7Qar7sDVMl1kTKfN2Je0kXbQ8DWPsAQ5q_v-VbrE3o,5475
|
177
|
-
test/mounted_files_test.py,sha256=ssgPZIqAjALks7TKNS5OSuTsu1AhXrbdiRHgJ12ukhs,12409
|
178
|
-
test/network_file_system_test.py,sha256=EBg_Tqtg0ryZeGANjSvwSeRFy1FGDdP29b6XTxNJGYM,6265
|
179
|
-
test/notebook_test.py,sha256=IkOFP9Tat8pEazSOV73OU7QMGgOlw3sU_5vTzOigrZU,2157
|
180
|
-
test/object_test.py,sha256=jyLxikU4quvVnDhdhIC9-rKRie1WOnB3hjaD-u383BM,1291
|
181
|
-
test/package_utils_test.py,sha256=ic3cJqwVbe7p2jOwnnTuGTwP9aDduz9QueqVwcA8r9I,795
|
182
|
-
test/queue_test.py,sha256=xtSVjCSv3sRvPsrra204muHE1OfSxF77nmGRE0X2H2I,3859
|
183
|
-
test/resolver_test.py,sha256=YlwYPYZO6ZNBH9lQ8ynABwMUfvIs0Mg1h3lKz3PsmAs,1782
|
184
|
-
test/retries_test.py,sha256=4x43pJc0Xt6VoPbk9ScnO2Xo_qFVX8QdtuoemO-prLk,1806
|
185
|
-
test/runner_test.py,sha256=DG0WVFKidX0KGIIOxn3AEiYRbNDge7wiu7lOISJytt0,2909
|
186
|
-
test/sandbox_test.py,sha256=SRsZbZdZjaQwv7VfsUu2MjT7P23m4YmaVMNlvDm77mA,5254
|
187
|
-
test/schedule_test.py,sha256=ZDFaaG7WAA6mx6qwlYPNlcf0LHE96uvGFcxfmrnqi78,354
|
188
|
-
test/scheduler_placement_test.py,sha256=f5AbbFldweCs-49zhcLq9HqYSAd_f-jDK8659pd1BVE,1610
|
189
|
-
test/secret_test.py,sha256=awmf8De5W81n7-XtbIth3lX_a9IUzH8RbzHfliuQJQI,2949
|
190
|
-
test/serialization_test.py,sha256=IaVZA3OVraHV6GqsKdbkVkcfjTiHVvwRf9b7dsRLgZM,2281
|
191
|
-
test/stub_composition_test.py,sha256=yMW7P0JqqwvKP_cP6kj7GTRiJl3dUjOd-nSED9mQItk,555
|
192
|
-
test/stub_test.py,sha256=E9ErL1ovO5n1wSy3Nl667QH83jMQLGduRvTgb-2KKEs,10906
|
193
|
-
test/test_asgi_wrapper.py,sha256=FPkh8FnZ1lEo4Y0fyCuCUZ85wf5U4nPNtwORBTE6OR0,7328
|
194
|
-
test/token_flow_test.py,sha256=tbxqsDFzRiMCkxfexDzxbbEomrmNlqJjOpPm8ndPE_c,614
|
195
|
-
test/traceback_test.py,sha256=3FNfnb00ek1gMVj8xcT8veAcyF4j4Fdrz3G9_giljsc,4747
|
196
|
-
test/tunnel_test.py,sha256=5v3FGmYS3VAcQB1xMjoXnmU1jLGvKu27TgFkH42N09w,768
|
197
|
-
test/utils_test.py,sha256=VRBxxpIAl3TvvY8X_rumvqCR-5ZozV2tfm_1Gy4ok6M,2679
|
198
|
-
test/version_test.py,sha256=lii24csueJzXzv0HM0fvHD83N_9FOOFRl-VRmDQZnDA,403
|
199
|
-
test/volume_test.py,sha256=AfjsB-aF-4oC4Ga-FtfScF8VIXRm8LgMn6ETsj-wicQ,14550
|
200
|
-
test/watcher_test.py,sha256=SJUAVLTJS_Fs5DsEM3VUCwq7nDCNtwRHihvMu93hfj4,2001
|
201
|
-
test/webhook_test.py,sha256=jxf5-Vz2ECedwNWS7a506T7jJTEMfcJZ-NQPEet6kmI,4171
|
202
|
-
modal-0.62.115.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
203
|
-
modal-0.62.115.dist-info/METADATA,sha256=eIx8_MlgCVhS1lRzvJyJCMQeYz1DNkRRb1R41wdaXhU,2301
|
204
|
-
modal-0.62.115.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
205
|
-
modal-0.62.115.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
206
|
-
modal-0.62.115.dist-info/top_level.txt,sha256=AfUN7pr_AWNHp5av5c2h5ntw_83jrhQ2-ytzdC-S4Z0,69
|
207
|
-
modal-0.62.115.dist-info/RECORD,,
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import asyncio
|
3
|
-
import sys
|
4
|
-
|
5
|
-
from modal import Image, Stub
|
6
|
-
|
7
|
-
|
8
|
-
async def main(client=None, python_version=None):
|
9
|
-
stub = Stub(image=Image.conda(python_version))
|
10
|
-
async with stub.run.aio(client=client):
|
11
|
-
pass
|
12
|
-
|
13
|
-
|
14
|
-
if __name__ == "__main__":
|
15
|
-
asyncio.run(main(python_version=sys.argv[1]))
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import asyncio
|
3
|
-
import sys
|
4
|
-
|
5
|
-
from modal import Image, Stub
|
6
|
-
|
7
|
-
|
8
|
-
async def main(client=None, python_version=None):
|
9
|
-
stub = Stub(image=Image.debian_slim(python_version))
|
10
|
-
async with stub.run.aio(client=client):
|
11
|
-
pass
|
12
|
-
|
13
|
-
|
14
|
-
if __name__ == "__main__":
|
15
|
-
asyncio.run(main(python_version=sys.argv[1]))
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import asyncio
|
3
|
-
import sys
|
4
|
-
|
5
|
-
from modal import Image, Stub
|
6
|
-
|
7
|
-
|
8
|
-
async def main(client=None, python_version=None):
|
9
|
-
stub = Stub(image=Image.micromamba(python_version))
|
10
|
-
async with stub.run.aio(client=client):
|
11
|
-
pass
|
12
|
-
|
13
|
-
|
14
|
-
if __name__ == "__main__":
|
15
|
-
asyncio.run(main(python_version=sys.argv[1]))
|
test/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
test/aio_test.py
DELETED
test/async_utils_test.py
DELETED
@@ -1,279 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import asyncio
|
3
|
-
import logging
|
4
|
-
import os
|
5
|
-
import platform
|
6
|
-
import pytest
|
7
|
-
|
8
|
-
from synchronicity import Synchronizer
|
9
|
-
|
10
|
-
from modal._utils import async_utils
|
11
|
-
from modal._utils.async_utils import (
|
12
|
-
ConcurrencyPool,
|
13
|
-
TaskContext,
|
14
|
-
queue_batch_iterator,
|
15
|
-
retry,
|
16
|
-
warn_if_generator_is_not_consumed,
|
17
|
-
)
|
18
|
-
|
19
|
-
skip_github_non_linux = pytest.mark.skipif(
|
20
|
-
(os.environ.get("GITHUB_ACTIONS") == "true" and platform.system() != "Linux"),
|
21
|
-
reason="sleep is inaccurate on GitHub Actions runners.",
|
22
|
-
)
|
23
|
-
|
24
|
-
|
25
|
-
class SampleException(Exception):
|
26
|
-
pass
|
27
|
-
|
28
|
-
|
29
|
-
class FailNTimes:
|
30
|
-
def __init__(self, n_failures, exc=SampleException("Something bad happened")):
|
31
|
-
self.n_failures = n_failures
|
32
|
-
self.n_calls = 0
|
33
|
-
self.exc = exc
|
34
|
-
|
35
|
-
async def __call__(self, x):
|
36
|
-
self.n_calls += 1
|
37
|
-
if self.n_calls <= self.n_failures:
|
38
|
-
raise self.exc
|
39
|
-
else:
|
40
|
-
return x + 1
|
41
|
-
|
42
|
-
|
43
|
-
@pytest.mark.asyncio
|
44
|
-
async def test_retry():
|
45
|
-
f_retry = retry(FailNTimes(2))
|
46
|
-
assert await f_retry(42) == 43
|
47
|
-
|
48
|
-
with pytest.raises(SampleException):
|
49
|
-
f_retry = retry(FailNTimes(3))
|
50
|
-
assert await f_retry(42) == 43
|
51
|
-
|
52
|
-
f_retry = retry(n_attempts=5)(FailNTimes(4))
|
53
|
-
assert await f_retry(42) == 43
|
54
|
-
|
55
|
-
with pytest.raises(SampleException):
|
56
|
-
f_retry = retry(n_attempts=5)(FailNTimes(5))
|
57
|
-
assert await f_retry(42) == 43
|
58
|
-
|
59
|
-
|
60
|
-
@pytest.mark.asyncio
|
61
|
-
async def test_task_context():
|
62
|
-
async with TaskContext() as task_context:
|
63
|
-
t = task_context.create_task(asyncio.sleep(0.1))
|
64
|
-
assert not t.done()
|
65
|
-
# await asyncio.sleep(0.0)
|
66
|
-
await asyncio.sleep(0.0) # just waste a loop step for the cancellation to go through
|
67
|
-
assert t.cancelled()
|
68
|
-
|
69
|
-
|
70
|
-
@pytest.mark.asyncio
|
71
|
-
async def test_task_context_grace():
|
72
|
-
async with TaskContext(grace=0.2) as task_context:
|
73
|
-
u = task_context.create_task(asyncio.sleep(0.1))
|
74
|
-
v = task_context.create_task(asyncio.sleep(0.3))
|
75
|
-
assert not u.done()
|
76
|
-
assert not v.done()
|
77
|
-
await asyncio.sleep(0.0)
|
78
|
-
assert u.done()
|
79
|
-
assert v.cancelled()
|
80
|
-
|
81
|
-
|
82
|
-
async def raise_exception():
|
83
|
-
raise SampleException("foo")
|
84
|
-
|
85
|
-
|
86
|
-
@skip_github_non_linux
|
87
|
-
@pytest.mark.asyncio
|
88
|
-
async def test_task_context_wait():
|
89
|
-
async with TaskContext(grace=0.1) as task_context:
|
90
|
-
u = task_context.create_task(asyncio.sleep(1.1))
|
91
|
-
v = task_context.create_task(asyncio.sleep(1.3))
|
92
|
-
await task_context.wait(u)
|
93
|
-
|
94
|
-
assert u.done()
|
95
|
-
assert v.cancelled()
|
96
|
-
|
97
|
-
with pytest.raises(SampleException):
|
98
|
-
async with TaskContext(grace=0.2) as task_context:
|
99
|
-
u = task_context.create_task(asyncio.sleep(1.1))
|
100
|
-
v = task_context.create_task(raise_exception())
|
101
|
-
await task_context.wait(u)
|
102
|
-
|
103
|
-
assert u.cancelled()
|
104
|
-
assert v.done()
|
105
|
-
|
106
|
-
|
107
|
-
@skip_github_non_linux
|
108
|
-
@pytest.mark.asyncio
|
109
|
-
async def test_task_context_infinite_loop():
|
110
|
-
async with TaskContext(grace=0.01) as task_context:
|
111
|
-
counter = 0
|
112
|
-
|
113
|
-
async def f():
|
114
|
-
nonlocal counter
|
115
|
-
counter += 1
|
116
|
-
|
117
|
-
t = task_context.infinite_loop(f, sleep=0.1)
|
118
|
-
assert not t.done()
|
119
|
-
await asyncio.sleep(0.35)
|
120
|
-
assert counter == 4 # at 0.00, 0.10, 0.20, 0.30
|
121
|
-
await asyncio.sleep(0.0) # just waste a loop step for the cancellation to go through
|
122
|
-
assert not t.cancelled()
|
123
|
-
assert t.done()
|
124
|
-
assert counter == 4 # should be exited immediately
|
125
|
-
|
126
|
-
|
127
|
-
DEBOUNCE_TIME = 0.1
|
128
|
-
|
129
|
-
|
130
|
-
@pytest.mark.asyncio
|
131
|
-
async def test_queue_batch_iterator():
|
132
|
-
queue: asyncio.Queue = asyncio.Queue()
|
133
|
-
await queue.put(1)
|
134
|
-
drained_items = []
|
135
|
-
|
136
|
-
async def drain_queue(logs_queue):
|
137
|
-
async for batch in queue_batch_iterator(logs_queue, debounce_time=DEBOUNCE_TIME):
|
138
|
-
drained_items.extend(batch)
|
139
|
-
|
140
|
-
async with TaskContext(grace=0.0) as tc:
|
141
|
-
tc.create_task(drain_queue(queue))
|
142
|
-
|
143
|
-
# Make sure the queue gets drained.
|
144
|
-
await asyncio.sleep(0.001)
|
145
|
-
|
146
|
-
assert len(drained_items) == 1
|
147
|
-
|
148
|
-
# Add items to the queue and a sentinel while it's still waiting for DEBOUNCE_TIME.
|
149
|
-
await queue.put(2)
|
150
|
-
await queue.put(3)
|
151
|
-
await queue.put(None)
|
152
|
-
|
153
|
-
await asyncio.sleep(DEBOUNCE_TIME + 0.001)
|
154
|
-
|
155
|
-
assert len(drained_items) == 3
|
156
|
-
|
157
|
-
|
158
|
-
@pytest.mark.asyncio
|
159
|
-
async def test_warn_if_generator_is_not_consumed(caplog):
|
160
|
-
@warn_if_generator_is_not_consumed()
|
161
|
-
async def my_generator():
|
162
|
-
yield 42
|
163
|
-
|
164
|
-
with caplog.at_level(logging.WARNING):
|
165
|
-
g = my_generator()
|
166
|
-
assert "my_generator" in repr(g)
|
167
|
-
del g # Force destructor
|
168
|
-
|
169
|
-
assert len(caplog.records) == 1
|
170
|
-
assert "my_generator" in caplog.text
|
171
|
-
assert "for" in caplog.text
|
172
|
-
assert "list" in caplog.text
|
173
|
-
|
174
|
-
|
175
|
-
@pytest.mark.asyncio
|
176
|
-
def test_warn_if_generator_is_not_consumed_sync(caplog):
|
177
|
-
@warn_if_generator_is_not_consumed()
|
178
|
-
def my_generator():
|
179
|
-
yield 42
|
180
|
-
|
181
|
-
with caplog.at_level(logging.WARNING):
|
182
|
-
g = my_generator()
|
183
|
-
assert "my_generator" in repr(g)
|
184
|
-
del g # Force destructor
|
185
|
-
|
186
|
-
assert len(caplog.records) == 1
|
187
|
-
assert "my_generator" in caplog.text
|
188
|
-
assert "for" in caplog.text
|
189
|
-
assert "list" in caplog.text
|
190
|
-
|
191
|
-
|
192
|
-
@pytest.mark.asyncio
|
193
|
-
async def test_no_warn_if_generator_is_consumed(caplog):
|
194
|
-
@warn_if_generator_is_not_consumed()
|
195
|
-
async def my_generator():
|
196
|
-
yield 42
|
197
|
-
|
198
|
-
with caplog.at_level(logging.WARNING):
|
199
|
-
g = my_generator()
|
200
|
-
async for _ in g:
|
201
|
-
pass
|
202
|
-
del g # Force destructor
|
203
|
-
|
204
|
-
assert len(caplog.records) == 0
|
205
|
-
|
206
|
-
|
207
|
-
def test_exit_handler():
|
208
|
-
result = None
|
209
|
-
sync = Synchronizer()
|
210
|
-
|
211
|
-
async def cleanup():
|
212
|
-
nonlocal result
|
213
|
-
result = "bye"
|
214
|
-
|
215
|
-
async def _setup_code():
|
216
|
-
async_utils.on_shutdown(cleanup())
|
217
|
-
|
218
|
-
setup_code = sync.create_blocking(_setup_code)
|
219
|
-
setup_code()
|
220
|
-
|
221
|
-
sync._close_loop() # this is called on exit by synchronicity, which shuts down the event loop
|
222
|
-
assert result == "bye"
|
223
|
-
|
224
|
-
|
225
|
-
@pytest.mark.asyncio
|
226
|
-
async def test_concurrency_pool():
|
227
|
-
max_running = 0
|
228
|
-
running = 0
|
229
|
-
|
230
|
-
async def f():
|
231
|
-
nonlocal running, max_running
|
232
|
-
running += 1
|
233
|
-
max_running = max(max_running, running)
|
234
|
-
await asyncio.sleep(0.1)
|
235
|
-
running -= 1
|
236
|
-
|
237
|
-
def gen():
|
238
|
-
for i in range(100):
|
239
|
-
yield f()
|
240
|
-
|
241
|
-
await asyncio.wait_for(ConcurrencyPool(50).run_coros(gen()), 0.3)
|
242
|
-
assert max_running == 50
|
243
|
-
|
244
|
-
|
245
|
-
@pytest.mark.asyncio
|
246
|
-
async def test_concurrency_pool_cancels_non_started():
|
247
|
-
counter = 0
|
248
|
-
|
249
|
-
async def f():
|
250
|
-
nonlocal counter
|
251
|
-
counter += 1
|
252
|
-
raise RuntimeError("some error")
|
253
|
-
|
254
|
-
def gen():
|
255
|
-
for i in range(100):
|
256
|
-
yield f()
|
257
|
-
|
258
|
-
with pytest.raises(RuntimeError):
|
259
|
-
await ConcurrencyPool(2).run_coros(gen(), return_exceptions=False)
|
260
|
-
await asyncio.sleep(0.1)
|
261
|
-
assert counter == 2
|
262
|
-
|
263
|
-
|
264
|
-
@pytest.mark.asyncio
|
265
|
-
async def test_concurrency_pool_return_exceptions():
|
266
|
-
async def f(x):
|
267
|
-
if x % 2:
|
268
|
-
raise RuntimeError("some error")
|
269
|
-
else:
|
270
|
-
return 42
|
271
|
-
|
272
|
-
def gen():
|
273
|
-
for x in range(4):
|
274
|
-
yield f(x)
|
275
|
-
|
276
|
-
res = await asyncio.wait_for(ConcurrencyPool(2).run_coros(gen(), return_exceptions=True), 0.1)
|
277
|
-
assert res[0] == res[2] == 42
|
278
|
-
assert isinstance(res[1], RuntimeError)
|
279
|
-
assert isinstance(res[3], RuntimeError)
|
test/blob_test.py
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
# Copyright Modal Labs 2022
|
2
|
-
import pytest
|
3
|
-
import random
|
4
|
-
|
5
|
-
from modal._utils.async_utils import synchronize_api
|
6
|
-
from modal._utils.blob_utils import (
|
7
|
-
blob_download as _blob_download,
|
8
|
-
blob_upload as _blob_upload,
|
9
|
-
blob_upload_file as _blob_upload_file,
|
10
|
-
)
|
11
|
-
from modal.exception import ExecutionError
|
12
|
-
|
13
|
-
from .supports.skip import skip_old_py
|
14
|
-
|
15
|
-
blob_upload = synchronize_api(_blob_upload)
|
16
|
-
blob_download = synchronize_api(_blob_download)
|
17
|
-
blob_upload_file = synchronize_api(_blob_upload_file)
|
18
|
-
|
19
|
-
|
20
|
-
@pytest.mark.asyncio
|
21
|
-
async def test_blob_put_get(servicer, blob_server, client):
|
22
|
-
# Upload
|
23
|
-
blob_id = await blob_upload.aio(b"Hello, world", client.stub)
|
24
|
-
|
25
|
-
# Download
|
26
|
-
data = await blob_download.aio(blob_id, client.stub)
|
27
|
-
assert data == b"Hello, world"
|
28
|
-
|
29
|
-
|
30
|
-
@pytest.mark.asyncio
|
31
|
-
async def test_blob_put_failure(servicer, blob_server, client):
|
32
|
-
with pytest.raises(ExecutionError):
|
33
|
-
await blob_upload.aio(b"FAILURE", client.stub)
|
34
|
-
|
35
|
-
|
36
|
-
@pytest.mark.asyncio
|
37
|
-
async def test_blob_get_failure(servicer, blob_server, client):
|
38
|
-
with pytest.raises(ExecutionError):
|
39
|
-
await blob_download.aio("bl-failure", client.stub)
|
40
|
-
|
41
|
-
|
42
|
-
@pytest.mark.asyncio
|
43
|
-
async def test_blob_large(servicer, blob_server, client):
|
44
|
-
data = b"*" * 10_000_000
|
45
|
-
blob_id = await blob_upload.aio(data, client.stub)
|
46
|
-
assert await blob_download.aio(blob_id, client.stub) == data
|
47
|
-
|
48
|
-
|
49
|
-
@skip_old_py("random.randbytes() was introduced in python 3.9", (3, 9))
|
50
|
-
@pytest.mark.asyncio
|
51
|
-
async def test_blob_multipart(servicer, blob_server, client, monkeypatch, tmp_path):
|
52
|
-
monkeypatch.setattr("modal._utils.blob_utils.DEFAULT_SEGMENT_CHUNK_SIZE", 128)
|
53
|
-
multipart_threshold = 1024
|
54
|
-
servicer.blob_multipart_threshold = multipart_threshold
|
55
|
-
# - set high # of parts, to test concurrency correctness
|
56
|
-
# - make last part significantly shorter than rest, creating uneven upload time.
|
57
|
-
data_len = (256 * multipart_threshold) + (multipart_threshold // 2)
|
58
|
-
data = random.randbytes(data_len) # random data will not hide byte re-ordering corruption
|
59
|
-
blob_id = await blob_upload.aio(data, client.stub)
|
60
|
-
assert await blob_download.aio(blob_id, client.stub) == data
|
61
|
-
|
62
|
-
data_len = (256 * multipart_threshold) + (multipart_threshold // 2)
|
63
|
-
data = random.randbytes(data_len) # random data will not hide byte re-ordering corruption
|
64
|
-
data_filepath = tmp_path / "temp.bin"
|
65
|
-
data_filepath.write_bytes(data)
|
66
|
-
blob_id = await blob_upload_file.aio(data_filepath.open("rb"), client.stub)
|
67
|
-
assert await blob_download.aio(blob_id, client.stub) == data
|