modal 1.1.1.dev38__tar.gz → 1.1.1.dev40__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.
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/PKG-INFO +1 -1
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_functions.py +1 -2
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_output.py +2 -2
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/async_utils.py +6 -4
- modal-1.1.1.dev40/modal/_utils/time_utils.py +19 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/app.py +4 -4
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/cluster.py +2 -2
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/container.py +2 -2
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/dict.py +2 -2
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/network_file_system.py +2 -2
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/queues.py +2 -2
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/secret.py +3 -3
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/volume.py +3 -3
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/client.pyi +2 -2
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/dict.py +2 -1
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/parallel_map.py +224 -85
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/parallel_map.pyi +12 -5
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/queue.py +2 -1
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/secret.py +2 -1
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/volume.py +2 -1
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_version/__init__.py +1 -1
- modal-1.1.1.dev38/modal/_utils/time_utils.py +0 -15
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/LICENSE +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/README.md +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/__main__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_clustered_functions.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_clustered_functions.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_container_entrypoint.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_ipython.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_location.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_object.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_partial_function.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_pty.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_resolver.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_resources.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/asgi.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/execution_context.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/telemetry.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_serialization.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_traceback.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_tunnel.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_tunnel.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_type_manager.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/app_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/blob_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/deprecation.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/docker_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/function_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/git_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/hash_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/http_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/logger.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/mount_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/name_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/package_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_utils/shell_utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_vendor/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_vendor/tblib.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/_watcher.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/app.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/app.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/builder/2023.12.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/builder/2024.04.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/builder/2024.10.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/builder/2025.06.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/builder/README.md +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/builder/base-images.json +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/call_graph.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/_download.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/_traceback.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/config.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/entry_point.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/environment.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/import_refs.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/launch.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/profile.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/programs/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/programs/vscode.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/run.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/token.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cli/utils.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/client.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cls.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/cls.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/config.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/container_process.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/container_process.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/dict.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/environments.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/environments.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/exception.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/experimental/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/experimental/flash.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/experimental/flash.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/experimental/ipython.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/file_io.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/file_io.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/file_pattern_matcher.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/functions.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/functions.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/gpu.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/image.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/image.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/io_streams.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/io_streams.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/mount.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/mount.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/network_file_system.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/network_file_system.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/object.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/object.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/output.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/partial_function.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/partial_function.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/proxy.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/proxy.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/py.typed +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/queue.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/retries.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/runner.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/runner.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/running_app.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/sandbox.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/sandbox.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/schedule.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/scheduler_placement.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/secret.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/serving.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/serving.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/snapshot.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/snapshot.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/stream_type.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/token_flow.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/token_flow.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal/volume.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal.egg-info/requires.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal.egg-info/top_level.txt +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_docs/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/__init__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/api.proto +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/api_grpc.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/api_pb2.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/options.proto +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/options_grpc.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/options_pb2.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_proto/py.typed +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/modal_version/__main__.py +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/pyproject.toml +0 -0
- {modal-1.1.1.dev38 → modal-1.1.1.dev40}/setup.cfg +0 -0
|
@@ -1513,8 +1513,7 @@ Use the `Function.get_web_url()` method instead.
|
|
|
1513
1513
|
else:
|
|
1514
1514
|
count_update_callback = None
|
|
1515
1515
|
|
|
1516
|
-
|
|
1517
|
-
if self._input_plane_url and False:
|
|
1516
|
+
if self._input_plane_url:
|
|
1518
1517
|
async with aclosing(
|
|
1519
1518
|
_map_invocation_inputplane(
|
|
1520
1519
|
self,
|
|
@@ -31,7 +31,7 @@ from rich.progress import (
|
|
|
31
31
|
from rich.spinner import Spinner
|
|
32
32
|
from rich.text import Text
|
|
33
33
|
|
|
34
|
-
from modal._utils.time_utils import
|
|
34
|
+
from modal._utils.time_utils import timestamp_to_localized_str
|
|
35
35
|
from modal_proto import api_pb2
|
|
36
36
|
|
|
37
37
|
from ._utils.grpc_utils import RETRYABLE_GRPC_STATUS_CODES, retry_transient_errors
|
|
@@ -91,7 +91,7 @@ class LineBufferedOutput:
|
|
|
91
91
|
|
|
92
92
|
if self._show_timestamps:
|
|
93
93
|
for i in range(0, len(chunks) - 1, 2):
|
|
94
|
-
chunks[i] = f"{
|
|
94
|
+
chunks[i] = f"{timestamp_to_localized_str(log.timestamp)} {chunks[i]}"
|
|
95
95
|
|
|
96
96
|
completed_lines = "".join(chunks[:-1])
|
|
97
97
|
remainder = chunks[-1]
|
|
@@ -279,7 +279,9 @@ class TimestampPriorityQueue(Generic[T]):
|
|
|
279
279
|
|
|
280
280
|
def __init__(self, maxsize: int = 0):
|
|
281
281
|
self.condition = asyncio.Condition()
|
|
282
|
-
self._queue: asyncio.PriorityQueue[tuple[float, Union[T, None]]] = asyncio.PriorityQueue(maxsize=maxsize)
|
|
282
|
+
self._queue: asyncio.PriorityQueue[tuple[float, int, Union[T, None]]] = asyncio.PriorityQueue(maxsize=maxsize)
|
|
283
|
+
# Used to tiebreak items with the same timestamp that are not comparable. (eg. protos)
|
|
284
|
+
self._counter = itertools.count()
|
|
283
285
|
|
|
284
286
|
async def close(self):
|
|
285
287
|
await self.put(self._MAX_PRIORITY, None)
|
|
@@ -288,7 +290,7 @@ class TimestampPriorityQueue(Generic[T]):
|
|
|
288
290
|
"""
|
|
289
291
|
Add an item to the queue to be processed at a specific timestamp.
|
|
290
292
|
"""
|
|
291
|
-
await self._queue.put((timestamp, item))
|
|
293
|
+
await self._queue.put((timestamp, next(self._counter), item))
|
|
292
294
|
async with self.condition:
|
|
293
295
|
self.condition.notify_all() # notify any waiting coroutines
|
|
294
296
|
|
|
@@ -301,7 +303,7 @@ class TimestampPriorityQueue(Generic[T]):
|
|
|
301
303
|
while self.empty():
|
|
302
304
|
await self.condition.wait()
|
|
303
305
|
# peek at the next item
|
|
304
|
-
timestamp, item = await self._queue.get()
|
|
306
|
+
timestamp, counter, item = await self._queue.get()
|
|
305
307
|
now = time.time()
|
|
306
308
|
if timestamp < now:
|
|
307
309
|
return item
|
|
@@ -309,7 +311,7 @@ class TimestampPriorityQueue(Generic[T]):
|
|
|
309
311
|
return None
|
|
310
312
|
# not ready yet, calculate sleep time
|
|
311
313
|
sleep_time = timestamp - now
|
|
312
|
-
self._queue.put_nowait((timestamp, item)) # put it back
|
|
314
|
+
self._queue.put_nowait((timestamp, counter, item)) # put it back
|
|
313
315
|
# wait until either the timeout or a new item is added
|
|
314
316
|
try:
|
|
315
317
|
await asyncio.wait_for(self.condition.wait(), timeout=sleep_time)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Copyright Modal Labs 2025
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def timestamp_to_localized_dt(ts: float) -> datetime:
|
|
7
|
+
locale_tz = datetime.now().astimezone().tzinfo
|
|
8
|
+
return datetime.fromtimestamp(ts, tz=locale_tz)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def timestamp_to_localized_str(ts: float, isotz: bool = True) -> Optional[str]:
|
|
12
|
+
if ts > 0:
|
|
13
|
+
dt = timestamp_to_localized_dt(ts)
|
|
14
|
+
if isotz:
|
|
15
|
+
return dt.isoformat(sep=" ", timespec="seconds")
|
|
16
|
+
else:
|
|
17
|
+
return f"{dt:%Y-%m-%d %H:%M %Z}"
|
|
18
|
+
else:
|
|
19
|
+
return None
|
|
@@ -15,7 +15,7 @@ from modal.client import _Client
|
|
|
15
15
|
from modal.environments import ensure_env
|
|
16
16
|
from modal_proto import api_pb2
|
|
17
17
|
|
|
18
|
-
from .._utils.time_utils import
|
|
18
|
+
from .._utils.time_utils import timestamp_to_localized_str
|
|
19
19
|
from .utils import ENV_OPTION, display_table, get_app_id_from_name, stream_app_logs
|
|
20
20
|
|
|
21
21
|
APP_IDENTIFIER = Argument("", help="App name or ID")
|
|
@@ -71,8 +71,8 @@ async def list_(env: Optional[str] = ENV_OPTION, json: bool = False):
|
|
|
71
71
|
app_stats.description,
|
|
72
72
|
state,
|
|
73
73
|
str(app_stats.n_running_tasks),
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
timestamp_to_localized_str(app_stats.created_at, json),
|
|
75
|
+
timestamp_to_localized_str(app_stats.stopped_at, json),
|
|
76
76
|
]
|
|
77
77
|
)
|
|
78
78
|
|
|
@@ -217,7 +217,7 @@ async def history(
|
|
|
217
217
|
|
|
218
218
|
row = [
|
|
219
219
|
Text(f"v{app_stats.version}", style=style),
|
|
220
|
-
Text(
|
|
220
|
+
Text(timestamp_to_localized_str(app_stats.deployed_at, json), style=style),
|
|
221
221
|
Text(app_stats.client_version, style=style),
|
|
222
222
|
Text(app_stats.deployed_by, style=style),
|
|
223
223
|
]
|
|
@@ -8,7 +8,7 @@ from modal._object import _get_environment_name
|
|
|
8
8
|
from modal._output import make_console
|
|
9
9
|
from modal._pty import get_pty_info
|
|
10
10
|
from modal._utils.async_utils import synchronizer
|
|
11
|
-
from modal._utils.time_utils import
|
|
11
|
+
from modal._utils.time_utils import timestamp_to_localized_str
|
|
12
12
|
from modal.cli.utils import ENV_OPTION, display_table, is_tty
|
|
13
13
|
from modal.client import _Client
|
|
14
14
|
from modal.config import config
|
|
@@ -42,7 +42,7 @@ async def list_(env: Optional[str] = ENV_OPTION, json: bool = False):
|
|
|
42
42
|
[
|
|
43
43
|
c.cluster_id,
|
|
44
44
|
c.app_id,
|
|
45
|
-
|
|
45
|
+
timestamp_to_localized_str(c.started_at, json) if c.started_at else "Pending",
|
|
46
46
|
str(len(c.task_ids)),
|
|
47
47
|
]
|
|
48
48
|
)
|
|
@@ -8,7 +8,7 @@ from modal._object import _get_environment_name
|
|
|
8
8
|
from modal._pty import get_pty_info
|
|
9
9
|
from modal._utils.async_utils import synchronizer
|
|
10
10
|
from modal._utils.grpc_utils import retry_transient_errors
|
|
11
|
-
from modal._utils.time_utils import
|
|
11
|
+
from modal._utils.time_utils import timestamp_to_localized_str
|
|
12
12
|
from modal.cli.utils import ENV_OPTION, display_table, is_tty, stream_app_logs
|
|
13
13
|
from modal.client import _Client
|
|
14
14
|
from modal.config import config
|
|
@@ -40,7 +40,7 @@ async def list_(env: Optional[str] = ENV_OPTION, json: bool = False):
|
|
|
40
40
|
task_stats.task_id,
|
|
41
41
|
task_stats.app_id,
|
|
42
42
|
task_stats.app_description,
|
|
43
|
-
|
|
43
|
+
timestamp_to_localized_str(task_stats.started_at, json) if task_stats.started_at else "Pending",
|
|
44
44
|
]
|
|
45
45
|
)
|
|
46
46
|
|
|
@@ -8,7 +8,7 @@ from modal._output import make_console
|
|
|
8
8
|
from modal._resolver import Resolver
|
|
9
9
|
from modal._utils.async_utils import synchronizer
|
|
10
10
|
from modal._utils.grpc_utils import retry_transient_errors
|
|
11
|
-
from modal._utils.time_utils import
|
|
11
|
+
from modal._utils.time_utils import timestamp_to_localized_str
|
|
12
12
|
from modal.cli.utils import ENV_OPTION, YES_OPTION, display_table
|
|
13
13
|
from modal.client import _Client
|
|
14
14
|
from modal.dict import _Dict
|
|
@@ -44,7 +44,7 @@ async def list_(*, json: bool = False, env: Optional[str] = ENV_OPTION):
|
|
|
44
44
|
request = api_pb2.DictListRequest(environment_name=env)
|
|
45
45
|
response = await retry_transient_errors(client.stub.DictList, request)
|
|
46
46
|
|
|
47
|
-
rows = [(d.name,
|
|
47
|
+
rows = [(d.name, timestamp_to_localized_str(d.created_at, json)) for d in response.dicts]
|
|
48
48
|
display_table(["Name", "Created at"], rows, json)
|
|
49
49
|
|
|
50
50
|
|
|
@@ -16,7 +16,7 @@ from modal._location import display_location
|
|
|
16
16
|
from modal._output import OutputManager, ProgressHandler, make_console
|
|
17
17
|
from modal._utils.async_utils import synchronizer
|
|
18
18
|
from modal._utils.grpc_utils import retry_transient_errors
|
|
19
|
-
from modal._utils.time_utils import
|
|
19
|
+
from modal._utils.time_utils import timestamp_to_localized_str
|
|
20
20
|
from modal.cli._download import _volume_download
|
|
21
21
|
from modal.cli.utils import ENV_OPTION, YES_OPTION, display_table
|
|
22
22
|
from modal.client import _Client
|
|
@@ -44,7 +44,7 @@ async def list_(env: Optional[str] = ENV_OPTION, json: Optional[bool] = False):
|
|
|
44
44
|
[
|
|
45
45
|
item.label,
|
|
46
46
|
display_location(item.cloud_provider),
|
|
47
|
-
|
|
47
|
+
timestamp_to_localized_str(item.created_at, json),
|
|
48
48
|
]
|
|
49
49
|
)
|
|
50
50
|
display_table(column_names, rows, json, title=f"Shared Volumes{env_part}")
|
|
@@ -8,7 +8,7 @@ from modal._output import make_console
|
|
|
8
8
|
from modal._resolver import Resolver
|
|
9
9
|
from modal._utils.async_utils import synchronizer
|
|
10
10
|
from modal._utils.grpc_utils import retry_transient_errors
|
|
11
|
-
from modal._utils.time_utils import
|
|
11
|
+
from modal._utils.time_utils import timestamp_to_localized_str
|
|
12
12
|
from modal.cli.utils import ENV_OPTION, YES_OPTION, display_table
|
|
13
13
|
from modal.client import _Client
|
|
14
14
|
from modal.environments import ensure_env
|
|
@@ -71,7 +71,7 @@ async def list_(*, json: bool = False, env: Optional[str] = ENV_OPTION):
|
|
|
71
71
|
rows = [
|
|
72
72
|
(
|
|
73
73
|
q.name,
|
|
74
|
-
|
|
74
|
+
timestamp_to_localized_str(q.created_at, json),
|
|
75
75
|
str(q.num_partitions),
|
|
76
76
|
str(q.total_size) if q.total_size <= max_total_size else f">{max_total_size}",
|
|
77
77
|
)
|
|
@@ -15,7 +15,7 @@ from typer import Argument
|
|
|
15
15
|
from modal._output import make_console
|
|
16
16
|
from modal._utils.async_utils import synchronizer
|
|
17
17
|
from modal._utils.grpc_utils import retry_transient_errors
|
|
18
|
-
from modal._utils.time_utils import
|
|
18
|
+
from modal._utils.time_utils import timestamp_to_localized_str
|
|
19
19
|
from modal.cli.utils import ENV_OPTION, YES_OPTION, display_table
|
|
20
20
|
from modal.client import _Client
|
|
21
21
|
from modal.environments import ensure_env
|
|
@@ -38,8 +38,8 @@ async def list_(env: Optional[str] = ENV_OPTION, json: bool = False):
|
|
|
38
38
|
rows.append(
|
|
39
39
|
[
|
|
40
40
|
item.label,
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
timestamp_to_localized_str(item.created_at, json),
|
|
42
|
+
timestamp_to_localized_str(item.last_used_at, json) if item.last_used_at else "-",
|
|
43
43
|
]
|
|
44
44
|
)
|
|
45
45
|
|
|
@@ -14,7 +14,7 @@ import modal
|
|
|
14
14
|
from modal._output import OutputManager, ProgressHandler, make_console
|
|
15
15
|
from modal._utils.async_utils import synchronizer
|
|
16
16
|
from modal._utils.grpc_utils import retry_transient_errors
|
|
17
|
-
from modal._utils.time_utils import
|
|
17
|
+
from modal._utils.time_utils import timestamp_to_localized_str
|
|
18
18
|
from modal.cli._download import _volume_download
|
|
19
19
|
from modal.cli.utils import ENV_OPTION, YES_OPTION, display_table
|
|
20
20
|
from modal.client import _Client
|
|
@@ -116,7 +116,7 @@ async def list_(env: Optional[str] = ENV_OPTION, json: Optional[bool] = False):
|
|
|
116
116
|
column_names = ["Name", "Created at"]
|
|
117
117
|
rows = []
|
|
118
118
|
for item in response.items:
|
|
119
|
-
rows.append([item.label,
|
|
119
|
+
rows.append([item.label, timestamp_to_localized_str(item.created_at, json)])
|
|
120
120
|
display_table(column_names, rows, json, title=f"Volumes{env_part}")
|
|
121
121
|
|
|
122
122
|
|
|
@@ -163,7 +163,7 @@ async def ls(
|
|
|
163
163
|
(
|
|
164
164
|
entry.path.encode("unicode_escape").decode("utf-8"),
|
|
165
165
|
filetype,
|
|
166
|
-
|
|
166
|
+
timestamp_to_localized_str(entry.mtime, False),
|
|
167
167
|
humanize_filesize(entry.size),
|
|
168
168
|
)
|
|
169
169
|
)
|
|
@@ -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.1.1.
|
|
36
|
+
version: str = "1.1.1.dev40",
|
|
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.1.1.
|
|
167
|
+
version: str = "1.1.1.dev40",
|
|
168
168
|
):
|
|
169
169
|
"""mdmd:hidden
|
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -17,6 +17,7 @@ from ._utils.async_utils import TaskContext, synchronize_api
|
|
|
17
17
|
from ._utils.deprecation import deprecation_warning, warn_if_passing_namespace
|
|
18
18
|
from ._utils.grpc_utils import retry_transient_errors
|
|
19
19
|
from ._utils.name_utils import check_object_name
|
|
20
|
+
from ._utils.time_utils import timestamp_to_localized_dt
|
|
20
21
|
from .client import _Client
|
|
21
22
|
from .config import logger
|
|
22
23
|
from .exception import RequestSizeError
|
|
@@ -248,7 +249,7 @@ class _Dict(_Object, type_prefix="di"):
|
|
|
248
249
|
creation_info = metadata.creation_info
|
|
249
250
|
return DictInfo(
|
|
250
251
|
name=metadata.name or None,
|
|
251
|
-
created_at=
|
|
252
|
+
created_at=timestamp_to_localized_dt(creation_info.created_at),
|
|
252
253
|
created_by=creation_info.created_by or None,
|
|
253
254
|
)
|
|
254
255
|
|