modAL 1.0.2__tar.gz → 1.0.2.dev1__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 (184) hide show
  1. {modal-1.0.2 → modal-1.0.2.dev1}/PKG-INFO +1 -1
  2. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_functions.py +0 -6
  3. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/bytes_io_segment_payload.py +5 -23
  4. {modal-1.0.2 → modal-1.0.2.dev1}/modal/client.pyi +10 -2
  5. {modal-1.0.2 → modal-1.0.2.dev1}/modal/exception.py +0 -2
  6. {modal-1.0.2 → modal-1.0.2.dev1}/modal/functions.pyi +6 -6
  7. {modal-1.0.2 → modal-1.0.2.dev1}/modal/image.py +16 -38
  8. {modal-1.0.2 → modal-1.0.2.dev1}/modal/sandbox.py +1 -2
  9. {modal-1.0.2 → modal-1.0.2.dev1}/modal/volume.py +15 -30
  10. {modal-1.0.2 → modal-1.0.2.dev1}/modal/volume.pyi +2 -2
  11. {modal-1.0.2 → modal-1.0.2.dev1}/modal.egg-info/PKG-INFO +1 -1
  12. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/api.proto +0 -3
  13. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/api_pb2.py +374 -374
  14. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/api_pb2.pyi +3 -16
  15. {modal-1.0.2 → modal-1.0.2.dev1}/modal_version/__init__.py +1 -1
  16. {modal-1.0.2 → modal-1.0.2.dev1}/LICENSE +0 -0
  17. {modal-1.0.2 → modal-1.0.2.dev1}/README.md +0 -0
  18. {modal-1.0.2 → modal-1.0.2.dev1}/modal/__init__.py +0 -0
  19. {modal-1.0.2 → modal-1.0.2.dev1}/modal/__main__.py +0 -0
  20. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_clustered_functions.py +0 -0
  21. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_clustered_functions.pyi +0 -0
  22. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_container_entrypoint.py +0 -0
  23. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_ipython.py +0 -0
  24. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_location.py +0 -0
  25. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_object.py +0 -0
  26. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_output.py +0 -0
  27. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_partial_function.py +0 -0
  28. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_pty.py +0 -0
  29. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_resolver.py +0 -0
  30. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_resources.py +0 -0
  31. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/__init__.py +0 -0
  32. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/asgi.py +0 -0
  33. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/container_io_manager.py +0 -0
  34. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/container_io_manager.pyi +0 -0
  35. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/execution_context.py +0 -0
  36. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/execution_context.pyi +0 -0
  37. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  38. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/telemetry.py +0 -0
  39. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_runtime/user_code_imports.py +0 -0
  40. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_serialization.py +0 -0
  41. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_traceback.py +0 -0
  42. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_tunnel.py +0 -0
  43. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_tunnel.pyi +0 -0
  44. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_type_manager.py +0 -0
  45. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/__init__.py +0 -0
  46. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/app_utils.py +0 -0
  47. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/async_utils.py +0 -0
  48. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/blob_utils.py +0 -0
  49. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/deprecation.py +0 -0
  50. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/docker_utils.py +0 -0
  51. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/function_utils.py +0 -0
  52. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/git_utils.py +0 -0
  53. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/grpc_testing.py +0 -0
  54. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/grpc_utils.py +0 -0
  55. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/hash_utils.py +0 -0
  56. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/http_utils.py +0 -0
  57. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/jwt_utils.py +0 -0
  58. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/logger.py +0 -0
  59. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/mount_utils.py +0 -0
  60. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/name_utils.py +0 -0
  61. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/package_utils.py +0 -0
  62. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/pattern_utils.py +0 -0
  63. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/rand_pb_testing.py +0 -0
  64. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/shell_utils.py +0 -0
  65. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_utils/time_utils.py +0 -0
  66. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_vendor/__init__.py +0 -0
  67. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  68. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_vendor/cloudpickle.py +0 -0
  69. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_vendor/tblib.py +0 -0
  70. {modal-1.0.2 → modal-1.0.2.dev1}/modal/_watcher.py +0 -0
  71. {modal-1.0.2 → modal-1.0.2.dev1}/modal/app.py +0 -0
  72. {modal-1.0.2 → modal-1.0.2.dev1}/modal/app.pyi +0 -0
  73. {modal-1.0.2 → modal-1.0.2.dev1}/modal/call_graph.py +0 -0
  74. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/__init__.py +0 -0
  75. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/_download.py +0 -0
  76. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/_traceback.py +0 -0
  77. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/app.py +0 -0
  78. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/cluster.py +0 -0
  79. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/config.py +0 -0
  80. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/container.py +0 -0
  81. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/dict.py +0 -0
  82. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/entry_point.py +0 -0
  83. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/environment.py +0 -0
  84. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/import_refs.py +0 -0
  85. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/launch.py +0 -0
  86. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/network_file_system.py +0 -0
  87. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/profile.py +0 -0
  88. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/programs/__init__.py +0 -0
  89. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/programs/run_jupyter.py +0 -0
  90. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/programs/vscode.py +0 -0
  91. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/queues.py +0 -0
  92. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/run.py +0 -0
  93. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/secret.py +0 -0
  94. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/token.py +0 -0
  95. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/utils.py +0 -0
  96. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cli/volume.py +0 -0
  97. {modal-1.0.2 → modal-1.0.2.dev1}/modal/client.py +0 -0
  98. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cloud_bucket_mount.py +0 -0
  99. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cloud_bucket_mount.pyi +0 -0
  100. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cls.py +0 -0
  101. {modal-1.0.2 → modal-1.0.2.dev1}/modal/cls.pyi +0 -0
  102. {modal-1.0.2 → modal-1.0.2.dev1}/modal/config.py +0 -0
  103. {modal-1.0.2 → modal-1.0.2.dev1}/modal/container_process.py +0 -0
  104. {modal-1.0.2 → modal-1.0.2.dev1}/modal/container_process.pyi +0 -0
  105. {modal-1.0.2 → modal-1.0.2.dev1}/modal/dict.py +0 -0
  106. {modal-1.0.2 → modal-1.0.2.dev1}/modal/dict.pyi +0 -0
  107. {modal-1.0.2 → modal-1.0.2.dev1}/modal/environments.py +0 -0
  108. {modal-1.0.2 → modal-1.0.2.dev1}/modal/environments.pyi +0 -0
  109. {modal-1.0.2 → modal-1.0.2.dev1}/modal/experimental/__init__.py +0 -0
  110. {modal-1.0.2 → modal-1.0.2.dev1}/modal/experimental/ipython.py +0 -0
  111. {modal-1.0.2 → modal-1.0.2.dev1}/modal/file_io.py +0 -0
  112. {modal-1.0.2 → modal-1.0.2.dev1}/modal/file_io.pyi +0 -0
  113. {modal-1.0.2 → modal-1.0.2.dev1}/modal/file_pattern_matcher.py +0 -0
  114. {modal-1.0.2 → modal-1.0.2.dev1}/modal/functions.py +0 -0
  115. {modal-1.0.2 → modal-1.0.2.dev1}/modal/gpu.py +0 -0
  116. {modal-1.0.2 → modal-1.0.2.dev1}/modal/image.pyi +0 -0
  117. {modal-1.0.2 → modal-1.0.2.dev1}/modal/io_streams.py +0 -0
  118. {modal-1.0.2 → modal-1.0.2.dev1}/modal/io_streams.pyi +0 -0
  119. {modal-1.0.2 → modal-1.0.2.dev1}/modal/mount.py +0 -0
  120. {modal-1.0.2 → modal-1.0.2.dev1}/modal/mount.pyi +0 -0
  121. {modal-1.0.2 → modal-1.0.2.dev1}/modal/network_file_system.py +0 -0
  122. {modal-1.0.2 → modal-1.0.2.dev1}/modal/network_file_system.pyi +0 -0
  123. {modal-1.0.2 → modal-1.0.2.dev1}/modal/object.py +0 -0
  124. {modal-1.0.2 → modal-1.0.2.dev1}/modal/object.pyi +0 -0
  125. {modal-1.0.2 → modal-1.0.2.dev1}/modal/output.py +0 -0
  126. {modal-1.0.2 → modal-1.0.2.dev1}/modal/parallel_map.py +0 -0
  127. {modal-1.0.2 → modal-1.0.2.dev1}/modal/parallel_map.pyi +0 -0
  128. {modal-1.0.2 → modal-1.0.2.dev1}/modal/partial_function.py +0 -0
  129. {modal-1.0.2 → modal-1.0.2.dev1}/modal/partial_function.pyi +0 -0
  130. {modal-1.0.2 → modal-1.0.2.dev1}/modal/proxy.py +0 -0
  131. {modal-1.0.2 → modal-1.0.2.dev1}/modal/proxy.pyi +0 -0
  132. {modal-1.0.2 → modal-1.0.2.dev1}/modal/py.typed +0 -0
  133. {modal-1.0.2 → modal-1.0.2.dev1}/modal/queue.py +0 -0
  134. {modal-1.0.2 → modal-1.0.2.dev1}/modal/queue.pyi +0 -0
  135. {modal-1.0.2 → modal-1.0.2.dev1}/modal/requirements/2023.12.312.txt +0 -0
  136. {modal-1.0.2 → modal-1.0.2.dev1}/modal/requirements/2023.12.txt +0 -0
  137. {modal-1.0.2 → modal-1.0.2.dev1}/modal/requirements/2024.04.txt +0 -0
  138. {modal-1.0.2 → modal-1.0.2.dev1}/modal/requirements/2024.10.txt +0 -0
  139. {modal-1.0.2 → modal-1.0.2.dev1}/modal/requirements/PREVIEW.txt +0 -0
  140. {modal-1.0.2 → modal-1.0.2.dev1}/modal/requirements/README.md +0 -0
  141. {modal-1.0.2 → modal-1.0.2.dev1}/modal/requirements/base-images.json +0 -0
  142. {modal-1.0.2 → modal-1.0.2.dev1}/modal/retries.py +0 -0
  143. {modal-1.0.2 → modal-1.0.2.dev1}/modal/runner.py +0 -0
  144. {modal-1.0.2 → modal-1.0.2.dev1}/modal/runner.pyi +0 -0
  145. {modal-1.0.2 → modal-1.0.2.dev1}/modal/running_app.py +0 -0
  146. {modal-1.0.2 → modal-1.0.2.dev1}/modal/sandbox.pyi +0 -0
  147. {modal-1.0.2 → modal-1.0.2.dev1}/modal/schedule.py +0 -0
  148. {modal-1.0.2 → modal-1.0.2.dev1}/modal/scheduler_placement.py +0 -0
  149. {modal-1.0.2 → modal-1.0.2.dev1}/modal/secret.py +0 -0
  150. {modal-1.0.2 → modal-1.0.2.dev1}/modal/secret.pyi +0 -0
  151. {modal-1.0.2 → modal-1.0.2.dev1}/modal/serving.py +0 -0
  152. {modal-1.0.2 → modal-1.0.2.dev1}/modal/serving.pyi +0 -0
  153. {modal-1.0.2 → modal-1.0.2.dev1}/modal/snapshot.py +0 -0
  154. {modal-1.0.2 → modal-1.0.2.dev1}/modal/snapshot.pyi +0 -0
  155. {modal-1.0.2 → modal-1.0.2.dev1}/modal/stream_type.py +0 -0
  156. {modal-1.0.2 → modal-1.0.2.dev1}/modal/token_flow.py +0 -0
  157. {modal-1.0.2 → modal-1.0.2.dev1}/modal/token_flow.pyi +0 -0
  158. {modal-1.0.2 → modal-1.0.2.dev1}/modal.egg-info/SOURCES.txt +0 -0
  159. {modal-1.0.2 → modal-1.0.2.dev1}/modal.egg-info/dependency_links.txt +0 -0
  160. {modal-1.0.2 → modal-1.0.2.dev1}/modal.egg-info/entry_points.txt +0 -0
  161. {modal-1.0.2 → modal-1.0.2.dev1}/modal.egg-info/requires.txt +0 -0
  162. {modal-1.0.2 → modal-1.0.2.dev1}/modal.egg-info/top_level.txt +0 -0
  163. {modal-1.0.2 → modal-1.0.2.dev1}/modal_docs/__init__.py +0 -0
  164. {modal-1.0.2 → modal-1.0.2.dev1}/modal_docs/gen_cli_docs.py +0 -0
  165. {modal-1.0.2 → modal-1.0.2.dev1}/modal_docs/gen_reference_docs.py +0 -0
  166. {modal-1.0.2 → modal-1.0.2.dev1}/modal_docs/mdmd/__init__.py +0 -0
  167. {modal-1.0.2 → modal-1.0.2.dev1}/modal_docs/mdmd/mdmd.py +0 -0
  168. {modal-1.0.2 → modal-1.0.2.dev1}/modal_docs/mdmd/signatures.py +0 -0
  169. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/__init__.py +0 -0
  170. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/api_grpc.py +0 -0
  171. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/api_pb2_grpc.py +0 -0
  172. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/api_pb2_grpc.pyi +0 -0
  173. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/modal_api_grpc.py +0 -0
  174. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/modal_options_grpc.py +0 -0
  175. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/options.proto +0 -0
  176. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/options_grpc.py +0 -0
  177. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/options_pb2.py +0 -0
  178. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/options_pb2.pyi +0 -0
  179. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/options_pb2_grpc.py +0 -0
  180. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/options_pb2_grpc.pyi +0 -0
  181. {modal-1.0.2 → modal-1.0.2.dev1}/modal_proto/py.typed +0 -0
  182. {modal-1.0.2 → modal-1.0.2.dev1}/modal_version/__main__.py +0 -0
  183. {modal-1.0.2 → modal-1.0.2.dev1}/pyproject.toml +0 -0
  184. {modal-1.0.2 → modal-1.0.2.dev1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.2
3
+ Version: 1.0.2.dev1
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -815,11 +815,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
815
815
  if app and app.name:
816
816
  app_name = app.name
817
817
 
818
- # on builder > 2024.10 we mount client dependencies at runtime
819
- mount_client_dependencies = False
820
- if image._metadata is not None:
821
- mount_client_dependencies = image._metadata.image_builder_version > "2024.10"
822
-
823
818
  # Relies on dicts being ordered (true as of Python 3.6).
824
819
  volume_mounts = [
825
820
  api_pb2.VolumeMount(
@@ -889,7 +884,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
889
884
  schedule=schedule.proto_message if schedule is not None else None,
890
885
  snapshot_debug=config.get("snapshot_debug"),
891
886
  experimental_options=experimental_options or {},
892
- mount_client_dependencies=mount_client_dependencies,
893
887
  # ---
894
888
  _experimental_group_size=cluster_size or 0, # Experimental: Clustered functions
895
889
  _experimental_concurrent_cancellations=True,
@@ -8,14 +8,14 @@ from typing import BinaryIO, Callable, Optional
8
8
  # Note: this module needs to import aiohttp in global scope
9
9
  # This takes about 50ms and isn't needed in many cases for Modal execution
10
10
  # To avoid this, we import it in local scope when needed (blob_utils.py)
11
- from aiohttp import Payload
11
+ from aiohttp import BytesIOPayload
12
12
  from aiohttp.abc import AbstractStreamWriter
13
13
 
14
14
  # read ~16MiB chunks by default
15
15
  DEFAULT_SEGMENT_CHUNK_SIZE = 2**24
16
16
 
17
17
 
18
- class BytesIOSegmentPayload(Payload):
18
+ class BytesIOSegmentPayload(BytesIOPayload):
19
19
  """Modified bytes payload for concurrent sends of chunks from the same file.
20
20
 
21
21
  Adds:
@@ -26,8 +26,6 @@ class BytesIOSegmentPayload(Payload):
26
26
  Feels like this should be in some standard lib...
27
27
  """
28
28
 
29
- _value: BinaryIO
30
-
31
29
  def __init__(
32
30
  self,
33
31
  bytes_io: BinaryIO, # should *not* be shared as IO position modification is not locked
@@ -38,7 +36,6 @@ class BytesIOSegmentPayload(Payload):
38
36
  ):
39
37
  # not thread safe constructor!
40
38
  super().__init__(bytes_io)
41
- self._size = segment_length
42
39
  self.initial_seek_pos = bytes_io.tell()
43
40
  self.segment_start = segment_start
44
41
  self.segment_length = segment_length
@@ -49,26 +46,18 @@ class BytesIOSegmentPayload(Payload):
49
46
  self.progress_report_cb = progress_report_cb or (lambda *_, **__: None)
50
47
  self.reset_state()
51
48
 
52
- def decode(self, encoding: str = "utf-8", errors: str = "strict") -> str:
53
- self._value.seek(self.initial_seek_pos)
54
- return self._value.read().decode(encoding, errors)
55
-
56
49
  def reset_state(self):
57
50
  self._md5_checksum = hashlib.md5()
58
51
  self.num_bytes_read = 0
59
52
  self._value.seek(self.initial_seek_pos)
60
53
 
61
54
  @contextmanager
62
- def reset_on_error(self, subtract_progress: bool = False):
55
+ def reset_on_error(self):
63
56
  try:
64
57
  yield
65
58
  except Exception as exc:
66
59
  try:
67
- if subtract_progress:
68
- negative_progress = -self.num_bytes_read
69
- self.progress_report_cb(advance=negative_progress)
70
- else:
71
- self.progress_report_cb(reset=True)
60
+ self.progress_report_cb(reset=True)
72
61
  except Exception as cb_exc:
73
62
  raise cb_exc from exc
74
63
  raise exc
@@ -83,21 +72,14 @@ class BytesIOSegmentPayload(Payload):
83
72
  return self._md5_checksum
84
73
 
85
74
  async def write(self, writer: "AbstractStreamWriter"):
86
- # On aiohttp < 3.12.0 - this is the method that's being called on a custom payload,
87
- # but on aiohttp 3.12+ `write_with_length` is called directly.
88
- await self.write_with_length(writer, None)
89
-
90
- async def write_with_length(self, writer: AbstractStreamWriter, content_length: Optional[int]):
91
75
  loop = asyncio.get_event_loop()
92
76
 
93
77
  async def safe_read():
94
78
  read_start = self.initial_seek_pos + self.segment_start + self.num_bytes_read
95
79
  self._value.seek(read_start)
96
80
  num_bytes = min(self.chunk_size, self.remaining_bytes())
97
- if content_length is not None:
98
- num_bytes = min(num_bytes, content_length)
99
-
100
81
  chunk = await loop.run_in_executor(None, self._value.read, num_bytes)
82
+
101
83
  await loop.run_in_executor(None, self._md5_checksum.update, chunk)
102
84
  self.num_bytes_read += len(chunk)
103
85
  return chunk
@@ -27,7 +27,11 @@ class _Client:
27
27
  _snapshotted: bool
28
28
 
29
29
  def __init__(
30
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "1.0.2"
30
+ self,
31
+ server_url: str,
32
+ client_type: int,
33
+ credentials: typing.Optional[tuple[str, str]],
34
+ version: str = "1.0.2.dev1",
31
35
  ): ...
32
36
  def is_closed(self) -> bool: ...
33
37
  @property
@@ -86,7 +90,11 @@ class Client:
86
90
  _snapshotted: bool
87
91
 
88
92
  def __init__(
89
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "1.0.2"
93
+ self,
94
+ server_url: str,
95
+ client_type: int,
96
+ credentials: typing.Optional[tuple[str, str]],
97
+ version: str = "1.0.2.dev1",
90
98
  ): ...
91
99
  def is_closed(self) -> bool: ...
92
100
  @property
@@ -161,8 +161,6 @@ def simulate_preemption(wait_seconds: int, jitter_seconds: int = 0):
161
161
  See https://modal.com/docs/guide/preemption for more details on preemption
162
162
  handling.
163
163
  """
164
- if wait_seconds <= 0:
165
- raise ValueError("Time to wait must be greater than 0")
166
164
  signal.signal(signal.SIGALRM, _simulate_preemption_interrupt)
167
165
  jitter = random.randrange(0, jitter_seconds) if jitter_seconds else 0
168
166
  signal.alarm(wait_seconds + jitter)
@@ -227,11 +227,11 @@ class Function(
227
227
 
228
228
  _call_generator: ___call_generator_spec[typing_extensions.Self]
229
229
 
230
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
230
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
231
231
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
232
232
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
233
233
 
234
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
234
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
235
235
 
236
236
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
237
237
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -246,12 +246,12 @@ class Function(
246
246
  self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
247
247
  ) -> modal._functions.OriginalReturnType: ...
248
248
 
249
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
249
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
250
250
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
251
251
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
252
252
 
253
253
  _experimental_spawn: ___experimental_spawn_spec[
254
- modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
254
+ modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
255
255
  ]
256
256
 
257
257
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -260,11 +260,11 @@ class Function(
260
260
 
261
261
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
262
262
 
263
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
263
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
264
264
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
265
265
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
266
266
 
267
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
267
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
268
268
 
269
269
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
270
270
 
@@ -1442,9 +1442,7 @@ class _Image(_Object, type_prefix="im"):
1442
1442
  if version > "2024.10":
1443
1443
  # for convenience when launching in a sandbox: sleep for 48h
1444
1444
  commands.append(f'CMD ["sleep", "{48 * 3600}"]')
1445
- context_files = {}
1446
- if version <= "2024.10":
1447
- context_files = {CONTAINER_REQUIREMENTS_PATH: _get_modal_requirements_path(version, python_version)}
1445
+ context_files = {CONTAINER_REQUIREMENTS_PATH: _get_modal_requirements_path(version, python_version)}
1448
1446
  return DockerfileSpec(commands=commands, context_files=context_files)
1449
1447
 
1450
1448
  return _Image._from_args(
@@ -1519,15 +1517,12 @@ class _Image(_Object, type_prefix="im"):
1519
1517
 
1520
1518
  # Note: this change is because we install dependencies with uv in 2024.10+
1521
1519
  requirements_prefix = "python -m " if builder_version < "2024.10" else ""
1522
- modal_requirements_commands = []
1523
- if builder_version <= "2024.10":
1524
- # past 2024.10, client dependencies are mounted at runtime
1525
- modal_requirements_commands.extend([
1526
- f"COPY {CONTAINER_REQUIREMENTS_PATH} {CONTAINER_REQUIREMENTS_PATH}",
1527
- f"RUN python -m pip install --upgrade {_base_image_config('package_tools', builder_version)}",
1528
- f"RUN {requirements_prefix}{_get_modal_requirements_command(builder_version)}",
1529
- ])
1530
- if "2024.10" >= builder_version > "2023.12":
1520
+ modal_requirements_commands = [
1521
+ f"COPY {CONTAINER_REQUIREMENTS_PATH} {CONTAINER_REQUIREMENTS_PATH}",
1522
+ f"RUN python -m pip install --upgrade {_base_image_config('package_tools', builder_version)}",
1523
+ f"RUN {requirements_prefix}{_get_modal_requirements_command(builder_version)}",
1524
+ ]
1525
+ if builder_version > "2023.12":
1531
1526
  modal_requirements_commands.append(f"RUN rm {CONTAINER_REQUIREMENTS_PATH}")
1532
1527
 
1533
1528
  return [
@@ -1590,9 +1585,7 @@ class _Image(_Object, type_prefix="im"):
1590
1585
 
1591
1586
  def build_dockerfile(version: ImageBuilderVersion) -> DockerfileSpec:
1592
1587
  commands = _Image._registry_setup_commands(tag, version, setup_dockerfile_commands, add_python)
1593
- context_files = {}
1594
- if version <= "2024.10":
1595
- context_files = {CONTAINER_REQUIREMENTS_PATH: _get_modal_requirements_path(version, add_python)}
1588
+ context_files = {CONTAINER_REQUIREMENTS_PATH: _get_modal_requirements_path(version, add_python)}
1596
1589
  return DockerfileSpec(commands=commands, context_files=context_files)
1597
1590
 
1598
1591
  return _Image._from_args(
@@ -1799,10 +1792,8 @@ class _Image(_Object, type_prefix="im"):
1799
1792
 
1800
1793
  def build_dockerfile_python(version: ImageBuilderVersion) -> DockerfileSpec:
1801
1794
  commands = _Image._registry_setup_commands("base", version, [], add_python)
1802
- context_files = {}
1803
- if version <= "2024.10":
1804
- requirements_path = _get_modal_requirements_path(version, add_python)
1805
- context_files = {CONTAINER_REQUIREMENTS_PATH: requirements_path}
1795
+ requirements_path = _get_modal_requirements_path(version, add_python)
1796
+ context_files = {CONTAINER_REQUIREMENTS_PATH: requirements_path}
1806
1797
  return DockerfileSpec(commands=commands, context_files=context_files)
1807
1798
 
1808
1799
  return _Image._from_args(
@@ -1819,35 +1810,22 @@ class _Image(_Object, type_prefix="im"):
1819
1810
  raise TypeError("The `python_version` argument should be a string, not a float.")
1820
1811
 
1821
1812
  def build_dockerfile(version: ImageBuilderVersion) -> DockerfileSpec:
1822
- context_files = {}
1823
- if version <= "2024.10":
1824
- requirements_path = _get_modal_requirements_path(version, python_version)
1825
- context_files = {CONTAINER_REQUIREMENTS_PATH: requirements_path}
1813
+ requirements_path = _get_modal_requirements_path(version, python_version)
1814
+ context_files = {CONTAINER_REQUIREMENTS_PATH: requirements_path}
1826
1815
  full_python_version = _dockerhub_python_version(version, python_version)
1827
1816
  debian_codename = _base_image_config("debian", version)
1828
1817
 
1829
1818
  commands = [
1830
1819
  f"FROM python:{full_python_version}-slim-{debian_codename}",
1831
- ]
1832
- if version <= "2024.10":
1833
- commands.extend([
1834
- f"COPY {CONTAINER_REQUIREMENTS_PATH} {CONTAINER_REQUIREMENTS_PATH}",
1835
- ])
1836
- commands.extend([
1820
+ f"COPY {CONTAINER_REQUIREMENTS_PATH} {CONTAINER_REQUIREMENTS_PATH}",
1837
1821
  "RUN apt-get update",
1838
1822
  "RUN apt-get install -y gcc gfortran build-essential",
1839
1823
  f"RUN pip install --upgrade {_base_image_config('package_tools', version)}",
1840
- ])
1841
- if version <= "2024.10":
1842
- # after 2024.10, modal requirements are mounted at runtime
1843
- commands.extend([
1844
- f"RUN {_get_modal_requirements_command(version)}",
1845
- ])
1846
- commands.extend([
1824
+ f"RUN {_get_modal_requirements_command(version)}",
1847
1825
  # Set debian front-end to non-interactive to avoid users getting stuck with input prompts.
1848
1826
  "RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections",
1849
- ])
1850
- if "2024.10" >= version > "2023.12":
1827
+ ]
1828
+ if version > "2023.12":
1851
1829
  commands.append(f"RUN rm {CONTAINER_REQUIREMENTS_PATH}")
1852
1830
  if version > "2024.10":
1853
1831
  # for convenience when launching in a sandbox: sleep for 48h
@@ -252,8 +252,7 @@ class _Sandbox(_Object, type_prefix="sb"):
252
252
  client: Optional[_Client] = None,
253
253
  ) -> "_Sandbox":
254
254
  """
255
- Create a new Sandbox to run untrusted, arbitrary code. The Sandbox's corresponding container
256
- will be created asynchronously.
255
+ Create a new Sandbox to run untrusted, arbitrary code.
257
256
 
258
257
  **Usage**
259
258
 
@@ -38,7 +38,6 @@ from ._utils.async_utils import (
38
38
  async_map,
39
39
  async_map_ordered,
40
40
  asyncnullcontext,
41
- retry,
42
41
  synchronize_api,
43
42
  )
44
43
  from ._utils.blob_utils import (
@@ -376,16 +375,10 @@ class _Volume(_Object, type_prefix="vo"):
376
375
  "Please remove the glob `*` suffix."
377
376
  )
378
377
 
379
- if self._is_v1:
380
- req = api_pb2.VolumeListFilesRequest(volume_id=self.object_id, path=path, recursive=recursive)
381
- async for batch in self._client.stub.VolumeListFiles.unary_stream(req):
382
- for entry in batch.entries:
383
- yield FileEntry._from_proto(entry)
384
- else:
385
- req = api_pb2.VolumeListFiles2Request(volume_id=self.object_id, path=path, recursive=recursive)
386
- async for batch in self._client.stub.VolumeListFiles2.unary_stream(req):
387
- for entry in batch.entries:
388
- yield FileEntry._from_proto(entry)
378
+ req = api_pb2.VolumeListFilesRequest(volume_id=self.object_id, path=path, recursive=recursive)
379
+ async for batch in self._client.stub.VolumeListFiles.unary_stream(req):
380
+ for entry in batch.entries:
381
+ yield FileEntry._from_proto(entry)
389
382
 
390
383
  @live_method
391
384
  async def listdir(self, path: str, *, recursive: bool = False) -> list[FileEntry]:
@@ -506,7 +499,7 @@ class _Volume(_Object, type_prefix="vo"):
506
499
  num_bytes_written = 0
507
500
 
508
501
  async with download_semaphore, ClientSessionRegistry.get_session().get(url) as get_response:
509
- async for chunk in get_response.content.iter_any():
502
+ async for chunk in get_response.content:
510
503
  num_chunk_bytes_written = 0
511
504
 
512
505
  while num_chunk_bytes_written < len(chunk):
@@ -533,12 +526,8 @@ class _Volume(_Object, type_prefix="vo"):
533
526
  @live_method
534
527
  async def remove_file(self, path: str, recursive: bool = False) -> None:
535
528
  """Remove a file or directory from a volume."""
536
- if self._is_v1:
537
- req = api_pb2.VolumeRemoveFileRequest(volume_id=self.object_id, path=path, recursive=recursive)
538
- await retry_transient_errors(self._client.stub.VolumeRemoveFile, req)
539
- else:
540
- req = api_pb2.VolumeRemoveFile2Request(volume_id=self.object_id, path=path, recursive=recursive)
541
- await retry_transient_errors(self._client.stub.VolumeRemoveFile2, req)
529
+ req = api_pb2.VolumeRemoveFileRequest(volume_id=self.object_id, path=path, recursive=recursive)
530
+ await retry_transient_errors(self._client.stub.VolumeRemoveFile, req)
542
531
 
543
532
  @live_method
544
533
  async def copy_files(self, src_paths: Sequence[str], dst_path: str) -> None:
@@ -836,7 +825,7 @@ class _VolumeUploadContextManager2(_AbstractVolumeUploadContextManager):
836
825
  progress_cb: Optional[Callable[..., Any]] = None,
837
826
  force: bool = False,
838
827
  hash_concurrency: int = multiprocessing.cpu_count(),
839
- put_concurrency: int = 128,
828
+ put_concurrency: int = multiprocessing.cpu_count(),
840
829
  ):
841
830
  """mdmd:hidden"""
842
831
  self._volume_id = volume_id
@@ -1021,16 +1010,6 @@ async def _put_missing_blocks(
1021
1010
  file_progress.pending_blocks.add(missing_block.block_index)
1022
1011
  task_progress_cb = functools.partial(progress_cb, task_id=file_progress.task_id)
1023
1012
 
1024
- @retry(n_attempts=5, base_delay=0.5, timeout=None)
1025
- async def put_missing_block_attempt(payload: BytesIOSegmentPayload) -> bytes:
1026
- with payload.reset_on_error(subtract_progress=True):
1027
- async with ClientSessionRegistry.get_session().put(
1028
- missing_block.put_url,
1029
- data=payload,
1030
- ) as response:
1031
- response.raise_for_status()
1032
- return await response.content.read()
1033
-
1034
1013
  async with put_semaphore:
1035
1014
  with file_spec.source() as source_fp:
1036
1015
  payload = BytesIOSegmentPayload(
@@ -1041,7 +1020,13 @@ async def _put_missing_blocks(
1041
1020
  chunk_size=256 * 1024,
1042
1021
  progress_report_cb=task_progress_cb,
1043
1022
  )
1044
- resp_data = await put_missing_block_attempt(payload)
1023
+
1024
+ async with ClientSessionRegistry.get_session().put(
1025
+ missing_block.put_url,
1026
+ data=payload,
1027
+ ) as response:
1028
+ response.raise_for_status()
1029
+ resp_data = await response.content.read()
1045
1030
 
1046
1031
  file_progress.pending_blocks.remove(missing_block.block_index)
1047
1032
 
@@ -494,7 +494,7 @@ class _VolumeUploadContextManager2(_AbstractVolumeUploadContextManager):
494
494
  progress_cb: typing.Optional[collections.abc.Callable[..., typing.Any]] = None,
495
495
  force: bool = False,
496
496
  hash_concurrency: int = 4,
497
- put_concurrency: int = 128,
497
+ put_concurrency: int = 4,
498
498
  ): ...
499
499
  async def __aenter__(self): ...
500
500
  async def __aexit__(self, exc_type, exc_val, exc_tb): ...
@@ -534,7 +534,7 @@ class VolumeUploadContextManager2(AbstractVolumeUploadContextManager):
534
534
  progress_cb: typing.Optional[collections.abc.Callable[..., typing.Any]] = None,
535
535
  force: bool = False,
536
536
  hash_concurrency: int = 4,
537
- put_concurrency: int = 128,
537
+ put_concurrency: int = 4,
538
538
  ): ...
539
539
  def __enter__(self): ...
540
540
  async def __aenter__(self): ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.2
3
+ Version: 1.0.2.dev1
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -2153,7 +2153,6 @@ message PTYInfo {
2153
2153
  message PortSpec {
2154
2154
  uint32 port = 1;
2155
2155
  bool unencrypted = 2;
2156
- optional string tunnel_type = 3;
2157
2156
  }
2158
2157
 
2159
2158
  message PortSpecs {
@@ -2587,7 +2586,6 @@ message SandboxWaitResponse {
2587
2586
  message Schedule {
2588
2587
  message Cron {
2589
2588
  string cron_string = 1;
2590
- string timezone = 2;
2591
2589
  }
2592
2590
  message Period {
2593
2591
  int32 years = 1;
@@ -2878,7 +2876,6 @@ message TunnelData {
2878
2876
  message TunnelStartRequest {
2879
2877
  uint32 port = 1;
2880
2878
  bool unencrypted = 2;
2881
- optional string tunnel_type = 3;
2882
2879
  }
2883
2880
 
2884
2881
  message TunnelStartResponse {