modal 1.0.6.dev11__py3-none-any.whl → 1.0.6.dev12__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.

Potentially problematic release.


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

modal/client.pyi CHANGED
@@ -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.
modal/image.py CHANGED
@@ -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,
modal/image.pyi CHANGED
@@ -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
@@ -22,7 +22,7 @@ modal/app.py,sha256=fCKq3TJ2Y5LB2WKNs6pp_5XECNH5avUL01jQljuoYRU,46603
22
22
  modal/app.pyi,sha256=Z6wi_dkXywiaM2rvAvguj2Wgu9ZgPjMSLl1nH1a7EYI,42243
23
23
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
24
24
  modal/client.py,sha256=OwISJvkgMb-rHm9Gc4i-7YcDgGiZgwJ7F_PzwZH7a6Q,16847
25
- modal/client.pyi,sha256=zl_EPLUEV_gmqQ_5xh00m4HrFWtdKfwD55do9q4k9ms,15081
25
+ modal/client.pyi,sha256=CyTf35ksjuSZFtTIS2si_oUalgKm6MjDSj77390VX4g,15081
26
26
  modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
27
27
  modal/cloud_bucket_mount.pyi,sha256=-qSfYAQvIoO_l2wsCCGTG5ZUwQieNKXdAO00yP1-LYU,7394
28
28
  modal/cls.py,sha256=EFrM949jNXJpmwB2G_1d28b8IpHShfKIEIaiPkZqeOU,39881
@@ -41,8 +41,8 @@ modal/file_pattern_matcher.py,sha256=urAue8es8jxqX94k9EYoZxxhtfgOlsEES8lbFHOorzc
41
41
  modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
42
42
  modal/functions.pyi,sha256=FJe_91dSrMCRNVT-YV1UhtxFKzIvL_C5q8xdk08-wT8,34840
43
43
  modal/gpu.py,sha256=Fe5ORvVPDIstSq1xjmM6OoNgLYFWvogP9r5BgmD3hYg,6769
44
- modal/image.py,sha256=W0Xg-nhsuLDO6weC1lk07MWVZFgZAxRdFqaA-Lt6_AI,94068
45
- modal/image.pyi,sha256=ha8QhMPDRmfTSoRlQ8CgV4-AZ7kYKK_-R2UXLyGPgQU,68172
44
+ modal/image.py,sha256=IuK__pPaqMpJoCtgUGO0kJoT3GK_Oostp9EGfFEoglA,99341
45
+ modal/image.pyi,sha256=pGuNaaDq1QEyCiIZYx_82wy5ER7iYDGUxzlJorPJJ7w,70338
46
46
  modal/io_streams.py,sha256=FUDpBsVK8isqwyC7DtAcQZhaHlMFSaNZGhYJOg-SFW0,15590
47
47
  modal/io_streams.pyi,sha256=5b3b93ztZeR8IpJtNIGffX24QLPgocE4-gAps8y7CKU,13824
48
48
  modal/mount.py,sha256=VrExPZApUnuh9shJx-tzdmQJ9ASTSK-SEaYHDBkQl-k,36632
@@ -147,7 +147,7 @@ modal/requirements/2024.10.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddR
147
147
  modal/requirements/PREVIEW.txt,sha256=KxDaVTOwatHvboDo4lorlgJ7-n-MfAwbPwxJ0zcJqrs,312
148
148
  modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,854
149
149
  modal/requirements/base-images.json,sha256=3oKVHov9vE88hMQGnn1OqDQK-ohxNF_TEL2DNPKg09s,1051
150
- modal-1.0.6.dev11.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
150
+ modal-1.0.6.dev12.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
151
151
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
152
152
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
153
153
  modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
@@ -170,10 +170,10 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
170
170
  modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
171
171
  modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
172
172
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
173
- modal_version/__init__.py,sha256=UqUMJ7n1L5vP9wjlbC4joFDzFMNE_BFE1_iQEgOqMkE,121
173
+ modal_version/__init__.py,sha256=BrUvkqiEK_ozM88NmqgW86Tjrim4cnV78o5CwsC0QCQ,121
174
174
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
175
- modal-1.0.6.dev11.dist-info/METADATA,sha256=AC8JBvzouxVsKTCU2bFOpfyDI_ZRXbB3N7HuzKNt4pk,2462
176
- modal-1.0.6.dev11.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
177
- modal-1.0.6.dev11.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
178
- modal-1.0.6.dev11.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
179
- modal-1.0.6.dev11.dist-info/RECORD,,
175
+ modal-1.0.6.dev12.dist-info/METADATA,sha256=JFjiNd2cvgC6aMWeNkEoC10PKl0IGzlZPNeg_KazQ3s,2462
176
+ modal-1.0.6.dev12.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
177
+ modal-1.0.6.dev12.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
178
+ modal-1.0.6.dev12.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
179
+ modal-1.0.6.dev12.dist-info/RECORD,,
modal_version/__init__.py CHANGED
@@ -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"