modal 1.2.2.dev31__py3-none-any.whl → 1.2.2.dev36__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/_functions.py CHANGED
@@ -1671,8 +1671,8 @@ Use the `Function.get_web_url()` method instead.
1671
1671
  input_queue,
1672
1672
  self.client,
1673
1673
  )
1674
- metadata = api_pb2.FunctionCallFromIdResponse(function_call_id=function_call_id, num_inputs=num_inputs)
1675
- fc: _FunctionCall[ReturnType] = _FunctionCall._new_hydrated(function_call_id, self.client, metadata)
1674
+ fc: _FunctionCall[ReturnType] = _FunctionCall._new_hydrated(function_call_id, self.client, None)
1675
+ fc._num_inputs = num_inputs # set the cached value of num_inputs
1676
1676
  return fc
1677
1677
 
1678
1678
  async def _call_function(self, args, kwargs) -> ReturnType:
@@ -1941,19 +1941,16 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
1941
1941
  def _invocation(self):
1942
1942
  return _Invocation(self.client.stub, self.object_id, self.client)
1943
1943
 
1944
- def _hydrate_metadata(self, metadata: Optional[Message]):
1945
- if not metadata:
1946
- return
1947
- assert isinstance(metadata, api_pb2.FunctionCallFromIdResponse)
1948
- self._num_inputs = metadata.num_inputs
1949
-
1950
1944
  @live_method
1951
1945
  async def num_inputs(self) -> int:
1952
1946
  """Get the number of inputs in the function call."""
1953
- # Should have been hydrated.
1954
- assert self._num_inputs is not None
1947
+ if self._num_inputs is None:
1948
+ request = api_pb2.FunctionCallFromIdRequest(function_call_id=self.object_id)
1949
+ resp = await self.client.stub.FunctionCallFromId(request)
1950
+ self._num_inputs = resp.num_inputs # cached
1955
1951
  return self._num_inputs
1956
1952
 
1953
+ @live_method
1957
1954
  async def get(self, timeout: Optional[float] = None, *, index: int = 0) -> ReturnType:
1958
1955
  """Get the result of the index-th input of the function call.
1959
1956
  `.spawn()` calls have a single output, so only specifying `index=0` is valid.
@@ -1997,6 +1994,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
1997
1994
  async for _, item in self._invocation().enumerate(start_index=start, end_index=end):
1998
1995
  yield item
1999
1996
 
1997
+ @live_method
2000
1998
  async def get_call_graph(self) -> list[InputInfo]:
2001
1999
  """Returns a structure representing the call graph from a given root
2002
2000
  call ID, along with the status of execution for each node.
@@ -2009,6 +2007,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2009
2007
  response = await self._client.stub.FunctionGetCallGraph(request)
2010
2008
  return _reconstruct_call_graph(response)
2011
2009
 
2010
+ @live_method
2012
2011
  async def cancel(
2013
2012
  self,
2014
2013
  # if true, containers running the inputs are forcibly terminated
@@ -2050,21 +2049,15 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2050
2049
  async def _load(
2051
2050
  self: _FunctionCall, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
2052
2051
  ):
2053
- request = api_pb2.FunctionCallFromIdRequest(function_call_id=function_call_id)
2054
- resp = await load_context.client.stub.FunctionCallFromId(request)
2055
- self._hydrate(function_call_id, load_context.client, resp)
2052
+ # this loader doesn't do anything in practice, but it will get the client from the load_context
2053
+ self._hydrate(function_call_id, load_context.client, None)
2056
2054
 
2057
2055
  rep = f"FunctionCall.from_id({function_call_id!r})"
2058
- fc: _FunctionCall[Any] = _FunctionCall._from_loader(
2056
+
2057
+ return _FunctionCall._from_loader(
2059
2058
  _load, rep, hydrate_lazily=True, load_context_overrides=LoadContext(client=client)
2060
2059
  )
2061
2060
 
2062
- # TODO(elias): Remove these
2063
- # We already know the object ID, so we can set it directly
2064
- fc._object_id = function_call_id
2065
- fc._client = client
2066
- return fc
2067
-
2068
2061
  @staticmethod
2069
2062
  async def gather(*function_calls: "_FunctionCall[T]") -> typing.Sequence[T]:
2070
2063
  """Wait until all Modal FunctionCall objects have results before returning.
modal/_load_context.py CHANGED
@@ -68,7 +68,7 @@ class LoadContext:
68
68
 
69
69
  return LoadContext(
70
70
  client=await _Client.from_env() if self._client is None else self.client,
71
- environment_name=config.get("environment") if self._environment_name is None else self._environment_name,
71
+ environment_name=self._environment_name or config.get("environment") or "",
72
72
  app_id=self._app_id,
73
73
  )
74
74
 
@@ -100,6 +100,6 @@ class LoadContext:
100
100
  ...
101
101
  """
102
102
  self._client = self._client or client or await _Client.from_env()
103
- self._environment_name = self._environment_name or environment_name or config.get("environment")
103
+ self._environment_name = self._environment_name or environment_name or config.get("environment") or ""
104
104
  self._app_id = self._app_id or app_id
105
105
  return self
modal/_object.py CHANGED
@@ -310,19 +310,19 @@ class _Object:
310
310
  logger.debug(f"rehydrating {self} after snapshot")
311
311
  self._is_hydrated = False # un-hydrate and re-resolve
312
312
  # Set the client on LoadContext before loading
313
- root_context = LoadContext(client=client)
313
+ root_load_context = LoadContext(client=client)
314
314
  resolver = Resolver()
315
- await resolver.load(typing.cast(_Object, self), root_context, existing_object_id=None)
315
+ await resolver.load(typing.cast(_Object, self), root_load_context)
316
316
  self._is_rehydrated = True
317
317
  logger.debug(f"rehydrated {self} with client {id(self.client)}")
318
318
  elif not self._hydrate_lazily:
319
319
  self._validate_is_hydrated()
320
320
  else:
321
321
  # Set the client on LoadContext before loading
322
- root_context = LoadContext(client=client)
322
+ root_load_context = LoadContext(client=client)
323
323
  resolver = Resolver()
324
324
  with suppress_tb_frames(1): # skip this frame by default
325
- await resolver.load(self, root_context)
325
+ await resolver.load(self, root_load_context)
326
326
  return self
327
327
 
328
328
 
modal/client.pyi CHANGED
@@ -33,7 +33,7 @@ class _Client:
33
33
  server_url: str,
34
34
  client_type: int,
35
35
  credentials: typing.Optional[tuple[str, str]],
36
- version: str = "1.2.2.dev31",
36
+ version: str = "1.2.2.dev36",
37
37
  ):
38
38
  """mdmd:hidden
39
39
  The Modal client object is not intended to be instantiated directly by users.
@@ -164,7 +164,7 @@ class Client:
164
164
  server_url: str,
165
165
  client_type: int,
166
166
  credentials: typing.Optional[tuple[str, str]],
167
- version: str = "1.2.2.dev31",
167
+ version: str = "1.2.2.dev36",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
modal/functions.pyi CHANGED
@@ -721,7 +721,6 @@ class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Obj
721
721
  ...
722
722
 
723
723
  def _invocation(self): ...
724
- def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
725
724
 
726
725
  class __num_inputs_spec(typing_extensions.Protocol[SUPERSELF]):
727
726
  def __call__(self, /) -> int:
modal/mount.py CHANGED
@@ -559,7 +559,7 @@ class _Mount(_Object, type_prefix="mo"):
559
559
  raise modal.exception.MountUploadTimeoutError(f"Mounting of {file_spec.source_description} timed out")
560
560
 
561
561
  # Upload files, or check if they already exist.
562
- n_concurrent_uploads = 512
562
+ n_concurrent_uploads = 64
563
563
  files: list[api_pb2.MountFile] = []
564
564
  async with aclosing(
565
565
  async_map(_Mount._get_files(self._entries), _put_file, concurrency=n_concurrent_uploads)
modal/secret.py CHANGED
@@ -206,6 +206,33 @@ class _SecretManager:
206
206
  SecretManager = synchronize_api(_SecretManager)
207
207
 
208
208
 
209
+ async def _load_from_env_dict(instance: "_Secret", load_context: LoadContext, env_dict: dict[str, str]):
210
+ """helper method for loaders .from_dict and .from_dotenv etc."""
211
+ if load_context.app_id is not None:
212
+ req = api_pb2.SecretGetOrCreateRequest(
213
+ object_creation_type=api_pb2.OBJECT_CREATION_TYPE_ANONYMOUS_OWNED_BY_APP,
214
+ env_dict=env_dict,
215
+ app_id=load_context.app_id,
216
+ environment_name=load_context.environment_name,
217
+ )
218
+ else:
219
+ req = api_pb2.SecretGetOrCreateRequest(
220
+ object_creation_type=api_pb2.OBJECT_CREATION_TYPE_EPHEMERAL,
221
+ env_dict=env_dict,
222
+ environment_name=load_context.environment_name,
223
+ )
224
+
225
+ try:
226
+ resp = await load_context.client.stub.SecretGetOrCreate(req)
227
+ except GRPCError as exc:
228
+ if exc.status == Status.INVALID_ARGUMENT:
229
+ raise InvalidError(exc.message)
230
+ if exc.status == Status.FAILED_PRECONDITION:
231
+ raise InvalidError(exc.message)
232
+ raise
233
+ instance._hydrate(resp.secret_id, load_context.client, resp.metadata)
234
+
235
+
209
236
  class _Secret(_Object, type_prefix="st"):
210
237
  """Secrets provide a dictionary of environment variables for images.
211
238
 
@@ -263,26 +290,7 @@ class _Secret(_Object, type_prefix="st"):
263
290
  async def _load(
264
291
  self: _Secret, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]
265
292
  ):
266
- if load_context.app_id is not None:
267
- object_creation_type = api_pb2.OBJECT_CREATION_TYPE_ANONYMOUS_OWNED_BY_APP
268
- else:
269
- object_creation_type = api_pb2.OBJECT_CREATION_TYPE_EPHEMERAL
270
-
271
- req = api_pb2.SecretGetOrCreateRequest(
272
- object_creation_type=object_creation_type,
273
- env_dict=env_dict_filtered,
274
- app_id=load_context.app_id,
275
- environment_name=load_context.environment_name,
276
- )
277
- try:
278
- resp = await load_context.client.stub.SecretGetOrCreate(req)
279
- except GRPCError as exc:
280
- if exc.status == Status.INVALID_ARGUMENT:
281
- raise InvalidError(exc.message)
282
- if exc.status == Status.FAILED_PRECONDITION:
283
- raise InvalidError(exc.message)
284
- raise
285
- self._hydrate(resp.secret_id, load_context.client, resp.metadata)
293
+ await _load_from_env_dict(self, load_context, env_dict_filtered)
286
294
 
287
295
  rep = f"Secret.from_dict([{', '.join(env_dict.keys())}])"
288
296
  # TODO: scoping - these should probably not be lazily hydrated without having an app and/or sandbox association
@@ -306,7 +314,7 @@ class _Secret(_Object, type_prefix="st"):
306
314
  return _Secret.from_dict({})
307
315
 
308
316
  @staticmethod
309
- def from_dotenv(path=None, *, filename=".env") -> "_Secret":
317
+ def from_dotenv(path=None, *, filename=".env", client: Optional[_Client] = None) -> "_Secret":
310
318
  """Create secrets from a .env file automatically.
311
319
 
312
320
  If no argument is provided, it will use the current working directory as the starting
@@ -360,19 +368,12 @@ class _Secret(_Object, type_prefix="st"):
360
368
  # To simplify this, we just support the cwd and don't do any automatic path inference.
361
369
  dotenv_path = find_dotenv(filename, usecwd=True)
362
370
 
363
- env_dict = dotenv_values(dotenv_path)
364
-
365
- req = api_pb2.SecretGetOrCreateRequest(
366
- object_creation_type=api_pb2.OBJECT_CREATION_TYPE_ANONYMOUS_OWNED_BY_APP,
367
- env_dict=env_dict,
368
- app_id=load_context.app_id, # TODO: what if app_id isn't set here (e.g. .hydrate())
369
- )
370
- resp = await load_context.client.stub.SecretGetOrCreate(req)
371
+ env_dict = {k: v or "" for k, v in dotenv_values(dotenv_path).items()}
371
372
 
372
- self._hydrate(resp.secret_id, load_context.client, resp.metadata)
373
+ await _load_from_env_dict(self, load_context, env_dict)
373
374
 
374
375
  return _Secret._from_loader(
375
- _load, "Secret.from_dotenv()", hydrate_lazily=True, load_context_overrides=LoadContext.empty()
376
+ _load, "Secret.from_dotenv()", hydrate_lazily=True, load_context_overrides=LoadContext(client=client)
376
377
  )
377
378
 
378
379
  @staticmethod
modal/secret.pyi CHANGED
@@ -1,5 +1,6 @@
1
1
  import datetime
2
2
  import google.protobuf.message
3
+ import modal._load_context
3
4
  import modal._object
4
5
  import modal.client
5
6
  import modal.object
@@ -355,6 +356,12 @@ class SecretManager:
355
356
 
356
357
  delete: __delete_spec
357
358
 
359
+ async def _load_from_env_dict(
360
+ instance: _Secret, load_context: modal._load_context.LoadContext, env_dict: dict[str, str]
361
+ ):
362
+ """helper method for loaders .from_dict and .from_dotenv etc."""
363
+ ...
364
+
358
365
  class _Secret(modal._object._Object):
359
366
  """Secrets provide a dictionary of environment variables for images.
360
367
 
@@ -392,7 +399,7 @@ class _Secret(modal._object._Object):
392
399
  ...
393
400
 
394
401
  @staticmethod
395
- def from_dotenv(path=None, *, filename=".env") -> _Secret:
402
+ def from_dotenv(path=None, *, filename=".env", client: typing.Optional[modal.client._Client] = None) -> _Secret:
396
403
  """Create secrets from a .env file automatically.
397
404
 
398
405
  If no argument is provided, it will use the current working directory as the starting
@@ -517,7 +524,7 @@ class Secret(modal.object.Object):
517
524
  ...
518
525
 
519
526
  @staticmethod
520
- def from_dotenv(path=None, *, filename=".env") -> Secret:
527
+ def from_dotenv(path=None, *, filename=".env", client: typing.Optional[modal.client.Client] = None) -> Secret:
521
528
  """Create secrets from a .env file automatically.
522
529
 
523
530
  If no argument is provided, it will use the current working directory as the starting
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.2.dev31
3
+ Version: 1.2.2.dev36
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -4,12 +4,12 @@ modal/_billing.py,sha256=C1jUN9f_1WqozSZAt9EOk1nImXUdiLrgFeeAu3R23cI,3012
4
4
  modal/_clustered_functions.py,sha256=7amiOxErtlciWeBJBL2KvaxerUomJpTAJ3qElflFHQA,2884
5
5
  modal/_clustered_functions.pyi,sha256=JmYwAGOLEnD5AF-gYF9O5tu-SgGjeoJz-X1j48b1Ijg,1157
6
6
  modal/_container_entrypoint.py,sha256=zYk5mC8_IMx4kWnyFMRHKOrFRLBWchy6x-py3M8FYEw,28084
7
- modal/_functions.py,sha256=1qzvFuLSgcW4PkowKiC4uDhfhb113jNMI1R3zDThlJo,91482
7
+ modal/_functions.py,sha256=nuIkMeklVmR8tSEVXK06EJOC5ui4m0rIpR35II4ylmg,91168
8
8
  modal/_grpc_client.py,sha256=KZcggVNvFL5jRQkFumshMppeFHMbaZI9Dzf13run6As,6083
9
9
  modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
10
- modal/_load_context.py,sha256=OL-rzWl-q2YNGe5nryInNsN1FaaUGOA3sOGlMqw0h9U,3730
10
+ modal/_load_context.py,sha256=YU5vhnnaLg_OexEp5W16a9pivwfmYw9I1ItPvYmLuoE,3706
11
11
  modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
12
- modal/_object.py,sha256=fb_FDjWLDnytVvuBsW4hudDKEer46hiUBNoLs3okOtk,12838
12
+ modal/_object.py,sha256=kuXkifDts65m1noObXNwKxDdxaurrtVs8DXj0iAZlXU,12833
13
13
  modal/_output.py,sha256=eikFqD82RA8uwF-LLVzO-A9EtmoVLnqg0X5nZE5hdLA,26852
14
14
  modal/_partial_function.py,sha256=t0yOVrYrDUdCJt7eVNyBS-atnUtjO56izKB3rDuN17Q,38573
15
15
  modal/_pty.py,sha256=E58MQ8d5-wkbMatRKpQR-G9FdbCRcZGiZxOpGy__VuY,1481
@@ -26,7 +26,7 @@ modal/app.pyi,sha256=5XnLb07hnNS5mI7MpLTHSFrDVJbh7lYqHOdU0jz7lnk,50683
26
26
  modal/billing.py,sha256=zmQ3bcCJlwa4KD1IA_QgdWpm1pn13c-7qfy79iEauYI,195
27
27
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
28
28
  modal/client.py,sha256=tPzihC7R9WtP56k6dyPKi5GLGdLEHdMA6YUj9Ry5G8o,14409
29
- modal/client.pyi,sha256=hY8EdKK9jmeJFFIL5qAdCVscW9iX2npr-dd8n3csMJg,13094
29
+ modal/client.pyi,sha256=n0peHkn8DFMWGtxlfkgDLpc8CWSCUyGx1KUGtG8sbyk,13094
30
30
  modal/cloud_bucket_mount.py,sha256=Ff8UFG_Z0HUzcRAAfo1jvDwzaNgiX_btTFOHL7CGyI8,6016
31
31
  modal/cloud_bucket_mount.pyi,sha256=vXusGMOUk9HjCs4lhxteuCK4xLQclPfugGWKo7LECEA,7539
32
32
  modal/cls.py,sha256=TSkc7XOdfYcMkVfXBHZzhqgnQTUYA8RPdv-DySIT9L0,41883
@@ -43,13 +43,13 @@ modal/file_io.py,sha256=Whs3QSl3pQbSoLzSRIIWfK4XyP-kwgyZmWgx3bhJ9u0,20933
43
43
  modal/file_io.pyi,sha256=xtO6Glf_BFwDE7QiQQo24QqcMf_Vv-iz7WojcGVlLBU,15932
44
44
  modal/file_pattern_matcher.py,sha256=A_Kdkej6q7YQyhM_2-BvpFmPqJ0oHb54B6yf9VqvPVE,8116
45
45
  modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
46
- modal/functions.pyi,sha256=9t4rVUEKJcK-_9mnr7IBtCLOyAesa6p_EJjsdSf_hU0,38146
46
+ modal/functions.pyi,sha256=11hKG3vRpHzXUycfz6ozZzJ-EUHLzBUo6la_et3pEPY,38049
47
47
  modal/gpu.py,sha256=Fe5ORvVPDIstSq1xjmM6OoNgLYFWvogP9r5BgmD3hYg,6769
48
48
  modal/image.py,sha256=wdgZlQqewK8Tj95uGOq7s8YZ8wFxMhKZtzJFTN-RT0Y,108328
49
49
  modal/image.pyi,sha256=grkqK9BfyKDXmJYNme-lGa0O3u7pOU5GifyLOAhG3sc,78202
50
50
  modal/io_streams.py,sha256=Lc-id7HvW-ffJKSoN1xQxf37pHARNkr4re2HKyGpKy4,29316
51
51
  modal/io_streams.pyi,sha256=P9kvQhXmh9fxQNGI2DtuFnnZ_9MJQ4ZiqOpDP2-QWUU,16746
52
- modal/mount.py,sha256=ifRV6PIU4VZJH4S00E4ILPQ2T7obzTHS_yBdyODSmO8,33298
52
+ modal/mount.py,sha256=GNdUfj7tWZy3-LaxVX-fvk70BqC51P1s2ktrMOMJGWU,33297
53
53
  modal/mount.pyi,sha256=3_Xftyk2lEMQbt8UzmUW5N77eb7t9EdbczPwj9wue9o,15828
54
54
  modal/network_file_system.py,sha256=23GUYz2DZ5kCzlUrdWBq1siBse6fP_CeGt2Lo9xHkR8,13598
55
55
  modal/network_file_system.pyi,sha256=A0YyIpxToPTRi-x5DQWtlWPgzw9qHGauvwW7jTcw6y0,15554
@@ -73,8 +73,8 @@ modal/sandbox.py,sha256=onH4cjq8SAbMhzn7eVOOkYzr-6odBatrCQBX6_R7qjk,50374
73
73
  modal/sandbox.pyi,sha256=XWH57XZIouFGeE-CidVYXdI_l5w-kjCzIhqN4kd2y8Q,57428
74
74
  modal/schedule.py,sha256=ng0g0AqNY5GQI9KhkXZQ5Wam5G42glbkqVQsNpBtbDE,3078
75
75
  modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
76
- modal/secret.py,sha256=-W_XuzvmGElDmLv6RawHPski-ZOufCLDhhzR1IF2ayo,18865
77
- modal/secret.pyi,sha256=LvlFGun262nWO1WbhllpZE4JBkV8-tyXgIjgYX3eXBA,20682
76
+ modal/secret.py,sha256=KancnGQ3X4ihl1ysx7SplJP1dBsM1TWQTv6WyXM8nIo,18783
77
+ modal/secret.pyi,sha256=Fm4Tbs0UPLlqJZbjJUdubMOPpcOmIxGUQlXFSC9eOEc,21023
78
78
  modal/serving.py,sha256=rfzj23Q4hPSMpc3vj_cQg3awkZULu4hLtRs83cOEB-w,4291
79
79
  modal/serving.pyi,sha256=eNqF_bhO_JQ0EDpqvSjSUdNs48vv7AcPXinp7GEs5wI,1966
80
80
  modal/snapshot.py,sha256=HiXLbJAZiQv2cEQ4ur8M3AVbI_ZSL-eoteVfCL77lUw,1640
@@ -158,7 +158,7 @@ modal/experimental/__init__.py,sha256=sCwNbBLcR2t-jhrpwtMAPGKt2WNqXBg0xkNZdyB-6C
158
158
  modal/experimental/flash.py,sha256=RKS3X3h4tY_mOLcMzbRs5tNCLPFL01dBAhCZSqCeBgA,26675
159
159
  modal/experimental/flash.pyi,sha256=uwinKAYxpunNNfBj58FP88DXb535Qik4F6tnJKPAIwQ,14696
160
160
  modal/experimental/ipython.py,sha256=TrCfmol9LGsRZMeDoeMPx3Hv3BFqQhYnmD_iH0pqdhk,2904
161
- modal-1.2.2.dev31.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
161
+ modal-1.2.2.dev36.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
162
162
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
163
163
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
164
164
  modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
@@ -166,10 +166,10 @@ modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,2
166
166
  modal_docs/mdmd/mdmd.py,sha256=tUTImNd4UMFk1opkaw8J672gX8AkBO5gbY2S_NMxsxs,7140
167
167
  modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
168
168
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
169
- modal_proto/api.proto,sha256=_S8S_Ci838KDw8dqf4fmhVOE5_apAuctufrX56ze7bk,109030
169
+ modal_proto/api.proto,sha256=o1gwFo-hSFA6vsqgwuj8mfCuU115IH9WRaGFYZCbxBE,109200
170
170
  modal_proto/api_grpc.py,sha256=vwC-GjejDKWbG5jRN3rkU8WBSqQ8Pdj-T2E2xAECAUw,134411
171
- modal_proto/api_pb2.py,sha256=9D9DrafONt1rKOa8o-Qa-4Et7AGk8_XwV9kYXuja4g8,381073
172
- modal_proto/api_pb2.pyi,sha256=vAuI2gGBbKY2APIcWitUCSjdw7uM92zU9FL32i6R75s,534109
171
+ modal_proto/api_pb2.py,sha256=SqMt_EbaHRTcCz4_HeelaJTvQSsbP_YPTJSmlLNn8BU,381467
172
+ modal_proto/api_pb2.pyi,sha256=EaDJnKXZxxs1497rPGGCIcj5ZjfGNj891QEqftQ2qiA,536365
173
173
  modal_proto/api_pb2_grpc.py,sha256=Hqw9jcbhpr-W6jsfog_tGU55ouZjITxGvA-DGNBqOLA,289714
174
174
  modal_proto/api_pb2_grpc.pyi,sha256=QLJ58ANCx147HeGJva58h0MTCLIDs9JmVjrx8bDdwlg,67776
175
175
  modal_proto/modal_api_grpc.py,sha256=MqaBZB2ZqYj6XTIgI_p5dOPjt9gKT4pAJNd_WXR3W84,21295
@@ -186,10 +186,10 @@ modal_proto/task_command_router_pb2.py,sha256=_pD2ZpU0bNzhwBdzmLoLyLtAtftI_Agxwn
186
186
  modal_proto/task_command_router_pb2.pyi,sha256=EyDgXPLr7alqjXYERV8w_MPuO404x0uCppmSkrfE9IE,14589
187
187
  modal_proto/task_command_router_pb2_grpc.py,sha256=uEQ0HdrCp8v-9bB5yIic9muA8spCShLHY6Bz9cCgOUE,10114
188
188
  modal_proto/task_command_router_pb2_grpc.pyi,sha256=s3Yxsrawdj4nr8vqQqsAxyX6ilWaGbdECy425KKbLIA,3301
189
- modal_version/__init__.py,sha256=BsqagvnCuIGsPhQjsCROvTtbZNa8sPTNoVYGTscS9uw,121
189
+ modal_version/__init__.py,sha256=782DByEJ_th6XWFxmR8yS5KZXKX4zFVE27W21dDjsPs,121
190
190
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
191
- modal-1.2.2.dev31.dist-info/METADATA,sha256=eHc4WZUCof9mgGVCIIcv874vclj0oqXSpp7Of1bdF7M,2490
192
- modal-1.2.2.dev31.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
193
- modal-1.2.2.dev31.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
194
- modal-1.2.2.dev31.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
195
- modal-1.2.2.dev31.dist-info/RECORD,,
191
+ modal-1.2.2.dev36.dist-info/METADATA,sha256=cTS-BK_hb6dcpVhvPmBf0q0XgS8d8voOmHkksd0NTJQ,2490
192
+ modal-1.2.2.dev36.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
193
+ modal-1.2.2.dev36.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
194
+ modal-1.2.2.dev36.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
195
+ modal-1.2.2.dev36.dist-info/RECORD,,
modal_proto/api.proto CHANGED
@@ -1289,6 +1289,8 @@ message EnvironmentListItem {
1289
1289
  bool default = 4;
1290
1290
  bool is_managed = 5;
1291
1291
  string environment_id = 6;
1292
+ optional int32 max_concurrent_tasks = 7;
1293
+ optional int32 max_concurrent_gpus = 8;
1292
1294
  }
1293
1295
 
1294
1296
  message EnvironmentListResponse {
@@ -1312,6 +1314,8 @@ message EnvironmentUpdateRequest {
1312
1314
  string current_name = 1;
1313
1315
  google.protobuf.StringValue name = 2;
1314
1316
  google.protobuf.StringValue web_suffix = 3;
1317
+ optional int32 max_concurrent_tasks = 4;
1318
+ optional int32 max_concurrent_gpus = 5;
1315
1319
  }
1316
1320
 
1317
1321
  // A file entry when listing files in a volume or network file system.