modal 1.0.6.dev11__tar.gz → 1.0.6.dev12__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.

Potentially problematic release.


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

Files changed (184) hide show
  1. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/PKG-INFO +1 -1
  2. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/client.pyi +2 -2
  3. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/image.py +108 -0
  4. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/image.pyi +60 -0
  5. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal.egg-info/PKG-INFO +1 -1
  6. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_version/__init__.py +1 -1
  7. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/LICENSE +0 -0
  8. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/README.md +0 -0
  9. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/__init__.py +0 -0
  10. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/__main__.py +0 -0
  11. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_clustered_functions.py +0 -0
  12. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_clustered_functions.pyi +0 -0
  13. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_container_entrypoint.py +0 -0
  14. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_functions.py +0 -0
  15. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_ipython.py +0 -0
  16. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_location.py +0 -0
  17. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_object.py +0 -0
  18. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_output.py +0 -0
  19. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_partial_function.py +0 -0
  20. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_pty.py +0 -0
  21. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_resolver.py +0 -0
  22. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_resources.py +0 -0
  23. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/__init__.py +0 -0
  24. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/asgi.py +0 -0
  25. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/container_io_manager.py +0 -0
  26. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/container_io_manager.pyi +0 -0
  27. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/execution_context.py +0 -0
  28. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/execution_context.pyi +0 -0
  29. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  30. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/telemetry.py +0 -0
  31. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_runtime/user_code_imports.py +0 -0
  32. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_serialization.py +0 -0
  33. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_traceback.py +0 -0
  34. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_tunnel.py +0 -0
  35. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_tunnel.pyi +0 -0
  36. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_type_manager.py +0 -0
  37. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/__init__.py +0 -0
  38. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/app_utils.py +0 -0
  39. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/async_utils.py +0 -0
  40. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/blob_utils.py +0 -0
  41. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/bytes_io_segment_payload.py +0 -0
  42. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/deprecation.py +0 -0
  43. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/docker_utils.py +0 -0
  44. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/function_utils.py +0 -0
  45. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/git_utils.py +0 -0
  46. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/grpc_testing.py +0 -0
  47. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/grpc_utils.py +0 -0
  48. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/hash_utils.py +0 -0
  49. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/http_utils.py +0 -0
  50. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/jwt_utils.py +0 -0
  51. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/logger.py +0 -0
  52. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/mount_utils.py +0 -0
  53. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/name_utils.py +0 -0
  54. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/package_utils.py +0 -0
  55. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/pattern_utils.py +0 -0
  56. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/rand_pb_testing.py +0 -0
  57. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/shell_utils.py +0 -0
  58. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_utils/time_utils.py +0 -0
  59. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_vendor/__init__.py +0 -0
  60. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  61. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_vendor/cloudpickle.py +0 -0
  62. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_vendor/tblib.py +0 -0
  63. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/_watcher.py +0 -0
  64. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/app.py +0 -0
  65. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/app.pyi +0 -0
  66. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/call_graph.py +0 -0
  67. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/__init__.py +0 -0
  68. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/_download.py +0 -0
  69. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/_traceback.py +0 -0
  70. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/app.py +0 -0
  71. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/cluster.py +0 -0
  72. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/config.py +0 -0
  73. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/container.py +0 -0
  74. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/dict.py +0 -0
  75. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/entry_point.py +0 -0
  76. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/environment.py +0 -0
  77. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/import_refs.py +0 -0
  78. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/launch.py +0 -0
  79. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/network_file_system.py +0 -0
  80. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/profile.py +0 -0
  81. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/programs/__init__.py +0 -0
  82. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/programs/run_jupyter.py +0 -0
  83. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/programs/vscode.py +0 -0
  84. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/queues.py +0 -0
  85. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/run.py +0 -0
  86. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/secret.py +0 -0
  87. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/token.py +0 -0
  88. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/utils.py +0 -0
  89. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cli/volume.py +0 -0
  90. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/client.py +0 -0
  91. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cloud_bucket_mount.py +0 -0
  92. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cloud_bucket_mount.pyi +0 -0
  93. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cls.py +0 -0
  94. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/cls.pyi +0 -0
  95. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/config.py +0 -0
  96. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/container_process.py +0 -0
  97. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/container_process.pyi +0 -0
  98. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/dict.py +0 -0
  99. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/dict.pyi +0 -0
  100. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/environments.py +0 -0
  101. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/environments.pyi +0 -0
  102. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/exception.py +0 -0
  103. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/experimental/__init__.py +0 -0
  104. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/experimental/ipython.py +0 -0
  105. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/file_io.py +0 -0
  106. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/file_io.pyi +0 -0
  107. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/file_pattern_matcher.py +0 -0
  108. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/functions.py +0 -0
  109. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/functions.pyi +0 -0
  110. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/gpu.py +0 -0
  111. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/io_streams.py +0 -0
  112. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/io_streams.pyi +0 -0
  113. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/mount.py +0 -0
  114. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/mount.pyi +0 -0
  115. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/network_file_system.py +0 -0
  116. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/network_file_system.pyi +0 -0
  117. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/object.py +0 -0
  118. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/object.pyi +0 -0
  119. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/output.py +0 -0
  120. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/parallel_map.py +0 -0
  121. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/parallel_map.pyi +0 -0
  122. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/partial_function.py +0 -0
  123. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/partial_function.pyi +0 -0
  124. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/proxy.py +0 -0
  125. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/proxy.pyi +0 -0
  126. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/py.typed +0 -0
  127. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/queue.py +0 -0
  128. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/queue.pyi +0 -0
  129. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/requirements/2023.12.312.txt +0 -0
  130. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/requirements/2023.12.txt +0 -0
  131. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/requirements/2024.04.txt +0 -0
  132. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/requirements/2024.10.txt +0 -0
  133. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/requirements/PREVIEW.txt +0 -0
  134. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/requirements/README.md +0 -0
  135. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/requirements/base-images.json +0 -0
  136. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/retries.py +0 -0
  137. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/runner.py +0 -0
  138. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/runner.pyi +0 -0
  139. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/running_app.py +0 -0
  140. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/sandbox.py +0 -0
  141. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/sandbox.pyi +0 -0
  142. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/schedule.py +0 -0
  143. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/scheduler_placement.py +0 -0
  144. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/secret.py +0 -0
  145. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/secret.pyi +0 -0
  146. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/serving.py +0 -0
  147. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/serving.pyi +0 -0
  148. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/snapshot.py +0 -0
  149. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/snapshot.pyi +0 -0
  150. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/stream_type.py +0 -0
  151. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/token_flow.py +0 -0
  152. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/token_flow.pyi +0 -0
  153. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/volume.py +0 -0
  154. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal/volume.pyi +0 -0
  155. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal.egg-info/SOURCES.txt +0 -0
  156. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal.egg-info/dependency_links.txt +0 -0
  157. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal.egg-info/entry_points.txt +0 -0
  158. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal.egg-info/requires.txt +0 -0
  159. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal.egg-info/top_level.txt +0 -0
  160. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_docs/__init__.py +0 -0
  161. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_docs/gen_cli_docs.py +0 -0
  162. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_docs/gen_reference_docs.py +0 -0
  163. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_docs/mdmd/__init__.py +0 -0
  164. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_docs/mdmd/mdmd.py +0 -0
  165. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_docs/mdmd/signatures.py +0 -0
  166. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/__init__.py +0 -0
  167. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/api.proto +0 -0
  168. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/api_grpc.py +0 -0
  169. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/api_pb2.py +0 -0
  170. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/api_pb2.pyi +0 -0
  171. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/api_pb2_grpc.py +0 -0
  172. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/api_pb2_grpc.pyi +0 -0
  173. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/modal_api_grpc.py +0 -0
  174. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/modal_options_grpc.py +0 -0
  175. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/options.proto +0 -0
  176. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/options_grpc.py +0 -0
  177. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/options_pb2.py +0 -0
  178. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/options_pb2.pyi +0 -0
  179. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/options_pb2_grpc.py +0 -0
  180. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/options_pb2_grpc.pyi +0 -0
  181. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_proto/py.typed +0 -0
  182. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/modal_version/__main__.py +0 -0
  183. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/pyproject.toml +0 -0
  184. {modal-1.0.6.dev11 → modal-1.0.6.dev12}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.6.dev11
3
+ Version: 1.0.6.dev12
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -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.6.dev11",
34
+ version: str = "1.0.6.dev12",
35
35
  ):
36
36
  """mdmd:hidden
37
37
  The Modal client object is not intended to be instantiated directly by users.
@@ -160,7 +160,7 @@ class Client:
160
160
  server_url: str,
161
161
  client_type: int,
162
162
  credentials: typing.Optional[tuple[str, str]],
163
- version: str = "1.0.6.dev11",
163
+ version: str = "1.0.6.dev12",
164
164
  ):
165
165
  """mdmd:hidden
166
166
  The Modal client object is not intended to be instantiated directly by users.
@@ -1222,6 +1222,114 @@ class _Image(_Object, type_prefix="im"):
1222
1222
  gpu_config=parse_gpu_config(gpu),
1223
1223
  )
1224
1224
 
1225
+ def uv_pip_install(
1226
+ self,
1227
+ *packages: Union[str, list[str]], # A list of Python packages, eg. ["numpy", "matplotlib>=3.5.0"]
1228
+ requirements: Optional[list[str]] = None, # Passes -r (--requirements) to uv pip install
1229
+ find_links: Optional[str] = None, # Passes -f (--find-links) to uv pip install
1230
+ index_url: Optional[str] = None, # Passes -i (--index-url) to uv pip install
1231
+ extra_index_url: Optional[str] = None, # Passes --extra-index-url to uv pip install
1232
+ pre: bool = False, # Allow pre-releases using uv pip install --prerelease allow
1233
+ extra_options: str = "", # Additional options to pass to pip install, e.g. "--no-build-isolation"
1234
+ force_build: bool = False, # Ignore cached builds, similar to 'docker build --no-cache'
1235
+ uv_version: Optional[str] = None, # uv version to use
1236
+ secrets: Sequence[_Secret] = [],
1237
+ gpu: GPU_T = None,
1238
+ ) -> "_Image":
1239
+ """Install a list of Python packages using uv pip install.
1240
+
1241
+ **Examples**
1242
+
1243
+ Simple installation:
1244
+ ```python
1245
+ image = modal.Image.debian_slim().uv_pip_install("torch==2.7.1", "numpy")
1246
+ ```
1247
+
1248
+ This method assumes that:
1249
+ - Python is on the `$PATH` and dependencies are installed with the first Python on the `$PATH`.
1250
+ - Shell supports backticks for substitution
1251
+ - `which` command is on the `$PATH`
1252
+ """
1253
+ pkgs = _flatten_str_args("uv_pip_install", "packages", packages)
1254
+
1255
+ if requirements is None or isinstance(requirements, list):
1256
+ requirements = requirements or []
1257
+ else:
1258
+ raise InvalidError("requirements must be None or a list of strings")
1259
+
1260
+ if not pkgs and not requirements:
1261
+ return self
1262
+ elif not _validate_packages(pkgs):
1263
+ raise InvalidError(
1264
+ "Package list for `Image.uv_pip_install` cannot contain other arguments;"
1265
+ " try the `extra_options` parameter instead."
1266
+ )
1267
+
1268
+ def build_dockerfile(version: ImageBuilderVersion) -> DockerfileSpec:
1269
+ commands = ["FROM base"]
1270
+ UV_ROOT = "/.uv"
1271
+ if uv_version is None:
1272
+ commands.append(f"COPY --from=ghcr.io/astral-sh/uv:latest /uv {UV_ROOT}/uv")
1273
+ else:
1274
+ commands.append(f"COPY --from=ghcr.io/astral-sh/uv:{uv_version} /uv {UV_ROOT}/uv")
1275
+
1276
+ # NOTE: Using `which python` assumes:
1277
+ # - python is on the PATH and uv is installing into the first python in the PATH
1278
+ # - the shell supports backticks for substitution
1279
+ # - `which` command is on the PATH
1280
+ uv_pip_args = ["--python `which python`", "--compile-bytecode"]
1281
+ context_files = {}
1282
+
1283
+ if find_links:
1284
+ uv_pip_args.append(f"--find-links {shlex.quote(find_links)}")
1285
+ if index_url:
1286
+ uv_pip_args.append(f"--index-url {shlex.quote(index_url)}")
1287
+ if extra_index_url:
1288
+ uv_pip_args.append(f"--extra-index-url {shlex.quote(extra_index_url)}")
1289
+ if pre:
1290
+ uv_pip_args.append("--prerelease allow")
1291
+ if extra_options:
1292
+ uv_pip_args.append(extra_options)
1293
+
1294
+ if requirements:
1295
+
1296
+ def _generate_paths(idx: int, req: str) -> dict:
1297
+ local_path = os.path.expanduser(req)
1298
+ basename = os.path.basename(req)
1299
+
1300
+ # The requirement files can have the same name but in different directories:
1301
+ # requirements=["test/requirements.txt", "a/b/c/requirements.txt"]
1302
+ # To uniquely identify these files, we add a `idx` prefix to every file's basename
1303
+ # - `test/requirements.txt` -> `/.0_requirements.txt` in context -> `/.uv/0/requirements.txt` to uv
1304
+ # - `a/b/c/requirements.txt` -> `/.1_requirements.txt` in context -> `/.uv/1/requirements.txt` to uv
1305
+ return {
1306
+ "local_path": local_path,
1307
+ "context_path": f"/.{idx}_{basename}",
1308
+ "dest_path": f"{UV_ROOT}/{idx}/{basename}",
1309
+ }
1310
+
1311
+ requirement_paths = [_generate_paths(idx, req) for idx, req in enumerate(requirements)]
1312
+ requirements_cli = " ".join(f"--requirements {req['dest_path']}" for req in requirement_paths)
1313
+ uv_pip_args.append(requirements_cli)
1314
+
1315
+ commands.extend([f"COPY {req['context_path']} {req['dest_path']}" for req in requirement_paths])
1316
+ context_files.update({req["context_path"]: req["local_path"] for req in requirement_paths})
1317
+
1318
+ uv_pip_args.extend(shlex.quote(p) for p in sorted(pkgs))
1319
+ uv_pip_args_joined = " ".join(uv_pip_args)
1320
+
1321
+ commands.append(f"RUN {UV_ROOT}/uv pip install {uv_pip_args_joined}")
1322
+
1323
+ return DockerfileSpec(commands=commands, context_files=context_files)
1324
+
1325
+ return _Image._from_args(
1326
+ base_images={"base": self},
1327
+ dockerfile_function=build_dockerfile,
1328
+ force_build=self.force_build or force_build,
1329
+ gpu_config=parse_gpu_config(gpu),
1330
+ secrets=secrets,
1331
+ )
1332
+
1225
1333
  def poetry_install_from_file(
1226
1334
  self,
1227
1335
  poetry_pyproject_toml: str,
@@ -505,6 +505,36 @@ class _Image(modal._object._Object):
505
505
  """
506
506
  ...
507
507
 
508
+ def uv_pip_install(
509
+ self,
510
+ *packages: typing.Union[str, list[str]],
511
+ requirements: typing.Optional[list[str]] = None,
512
+ find_links: typing.Optional[str] = None,
513
+ index_url: typing.Optional[str] = None,
514
+ extra_index_url: typing.Optional[str] = None,
515
+ pre: bool = False,
516
+ extra_options: str = "",
517
+ force_build: bool = False,
518
+ uv_version: typing.Optional[str] = None,
519
+ secrets: collections.abc.Sequence[modal.secret._Secret] = [],
520
+ gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
521
+ ) -> _Image:
522
+ """Install a list of Python packages using uv pip install.
523
+
524
+ **Examples**
525
+
526
+ Simple installation:
527
+ ```python
528
+ image = modal.Image.debian_slim().uv_pip_install("torch==2.7.1", "numpy")
529
+ ```
530
+
531
+ This method assumes that:
532
+ - Python is on the `$PATH` and dependencies are installed with the first Python on the `$PATH`.
533
+ - Shell supports backticks for substitution
534
+ - `which` command is on the `$PATH`
535
+ """
536
+ ...
537
+
508
538
  def poetry_install_from_file(
509
539
  self,
510
540
  poetry_pyproject_toml: str,
@@ -1348,6 +1378,36 @@ class Image(modal.object.Object):
1348
1378
  """
1349
1379
  ...
1350
1380
 
1381
+ def uv_pip_install(
1382
+ self,
1383
+ *packages: typing.Union[str, list[str]],
1384
+ requirements: typing.Optional[list[str]] = None,
1385
+ find_links: typing.Optional[str] = None,
1386
+ index_url: typing.Optional[str] = None,
1387
+ extra_index_url: typing.Optional[str] = None,
1388
+ pre: bool = False,
1389
+ extra_options: str = "",
1390
+ force_build: bool = False,
1391
+ uv_version: typing.Optional[str] = None,
1392
+ secrets: collections.abc.Sequence[modal.secret.Secret] = [],
1393
+ gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
1394
+ ) -> Image:
1395
+ """Install a list of Python packages using uv pip install.
1396
+
1397
+ **Examples**
1398
+
1399
+ Simple installation:
1400
+ ```python
1401
+ image = modal.Image.debian_slim().uv_pip_install("torch==2.7.1", "numpy")
1402
+ ```
1403
+
1404
+ This method assumes that:
1405
+ - Python is on the `$PATH` and dependencies are installed with the first Python on the `$PATH`.
1406
+ - Shell supports backticks for substitution
1407
+ - `which` command is on the `$PATH`
1408
+ """
1409
+ ...
1410
+
1351
1411
  def poetry_install_from_file(
1352
1412
  self,
1353
1413
  poetry_pyproject_toml: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.6.dev11
3
+ Version: 1.0.6.dev12
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.6.dev11"
4
+ __version__ = "1.0.6.dev12"
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