modal 1.0.0.dev15__tar.gz → 1.0.0.dev17__tar.gz

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 (183) hide show
  1. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/PKG-INFO +1 -1
  2. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/__init__.py +10 -2
  3. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_functions.py +31 -9
  4. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/function_utils.py +4 -1
  5. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/app.py +0 -32
  6. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/app.pyi +0 -29
  7. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/client.pyi +2 -2
  8. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/exception.py +1 -1
  9. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/functions.pyi +6 -6
  10. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal.egg-info/PKG-INFO +1 -1
  11. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_version/__init__.py +1 -1
  12. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/LICENSE +0 -0
  13. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/README.md +0 -0
  14. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/__main__.py +0 -0
  15. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_clustered_functions.py +0 -0
  16. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_clustered_functions.pyi +0 -0
  17. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_container_entrypoint.py +0 -0
  18. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_ipython.py +0 -0
  19. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_location.py +0 -0
  20. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_object.py +0 -0
  21. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_output.py +0 -0
  22. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_partial_function.py +0 -0
  23. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_pty.py +0 -0
  24. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_resolver.py +0 -0
  25. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_resources.py +0 -0
  26. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/__init__.py +0 -0
  27. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/asgi.py +0 -0
  28. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/container_io_manager.py +0 -0
  29. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/container_io_manager.pyi +0 -0
  30. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/execution_context.py +0 -0
  31. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/execution_context.pyi +0 -0
  32. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  33. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/telemetry.py +0 -0
  34. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_runtime/user_code_imports.py +0 -0
  35. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_serialization.py +0 -0
  36. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_traceback.py +0 -0
  37. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_tunnel.py +0 -0
  38. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_tunnel.pyi +0 -0
  39. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_type_manager.py +0 -0
  40. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/__init__.py +0 -0
  41. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/app_utils.py +0 -0
  42. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/async_utils.py +0 -0
  43. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/blob_utils.py +0 -0
  44. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/bytes_io_segment_payload.py +0 -0
  45. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/deprecation.py +0 -0
  46. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/docker_utils.py +0 -0
  47. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/git_utils.py +0 -0
  48. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/grpc_testing.py +0 -0
  49. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/grpc_utils.py +0 -0
  50. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/hash_utils.py +0 -0
  51. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/http_utils.py +0 -0
  52. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/jwt_utils.py +0 -0
  53. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/logger.py +0 -0
  54. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/mount_utils.py +0 -0
  55. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/name_utils.py +0 -0
  56. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/package_utils.py +0 -0
  57. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/pattern_utils.py +0 -0
  58. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/rand_pb_testing.py +0 -0
  59. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_utils/shell_utils.py +0 -0
  60. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_vendor/__init__.py +0 -0
  61. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  62. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_vendor/cloudpickle.py +0 -0
  63. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_vendor/tblib.py +0 -0
  64. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/_watcher.py +0 -0
  65. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/call_graph.py +0 -0
  66. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/__init__.py +0 -0
  67. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/_download.py +0 -0
  68. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/_traceback.py +0 -0
  69. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/app.py +0 -0
  70. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/cluster.py +0 -0
  71. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/config.py +0 -0
  72. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/container.py +0 -0
  73. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/dict.py +0 -0
  74. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/entry_point.py +0 -0
  75. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/environment.py +0 -0
  76. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/import_refs.py +0 -0
  77. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/launch.py +0 -0
  78. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/network_file_system.py +0 -0
  79. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/profile.py +0 -0
  80. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/programs/__init__.py +0 -0
  81. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/programs/run_jupyter.py +0 -0
  82. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/programs/vscode.py +0 -0
  83. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/queues.py +0 -0
  84. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/run.py +0 -0
  85. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/secret.py +0 -0
  86. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/token.py +0 -0
  87. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/utils.py +0 -0
  88. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cli/volume.py +0 -0
  89. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/client.py +0 -0
  90. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cloud_bucket_mount.py +0 -0
  91. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cloud_bucket_mount.pyi +0 -0
  92. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cls.py +0 -0
  93. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/cls.pyi +0 -0
  94. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/config.py +0 -0
  95. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/container_process.py +0 -0
  96. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/container_process.pyi +0 -0
  97. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/dict.py +0 -0
  98. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/dict.pyi +0 -0
  99. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/environments.py +0 -0
  100. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/environments.pyi +0 -0
  101. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/experimental/__init__.py +0 -0
  102. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/experimental/ipython.py +0 -0
  103. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/file_io.py +0 -0
  104. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/file_io.pyi +0 -0
  105. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/file_pattern_matcher.py +0 -0
  106. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/functions.py +0 -0
  107. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/gpu.py +0 -0
  108. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/image.py +0 -0
  109. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/image.pyi +0 -0
  110. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/io_streams.py +0 -0
  111. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/io_streams.pyi +0 -0
  112. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/mount.py +0 -0
  113. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/mount.pyi +0 -0
  114. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/network_file_system.py +0 -0
  115. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/network_file_system.pyi +0 -0
  116. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/object.py +0 -0
  117. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/object.pyi +0 -0
  118. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/output.py +0 -0
  119. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/parallel_map.py +0 -0
  120. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/parallel_map.pyi +0 -0
  121. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/partial_function.py +0 -0
  122. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/partial_function.pyi +0 -0
  123. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/proxy.py +0 -0
  124. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/proxy.pyi +0 -0
  125. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/py.typed +0 -0
  126. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/queue.py +0 -0
  127. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/queue.pyi +0 -0
  128. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/requirements/2023.12.312.txt +0 -0
  129. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/requirements/2023.12.txt +0 -0
  130. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/requirements/2024.04.txt +0 -0
  131. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/requirements/2024.10.txt +0 -0
  132. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/requirements/PREVIEW.txt +0 -0
  133. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/requirements/README.md +0 -0
  134. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/requirements/base-images.json +0 -0
  135. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/retries.py +0 -0
  136. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/runner.py +0 -0
  137. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/runner.pyi +0 -0
  138. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/running_app.py +0 -0
  139. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/sandbox.py +0 -0
  140. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/sandbox.pyi +0 -0
  141. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/schedule.py +0 -0
  142. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/scheduler_placement.py +0 -0
  143. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/secret.py +0 -0
  144. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/secret.pyi +0 -0
  145. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/serving.py +0 -0
  146. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/serving.pyi +0 -0
  147. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/snapshot.py +0 -0
  148. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/snapshot.pyi +0 -0
  149. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/stream_type.py +0 -0
  150. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/token_flow.py +0 -0
  151. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/token_flow.pyi +0 -0
  152. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/volume.py +0 -0
  153. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal/volume.pyi +0 -0
  154. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal.egg-info/SOURCES.txt +0 -0
  155. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal.egg-info/dependency_links.txt +0 -0
  156. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal.egg-info/entry_points.txt +0 -0
  157. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal.egg-info/requires.txt +0 -0
  158. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal.egg-info/top_level.txt +0 -0
  159. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_docs/__init__.py +0 -0
  160. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_docs/gen_cli_docs.py +0 -0
  161. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_docs/gen_reference_docs.py +0 -0
  162. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_docs/mdmd/__init__.py +0 -0
  163. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_docs/mdmd/mdmd.py +0 -0
  164. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_docs/mdmd/signatures.py +0 -0
  165. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/__init__.py +0 -0
  166. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/api.proto +0 -0
  167. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/api_grpc.py +0 -0
  168. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/api_pb2.py +0 -0
  169. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/api_pb2.pyi +0 -0
  170. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/api_pb2_grpc.py +0 -0
  171. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/api_pb2_grpc.pyi +0 -0
  172. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/modal_api_grpc.py +0 -0
  173. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/modal_options_grpc.py +0 -0
  174. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/options.proto +0 -0
  175. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/options_grpc.py +0 -0
  176. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/options_pb2.py +0 -0
  177. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/options_pb2.pyi +0 -0
  178. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/options_pb2_grpc.py +0 -0
  179. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/options_pb2_grpc.pyi +0 -0
  180. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_proto/py.typed +0 -0
  181. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/modal_version/__main__.py +0 -0
  182. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/pyproject.toml +0 -0
  183. {modal-1.0.0.dev15 → modal-1.0.0.dev17}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.0.dev15
3
+ Version: 1.0.0.dev17
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -11,7 +11,7 @@ from modal_version import __version__
11
11
  try:
12
12
  from ._runtime.execution_context import current_function_call_id, current_input_id, interact, is_local
13
13
  from ._tunnel import Tunnel, forward
14
- from .app import App, Stub
14
+ from .app import App
15
15
  from .client import Client
16
16
  from .cloud_bucket_mount import CloudBucketMount
17
17
  from .cls import Cls, parameter
@@ -54,6 +54,7 @@ except Exception:
54
54
  print()
55
55
  raise
56
56
 
57
+
57
58
  __all__ = [
58
59
  "__version__",
59
60
  "App",
@@ -77,7 +78,6 @@ __all__ = [
77
78
  "SandboxSnapshot",
78
79
  "SchedulerPlacement",
79
80
  "Secret",
80
- "Stub",
81
81
  "Tunnel",
82
82
  "Volume",
83
83
  "asgi_app",
@@ -99,3 +99,11 @@ __all__ = [
99
99
  "web_server",
100
100
  "wsgi_app",
101
101
  ]
102
+
103
+
104
+ def __getattr__(name):
105
+ if name == "Stub":
106
+ raise AttributeError(
107
+ "Module 'modal' has no attribute 'Stub'. Use `modal.App` instead. This is a simple name change."
108
+ )
109
+ raise AttributeError(f"module 'modal' has no attribute '{name}'")
@@ -99,6 +99,7 @@ if TYPE_CHECKING:
99
99
  import modal.cls
100
100
  import modal.partial_function
101
101
 
102
+ MAX_INTERNAL_FAILURE_COUNT = 100
102
103
 
103
104
  @dataclasses.dataclass
104
105
  class _RetryContext:
@@ -348,10 +349,14 @@ class _InputPlaneInvocation:
348
349
  stub: ModalClientModal,
349
350
  attempt_token: str,
350
351
  client: _Client,
352
+ input_item: api_pb2.FunctionPutInputsItem,
353
+ function_id: str
351
354
  ):
352
355
  self.stub = stub
353
356
  self.client = client # Used by the deserializer.
354
357
  self.attempt_token = attempt_token
358
+ self.input_item = input_item
359
+ self.function_id = function_id
355
360
 
356
361
  @staticmethod
357
362
  async def create(
@@ -365,36 +370,53 @@ class _InputPlaneInvocation:
365
370
  stub = await client.get_stub(input_plane_url)
366
371
 
367
372
  function_id = function.object_id
368
- item = await _create_input(args, kwargs, stub, method_name=function._use_method_name)
373
+ input_item = await _create_input(args, kwargs, stub, method_name=function._use_method_name)
369
374
 
370
375
  request = api_pb2.AttemptStartRequest(
371
376
  function_id=function_id,
372
377
  parent_input_id=current_input_id() or "",
373
- input=item,
378
+ input=input_item,
374
379
  )
375
380
  response = await retry_transient_errors(stub.AttemptStart, request)
376
381
  attempt_token = response.attempt_token
377
382
 
378
- return _InputPlaneInvocation(stub, attempt_token, client)
383
+ return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id)
379
384
 
380
385
  async def run_function(self) -> Any:
381
- # TODO(nathan): add retry logic
386
+ # This will retry when the server returns GENERIC_STATUS_INTERNAL_FAILURE, i.e. lost inputs or worker preemption
387
+ # TODO(ryan): add logic to retry for user defined
388
+ internal_failure_count = 0
382
389
  while True:
383
- request = api_pb2.AttemptAwaitRequest(
390
+ await_request = api_pb2.AttemptAwaitRequest(
384
391
  attempt_token=self.attempt_token,
385
392
  timeout_secs=OUTPUTS_TIMEOUT,
386
393
  requested_at=time.time(),
387
394
  )
388
- response: api_pb2.AttemptAwaitResponse = await retry_transient_errors(
395
+ await_response: api_pb2.AttemptAwaitResponse = await retry_transient_errors(
389
396
  self.stub.AttemptAwait,
390
- request,
397
+ await_request,
391
398
  attempt_timeout=OUTPUTS_TIMEOUT + ATTEMPT_TIMEOUT_GRACE_PERIOD,
392
399
  )
393
400
 
394
- if response.HasField("output"):
401
+ try:
395
402
  return await _process_result(
396
- response.output.result, response.output.data_format, self.stub, self.client
403
+ await_response.output.result, await_response.output.data_format, self.stub, self.client
404
+ )
405
+ except InternalFailure as e:
406
+ internal_failure_count += 1
407
+ # Limit the number of times we retry
408
+ if internal_failure_count >= MAX_INTERNAL_FAILURE_COUNT:
409
+ raise e
410
+ # For system failures on the server, we retry immediately,
411
+ # and the failure does not count towards the retry policy.
412
+ retry_request = api_pb2.AttemptRetryRequest(
413
+ function_id=self.function_id,
414
+ parent_input_id=current_input_id() or "",
415
+ input=self.input_item,
416
+ attempt_token=self.attempt_token
397
417
  )
418
+ retry_response = await retry_transient_errors(self.stub.AttemptRetry, retry_request)
419
+ self.attempt_token = retry_response.attempt_token
398
420
 
399
421
 
400
422
  # Wrapper type for api_pb2.FunctionStats
@@ -466,7 +466,10 @@ async def _process_result(result: api_pb2.GenericResult, data_format: int, stub,
466
466
 
467
467
  if result.status == api_pb2.GenericResult.GENERIC_STATUS_TIMEOUT:
468
468
  raise FunctionTimeoutError(result.exception)
469
- elif result.status == api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
469
+ elif result.status in [
470
+ api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE,
471
+ api_pb2.GenericResult.GENERIC_STATUS_TERMINATED,
472
+ ]:
470
473
  raise InternalFailure(result.exception)
471
474
  elif result.status != api_pb2.GenericResult.GENERIC_STATUS_SUCCESS:
472
475
  if data:
@@ -1,7 +1,6 @@
1
1
  # Copyright Modal Labs 2022
2
2
  import inspect
3
3
  import typing
4
- import warnings
5
4
  from collections.abc import AsyncGenerator, Coroutine, Sequence
6
5
  from pathlib import PurePosixPath
7
6
  from textwrap import dedent
@@ -78,11 +77,6 @@ class _LocalEntrypoint:
78
77
  def app(self) -> "_App":
79
78
  return self._app
80
79
 
81
- @property
82
- def stub(self) -> "_App":
83
- # Deprecated soon, only for backwards compatibility
84
- return self._app
85
-
86
80
 
87
81
  LocalEntrypoint = synchronize_api(_LocalEntrypoint)
88
82
 
@@ -781,12 +775,6 @@ class _App:
781
775
  rdma = None
782
776
  i6pn_enabled = i6pn
783
777
 
784
- if info.function_name.endswith(".app"):
785
- warnings.warn(
786
- "Beware: the function name is `app`. Modal will soon rename `Stub` to `App`, "
787
- "so you might run into issues if you have code like `app = modal.App()` in the same scope"
788
- )
789
-
790
778
  if is_generator is None:
791
779
  is_generator = inspect.isgeneratorfunction(raw_f) or inspect.isasyncgenfunction(raw_f)
792
780
 
@@ -1096,23 +1084,3 @@ class _App:
1096
1084
 
1097
1085
 
1098
1086
  App = synchronize_api(_App)
1099
-
1100
-
1101
- class _Stub(_App):
1102
- """mdmd:hidden
1103
- This enables using a "Stub" class instead of "App".
1104
-
1105
- For most of Modal's history, the app class was called "Stub", so this exists for
1106
- backwards compatibility, in order to facilitate moving from "Stub" to "App".
1107
- """
1108
-
1109
- def __new__(cls, *args, **kwargs):
1110
- deprecation_warning(
1111
- (2024, 4, 29),
1112
- 'The use of "Stub" has been deprecated in favor of "App".'
1113
- " This is a pure name change with no other implications.",
1114
- )
1115
- return _App(*args, **kwargs)
1116
-
1117
-
1118
- Stub = synchronize_api(_Stub)
@@ -33,8 +33,6 @@ class _LocalEntrypoint:
33
33
  def info(self) -> modal._utils.function_utils.FunctionInfo: ...
34
34
  @property
35
35
  def app(self) -> _App: ...
36
- @property
37
- def stub(self) -> _App: ...
38
36
 
39
37
  class LocalEntrypoint:
40
38
  _info: modal._utils.function_utils.FunctionInfo
@@ -46,8 +44,6 @@ class LocalEntrypoint:
46
44
  def info(self) -> modal._utils.function_utils.FunctionInfo: ...
47
45
  @property
48
46
  def app(self) -> App: ...
49
- @property
50
- def stub(self) -> App: ...
51
47
 
52
48
  def check_sequence(items: typing.Sequence[typing.Any], item_type: type[typing.Any], error_msg: str) -> None: ...
53
49
 
@@ -520,29 +516,4 @@ class App:
520
516
  @classmethod
521
517
  def _reset_container_app(cls): ...
522
518
 
523
- class _Stub(_App):
524
- @staticmethod
525
- def __new__(
526
- cls,
527
- name: typing.Optional[str] = None,
528
- *,
529
- image: typing.Optional[modal.image._Image] = None,
530
- mounts: collections.abc.Sequence[modal.mount._Mount] = [],
531
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
532
- volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume._Volume] = {},
533
- include_source: typing.Optional[bool] = None,
534
- ): ...
535
-
536
- class Stub(App):
537
- def __init__(
538
- self,
539
- name: typing.Optional[str] = None,
540
- *,
541
- image: typing.Optional[modal.image.Image] = None,
542
- mounts: collections.abc.Sequence[modal.mount.Mount] = [],
543
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
544
- volumes: dict[typing.Union[str, pathlib.PurePosixPath], modal.volume.Volume] = {},
545
- include_source: typing.Optional[bool] = None,
546
- ) -> None: ...
547
-
548
519
  _default_image: modal.image._Image
@@ -31,7 +31,7 @@ class _Client:
31
31
  server_url: str,
32
32
  client_type: int,
33
33
  credentials: typing.Optional[tuple[str, str]],
34
- version: str = "1.0.0.dev15",
34
+ version: str = "1.0.0.dev17",
35
35
  ): ...
36
36
  def is_closed(self) -> bool: ...
37
37
  @property
@@ -94,7 +94,7 @@ class Client:
94
94
  server_url: str,
95
95
  client_type: int,
96
96
  credentials: typing.Optional[tuple[str, str]],
97
- version: str = "1.0.0.dev15",
97
+ version: str = "1.0.0.dev17",
98
98
  ): ...
99
99
  def is_closed(self) -> bool: ...
100
100
  @property
@@ -116,7 +116,7 @@ class InternalFailure(Error):
116
116
 
117
117
  class _CliUserExecutionError(Exception):
118
118
  """mdmd:hidden
119
- Private wrapper for exceptions during when importing or running stubs from the CLI.
119
+ Private wrapper for exceptions during when importing or running Apps from the CLI.
120
120
 
121
121
  This intentionally does not inherit from `modal.exception.Error` because it
122
122
  is a private type that should never bubble up to users. Exceptions raised in
@@ -228,11 +228,11 @@ class Function(
228
228
 
229
229
  _call_generator: ___call_generator_spec[typing_extensions.Self]
230
230
 
231
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
231
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
232
232
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
233
233
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
234
234
 
235
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
235
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
236
236
 
237
237
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
238
238
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -247,12 +247,12 @@ class Function(
247
247
  self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
248
248
  ) -> modal._functions.OriginalReturnType: ...
249
249
 
250
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
250
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
251
251
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
252
252
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
253
253
 
254
254
  _experimental_spawn: ___experimental_spawn_spec[
255
- modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
255
+ modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
256
256
  ]
257
257
 
258
258
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -261,11 +261,11 @@ class Function(
261
261
 
262
262
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
263
263
 
264
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
264
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
265
265
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
266
266
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
267
267
 
268
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
268
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
269
269
 
270
270
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
271
271
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.0.dev15
3
+ Version: 1.0.0.dev17
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.0.0.dev15"
4
+ __version__ = "1.0.0.dev17"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes