modAL 1.5.6.dev4__py3-none-any.whl → 1.5.6.dev5__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.
@@ -199,16 +199,23 @@ class ConnectionManager:
199
199
  self._client = client
200
200
  # This metadata is injected into all requests on all channels created by this manager.
201
201
  self._metadata = metadata
202
- self._channels: dict[str, grpclib.client.Channel] = {}
202
+ self._channels: dict[str, asyncio.Future[grpclib.client.Channel]] = {}
203
203
 
204
204
  async def get_or_create_channel(self, server_url: str) -> grpclib.client.Channel:
205
- if server_url not in self._channels:
206
- self._channels[server_url] = await create_channel_with_fallbacks(server_url, self._metadata)
207
- return self._channels[server_url]
205
+ fut = self._channels.get(server_url)
206
+ if fut is None or (fut.done() and (fut.cancelled() or fut.exception() is not None)):
207
+ # Cache the attempt rather than the channel, so callers racing to connect share one.
208
+ fut = asyncio.ensure_future(create_channel_with_fallbacks(server_url, self._metadata))
209
+ self._channels[server_url] = fut
210
+ # Shielded so one caller giving up doesn't cancel the connection for the others.
211
+ return await asyncio.shield(fut)
208
212
 
209
213
  def close(self):
210
- for channel in self._channels.values():
211
- channel.close()
214
+ for fut in self._channels.values():
215
+ if fut.done() and not fut.cancelled() and fut.exception() is None:
216
+ fut.result().close()
217
+ else:
218
+ fut.cancel()
212
219
  self._channels.clear()
213
220
 
214
221
 
modal/client.pyi CHANGED
@@ -77,7 +77,7 @@ class _Client:
77
77
  server_url: str,
78
78
  client_type: int,
79
79
  credentials: typing.Optional[tuple[str, str]],
80
- version: str = "1.5.6.dev4",
80
+ version: str = "1.5.6.dev5",
81
81
  *,
82
82
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
83
83
  ):
@@ -277,7 +277,7 @@ class Client:
277
277
  server_url: str,
278
278
  client_type: int,
279
279
  credentials: typing.Optional[tuple[str, str]],
280
- version: str = "1.5.6.dev4",
280
+ version: str = "1.5.6.dev5",
281
281
  *,
282
282
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
283
283
  ):
modal/mount.py CHANGED
@@ -851,7 +851,7 @@ async def _create_single_client_dependency_mount(
851
851
  print(f"📦 Building {mount_name}.") # noqa: T201
852
852
  requirements = os.path.join(os.path.dirname(__file__), f"builder/{builder_version}.txt")
853
853
  cmd = [
854
- "uv",
854
+ os.environ.get("MODAL_UV_PATH", "uv"),
855
855
  "pip",
856
856
  "install",
857
857
  "--strict",
@@ -867,6 +867,11 @@ async def _create_single_client_dependency_mount(
867
867
  "--python",
868
868
  python_version,
869
869
  ]
870
+ # A directory holding wheels for every pin in the requirements file, for
871
+ # building mounts where no package index is reachable.
872
+ find_links = os.environ.get("MODAL_BUILDER_WHEEL_DIR")
873
+ if find_links:
874
+ cmd += ["--no-index", "--find-links", find_links]
870
875
  # Retry uv pip install on transient failures (e.g. network blips,
871
876
  # resource contention). uv exits with non-zero on recoverable errors
872
877
  # like rate limits or connection resets.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.6.dev4
3
+ Version: 1.5.6.dev5
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -34,7 +34,7 @@ modal/billing.py,sha256=E1-P_P8bJFLp-bTaggYd4BaaViImPB5UdtXiY8VeAZQ,390
34
34
  modal/billing.pyi,sha256=4m7VLYNS8IiJ2I3CJx0awvrOM6BILWRVLfdeqtAYr8M,7189
35
35
  modal/call_graph.py,sha256=XGALIDn1bLchWo_goyX23bcPjzCZcfqKUo8INIfDapo,1775
36
36
  modal/client.py,sha256=CiBsT2XuUuKps5RYc3jwJcfI_VQKK09cbkqeHfHpx3E,21476
37
- modal/client.pyi,sha256=xkqw20bz3fiI_5-ZnD4A62-enjwyGv30XalTd0tQ61g,22281
37
+ modal/client.pyi,sha256=Az1OGzZ2UbWjkDPFoJDmCv35X9b2ubgDOpF8q75ZN5Q,22281
38
38
  modal/cloud_bucket_mount.py,sha256=NrdNV9r9aL3QFrlt-Dhtd7_K3f8v1igrHf2FRwgJ1CI,6827
39
39
  modal/cloud_bucket_mount.pyi,sha256=0E8d53pMh2KsFa-rMh_i6LxlzW4cMV8drVmmkPHSqZk,8149
40
40
  modal/cls.py,sha256=oF4hswFWv72C7_FTEVqOsLEzMTv43b5bKAScnCR14x0,41737
@@ -56,7 +56,7 @@ modal/image.py,sha256=c0lUSAoU-Ip3g5DGZ0uhdCzoWSQWh1g0i-7Rxo-Sz-I,160
56
56
  modal/image.pyi,sha256=R5rdY4P30IEm-F7A2S9CdXa6QYNk-pQwsEun9BKTyLw,61094
57
57
  modal/io_streams.py,sha256=3fhhb7SDJ69pVUu9J3PiMLBePD9bpiIxPN05SCzf8FE,29118
58
58
  modal/io_streams.pyi,sha256=5uQAgwxN3aouY8UJbRmDnRj9vOId5psRaMrU4IpyQgw,24471
59
- modal/mount.py,sha256=pWVsUwr3kPiNIHuzzj_fLvr7g9WFsPNGnhHhDiabC_k,36168
59
+ modal/mount.py,sha256=Mks6IcgK5W7q6B5NmWHc95e4az74kSZvAvRLXPT2_KU,36493
60
60
  modal/mount.pyi,sha256=5JFXGXvA9uOxh5n-xYL6ruRvrs59K84-LS7BKwwNjHU,16391
61
61
  modal/network_file_system.py,sha256=Mr7gWcxqhS-SqBkFfDgt9lt5Sh36vxb3HXpeGF2qCVE,14159
62
62
  modal/network_file_system.pyi,sha256=MS4srjGFl-ogqgNLxYRlj6Ik1ObwZKJ0WrneYKMKk-A,17927
@@ -129,7 +129,7 @@ modal/_utils/docker_utils.py,sha256=k8fkYT6G-X_B3iamjxiSpwSE-k58xGVHtsk2_gR7i2Q,
129
129
  modal/_utils/function_utils.py,sha256=Gmirx0Qs-xu41UF0LZjbgzqtis1i8Y73oIZWpJngsf8,26661
130
130
  modal/_utils/git_utils.py,sha256=Lat_l4O4hwOYgylEtWup3hyqWT8D7JoCIjCflXcX8BE,3148
131
131
  modal/_utils/grpc_testing.py,sha256=udyK_wRXX_yc9eLt8mIZZqx12XlaiUqORxaGNvfI_MM,8697
132
- modal/_utils/grpc_utils.py,sha256=vGL6JUNRahbe4HRWV_bS1ceCfszzKNVIgAW_bzUNo74,24249
132
+ modal/_utils/grpc_utils.py,sha256=bcShkAZCN0OaGAWQy9TnrUwLZMd2DKH4J1q1oKyazdA,24713
133
133
  modal/_utils/hash_utils.py,sha256=WHuMRwmB4fnaM-qmyWXR87C2CinvLnmRoygSzsTEunA,3008
134
134
  modal/_utils/http_utils.py,sha256=TO9nnKR0Cc-iWCmkou56wJh9MHgNZwQMosK8WK-GD5Y,3133
135
135
  modal/_utils/jwt_utils.py,sha256=KUoqGHMM4ewDyTsTKXPm1wrMu8Z6lp0l8VILHufm484,1354
@@ -198,7 +198,7 @@ modal/experimental/flash.py,sha256=m803RsPvMgLCSNJfT_11da1sz9l1BIr1MDxAA_qtK2k,1
198
198
  modal/experimental/flash.pyi,sha256=tHS2un-PxndcxV27l7CAWnPhRPmiIs2cCNzKLXBNxJA,8520
199
199
  modal/experimental/ipython.py,sha256=kJ6o9wkAY_MiSb7paewI7f1MJAeqdi8TX5pBdhr_mUI,2925
200
200
  modal/skills/modal/SKILL.md,sha256=ERhA-zss3OoPXU_d3Qo8-PNrK2QI_ctyhGavou3egd0,5276
201
- modal-1.5.6.dev4.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
201
+ modal-1.5.6.dev5.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
202
202
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
203
203
  modal_docs/gen_cli_docs.py,sha256=9-b8vl2EsLWD9zJqpCK8IUi5h44Bjn3i3rSdedZV4bA,6415
204
204
  modal_docs/gen_cli_docs_main.py,sha256=UPGr7O1DYTIRLwfINe2rbdh89J3cPVTU1OWL-SjxnOQ,198
@@ -222,10 +222,10 @@ modal_proto/task_command_router_pb2.py,sha256=rMwEVv6DV1Hpv8_hi7SE0zxCkrv6elWgwK
222
222
  modal_proto/task_command_router_pb2.pyi,sha256=OQ2jBFSduSEPtP3llAhFhW2dZJJxsqBy3Y5s8Yj40nA,47640
223
223
  modal_proto/task_command_router_pb2_grpc.py,sha256=zuFkJgKcswB2ftjnyEgs70dp61VMA7gK0h0uzR3gYFw,42563
224
224
  modal_proto/task_command_router_pb2_grpc.pyi,sha256=UjAJFqz9DpOFXP04fVm5lB2eAyTtjOg3oKjfWei8yLU,14262
225
- modal_version/__init__.py,sha256=44vhXqcK_Swn8S11Mfc4Ss4Kqm7A3Nhi3vo7-C6Pc14,120
225
+ modal_version/__init__.py,sha256=1Y1uszdzAdc5YuQwhDVETA8SeQfpdkcem9vbnPjWAPw,120
226
226
  modal_version/__main__.py,sha256=nLUbubxKx7GXNzJIkTB7M7_u8080LyLM0IS0rzFkC_c,119
227
- modal-1.5.6.dev4.dist-info/METADATA,sha256=1G6fdSftvRj_xzOuvUZbpwvvsDaHMyt1MTpzsSHi0Lw,2512
228
- modal-1.5.6.dev4.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
229
- modal-1.5.6.dev4.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
230
- modal-1.5.6.dev4.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
231
- modal-1.5.6.dev4.dist-info/RECORD,,
227
+ modal-1.5.6.dev5.dist-info/METADATA,sha256=_ObE2xNtjjyvY35Me_pREbBs1YZnTBLagzDc8Jwhe-g,2512
228
+ modal-1.5.6.dev5.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
229
+ modal-1.5.6.dev5.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
230
+ modal-1.5.6.dev5.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
231
+ modal-1.5.6.dev5.dist-info/RECORD,,
modal_version/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2026
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.5.6.dev4"
4
+ __version__ = "1.5.6.dev5"