modal 0.67.0__py3-none-any.whl → 0.67.5__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.
modal/_runtime/asgi.py CHANGED
@@ -280,9 +280,48 @@ def wait_for_web_server(host: str, port: int, *, timeout: float) -> None:
280
280
  ) from ex
281
281
 
282
282
 
283
+ def _add_forwarded_for_header(scope):
284
+ # we strip X-Forwarded-For headers from the scope
285
+ # but we can add it back from the ASGI scope
286
+ # https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope
287
+
288
+ # X-Forwarded-For headers is a comma separated list of IP addresses
289
+ # there may be multiple X-Forwarded-For headers
290
+ # we want to prepend the client IP to the first one
291
+ # but only if it doesn't exist in one of the headers already
292
+
293
+ first_x_forwarded_for_idx = None
294
+ if "headers" in scope and "client" in scope:
295
+ client_host = scope["client"][0]
296
+
297
+ for idx, header in enumerate(scope["headers"]):
298
+ if header[0] == b"X-Forwarded-For":
299
+ if first_x_forwarded_for_idx is None:
300
+ first_x_forwarded_for_idx = idx
301
+ values = header[1].decode().split(", ")
302
+
303
+ if client_host in values:
304
+ # we already have the client IP in this header
305
+ # return early
306
+ return scope
307
+
308
+ if first_x_forwarded_for_idx is not None:
309
+ # we have X-Forwarded-For headers but they don't have the client IP
310
+ # we need to prepend the client IP to the first one
311
+ values = [client_host] + scope["headers"][first_x_forwarded_for_idx][1].decode().split(", ")
312
+ scope["headers"][first_x_forwarded_for_idx] = (b"X-Forwarded-For", ", ".join(values).encode())
313
+ else:
314
+ # we don't have X-Forwarded-For headers, we need to add one
315
+ scope["headers"].append((b"X-Forwarded-For", client_host.encode()))
316
+
317
+ return scope
318
+
319
+
283
320
  async def _proxy_http_request(session: aiohttp.ClientSession, scope, receive, send) -> None:
284
321
  proxy_response: aiohttp.ClientResponse
285
322
 
323
+ scope = _add_forwarded_for_header(scope)
324
+
286
325
  async def request_generator() -> AsyncGenerator[bytes, None]:
287
326
  while True:
288
327
  message = await receive()
modal/_tunnel.py CHANGED
@@ -61,7 +61,7 @@ async def _forward(port: int, *, unencrypted: bool = False, client: Optional[_Cl
61
61
 
62
62
  **Usage:**
63
63
 
64
- ```python
64
+ ```python notest
65
65
  import modal
66
66
  from flask import Flask
67
67
 
@@ -573,6 +573,46 @@ STOP_SENTINEL = StopSentinelType()
573
573
 
574
574
 
575
575
  async def async_merge(*generators: AsyncGenerator[T, None]) -> AsyncGenerator[T, None]:
576
+ """
577
+ Asynchronously merges multiple async generators into a single async generator.
578
+
579
+ This function takes multiple async generators and yields their values in the order
580
+ they are produced. If any generator raises an exception, the exception is propagated.
581
+
582
+ Args:
583
+ *generators: One or more async generators to be merged.
584
+
585
+ Yields:
586
+ The values produced by the input async generators.
587
+
588
+ Raises:
589
+ Exception: If any of the input generators raises an exception, it is propagated.
590
+
591
+ Usage:
592
+ ```python
593
+ import asyncio
594
+ from modal._utils.async_utils import async_merge
595
+
596
+ async def gen1():
597
+ yield 1
598
+ yield 2
599
+
600
+ async def gen2():
601
+ yield "a"
602
+ yield "b"
603
+
604
+ async def example():
605
+ values = set()
606
+ async for value in async_merge(gen1(), gen2()):
607
+ values.add(value)
608
+
609
+ return values
610
+
611
+ # Output could be: {1, "a", 2, "b"} (order may vary)
612
+ values = asyncio.run(example())
613
+ assert values == {1, "a", 2, "b"}
614
+ ```
615
+ """
576
616
  queue: asyncio.Queue[Union[ValueWrapper[T], ExceptionWrapper]] = asyncio.Queue(maxsize=len(generators) * 10)
577
617
 
578
618
  async def producer(generator: AsyncGenerator[T, None]):
modal/app.py CHANGED
@@ -401,14 +401,14 @@ class _App:
401
401
 
402
402
  **Example**
403
403
 
404
- ```python
404
+ ```python notest
405
405
  with app.run():
406
406
  some_modal_function.remote()
407
407
  ```
408
408
 
409
409
  To enable output printing, use `modal.enable_output()`:
410
410
 
411
- ```python
411
+ ```python notest
412
412
  with modal.enable_output():
413
413
  with app.run():
414
414
  some_modal_function.remote()
@@ -492,13 +492,19 @@ class _App:
492
492
 
493
493
  _App._container_app = running_app
494
494
 
495
- # Hydrate objects on app
496
- indexed_objects = dict(**self._functions, **self._classes)
497
- for tag, object_id in running_app.tag_to_object_id.items():
498
- if tag in indexed_objects:
499
- obj = indexed_objects[tag]
500
- handle_metadata = running_app.object_handle_metadata[object_id]
501
- obj._hydrate(object_id, client, handle_metadata)
495
+ # Hydrate objects on app -- hydrating functions first so that when a class is being hydrated its
496
+ # corresponding class service function is already hydrated.
497
+ def hydrate_objects(objects_dict):
498
+ for tag, object_id in running_app.tag_to_object_id.items():
499
+ if tag in objects_dict:
500
+ obj = objects_dict[tag]
501
+ handle_metadata = running_app.object_handle_metadata[object_id]
502
+ obj._hydrate(object_id, client, handle_metadata)
503
+
504
+ # Hydrate function objects
505
+ hydrate_objects(self._functions)
506
+ # Hydrate class objects
507
+ hydrate_objects(self._classes)
502
508
 
503
509
  @property
504
510
  def registered_functions(self) -> Dict[str, _Function]:
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[typing.Tuple[str, str]],
34
- version: str = "0.67.0",
34
+ version: str = "0.67.5",
35
35
  ): ...
36
36
  def is_closed(self) -> bool: ...
37
37
  @property
@@ -90,7 +90,7 @@ class Client:
90
90
  server_url: str,
91
91
  client_type: int,
92
92
  credentials: typing.Optional[typing.Tuple[str, str]],
93
- version: str = "0.67.0",
93
+ version: str = "0.67.5",
94
94
  ): ...
95
95
  def is_closed(self) -> bool: ...
96
96
  @property
modal/cls.py CHANGED
@@ -154,7 +154,7 @@ class _Obj:
154
154
  Note that all Modal methods and web endpoints of a class share the same set
155
155
  of containers and the warm_pool_size affects that common container pool.
156
156
 
157
- ```python
157
+ ```python notest
158
158
  # Usage on a parametrized function.
159
159
  Model = modal.Cls.lookup("my-app", "Model")
160
160
  Model("fine-tuned-model").keep_warm(2)
@@ -524,7 +524,7 @@ class _Cls(_Object, type_prefix="cs"):
524
524
  In contrast to `modal.Cls.from_name`, this is an eager method
525
525
  that will hydrate the local object with metadata from Modal servers.
526
526
 
527
- ```python
527
+ ```python notest
528
528
  Class = modal.Cls.lookup("other-app", "Class")
529
529
  obj = Class()
530
530
  ```
modal/dict.py CHANGED
@@ -88,7 +88,9 @@ class _Dict(_Object, type_prefix="di"):
88
88
 
89
89
  with Dict.ephemeral() as d:
90
90
  d["foo"] = "bar"
91
+ ```
91
92
 
93
+ ```python notest
92
94
  async with Dict.ephemeral() as d:
93
95
  await d.put.aio("foo", "bar")
94
96
  ```
modal/functions.py CHANGED
@@ -997,7 +997,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
997
997
  Please exercise care when using this advanced feature!
998
998
  Setting and forgetting a warm pool on functions can lead to increased costs.
999
999
 
1000
- ```python
1000
+ ```python notest
1001
1001
  # Usage on a regular function.
1002
1002
  f = modal.Function.lookup("my-app", "function")
1003
1003
  f.keep_warm(2)
@@ -1076,7 +1076,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1076
1076
  In contrast to `modal.Function.from_name`, this is an eager method
1077
1077
  that will hydrate the local object with metadata from Modal servers.
1078
1078
 
1079
- ```python
1079
+ ```python notest
1080
1080
  f = modal.Function.lookup("other-app", "function")
1081
1081
  ```
1082
1082
  """
modal/image.py CHANGED
@@ -375,7 +375,7 @@ class _Image(_Object, type_prefix="im"):
375
375
  "\n"
376
376
  "Run `image.add_local_*` commands last in your image build to avoid rebuilding images with every local "
377
377
  "file change. Modal will then add these files to containers on startup instead, saving build time.\n"
378
- "If you need to run other build steps after adding local files, set `copy=True` to copy the files"
378
+ "If you need to run other build steps after adding local files, set `copy=True` to copy the files "
379
379
  "directly into the image, at the expense of some added build time.\n"
380
380
  "\n"
381
381
  "Example:\n"
modal/io_streams.py CHANGED
@@ -385,13 +385,14 @@ class _StreamWriter:
385
385
 
386
386
  **Usage**
387
387
 
388
- ```python
389
- # Synchronous
388
+ ```python notest
390
389
  writer.write(data)
391
390
  writer.drain()
391
+ ```
392
392
 
393
- # Async
394
- writer.write(data)
393
+ Async usage:
394
+ ```python notest
395
+ writer.write(data) # not a blocking operation
395
396
  await writer.drain.aio()
396
397
  ```
397
398
  """
@@ -152,11 +152,13 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
152
152
 
153
153
  Usage:
154
154
  ```python
155
- with NetworkFileSystem.ephemeral() as nfs:
156
- assert nfs.listdir() == []
155
+ with modal.NetworkFileSystem.ephemeral() as nfs:
156
+ assert nfs.listdir("/") == []
157
+ ```
157
158
 
158
- async with NetworkFileSystem.ephemeral() as nfs:
159
- assert await nfs.listdir() == []
159
+ ```python notest
160
+ async with modal.NetworkFileSystem.ephemeral() as nfs:
161
+ assert await nfs.listdir("/") == []
160
162
  ```
161
163
  """
162
164
  if client is None:
@@ -184,7 +186,7 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
184
186
  In contrast to `modal.NetworkFileSystem.from_name`, this is an eager method
185
187
  that will hydrate the local object with metadata from Modal servers.
186
188
 
187
- ```python
189
+ ```python notest
188
190
  nfs = modal.NetworkFileSystem.lookup("my-nfs")
189
191
  print(nfs.listdir("/"))
190
192
  ```
modal/queue.py CHANGED
@@ -126,7 +126,9 @@ class _Queue(_Object, type_prefix="qu"):
126
126
 
127
127
  with Queue.ephemeral() as q:
128
128
  q.put(123)
129
+ ```
129
130
 
131
+ ```python notest
130
132
  async with Queue.ephemeral() as q:
131
133
  await q.put.aio(123)
132
134
  ```
modal/volume.py CHANGED
@@ -200,11 +200,14 @@ class _Volume(_Object, type_prefix="vo"):
200
200
 
201
201
  Usage:
202
202
  ```python
203
- with Volume.ephemeral() as vol:
204
- assert vol.listdir() == []
203
+ import modal
204
+ with modal.Volume.ephemeral() as vol:
205
+ assert vol.listdir("/") == []
206
+ ```
205
207
 
206
- async with Volume.ephemeral() as vol:
207
- assert await vol.listdir() == []
208
+ ```python notest
209
+ async with modal.Volume.ephemeral() as vol:
210
+ assert await vol.listdir("/") == []
208
211
  ```
209
212
  """
210
213
  if client is None:
@@ -234,7 +237,7 @@ class _Volume(_Object, type_prefix="vo"):
234
237
  In contrast to `modal.Volume.from_name`, this is an eager method
235
238
  that will hydrate the local object with metadata from Modal servers.
236
239
 
237
- ```python
240
+ ```python notest
238
241
  vol = modal.Volume.lookup("my-volume")
239
242
  print(vol.listdir("/"))
240
243
  ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.67.0
3
+ Version: 0.67.5
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -12,37 +12,37 @@ modal/_resolver.py,sha256=s2YSLnpZbwUQHLs2ahltvEVDMLRYyIagdTcWr2-qkeA,6760
12
12
  modal/_resources.py,sha256=zTCcXvmG1erERnTvUcN0r4IjjwVEs4N8fs7OnkpvbJQ,1740
13
13
  modal/_serialization.py,sha256=b1X44hDP7WDTX3iz3HrPyFJJz51a69luq5Tyhnm1fK0,18762
14
14
  modal/_traceback.py,sha256=1yNp1Dqq4qRIQp8idDp5PEqjwH4eA8MNI0FhFkCOFgo,4408
15
- modal/_tunnel.py,sha256=SVmQxGbV7dcLwyY9eB2PIWmXw8QQmcKg2ppTcRQgZrU,6283
15
+ modal/_tunnel.py,sha256=BC9Fbvr9xvE3UMp5t8rn4ek-jXu2uwU778cKPMJfTtM,6290
16
16
  modal/_tunnel.pyi,sha256=SA_Q0UGB-D9skFjv6CqlTnCEWU67a2xJxfwVdXtar3Y,1259
17
17
  modal/_watcher.py,sha256=STlDe73R7IS33a_GMW2HnDc3hCDKLdsBfMxRpVh-flA,3581
18
- modal/app.py,sha256=ZQux8ZGLblIWbKHn7s15mucx97EwbjJso9WKRTYYOf0,45208
18
+ modal/app.py,sha256=Nm__k-xIebchBkVM4qBdz4XbAfF4GTWmi00IEx_0_n4,45500
19
19
  modal/app.pyi,sha256=sX2BXX_178lp8O_GvwZqsxDdxQi1j3DjNfthMvlMlJU,25273
20
20
  modal/call_graph.py,sha256=l-Wi6vM8aosCdHTWegcCyGeVJGFdZ_fzlCmbRVPBXFI,2593
21
21
  modal/client.py,sha256=4SpWb4n0nolITR36kADZl1tYLOg6avukmzZU56UQjCo,16385
22
- modal/client.pyi,sha256=jlf2MUYWkAYNXCWT8djnfXiTMAPYdp62kqR3Z63wvhg,7370
22
+ modal/client.pyi,sha256=DwioUlUaUhBrb50Q3q3ZZrEPaIzry87laj5l2opfpXI,7370
23
23
  modal/cloud_bucket_mount.py,sha256=eWQhCtMIczpokjfTZEgNBCGO_s5ft46PqTSLfKBykq4,5748
24
24
  modal/cloud_bucket_mount.pyi,sha256=tTF7M4FR9bTA30cFkz8qq3ZTlFL19NHU_36e_5GgAGA,1424
25
- modal/cls.py,sha256=W3fGE7wdShFwCeWS1oT0LX2_SHBCXy04DgfVt4ggXZA,24692
25
+ modal/cls.py,sha256=v3Uad6nTpHNwkAZ04KlQY3jZGgntKt5Onz6DusFRtg8,24706
26
26
  modal/cls.pyi,sha256=eVQ3QQC2XwGe2rvYFvjQ57d8ToBXbpI6M-9_YyVQkbo,8214
27
27
  modal/config.py,sha256=bij_YRIynxQtwDmS73BNMR9YZf6CHcqbFYdfRqDrWV0,10929
28
28
  modal/container_process.py,sha256=c_jBPtyPeSxbIcbLfs_FzTrt-1eErtRSnsfxkDozFoY,5589
29
29
  modal/container_process.pyi,sha256=k2kClwaSzz11eci1pzFZgCm-ptXapHAyHTOENorlazA,2594
30
- modal/dict.py,sha256=axbUKiXhgOVvE1IrNMK3uHg3rp3N0Uji5elQNijnhH4,12571
30
+ modal/dict.py,sha256=ncy0q21IU2PqZa4CpFfPfNIMWpOLwKvdU40xZhxCemc,12608
31
31
  modal/dict.pyi,sha256=4Rh5HNzXk99hotPUzoj1kYOHNlEgndZFfA-hlmBtBIc,7223
32
32
  modal/environments.py,sha256=KwKdrWfSnz2XF5eYXZyd0kdac1x1PVw2uxPYsGy8cys,6517
33
33
  modal/environments.pyi,sha256=oScvFAclF55-tL9UioLIL_SPBwgy_9O-BBvJ-PLbRgY,3542
34
34
  modal/exception.py,sha256=K-czk1oK8wFvK8snWrytXSByo2WNb9SJAlgBVPGWZBs,6417
35
35
  modal/experimental.py,sha256=jFuNbwrNHos47viMB9q-cHJSvf2RDxDdoEcss9plaZE,2302
36
- modal/functions.py,sha256=Z7nTQ51gMyjtSNQNEj55nEhoGWm2scHAFaShfOdPVMM,66939
36
+ modal/functions.py,sha256=Gfr-IsAeH0uIHCSfVYNWSzjnnrN33LPY3Ui4S6c6Pvo,66953
37
37
  modal/functions.pyi,sha256=5i5CTK6Eic-80o8NAPXHPujg_qpLj9d95eN71lpYSxE,24375
38
38
  modal/gpu.py,sha256=r4rL6uH3UJIQthzYvfWauXNyh01WqCPtKZCmmSX1fd4,6881
39
- modal/image.py,sha256=f4OB4gfyaSz3mQjumzEMeZT4Uq0SzsGBMN5NkPQQSec,79550
39
+ modal/image.py,sha256=DoubwAD9ebYNIEO3GJWbtAaJl_ZRW4K0tpIJdS9CZAg,79551
40
40
  modal/image.pyi,sha256=3rfae_E0KuNHqdi5j33nHXp_7P3tTkt7QKH5cXYczUc,24672
41
- modal/io_streams.py,sha256=XUsNsxRzDrhkjyb2Hx0hugCoOEz266SHQF8wP-VgsfY,14582
41
+ modal/io_streams.py,sha256=AAY-qcISGCIMp-F6SwX6vhZWJv7Sg_KudDBW0rMfc-E,14637
42
42
  modal/io_streams.pyi,sha256=WJmSI1WvZITUNBO7mnIuJgYdSKdbLaHk10V4GbttAVw,4452
43
43
  modal/mount.py,sha256=QZ4nabpbNU9tjLIPCq86rlHor9CXzADMkhJWBYfKKgg,27750
44
44
  modal/mount.pyi,sha256=nywUmeUELLY2OEnAc1NNBHmSxuEylTWBzkh6nuXkkuc,9965
45
- modal/network_file_system.py,sha256=P_LsILecyda1SRHU76Hk4Lq3M1HSx9shFJbaLThzw0U,14071
45
+ modal/network_file_system.py,sha256=xCQDM8aajiGydGVm8BaJo0yTgsceHNMmAfG5D3L3d_I,14133
46
46
  modal/network_file_system.pyi,sha256=XLyUnDx55ExbJcF_xlKxRax_r06XTvSsQh-a-_EyCOU,7239
47
47
  modal/object.py,sha256=Qgee_lQJY_583YsGIVrSNuDF_gJA_qmTAeVTVI1tf-g,9637
48
48
  modal/object.pyi,sha256=uGGD5A2B_mj8jxLfFiHama5wzCcBS_GNvPSKsIfsCO0,8518
@@ -54,7 +54,7 @@ modal/partial_function.pyi,sha256=BqKN7It5QLxS2yhhhDX0RgI8EyNMPBD6Duk21kN_fvA,89
54
54
  modal/proxy.py,sha256=ZrOsuQP7dSZFq1OrIxalNnt0Zvsnp1h86Th679sSL40,1417
55
55
  modal/proxy.pyi,sha256=UvygdOYneLTuoDY6hVaMNCyZ947Tmx93IdLjErUqkvM,368
56
56
  modal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
- modal/queue.py,sha256=qCBE-V2QRl_taSDUR5bDJL91J0A8xwbTxfEU3taA4Es,18338
57
+ modal/queue.py,sha256=WdiU0eiBtQx3tOk-QojyScieHZRkIqaXWQdJwCMlDCc,18375
58
58
  modal/queue.pyi,sha256=t5yhDqXRtexy7AVraCexPyT6Xo3QA_H5OxVe_JLzTps,9999
59
59
  modal/retries.py,sha256=z4dYXdksUcjkefM3vGLkhCQ_m_TUPLJgC4uSYDzWSOU,3750
60
60
  modal/runner.py,sha256=Yx8SdnxGzHIlqMxhIQiBukF12yj7wh-c6jWwy8w76u8,24081
@@ -71,17 +71,17 @@ modal/serving.pyi,sha256=0KWUH5rdYnihSv1XB8bK9GokzpfzrCq8Sf6nYlUvQI8,1689
71
71
  modal/stream_type.py,sha256=A6320qoAAWhEfwOCZfGtymQTu5AfLfJXXgARqooTPvY,417
72
72
  modal/token_flow.py,sha256=lsVpJACut76AeJLw44vJKMSlpcqp8wcvxdUOoX6CIOc,6754
73
73
  modal/token_flow.pyi,sha256=qEYP7grgqSA440w7kBREU9Ezeo_NxCT67OciIPgDzcc,1958
74
- modal/volume.py,sha256=5IdcerxXjP9MpAZm9QXPTWRDYZD5UJSFebWGglCha8k,29301
74
+ modal/volume.py,sha256=uq1hyHXRdCG10rbIDWq6B9mveeJlOE5mXWKUaynhN4o,29384
75
75
  modal/volume.pyi,sha256=3lB6wiC75u3o44cwJVqDsmvR4wsP2JXSxJrVXi9KrK4,11127
76
76
  modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
77
- modal/_runtime/asgi.py,sha256=WoAwIiGKpk089MOca3_iA73h36v0uBuoPx0-87ajIDY,19843
77
+ modal/_runtime/asgi.py,sha256=69X60gSg6AnH8dZlMC1C5eWkC0nypewbHbzAcy9-_gg,21523
78
78
  modal/_runtime/container_io_manager.py,sha256=qFxBdmOh6Vz_Jc9HW27yM-Wt6rOvhMi1yHUW1CzCneg,44146
79
79
  modal/_runtime/execution_context.py,sha256=cXEVY4wEK-oZJVJptyj1ZplZvVQ1HDzFsyHxhaY4o8M,2718
80
80
  modal/_runtime/telemetry.py,sha256=3NbrfwYH6mvDckzdTppymmda2lQKX2oHGc2JwdFZdUc,5191
81
81
  modal/_runtime/user_code_imports.py,sha256=2COhqA77zwbP__-DWiDHEScHM-Go3CmI-AlKvT_oBOU,14545
82
82
  modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
83
83
  modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
84
- modal/_utils/async_utils.py,sha256=3H4pBC4DW6rCA6hgRux6FMxGqPgHM-G-BTs7KXZiWz4,23958
84
+ modal/_utils/async_utils.py,sha256=LInaa9xOl256MwXPtFlgmgk9iS2OEJGF15BCyi_O0hE,24994
85
85
  modal/_utils/blob_utils.py,sha256=pAY22w0oVc6ujGfI7La7HPUMOf42FehIapuhSDeeqEs,15835
86
86
  modal/_utils/function_utils.py,sha256=28mxgg_-7JF1DDiNnp3iNVsFQkOzMFjORsetdvZZTHU,24475
87
87
  modal/_utils/grpc_testing.py,sha256=LOzWygTdHINzV-o_Ajbl7sOFbUQFoonP0iKpsJjA_nc,8301
@@ -159,10 +159,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
159
159
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
160
160
  modal_version/__init__.py,sha256=3IY-AWLH55r35_mQXIaut0jrJvoPuf1NZJBQQfSbPuo,470
161
161
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
162
- modal_version/_version_generated.py,sha256=v_S9jRzfg8SYOLr5xkcxf8a_PenQzvMuDRleYNn-7Xw,148
163
- modal-0.67.0.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
- modal-0.67.0.dist-info/METADATA,sha256=WiZvxXOnASb0bk5GT9p8Ut5bQR7Q21SyTEtsFvl10SA,2328
165
- modal-0.67.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
- modal-0.67.0.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
- modal-0.67.0.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
- modal-0.67.0.dist-info/RECORD,,
162
+ modal_version/_version_generated.py,sha256=oSCusXuRJhNxjKI1nhoJGUM9jZoGrCEMXuKzaocBL8s,148
163
+ modal-0.67.5.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
164
+ modal-0.67.5.dist-info/METADATA,sha256=oqZ1Di5flX86xT97UGavXlInaXyj17h83iEOOsUn3v0,2328
165
+ modal-0.67.5.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
166
+ modal-0.67.5.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
167
+ modal-0.67.5.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
168
+ modal-0.67.5.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2024
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 0 # git: 5d793ef
4
+ build_number = 5 # git: 99a7dd7
File without changes