modal 1.5.4.dev7__tar.gz → 1.5.4.dev8__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.
Files changed (236) hide show
  1. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/PKG-INFO +1 -1
  2. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_functions.py +11 -1
  3. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_logs_manager.py +29 -33
  4. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_logs_manager.pyi +24 -158
  5. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_output/pty.py +12 -9
  6. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/container_io_manager.py +98 -13
  7. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/container_io_manager.pyi +15 -4
  8. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/async_utils.py +19 -2
  9. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/auth_token_manager.py +66 -19
  10. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/blob_utils.py +17 -11
  11. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/function_utils.py +9 -4
  12. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/grpc_utils.py +4 -2
  13. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/task_command_router_client.py +45 -11
  14. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/shell.py +3 -3
  15. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/client.pyi +2 -2
  16. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/dict.py +19 -15
  17. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/functions.pyi +9 -8
  18. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/network_file_system.py +15 -11
  19. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/parallel_map.py +14 -12
  20. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/parallel_map.pyi +3 -2
  21. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/queue.py +19 -15
  22. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/sandbox.py +32 -13
  23. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/sandbox.pyi +65 -18
  24. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/volume.py +61 -39
  25. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/volume.pyi +21 -15
  26. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal.egg-info/PKG-INFO +1 -1
  27. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/api_pb2.py +1101 -1091
  28. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/api_pb2.pyi +23 -2
  29. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_version/__init__.py +1 -1
  30. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/pyproject.toml +5 -17
  31. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/LICENSE +0 -0
  32. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/README.md +0 -0
  33. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/__init__.py +0 -0
  34. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/__main__.py +0 -0
  35. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_billing.py +0 -0
  36. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_clustered_functions.py +0 -0
  37. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_clustered_functions.pyi +0 -0
  38. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_container_entrypoint.py +0 -0
  39. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_environments.py +0 -0
  40. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_function_variants.py +0 -0
  41. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_grpc_client.py +0 -0
  42. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_image.py +0 -0
  43. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_ipython.py +0 -0
  44. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_load_context.py +0 -0
  45. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_location.py +0 -0
  46. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_logs.py +0 -0
  47. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_object.py +0 -0
  48. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_output/__init__.py +0 -0
  49. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_output/manager.py +0 -0
  50. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_output/rich.py +0 -0
  51. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_output/status.py +0 -0
  52. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_partial_function.py +0 -0
  53. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_resolver.py +0 -0
  54. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_resources.py +0 -0
  55. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/__init__.py +0 -0
  56. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/asgi.py +0 -0
  57. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/execution_context.py +0 -0
  58. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/execution_context.pyi +0 -0
  59. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  60. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/task_lifecycle_manager.py +0 -0
  61. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
  62. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/telemetry.py +0 -0
  63. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/user_code_event_loop.py +0 -0
  64. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_runtime/user_code_imports.py +0 -0
  65. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_serialization.py +0 -0
  66. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_server.py +0 -0
  67. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_supports_logs.py +0 -0
  68. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_traceback.py +0 -0
  69. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_tunnel.py +0 -0
  70. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_tunnel.pyi +0 -0
  71. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_type_manager.py +0 -0
  72. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/__init__.py +0 -0
  73. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/app_utils.py +0 -0
  74. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/browser_utils.py +0 -0
  75. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/bytes_io_segment_payload.py +0 -0
  76. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/curl_utils.py +0 -0
  77. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/deprecation.py +0 -0
  78. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/display_utils.py +0 -0
  79. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/docker_utils.py +0 -0
  80. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/git_utils.py +0 -0
  81. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/grpc_testing.py +0 -0
  82. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/hash_utils.py +0 -0
  83. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/http_utils.py +0 -0
  84. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/jwt_utils.py +0 -0
  85. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/logger.py +0 -0
  86. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/mount_utils.py +0 -0
  87. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/name_utils.py +0 -0
  88. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/package_utils.py +0 -0
  89. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/pattern_utils.py +0 -0
  90. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/proxy_support.py +0 -0
  91. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/rand_pb_testing.py +0 -0
  92. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/sandbox_fs_utils.py +0 -0
  93. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/shell_utils.py +0 -0
  94. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_utils/time_utils.py +0 -0
  95. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_vendor/__init__.py +0 -0
  96. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  97. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_vendor/cloudpickle.py +0 -0
  98. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_vendor/tblib.py +0 -0
  99. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_vendor/version.py +0 -0
  100. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_watcher.py +0 -0
  101. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/_workspace.py +0 -0
  102. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/app.py +0 -0
  103. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/app.pyi +0 -0
  104. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/billing.py +0 -0
  105. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/billing.pyi +0 -0
  106. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/builder/2023.12.312.txt +0 -0
  107. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/builder/2023.12.txt +0 -0
  108. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/builder/2024.04.txt +0 -0
  109. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/builder/2024.10.txt +0 -0
  110. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/builder/2025.06.txt +0 -0
  111. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/builder/PREVIEW.txt +0 -0
  112. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/builder/README.md +0 -0
  113. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/builder/base-images.json +0 -0
  114. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/call_graph.py +0 -0
  115. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/__init__.py +0 -0
  116. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/_download.py +0 -0
  117. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/_help.py +0 -0
  118. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/_traceback.py +0 -0
  119. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/app.py +0 -0
  120. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/billing.py +0 -0
  121. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/bootstrap.py +0 -0
  122. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/changelog.py +0 -0
  123. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/cluster.py +0 -0
  124. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/config.py +0 -0
  125. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/container.py +0 -0
  126. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/curl.py +0 -0
  127. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/dashboard.py +0 -0
  128. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/dict.py +0 -0
  129. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/endpoint.py +0 -0
  130. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/entry_point.py +0 -0
  131. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/environment.py +0 -0
  132. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/image.py +0 -0
  133. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/import_refs.py +0 -0
  134. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/launch.py +0 -0
  135. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/logo.py +0 -0
  136. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/network_file_system.py +0 -0
  137. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/profile.py +0 -0
  138. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/programs/__init__.py +0 -0
  139. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/programs/run_jupyter.py +0 -0
  140. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/programs/vscode.py +0 -0
  141. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/queues.py +0 -0
  142. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/run.py +0 -0
  143. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/secret.py +0 -0
  144. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/selector.py +0 -0
  145. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/skills.py +0 -0
  146. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/token.py +0 -0
  147. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/utils.py +0 -0
  148. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/volume.py +0 -0
  149. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cli/workspace.py +0 -0
  150. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/client.py +0 -0
  151. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cloud_bucket_mount.py +0 -0
  152. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cloud_bucket_mount.pyi +0 -0
  153. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cls.py +0 -0
  154. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/cls.pyi +0 -0
  155. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/config.py +0 -0
  156. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/container_process.py +0 -0
  157. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/container_process.pyi +0 -0
  158. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/dict.pyi +0 -0
  159. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/environments.py +0 -0
  160. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/environments.pyi +0 -0
  161. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/exception.py +0 -0
  162. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/experimental/__init__.py +0 -0
  163. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/experimental/flash.py +0 -0
  164. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/experimental/flash.pyi +0 -0
  165. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/experimental/ipython.py +0 -0
  166. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/file_io.py +0 -0
  167. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/file_io.pyi +0 -0
  168. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/file_pattern_matcher.py +0 -0
  169. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/functions.py +0 -0
  170. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/image.py +0 -0
  171. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/image.pyi +0 -0
  172. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/io_streams.py +0 -0
  173. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/io_streams.pyi +0 -0
  174. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/mount.py +0 -0
  175. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/mount.pyi +0 -0
  176. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/network_file_system.pyi +0 -0
  177. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/object.py +0 -0
  178. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/object.pyi +0 -0
  179. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/output.py +0 -0
  180. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/partial_function.py +0 -0
  181. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/partial_function.pyi +0 -0
  182. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/proxy.py +0 -0
  183. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/proxy.pyi +0 -0
  184. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/py.typed +0 -0
  185. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/queue.pyi +0 -0
  186. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/retries.py +0 -0
  187. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/runner.py +0 -0
  188. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/runner.pyi +0 -0
  189. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/running_app.py +0 -0
  190. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/sandbox_fs.py +0 -0
  191. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/sandbox_fs.pyi +0 -0
  192. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/schedule.py +0 -0
  193. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/scheduler_placement.py +0 -0
  194. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/secret.py +0 -0
  195. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/secret.pyi +0 -0
  196. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/server.py +0 -0
  197. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/server.pyi +0 -0
  198. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/serving.py +0 -0
  199. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/serving.pyi +0 -0
  200. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/skills/modal/SKILL.md +0 -0
  201. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/snapshot.py +0 -0
  202. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/snapshot.pyi +0 -0
  203. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/stream_type.py +0 -0
  204. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/token_flow.py +0 -0
  205. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/token_flow.pyi +0 -0
  206. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/types.py +0 -0
  207. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/workspace.py +0 -0
  208. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal/workspace.pyi +0 -0
  209. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal.egg-info/SOURCES.txt +0 -0
  210. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal.egg-info/dependency_links.txt +0 -0
  211. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal.egg-info/entry_points.txt +0 -0
  212. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal.egg-info/requires.txt +0 -0
  213. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal.egg-info/top_level.txt +0 -0
  214. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/__init__.py +0 -0
  215. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/gen_cli_docs.py +0 -0
  216. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/gen_cli_docs_main.py +0 -0
  217. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/gen_reference_docs.py +0 -0
  218. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/gen_reference_docs_main.py +0 -0
  219. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/mdmd/__init__.py +0 -0
  220. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/mdmd/mdmd.py +0 -0
  221. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/mdmd/signatures.py +0 -0
  222. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/mdmd/types.py +0 -0
  223. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_docs/reference_intro.md +0 -0
  224. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/__init__.py +0 -0
  225. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/api_grpc.py +0 -0
  226. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/api_pb2_grpc.py +0 -0
  227. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/api_pb2_grpc.pyi +0 -0
  228. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/modal_api_grpc.py +0 -0
  229. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/py.typed +0 -0
  230. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/task_command_router_grpc.py +0 -0
  231. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/task_command_router_pb2.py +0 -0
  232. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/task_command_router_pb2.pyi +0 -0
  233. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  234. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  235. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/modal_version/__main__.py +0 -0
  236. {modal-1.5.4.dev7 → modal-1.5.4.dev8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.4.dev7
3
+ Version: 1.5.4.dev8
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -45,7 +45,7 @@ from ._utils.async_utils import (
45
45
  synchronizer,
46
46
  warn_if_generator_is_not_consumed,
47
47
  )
48
- from ._utils.blob_utils import MAX_OBJECT_SIZE_BYTES
48
+ from ._utils.blob_utils import MAX_ASYNC_OBJECT_SIZE_BYTES, MAX_OBJECT_SIZE_BYTES
49
49
  from ._utils.function_utils import (
50
50
  ATTEMPT_TIMEOUT_GRACE_PERIOD,
51
51
  OUTPUTS_TIMEOUT,
@@ -424,6 +424,7 @@ class _InputPlaneInvocation:
424
424
  client: _Client,
425
425
  input_plane_url: str,
426
426
  input_plane_region: str,
427
+ function_call_invocation_type: "api_pb2.FunctionCallInvocationType.ValueType",
427
428
  ) -> "_InputPlaneInvocation":
428
429
  stub = await client.get_stub(input_plane_url)
429
430
 
@@ -435,6 +436,7 @@ class _InputPlaneInvocation:
435
436
  kwargs,
436
437
  control_plane_stub,
437
438
  function=function,
439
+ function_call_invocation_type=function_call_invocation_type,
438
440
  )
439
441
 
440
442
  request = api_pb2.AttemptStartRequest(
@@ -1449,6 +1451,11 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1449
1451
  self._max_object_size_bytes = (
1450
1452
  metadata.max_object_size_bytes if metadata.HasField("max_object_size_bytes") else MAX_OBJECT_SIZE_BYTES
1451
1453
  )
1454
+ self._max_async_object_size_bytes = (
1455
+ metadata.max_async_object_size_bytes
1456
+ if metadata.HasField("max_async_object_size_bytes")
1457
+ else MAX_ASYNC_OBJECT_SIZE_BYTES
1458
+ )
1452
1459
  self._experimental_flash_urls = metadata._experimental_flash_urls
1453
1460
  self._app_id = metadata.app_id or None
1454
1461
 
@@ -1473,6 +1480,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1473
1480
  input_plane_url=self._input_plane_url,
1474
1481
  input_plane_region=self._input_plane_region,
1475
1482
  max_object_size_bytes=self._max_object_size_bytes,
1483
+ max_async_object_size_bytes=self._max_async_object_size_bytes,
1476
1484
  _experimental_flash_urls=self._experimental_flash_urls,
1477
1485
  supported_input_formats=self._metadata.supported_input_formats if self._metadata else [],
1478
1486
  supported_output_formats=self._metadata.supported_output_formats if self._metadata else [],
@@ -1736,6 +1744,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1736
1744
  client=self.client,
1737
1745
  input_plane_url=self._input_plane_url,
1738
1746
  input_plane_region=self._input_plane_region,
1747
+ function_call_invocation_type=api_pb2.FUNCTION_CALL_INVOCATION_TYPE_SYNC,
1739
1748
  )
1740
1749
  else:
1741
1750
  invocation = await _Invocation.create(
@@ -1777,6 +1786,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1777
1786
  client=self.client,
1778
1787
  input_plane_url=self._input_plane_url,
1779
1788
  input_plane_region=self._input_plane_region,
1789
+ function_call_invocation_type=api_pb2.FUNCTION_CALL_INVOCATION_TYPE_SYNC_LEGACY,
1780
1790
  )
1781
1791
  else:
1782
1792
  invocation = await _Invocation.create(
@@ -121,7 +121,7 @@ class _LogsManager:
121
121
  if self._stop_stream is not None and await self._stop_stream():
122
122
  return _StreamStopReason.STOP_STREAM
123
123
 
124
- sleep_time = _STREAM_POLL_INTERVAL_SECONDS
124
+ sleep_time: float = _STREAM_POLL_INTERVAL_SECONDS
125
125
  if deadline.value is not None:
126
126
  sleep_time = min(sleep_time, max(0.0, deadline.value - time.monotonic()))
127
127
  await asyncio.sleep(sleep_time)
@@ -317,15 +317,12 @@ class _LogsManager:
317
317
  pass
318
318
 
319
319
 
320
- LogsManager = synchronize_api(_LogsManager, target_module=__name__)
321
-
322
-
323
- class _FunctionLogsManager(_LogsManager):
320
+ class _FunctionLogsManager:
324
321
  """mdmd:namespace"""
325
322
 
326
323
  def __init__(self, source: _SupportsLogs):
327
324
  """mdmd:hidden"""
328
- super().__init__(source)
325
+ self._manager = _LogsManager(source)
329
326
 
330
327
  async def fetch(
331
328
  self,
@@ -338,7 +335,8 @@ class _FunctionLogsManager(_LogsManager):
338
335
  """Fetch Function logs corresponding to the date range and filters.
339
336
 
340
337
  Args:
341
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
338
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
339
+ which is interpreted as local time.
342
340
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
343
341
  as local time.
344
342
  source: Filter by source: 'stdout', 'stderr', or 'system'.
@@ -359,7 +357,7 @@ class _FunctionLogsManager(_LogsManager):
359
357
  print(entry.message, end="")
360
358
  ```
361
359
  """
362
- async for log_entry in super().fetch(since=since, until=until, source=source, search_text=search_text):
360
+ async for log_entry in self._manager.fetch(since=since, until=until, source=source, search_text=search_text):
363
361
  yield log_entry
364
362
 
365
363
  async def tail(
@@ -386,7 +384,7 @@ class _FunctionLogsManager(_LogsManager):
386
384
  print(entry.message, end="")
387
385
  ```
388
386
  """
389
- async for log_entry in super().tail(entries, source=source):
387
+ async for log_entry in self._manager.tail(entries, source=source):
390
388
  yield log_entry
391
389
 
392
390
  async def stream(self, timeout: float | None = None) -> AsyncGenerator[LogEntry, None]:
@@ -408,19 +406,19 @@ class _FunctionLogsManager(_LogsManager):
408
406
  print(entry.message, end="")
409
407
  ```
410
408
  """
411
- async for log_entry in super().stream(timeout=timeout):
409
+ async for log_entry in self._manager.stream(timeout=timeout):
412
410
  yield log_entry
413
411
 
414
412
 
415
413
  FunctionLogsManager = synchronize_api(_FunctionLogsManager, target_module=__name__)
416
414
 
417
415
 
418
- class _ServerLogsManager(_LogsManager):
416
+ class _ServerLogsManager:
419
417
  """mdmd:namespace"""
420
418
 
421
419
  def __init__(self, source: _SupportsLogs):
422
420
  """mdmd:hidden"""
423
- super().__init__(source)
421
+ self._manager = _LogsManager(source)
424
422
 
425
423
  async def fetch(
426
424
  self,
@@ -433,7 +431,8 @@ class _ServerLogsManager(_LogsManager):
433
431
  """Fetch Server logs corresponding to the date range and filters.
434
432
 
435
433
  Args:
436
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
434
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
435
+ which is interpreted as local time.
437
436
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
438
437
  as local time.
439
438
  source: Filter by source: 'stdout', 'stderr', or 'system'.
@@ -454,7 +453,7 @@ class _ServerLogsManager(_LogsManager):
454
453
  print(entry.message, end="")
455
454
  ```
456
455
  """
457
- async for log_entry in super().fetch(since=since, until=until, source=source, search_text=search_text):
456
+ async for log_entry in self._manager.fetch(since=since, until=until, source=source, search_text=search_text):
458
457
  yield log_entry
459
458
 
460
459
  async def tail(
@@ -481,7 +480,7 @@ class _ServerLogsManager(_LogsManager):
481
480
  print(entry.message, end="")
482
481
  ```
483
482
  """
484
- async for log_entry in super().tail(entries, source=source):
483
+ async for log_entry in self._manager.tail(entries, source=source):
485
484
  yield log_entry
486
485
 
487
486
  async def stream(self, timeout: float | None = None) -> AsyncGenerator[LogEntry, None]:
@@ -503,34 +502,29 @@ class _ServerLogsManager(_LogsManager):
503
502
  print(entry.message, end="")
504
503
  ```
505
504
  """
506
- async for log_entry in super().stream(timeout=timeout):
505
+ async for log_entry in self._manager.stream(timeout=timeout):
507
506
  yield log_entry
508
507
 
509
508
 
510
509
  ServerLogsManager = synchronize_api(_ServerLogsManager, target_module=__name__)
511
510
 
512
511
 
513
- class _FunctionCallLogsManager(_LogsManager):
512
+ class _FunctionCallLogsManager:
514
513
  """mdmd:namespace"""
515
514
 
516
515
  def __init__(self, source: _SupportsLogs):
517
516
  """mdmd:hidden"""
518
- super().__init__(source, stop_stream=self._determine_function_call_stop)
517
+ self._source = source
519
518
  self._function_id: str | None = None
520
-
521
- async def _params(self) -> _LogQueryData:
522
- params = await super()._params()
523
- if self._function_id is None:
524
- self._function_id = getattr(self._source, "_function_id", None)
525
- return params
519
+ self._manager = _LogsManager(source, stop_stream=self._determine_function_call_stop)
526
520
 
527
521
  async def _get_function_call_info(self) -> api_pb2.FunctionCallInfo:
528
522
  for i in range(5):
529
523
  try:
530
- params = await self._params()
531
- assert hasattr(self, "_function_id") and self._function_id is not None, (
532
- "Function ID should be set during hydration"
533
- )
524
+ params = await self._manager._params()
525
+ if self._function_id is None:
526
+ self._function_id = getattr(self._source, "_function_id", None)
527
+ assert self._function_id is not None, "Function ID should be set during hydration"
534
528
  request = api_pb2.FunctionCallGetInfoRequest(
535
529
  function_id=self._function_id,
536
530
  function_call_id=params.filters.function_call_id,
@@ -542,6 +536,7 @@ class _FunctionCallLogsManager(_LogsManager):
542
536
  await asyncio.sleep(1)
543
537
  continue
544
538
  raise
539
+ raise NotFoundError(f"Function call {self._source.object_id} not found after retries.")
545
540
 
546
541
  async def _determine_function_call_stop(self) -> bool:
547
542
  try:
@@ -553,7 +548,7 @@ class _FunctionCallLogsManager(_LogsManager):
553
548
  except NotFoundError:
554
549
  return False
555
550
  except (ServiceError, InternalError, StreamTerminatedError, socket.gaierror, AttributeError) as exc:
556
- if self._is_transient_stream_error(exc):
551
+ if self._manager._is_transient_stream_error(exc):
557
552
  logger.debug("Function call status check interrupted. Retrying ...")
558
553
  return False
559
554
  raise
@@ -592,7 +587,7 @@ class _FunctionCallLogsManager(_LogsManager):
592
587
  print(entry.message, end="")
593
588
  ```
594
589
  """
595
- async for log_entry in super().stream(timeout=timeout):
590
+ async for log_entry in self._manager.stream(timeout=timeout):
596
591
  yield log_entry
597
592
 
598
593
  async def tail(
@@ -620,7 +615,7 @@ class _FunctionCallLogsManager(_LogsManager):
620
615
  print(entry.timestamp, entry.message, end="")
621
616
  ```
622
617
  """
623
- async for log_entry in super().tail(entries, source=source):
618
+ async for log_entry in self._manager.tail(entries, source=source):
624
619
  yield log_entry
625
620
 
626
621
  async def fetch(
@@ -634,7 +629,8 @@ class _FunctionCallLogsManager(_LogsManager):
634
629
  """Fetch all associated logs corresponding to the date range and filters.
635
630
 
636
631
  Args:
637
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
632
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
633
+ which is interpreted as local time.
638
634
  By default, this will fetch logs from the start of the function call.
639
635
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
640
636
  as local time.
@@ -667,7 +663,7 @@ class _FunctionCallLogsManager(_LogsManager):
667
663
  if since_was_defaulted and until_was_defaulted and since > until:
668
664
  until = since
669
665
 
670
- async for log_entry in super().fetch(since=since, until=until, source=source, search_text=search_text):
666
+ async for log_entry in self._manager.fetch(since=since, until=until, source=source, search_text=search_text):
671
667
  yield log_entry
672
668
 
673
669
 
@@ -101,143 +101,7 @@ class _LogsManager:
101
101
  @staticmethod
102
102
  async def _suppress_cancelled(task: asyncio.Task) -> None: ...
103
103
 
104
- class LogsManager:
105
- """mdmd:namespace"""
106
- def __init__(
107
- self,
108
- source: modal._supports_logs._SupportsLogs,
109
- stop_stream: typing.Optional[collections.abc.Callable[[], bool]] = None,
110
- ):
111
- """mdmd:hidden"""
112
- ...
113
-
114
- class ___params_spec(typing_extensions.Protocol):
115
- def __call__(self, /) -> modal._supports_logs._LogQueryData: ...
116
- async def aio(self, /) -> modal._supports_logs._LogQueryData: ...
117
-
118
- _params: ___params_spec
119
-
120
- @staticmethod
121
- def _resolve_source(source: typing.Optional[typing.Literal["stdout", "stderr", "system"]]) -> int: ...
122
- @staticmethod
123
- def _normalize_utc_datetime(value: datetime.datetime, name: str) -> datetime.datetime: ...
124
- @staticmethod
125
- def _entry_source(file_descriptor: int) -> typing.Literal["stdout", "stderr", "system"]: ...
126
- @staticmethod
127
- def _entry_timestamp(item: modal_proto.api_pb2.TaskLogs) -> datetime.datetime: ...
128
- def _entry_context_ids(
129
- self, item: modal_proto.api_pb2.TaskLogs, batch: modal_proto.api_pb2.TaskLogsBatch
130
- ) -> list[str]: ...
131
- def _entry_from_item(
132
- self, item: modal_proto.api_pb2.TaskLogs, batch: modal_proto.api_pb2.TaskLogsBatch
133
- ) -> modal.types.LogEntry: ...
134
-
135
- class ___watch_stream_stop_spec(typing_extensions.Protocol):
136
- def __call__(self, /, deadline: _Deadline) -> typing.Optional[_StreamStopReason]: ...
137
- async def aio(self, /, deadline: _Deadline) -> typing.Optional[_StreamStopReason]: ...
138
-
139
- _watch_stream_stop: ___watch_stream_stop_spec
140
-
141
- class __fetch_spec(typing_extensions.Protocol):
142
- def __call__(
143
- self,
144
- /,
145
- *,
146
- since: datetime.datetime,
147
- until: typing.Optional[datetime.datetime] = None,
148
- source: typing.Optional[typing.Literal["stdout", "stderr", "system"]] = None,
149
- search_text: str = "",
150
- ) -> typing.Generator[modal.types.LogEntry, None, None]:
151
- """Fetch all associated logs corresponding to the date range and filters."""
152
- ...
153
-
154
- def aio(
155
- self,
156
- /,
157
- *,
158
- since: datetime.datetime,
159
- until: typing.Optional[datetime.datetime] = None,
160
- source: typing.Optional[typing.Literal["stdout", "stderr", "system"]] = None,
161
- search_text: str = "",
162
- ) -> collections.abc.AsyncGenerator[modal.types.LogEntry, None]:
163
- """Fetch all associated logs corresponding to the date range and filters."""
164
- ...
165
-
166
- fetch: __fetch_spec
167
-
168
- class __tail_spec(typing_extensions.Protocol):
169
- def __call__(
170
- self, /, entries: int = 100, *, source: typing.Optional[typing.Literal["stdout", "stderr", "system"]] = None
171
- ) -> typing.Generator[modal.types.LogEntry, None, None]:
172
- """Fetch the most recent logs."""
173
- ...
174
-
175
- def aio(
176
- self, /, entries: int = 100, *, source: typing.Optional[typing.Literal["stdout", "stderr", "system"]] = None
177
- ) -> collections.abc.AsyncGenerator[modal.types.LogEntry, None]:
178
- """Fetch the most recent logs."""
179
- ...
180
-
181
- tail: __tail_spec
182
-
183
- class ___create_log_stream_spec(typing_extensions.Protocol):
184
- def __call__(
185
- self, /, params: modal._supports_logs._LogQueryData, last_entry_id: str, timeout: float
186
- ) -> typing.Generator[modal_proto.api_pb2.TaskLogsBatch, None, None]:
187
- """Helper for creating the log stream RPC."""
188
- ...
189
-
190
- def aio(
191
- self, /, params: modal._supports_logs._LogQueryData, last_entry_id: str, timeout: float
192
- ) -> collections.abc.AsyncGenerator[modal_proto.api_pb2.TaskLogsBatch, None]:
193
- """Helper for creating the log stream RPC."""
194
- ...
195
-
196
- _create_log_stream: ___create_log_stream_spec
197
-
198
- def _stream_entries(self, batch: modal_proto.api_pb2.TaskLogsBatch): ...
199
- @staticmethod
200
- def _advance_batch(batch: modal_proto.api_pb2.TaskLogsBatch, last_entry_id: str) -> tuple[str, bool]: ...
201
- @staticmethod
202
- def _is_transient_stream_error(exc: Exception) -> bool: ...
203
-
204
- class ___drain_stream_spec(typing_extensions.Protocol):
205
- def __call__(
206
- self, /, params: modal._supports_logs._LogQueryData, last_entry_id: str, timeout: float
207
- ) -> typing.Generator[modal.types.LogEntry, None, None]:
208
- """Do a final bounded drain in the logs to catch any remaining logs after the stop condition is met."""
209
- ...
210
-
211
- def aio(
212
- self, /, params: modal._supports_logs._LogQueryData, last_entry_id: str, timeout: float
213
- ) -> collections.abc.AsyncGenerator[modal.types.LogEntry, None]:
214
- """Do a final bounded drain in the logs to catch any remaining logs after the stop condition is met."""
215
- ...
216
-
217
- _drain_stream: ___drain_stream_spec
218
-
219
- class __stream_spec(typing_extensions.Protocol):
220
- def __call__(
221
- self, /, timeout: typing.Optional[float] = None
222
- ) -> typing.Generator[modal.types.LogEntry, None, None]:
223
- """Stream new logs until no logs arrive within the timeout."""
224
- ...
225
-
226
- def aio(
227
- self, /, timeout: typing.Optional[float] = None
228
- ) -> collections.abc.AsyncGenerator[modal.types.LogEntry, None]:
229
- """Stream new logs until no logs arrive within the timeout."""
230
- ...
231
-
232
- stream: __stream_spec
233
-
234
- class ___suppress_cancelled_spec(typing_extensions.Protocol):
235
- def __call__(self, /, task: asyncio.Task) -> None: ...
236
- async def aio(self, /, task: asyncio.Task) -> None: ...
237
-
238
- _suppress_cancelled: typing.ClassVar[___suppress_cancelled_spec]
239
-
240
- class _FunctionLogsManager(_LogsManager):
104
+ class _FunctionLogsManager:
241
105
  """mdmd:namespace"""
242
106
  def __init__(self, source: modal._supports_logs._SupportsLogs):
243
107
  """mdmd:hidden"""
@@ -254,7 +118,8 @@ class _FunctionLogsManager(_LogsManager):
254
118
  """Fetch Function logs corresponding to the date range and filters.
255
119
 
256
120
  Args:
257
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
121
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
122
+ which is interpreted as local time.
258
123
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
259
124
  as local time.
260
125
  source: Filter by source: 'stdout', 'stderr', or 'system'.
@@ -323,7 +188,7 @@ class _FunctionLogsManager(_LogsManager):
323
188
  """
324
189
  ...
325
190
 
326
- class FunctionLogsManager(LogsManager):
191
+ class FunctionLogsManager:
327
192
  """mdmd:namespace"""
328
193
  def __init__(self, source: modal._supports_logs._SupportsLogs):
329
194
  """mdmd:hidden"""
@@ -342,7 +207,8 @@ class FunctionLogsManager(LogsManager):
342
207
  """Fetch Function logs corresponding to the date range and filters.
343
208
 
344
209
  Args:
345
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
210
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
211
+ which is interpreted as local time.
346
212
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
347
213
  as local time.
348
214
  source: Filter by source: 'stdout', 'stderr', or 'system'.
@@ -377,7 +243,8 @@ class FunctionLogsManager(LogsManager):
377
243
  """Fetch Function logs corresponding to the date range and filters.
378
244
 
379
245
  Args:
380
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
246
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
247
+ which is interpreted as local time.
381
248
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
382
249
  as local time.
383
250
  source: Filter by source: 'stdout', 'stderr', or 'system'.
@@ -500,7 +367,7 @@ class FunctionLogsManager(LogsManager):
500
367
 
501
368
  stream: __stream_spec
502
369
 
503
- class _ServerLogsManager(_LogsManager):
370
+ class _ServerLogsManager:
504
371
  """mdmd:namespace"""
505
372
  def __init__(self, source: modal._supports_logs._SupportsLogs):
506
373
  """mdmd:hidden"""
@@ -517,7 +384,8 @@ class _ServerLogsManager(_LogsManager):
517
384
  """Fetch Server logs corresponding to the date range and filters.
518
385
 
519
386
  Args:
520
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
387
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
388
+ which is interpreted as local time.
521
389
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
522
390
  as local time.
523
391
  source: Filter by source: 'stdout', 'stderr', or 'system'.
@@ -586,7 +454,7 @@ class _ServerLogsManager(_LogsManager):
586
454
  """
587
455
  ...
588
456
 
589
- class ServerLogsManager(LogsManager):
457
+ class ServerLogsManager:
590
458
  """mdmd:namespace"""
591
459
  def __init__(self, source: modal._supports_logs._SupportsLogs):
592
460
  """mdmd:hidden"""
@@ -605,7 +473,8 @@ class ServerLogsManager(LogsManager):
605
473
  """Fetch Server logs corresponding to the date range and filters.
606
474
 
607
475
  Args:
608
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
476
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
477
+ which is interpreted as local time.
609
478
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
610
479
  as local time.
611
480
  source: Filter by source: 'stdout', 'stderr', or 'system'.
@@ -640,7 +509,8 @@ class ServerLogsManager(LogsManager):
640
509
  """Fetch Server logs corresponding to the date range and filters.
641
510
 
642
511
  Args:
643
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
512
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
513
+ which is interpreted as local time.
644
514
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
645
515
  as local time.
646
516
  source: Filter by source: 'stdout', 'stderr', or 'system'.
@@ -763,13 +633,12 @@ class ServerLogsManager(LogsManager):
763
633
 
764
634
  stream: __stream_spec
765
635
 
766
- class _FunctionCallLogsManager(_LogsManager):
636
+ class _FunctionCallLogsManager:
767
637
  """mdmd:namespace"""
768
638
  def __init__(self, source: modal._supports_logs._SupportsLogs):
769
639
  """mdmd:hidden"""
770
640
  ...
771
641
 
772
- async def _params(self) -> modal._supports_logs._LogQueryData: ...
773
642
  async def _get_function_call_info(self) -> modal_proto.api_pb2.FunctionCallInfo: ...
774
643
  async def _determine_function_call_stop(self) -> bool: ...
775
644
  def stream(
@@ -835,7 +704,8 @@ class _FunctionCallLogsManager(_LogsManager):
835
704
  """Fetch all associated logs corresponding to the date range and filters.
836
705
 
837
706
  Args:
838
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
707
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
708
+ which is interpreted as local time.
839
709
  By default, this will fetch logs from the start of the function call.
840
710
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
841
711
  as local time.
@@ -857,18 +727,12 @@ class _FunctionCallLogsManager(_LogsManager):
857
727
  """
858
728
  ...
859
729
 
860
- class FunctionCallLogsManager(LogsManager):
730
+ class FunctionCallLogsManager:
861
731
  """mdmd:namespace"""
862
732
  def __init__(self, source: modal._supports_logs._SupportsLogs):
863
733
  """mdmd:hidden"""
864
734
  ...
865
735
 
866
- class ___params_spec(typing_extensions.Protocol):
867
- def __call__(self, /) -> modal._supports_logs._LogQueryData: ...
868
- async def aio(self, /) -> modal._supports_logs._LogQueryData: ...
869
-
870
- _params: ___params_spec
871
-
872
736
  class ___get_function_call_info_spec(typing_extensions.Protocol):
873
737
  def __call__(self, /) -> modal_proto.api_pb2.FunctionCallInfo: ...
874
738
  async def aio(self, /) -> modal_proto.api_pb2.FunctionCallInfo: ...
@@ -1004,7 +868,8 @@ class FunctionCallLogsManager(LogsManager):
1004
868
  """Fetch all associated logs corresponding to the date range and filters.
1005
869
 
1006
870
  Args:
1007
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
871
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
872
+ which is interpreted as local time.
1008
873
  By default, this will fetch logs from the start of the function call.
1009
874
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
1010
875
  as local time.
@@ -1038,7 +903,8 @@ class FunctionCallLogsManager(LogsManager):
1038
903
  """Fetch all associated logs corresponding to the date range and filters.
1039
904
 
1040
905
  Args:
1041
- since: Start date to fetch logs from. Must be in UTC or timezone-naive, which is interpreted as local time.
906
+ since: Start date to fetch logs from. Must be in UTC or timezone-naive,
907
+ which is interpreted as local time.
1042
908
  By default, this will fetch logs from the start of the function call.
1043
909
  until: Defaults to current date if None. Must be in UTC or timezone-naive, which is interpreted
1044
910
  as local time.
@@ -32,11 +32,11 @@ def get_pty_info(shell: bool, no_terminate_on_idle_stdin: bool = False) -> api_p
32
32
  rows, cols = get_winsz()
33
33
  return api_pb2.PTYInfo(
34
34
  enabled=True, # TODO(erikbern): deprecated
35
- winsz_rows=rows,
36
- winsz_cols=cols,
37
- env_term=os.environ.get("TERM"),
38
- env_colorterm=os.environ.get("COLORTERM"),
39
- env_term_program=os.environ.get("TERM_PROGRAM"),
35
+ winsz_rows=rows or 0,
36
+ winsz_cols=cols or 0,
37
+ env_term=os.environ.get("TERM", ""),
38
+ env_colorterm=os.environ.get("COLORTERM", ""),
39
+ env_term_program=os.environ.get("TERM_PROGRAM", ""),
40
40
  pty_type=api_pb2.PTYInfo.PTY_TYPE_SHELL if shell else api_pb2.PTYInfo.PTY_TYPE_FUNCTION,
41
41
  no_terminate_on_idle_stdin=no_terminate_on_idle_stdin,
42
42
  )
@@ -158,10 +158,12 @@ async def get_app_logs_loop(
158
158
  log_prefix = _build_log_prefix(log_batch, log, _prefixes)
159
159
  await output_mgr.put_streaming_log(log, prefix=log_prefix)
160
160
 
161
- async def _get_logs():
161
+ async def _get_logs() -> bool:
162
+ """Fetch a batch of logs, returning True once the app signals that its logs are complete."""
162
163
  nonlocal last_log_batch_entry_id
163
164
  nonlocal pty_shell_finish_event, pty_shell_task_id, pty_shell_input_task
164
165
 
166
+ app_done = False
165
167
  request = api_pb2.AppGetLogsRequest(
166
168
  app_id=app_id or "",
167
169
  task_id=task_id or "",
@@ -179,7 +181,7 @@ async def get_app_logs_loop(
179
181
  last_log_batch_entry_id = log_batch.entry_id
180
182
  if log_batch.app_done:
181
183
  logger.debug("App logs are done")
182
- last_log_batch_entry_id = None
184
+ app_done = True
183
185
  break
184
186
  elif log_batch.image_id and not output_mgr._show_image_logs:
185
187
  # Ignore image logs while app is creating objects.
@@ -212,10 +214,11 @@ async def get_app_logs_loop(
212
214
  await stop_pty_shell()
213
215
 
214
216
  output_mgr.flush_lines()
217
+ return app_done
215
218
 
216
219
  while True:
217
220
  try:
218
- await _get_logs()
221
+ app_done = await _get_logs()
219
222
  except (ServiceError, InternalError, StreamTerminatedError, socket.gaierror, AttributeError) as exc:
220
223
  if isinstance(exc, (ServiceError, InternalError)):
221
224
  # Try again if we had a temporary connection drop, for example if computer went to sleep.
@@ -237,7 +240,7 @@ async def get_app_logs_loop(
237
240
  continue
238
241
  raise
239
242
 
240
- if last_log_batch_entry_id is None or not follow:
243
+ if app_done or not follow:
241
244
  break
242
245
 
243
246
  await stop_pty_shell()