modal 0.62.16__py3-none-any.whl → 0.72.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. modal/__init__.py +17 -13
  2. modal/__main__.py +41 -3
  3. modal/_clustered_functions.py +80 -0
  4. modal/_clustered_functions.pyi +22 -0
  5. modal/_container_entrypoint.py +420 -937
  6. modal/_ipython.py +3 -13
  7. modal/_location.py +17 -10
  8. modal/_output.py +243 -99
  9. modal/_pty.py +2 -2
  10. modal/_resolver.py +55 -59
  11. modal/_resources.py +51 -0
  12. modal/_runtime/__init__.py +1 -0
  13. modal/_runtime/asgi.py +519 -0
  14. modal/_runtime/container_io_manager.py +1036 -0
  15. modal/_runtime/execution_context.py +89 -0
  16. modal/_runtime/telemetry.py +169 -0
  17. modal/_runtime/user_code_imports.py +356 -0
  18. modal/_serialization.py +134 -9
  19. modal/_traceback.py +47 -187
  20. modal/_tunnel.py +52 -16
  21. modal/_tunnel.pyi +19 -36
  22. modal/_utils/app_utils.py +3 -17
  23. modal/_utils/async_utils.py +479 -100
  24. modal/_utils/blob_utils.py +157 -186
  25. modal/_utils/bytes_io_segment_payload.py +97 -0
  26. modal/_utils/deprecation.py +89 -0
  27. modal/_utils/docker_utils.py +98 -0
  28. modal/_utils/function_utils.py +460 -171
  29. modal/_utils/grpc_testing.py +47 -31
  30. modal/_utils/grpc_utils.py +62 -109
  31. modal/_utils/hash_utils.py +61 -19
  32. modal/_utils/http_utils.py +39 -9
  33. modal/_utils/logger.py +2 -1
  34. modal/_utils/mount_utils.py +34 -16
  35. modal/_utils/name_utils.py +58 -0
  36. modal/_utils/package_utils.py +14 -1
  37. modal/_utils/pattern_utils.py +205 -0
  38. modal/_utils/rand_pb_testing.py +5 -7
  39. modal/_utils/shell_utils.py +15 -49
  40. modal/_vendor/a2wsgi_wsgi.py +62 -72
  41. modal/_vendor/cloudpickle.py +1 -1
  42. modal/_watcher.py +14 -12
  43. modal/app.py +1003 -314
  44. modal/app.pyi +540 -264
  45. modal/call_graph.py +7 -6
  46. modal/cli/_download.py +63 -53
  47. modal/cli/_traceback.py +200 -0
  48. modal/cli/app.py +205 -45
  49. modal/cli/config.py +12 -5
  50. modal/cli/container.py +62 -14
  51. modal/cli/dict.py +128 -0
  52. modal/cli/entry_point.py +26 -13
  53. modal/cli/environment.py +40 -9
  54. modal/cli/import_refs.py +64 -58
  55. modal/cli/launch.py +32 -18
  56. modal/cli/network_file_system.py +64 -83
  57. modal/cli/profile.py +1 -1
  58. modal/cli/programs/run_jupyter.py +35 -10
  59. modal/cli/programs/vscode.py +60 -10
  60. modal/cli/queues.py +131 -0
  61. modal/cli/run.py +234 -131
  62. modal/cli/secret.py +8 -7
  63. modal/cli/token.py +7 -2
  64. modal/cli/utils.py +79 -10
  65. modal/cli/volume.py +110 -109
  66. modal/client.py +250 -144
  67. modal/client.pyi +157 -118
  68. modal/cloud_bucket_mount.py +108 -34
  69. modal/cloud_bucket_mount.pyi +32 -38
  70. modal/cls.py +535 -148
  71. modal/cls.pyi +190 -146
  72. modal/config.py +41 -19
  73. modal/container_process.py +177 -0
  74. modal/container_process.pyi +82 -0
  75. modal/dict.py +111 -65
  76. modal/dict.pyi +136 -131
  77. modal/environments.py +106 -5
  78. modal/environments.pyi +77 -25
  79. modal/exception.py +34 -43
  80. modal/experimental.py +61 -2
  81. modal/extensions/ipython.py +5 -5
  82. modal/file_io.py +537 -0
  83. modal/file_io.pyi +235 -0
  84. modal/file_pattern_matcher.py +197 -0
  85. modal/functions.py +906 -911
  86. modal/functions.pyi +466 -430
  87. modal/gpu.py +57 -44
  88. modal/image.py +1089 -479
  89. modal/image.pyi +584 -228
  90. modal/io_streams.py +434 -0
  91. modal/io_streams.pyi +122 -0
  92. modal/mount.py +314 -101
  93. modal/mount.pyi +241 -235
  94. modal/network_file_system.py +92 -92
  95. modal/network_file_system.pyi +152 -110
  96. modal/object.py +67 -36
  97. modal/object.pyi +166 -143
  98. modal/output.py +63 -0
  99. modal/parallel_map.py +434 -0
  100. modal/parallel_map.pyi +75 -0
  101. modal/partial_function.py +282 -117
  102. modal/partial_function.pyi +222 -129
  103. modal/proxy.py +15 -12
  104. modal/proxy.pyi +3 -8
  105. modal/queue.py +182 -65
  106. modal/queue.pyi +218 -118
  107. modal/requirements/2024.04.txt +29 -0
  108. modal/requirements/2024.10.txt +16 -0
  109. modal/requirements/README.md +21 -0
  110. modal/requirements/base-images.json +22 -0
  111. modal/retries.py +48 -7
  112. modal/runner.py +459 -156
  113. modal/runner.pyi +135 -71
  114. modal/running_app.py +38 -0
  115. modal/sandbox.py +514 -236
  116. modal/sandbox.pyi +397 -169
  117. modal/schedule.py +4 -4
  118. modal/scheduler_placement.py +20 -3
  119. modal/secret.py +56 -31
  120. modal/secret.pyi +62 -42
  121. modal/serving.py +51 -56
  122. modal/serving.pyi +44 -36
  123. modal/stream_type.py +15 -0
  124. modal/token_flow.py +5 -3
  125. modal/token_flow.pyi +37 -32
  126. modal/volume.py +285 -157
  127. modal/volume.pyi +249 -184
  128. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/METADATA +7 -7
  129. modal-0.72.11.dist-info/RECORD +174 -0
  130. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/top_level.txt +0 -1
  131. modal_docs/gen_reference_docs.py +3 -1
  132. modal_docs/mdmd/mdmd.py +0 -1
  133. modal_docs/mdmd/signatures.py +5 -2
  134. modal_global_objects/images/base_images.py +28 -0
  135. modal_global_objects/mounts/python_standalone.py +2 -2
  136. modal_proto/__init__.py +1 -1
  137. modal_proto/api.proto +1288 -533
  138. modal_proto/api_grpc.py +856 -456
  139. modal_proto/api_pb2.py +2165 -1157
  140. modal_proto/api_pb2.pyi +8859 -0
  141. modal_proto/api_pb2_grpc.py +1674 -855
  142. modal_proto/api_pb2_grpc.pyi +1416 -0
  143. modal_proto/modal_api_grpc.py +149 -0
  144. modal_proto/modal_options_grpc.py +3 -0
  145. modal_proto/options_pb2.pyi +20 -0
  146. modal_proto/options_pb2_grpc.pyi +7 -0
  147. modal_proto/py.typed +0 -0
  148. modal_version/__init__.py +1 -1
  149. modal_version/_version_generated.py +2 -2
  150. modal/_asgi.py +0 -370
  151. modal/_container_entrypoint.pyi +0 -378
  152. modal/_container_exec.py +0 -128
  153. modal/_sandbox_shell.py +0 -49
  154. modal/shared_volume.py +0 -23
  155. modal/shared_volume.pyi +0 -24
  156. modal/stub.py +0 -783
  157. modal/stub.pyi +0 -332
  158. modal-0.62.16.dist-info/RECORD +0 -198
  159. modal_global_objects/images/conda.py +0 -15
  160. modal_global_objects/images/debian_slim.py +0 -15
  161. modal_global_objects/images/micromamba.py +0 -15
  162. test/__init__.py +0 -1
  163. test/aio_test.py +0 -12
  164. test/async_utils_test.py +0 -262
  165. test/blob_test.py +0 -67
  166. test/cli_imports_test.py +0 -149
  167. test/cli_test.py +0 -659
  168. test/client_test.py +0 -194
  169. test/cls_test.py +0 -630
  170. test/config_test.py +0 -137
  171. test/conftest.py +0 -1420
  172. test/container_app_test.py +0 -32
  173. test/container_test.py +0 -1389
  174. test/cpu_test.py +0 -23
  175. test/decorator_test.py +0 -85
  176. test/deprecation_test.py +0 -34
  177. test/dict_test.py +0 -33
  178. test/e2e_test.py +0 -68
  179. test/error_test.py +0 -7
  180. test/function_serialization_test.py +0 -32
  181. test/function_test.py +0 -653
  182. test/function_utils_test.py +0 -101
  183. test/gpu_test.py +0 -159
  184. test/grpc_utils_test.py +0 -141
  185. test/helpers.py +0 -42
  186. test/image_test.py +0 -669
  187. test/live_reload_test.py +0 -80
  188. test/lookup_test.py +0 -70
  189. test/mdmd_test.py +0 -329
  190. test/mount_test.py +0 -162
  191. test/mounted_files_test.py +0 -329
  192. test/network_file_system_test.py +0 -181
  193. test/notebook_test.py +0 -66
  194. test/object_test.py +0 -41
  195. test/package_utils_test.py +0 -25
  196. test/queue_test.py +0 -97
  197. test/resolver_test.py +0 -58
  198. test/retries_test.py +0 -67
  199. test/runner_test.py +0 -85
  200. test/sandbox_test.py +0 -191
  201. test/schedule_test.py +0 -15
  202. test/scheduler_placement_test.py +0 -29
  203. test/secret_test.py +0 -78
  204. test/serialization_test.py +0 -42
  205. test/stub_composition_test.py +0 -10
  206. test/stub_test.py +0 -360
  207. test/test_asgi_wrapper.py +0 -234
  208. test/token_flow_test.py +0 -18
  209. test/traceback_test.py +0 -135
  210. test/tunnel_test.py +0 -29
  211. test/utils_test.py +0 -88
  212. test/version_test.py +0 -14
  213. test/volume_test.py +0 -341
  214. test/watcher_test.py +0 -30
  215. test/webhook_test.py +0 -146
  216. /modal/{requirements.312.txt → requirements/2023.12.312.txt} +0 -0
  217. /modal/{requirements.txt → requirements/2023.12.txt} +0 -0
  218. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/LICENSE +0 -0
  219. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/WHEEL +0 -0
  220. {modal-0.62.16.dist-info → modal-0.72.11.dist-info}/entry_points.txt +0 -0
test/config_test.py DELETED
@@ -1,137 +0,0 @@
1
- # Copyright Modal Labs 2022
2
- import os
3
- import pathlib
4
- import pytest
5
- import subprocess
6
- import sys
7
-
8
- import toml
9
-
10
- import modal
11
- from modal.config import _lookup_workspace, config
12
-
13
-
14
- def _cli(args, env={}):
15
- lib_dir = pathlib.Path(modal.__file__).parent.parent
16
- args = [sys.executable, "-m", "modal.cli.entry_point"] + args
17
- env = {
18
- **os.environ,
19
- **env,
20
- # For windows
21
- "PYTHONUTF8": "1",
22
- }
23
- ret = subprocess.run(args, cwd=lib_dir, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
24
- stdout = ret.stdout.decode()
25
- stderr = ret.stderr.decode()
26
- if ret.returncode != 0:
27
- raise Exception(f"Failed with {ret.returncode} stdout: {stdout} stderr: {stderr}")
28
- return stdout
29
-
30
-
31
- def _get_config(env={}):
32
- stdout = _cli(["config", "show"], env=env)
33
- return eval(stdout)
34
-
35
-
36
- def test_config():
37
- config = _get_config()
38
- assert config["server_url"]
39
-
40
-
41
- def test_config_env_override():
42
- config = _get_config(env={"MODAL_SERVER_URL": "xyz.corp"})
43
- assert config["server_url"] == "xyz.corp"
44
-
45
-
46
- def test_config_store_user(servicer, modal_config):
47
- with modal_config(show_on_error=True) as config_file_path:
48
- env = {"MODAL_SERVER_URL": servicer.remote_addr}
49
-
50
- # No token by default
51
- config = _get_config(env=env)
52
- assert config["token_id"] is None
53
-
54
- # Set creds to abc / xyz
55
- _cli(["token", "set", "--token-id", "abc", "--token-secret", "xyz"], env=env)
56
-
57
- # Set creds to foo / bar1 for the prof_1 profile
58
- _cli(
59
- ["token", "set", "--token-id", "foo", "--token-secret", "bar1", "--profile", "prof_1", "--no-activate"],
60
- env=env,
61
- )
62
-
63
- # Set creds to foo / bar2 for the prof_2 profile (given as an env var)
64
- _cli(
65
- ["token", "set", "--token-id", "foo", "--token-secret", "bar2", "--no-activate"],
66
- env={"MODAL_PROFILE": "prof_2", **env},
67
- )
68
-
69
- # Now these should be stored in the user's home directory
70
- config = _get_config(env=env)
71
- assert config["token_id"] == "abc"
72
- assert config["token_secret"] == "xyz"
73
-
74
- # Make sure it can be overridden too
75
- config = _get_config(env={"MODAL_TOKEN_ID": "foo", **env})
76
- assert config["token_id"] == "foo"
77
- assert config["token_secret"] == "xyz"
78
-
79
- # Check that the profile is named after the workspace username by default
80
- config = _get_config(env={"MODAL_PROFILE": "test-username", **env})
81
- assert config["token_id"] == "abc"
82
- assert config["token_secret"] == "xyz"
83
-
84
- # Check that we can get the prof_1 env creds too
85
- config = _get_config(env={"MODAL_PROFILE": "prof_1", **env})
86
- assert config["token_id"] == "foo"
87
- assert config["token_secret"] == "bar1"
88
-
89
- # Check that we can get the prof_2 env creds too
90
- config = _get_config(env={"MODAL_PROFILE": "prof_2", **env})
91
- assert config["token_id"] == "foo"
92
- assert config["token_secret"] == "bar2"
93
-
94
- # Check that an empty string falls back to the active profile
95
- config = _get_config(env={"MODAL_PROFILE": "", **env})
96
- assert config["token_secret"] == "xyz"
97
-
98
- # Test that only the first profile was explicitly activated
99
- for profile, profile_config in toml.load(config_file_path).items():
100
- if profile == "test-username":
101
- assert profile_config["active"] is True
102
- else:
103
- assert "active" not in profile_config
104
-
105
- # Check that we can overwrite the default profile
106
- _cli(["token", "set", "--token-id", "ABC", "--token-secret", "XYZ"], env=env)
107
- assert toml.load(config_file_path)["test-username"]["token_id"] == "ABC"
108
-
109
- # Check that we activate a profile by default while setting a token
110
- _cli(
111
- ["token", "set", "--token-id", "foo", "--token-secret", "bar3", "--profile", "prof_3"],
112
- env=env,
113
- )
114
- for profile, profile_config in toml.load(config_file_path).items():
115
- if profile == "prof_3":
116
- assert profile_config["active"] is True
117
- else:
118
- assert "active" not in profile_config
119
-
120
-
121
- def test_config_env_override_arbitrary_env():
122
- """config.override_locally() replaces existing env var if not part of config."""
123
- key = "NVIDIA_VISIBLE_DEVICES"
124
- value = "0,1"
125
-
126
- # Place old value in memory.
127
- os.environ[key] = "none"
128
-
129
- # Expect value to be overwritten.
130
- config.override_locally(key, value)
131
- assert os.getenv(key) == value
132
-
133
-
134
- @pytest.mark.asyncio
135
- async def test_workspace_lookup(servicer, server_url_env):
136
- resp = await _lookup_workspace(servicer.remote_addr, "ak-abc", "as-xyz")
137
- assert resp.workspace_name == "test-workspace"