modal 0.73.47__tar.gz → 0.73.49__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 (182) hide show
  1. {modal-0.73.47 → modal-0.73.49}/PKG-INFO +1 -1
  2. {modal-0.73.47 → modal-0.73.49}/modal/_functions.py +1 -0
  3. {modal-0.73.47 → modal-0.73.49}/modal/client.pyi +2 -2
  4. {modal-0.73.47 → modal-0.73.49}/modal/functions.pyi +6 -6
  5. {modal-0.73.47 → modal-0.73.49}/modal.egg-info/PKG-INFO +1 -1
  6. {modal-0.73.47 → modal-0.73.49}/modal.egg-info/SOURCES.txt +3 -0
  7. modal-0.73.49/modal_docs/mdmd/__init__.py +1 -0
  8. modal-0.73.49/modal_docs/mdmd/mdmd.py +195 -0
  9. modal-0.73.49/modal_docs/mdmd/signatures.py +76 -0
  10. {modal-0.73.47 → modal-0.73.49}/modal_proto/api.proto +3 -0
  11. {modal-0.73.47 → modal-0.73.49}/modal_proto/api_pb2.py +504 -504
  12. {modal-0.73.47 → modal-0.73.49}/modal_proto/api_pb2.pyi +7 -2
  13. {modal-0.73.47 → modal-0.73.49}/modal_version/_version_generated.py +1 -1
  14. {modal-0.73.47 → modal-0.73.49}/pyproject.toml +1 -1
  15. {modal-0.73.47 → modal-0.73.49}/LICENSE +0 -0
  16. {modal-0.73.47 → modal-0.73.49}/README.md +0 -0
  17. {modal-0.73.47 → modal-0.73.49}/modal/__init__.py +0 -0
  18. {modal-0.73.47 → modal-0.73.49}/modal/__main__.py +0 -0
  19. {modal-0.73.47 → modal-0.73.49}/modal/_clustered_functions.py +0 -0
  20. {modal-0.73.47 → modal-0.73.49}/modal/_clustered_functions.pyi +0 -0
  21. {modal-0.73.47 → modal-0.73.49}/modal/_container_entrypoint.py +0 -0
  22. {modal-0.73.47 → modal-0.73.49}/modal/_ipython.py +0 -0
  23. {modal-0.73.47 → modal-0.73.49}/modal/_location.py +0 -0
  24. {modal-0.73.47 → modal-0.73.49}/modal/_object.py +0 -0
  25. {modal-0.73.47 → modal-0.73.49}/modal/_output.py +0 -0
  26. {modal-0.73.47 → modal-0.73.49}/modal/_partial_function.py +0 -0
  27. {modal-0.73.47 → modal-0.73.49}/modal/_proxy_tunnel.py +0 -0
  28. {modal-0.73.47 → modal-0.73.49}/modal/_pty.py +0 -0
  29. {modal-0.73.47 → modal-0.73.49}/modal/_resolver.py +0 -0
  30. {modal-0.73.47 → modal-0.73.49}/modal/_resources.py +0 -0
  31. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/__init__.py +0 -0
  32. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/asgi.py +0 -0
  33. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/container_io_manager.py +0 -0
  34. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/container_io_manager.pyi +0 -0
  35. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/execution_context.py +0 -0
  36. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/execution_context.pyi +0 -0
  37. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  38. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/telemetry.py +0 -0
  39. {modal-0.73.47 → modal-0.73.49}/modal/_runtime/user_code_imports.py +0 -0
  40. {modal-0.73.47 → modal-0.73.49}/modal/_serialization.py +0 -0
  41. {modal-0.73.47 → modal-0.73.49}/modal/_traceback.py +0 -0
  42. {modal-0.73.47 → modal-0.73.49}/modal/_tunnel.py +0 -0
  43. {modal-0.73.47 → modal-0.73.49}/modal/_tunnel.pyi +0 -0
  44. {modal-0.73.47 → modal-0.73.49}/modal/_utils/__init__.py +0 -0
  45. {modal-0.73.47 → modal-0.73.49}/modal/_utils/app_utils.py +0 -0
  46. {modal-0.73.47 → modal-0.73.49}/modal/_utils/async_utils.py +0 -0
  47. {modal-0.73.47 → modal-0.73.49}/modal/_utils/blob_utils.py +0 -0
  48. {modal-0.73.47 → modal-0.73.49}/modal/_utils/bytes_io_segment_payload.py +0 -0
  49. {modal-0.73.47 → modal-0.73.49}/modal/_utils/deprecation.py +0 -0
  50. {modal-0.73.47 → modal-0.73.49}/modal/_utils/docker_utils.py +0 -0
  51. {modal-0.73.47 → modal-0.73.49}/modal/_utils/function_utils.py +0 -0
  52. {modal-0.73.47 → modal-0.73.49}/modal/_utils/grpc_testing.py +0 -0
  53. {modal-0.73.47 → modal-0.73.49}/modal/_utils/grpc_utils.py +0 -0
  54. {modal-0.73.47 → modal-0.73.49}/modal/_utils/hash_utils.py +0 -0
  55. {modal-0.73.47 → modal-0.73.49}/modal/_utils/http_utils.py +0 -0
  56. {modal-0.73.47 → modal-0.73.49}/modal/_utils/logger.py +0 -0
  57. {modal-0.73.47 → modal-0.73.49}/modal/_utils/mount_utils.py +0 -0
  58. {modal-0.73.47 → modal-0.73.49}/modal/_utils/name_utils.py +0 -0
  59. {modal-0.73.47 → modal-0.73.49}/modal/_utils/package_utils.py +0 -0
  60. {modal-0.73.47 → modal-0.73.49}/modal/_utils/pattern_utils.py +0 -0
  61. {modal-0.73.47 → modal-0.73.49}/modal/_utils/rand_pb_testing.py +0 -0
  62. {modal-0.73.47 → modal-0.73.49}/modal/_utils/shell_utils.py +0 -0
  63. {modal-0.73.47 → modal-0.73.49}/modal/_vendor/__init__.py +0 -0
  64. {modal-0.73.47 → modal-0.73.49}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  65. {modal-0.73.47 → modal-0.73.49}/modal/_vendor/cloudpickle.py +0 -0
  66. {modal-0.73.47 → modal-0.73.49}/modal/_vendor/tblib.py +0 -0
  67. {modal-0.73.47 → modal-0.73.49}/modal/_watcher.py +0 -0
  68. {modal-0.73.47 → modal-0.73.49}/modal/app.py +0 -0
  69. {modal-0.73.47 → modal-0.73.49}/modal/app.pyi +0 -0
  70. {modal-0.73.47 → modal-0.73.49}/modal/call_graph.py +0 -0
  71. {modal-0.73.47 → modal-0.73.49}/modal/cli/__init__.py +0 -0
  72. {modal-0.73.47 → modal-0.73.49}/modal/cli/_download.py +0 -0
  73. {modal-0.73.47 → modal-0.73.49}/modal/cli/_traceback.py +0 -0
  74. {modal-0.73.47 → modal-0.73.49}/modal/cli/app.py +0 -0
  75. {modal-0.73.47 → modal-0.73.49}/modal/cli/config.py +0 -0
  76. {modal-0.73.47 → modal-0.73.49}/modal/cli/container.py +0 -0
  77. {modal-0.73.47 → modal-0.73.49}/modal/cli/dict.py +0 -0
  78. {modal-0.73.47 → modal-0.73.49}/modal/cli/entry_point.py +0 -0
  79. {modal-0.73.47 → modal-0.73.49}/modal/cli/environment.py +0 -0
  80. {modal-0.73.47 → modal-0.73.49}/modal/cli/import_refs.py +0 -0
  81. {modal-0.73.47 → modal-0.73.49}/modal/cli/launch.py +0 -0
  82. {modal-0.73.47 → modal-0.73.49}/modal/cli/network_file_system.py +0 -0
  83. {modal-0.73.47 → modal-0.73.49}/modal/cli/profile.py +0 -0
  84. {modal-0.73.47 → modal-0.73.49}/modal/cli/programs/__init__.py +0 -0
  85. {modal-0.73.47 → modal-0.73.49}/modal/cli/programs/run_jupyter.py +0 -0
  86. {modal-0.73.47 → modal-0.73.49}/modal/cli/programs/vscode.py +0 -0
  87. {modal-0.73.47 → modal-0.73.49}/modal/cli/queues.py +0 -0
  88. {modal-0.73.47 → modal-0.73.49}/modal/cli/run.py +0 -0
  89. {modal-0.73.47 → modal-0.73.49}/modal/cli/secret.py +0 -0
  90. {modal-0.73.47 → modal-0.73.49}/modal/cli/token.py +0 -0
  91. {modal-0.73.47 → modal-0.73.49}/modal/cli/utils.py +0 -0
  92. {modal-0.73.47 → modal-0.73.49}/modal/cli/volume.py +0 -0
  93. {modal-0.73.47 → modal-0.73.49}/modal/client.py +0 -0
  94. {modal-0.73.47 → modal-0.73.49}/modal/cloud_bucket_mount.py +0 -0
  95. {modal-0.73.47 → modal-0.73.49}/modal/cloud_bucket_mount.pyi +0 -0
  96. {modal-0.73.47 → modal-0.73.49}/modal/cls.py +0 -0
  97. {modal-0.73.47 → modal-0.73.49}/modal/cls.pyi +0 -0
  98. {modal-0.73.47 → modal-0.73.49}/modal/config.py +0 -0
  99. {modal-0.73.47 → modal-0.73.49}/modal/container_process.py +0 -0
  100. {modal-0.73.47 → modal-0.73.49}/modal/container_process.pyi +0 -0
  101. {modal-0.73.47 → modal-0.73.49}/modal/dict.py +0 -0
  102. {modal-0.73.47 → modal-0.73.49}/modal/dict.pyi +0 -0
  103. {modal-0.73.47 → modal-0.73.49}/modal/environments.py +0 -0
  104. {modal-0.73.47 → modal-0.73.49}/modal/environments.pyi +0 -0
  105. {modal-0.73.47 → modal-0.73.49}/modal/exception.py +0 -0
  106. {modal-0.73.47 → modal-0.73.49}/modal/experimental.py +0 -0
  107. {modal-0.73.47 → modal-0.73.49}/modal/experimental.pyi +0 -0
  108. {modal-0.73.47 → modal-0.73.49}/modal/extensions/__init__.py +0 -0
  109. {modal-0.73.47 → modal-0.73.49}/modal/extensions/ipython.py +0 -0
  110. {modal-0.73.47 → modal-0.73.49}/modal/file_io.py +0 -0
  111. {modal-0.73.47 → modal-0.73.49}/modal/file_io.pyi +0 -0
  112. {modal-0.73.47 → modal-0.73.49}/modal/file_pattern_matcher.py +0 -0
  113. {modal-0.73.47 → modal-0.73.49}/modal/functions.py +0 -0
  114. {modal-0.73.47 → modal-0.73.49}/modal/gpu.py +0 -0
  115. {modal-0.73.47 → modal-0.73.49}/modal/image.py +0 -0
  116. {modal-0.73.47 → modal-0.73.49}/modal/image.pyi +0 -0
  117. {modal-0.73.47 → modal-0.73.49}/modal/io_streams.py +0 -0
  118. {modal-0.73.47 → modal-0.73.49}/modal/io_streams.pyi +0 -0
  119. {modal-0.73.47 → modal-0.73.49}/modal/mount.py +0 -0
  120. {modal-0.73.47 → modal-0.73.49}/modal/mount.pyi +0 -0
  121. {modal-0.73.47 → modal-0.73.49}/modal/network_file_system.py +0 -0
  122. {modal-0.73.47 → modal-0.73.49}/modal/network_file_system.pyi +0 -0
  123. {modal-0.73.47 → modal-0.73.49}/modal/object.py +0 -0
  124. {modal-0.73.47 → modal-0.73.49}/modal/object.pyi +0 -0
  125. {modal-0.73.47 → modal-0.73.49}/modal/output.py +0 -0
  126. {modal-0.73.47 → modal-0.73.49}/modal/parallel_map.py +0 -0
  127. {modal-0.73.47 → modal-0.73.49}/modal/parallel_map.pyi +0 -0
  128. {modal-0.73.47 → modal-0.73.49}/modal/partial_function.py +0 -0
  129. {modal-0.73.47 → modal-0.73.49}/modal/partial_function.pyi +0 -0
  130. {modal-0.73.47 → modal-0.73.49}/modal/proxy.py +0 -0
  131. {modal-0.73.47 → modal-0.73.49}/modal/proxy.pyi +0 -0
  132. {modal-0.73.47 → modal-0.73.49}/modal/py.typed +0 -0
  133. {modal-0.73.47 → modal-0.73.49}/modal/queue.py +0 -0
  134. {modal-0.73.47 → modal-0.73.49}/modal/queue.pyi +0 -0
  135. {modal-0.73.47 → modal-0.73.49}/modal/requirements/2023.12.312.txt +0 -0
  136. {modal-0.73.47 → modal-0.73.49}/modal/requirements/2023.12.txt +0 -0
  137. {modal-0.73.47 → modal-0.73.49}/modal/requirements/2024.04.txt +0 -0
  138. {modal-0.73.47 → modal-0.73.49}/modal/requirements/2024.10.txt +0 -0
  139. {modal-0.73.47 → modal-0.73.49}/modal/requirements/README.md +0 -0
  140. {modal-0.73.47 → modal-0.73.49}/modal/requirements/base-images.json +0 -0
  141. {modal-0.73.47 → modal-0.73.49}/modal/retries.py +0 -0
  142. {modal-0.73.47 → modal-0.73.49}/modal/runner.py +0 -0
  143. {modal-0.73.47 → modal-0.73.49}/modal/runner.pyi +0 -0
  144. {modal-0.73.47 → modal-0.73.49}/modal/running_app.py +0 -0
  145. {modal-0.73.47 → modal-0.73.49}/modal/sandbox.py +0 -0
  146. {modal-0.73.47 → modal-0.73.49}/modal/sandbox.pyi +0 -0
  147. {modal-0.73.47 → modal-0.73.49}/modal/schedule.py +0 -0
  148. {modal-0.73.47 → modal-0.73.49}/modal/scheduler_placement.py +0 -0
  149. {modal-0.73.47 → modal-0.73.49}/modal/secret.py +0 -0
  150. {modal-0.73.47 → modal-0.73.49}/modal/secret.pyi +0 -0
  151. {modal-0.73.47 → modal-0.73.49}/modal/serving.py +0 -0
  152. {modal-0.73.47 → modal-0.73.49}/modal/serving.pyi +0 -0
  153. {modal-0.73.47 → modal-0.73.49}/modal/snapshot.py +0 -0
  154. {modal-0.73.47 → modal-0.73.49}/modal/snapshot.pyi +0 -0
  155. {modal-0.73.47 → modal-0.73.49}/modal/stream_type.py +0 -0
  156. {modal-0.73.47 → modal-0.73.49}/modal/token_flow.py +0 -0
  157. {modal-0.73.47 → modal-0.73.49}/modal/token_flow.pyi +0 -0
  158. {modal-0.73.47 → modal-0.73.49}/modal/volume.py +0 -0
  159. {modal-0.73.47 → modal-0.73.49}/modal/volume.pyi +0 -0
  160. {modal-0.73.47 → modal-0.73.49}/modal.egg-info/dependency_links.txt +0 -0
  161. {modal-0.73.47 → modal-0.73.49}/modal.egg-info/entry_points.txt +0 -0
  162. {modal-0.73.47 → modal-0.73.49}/modal.egg-info/requires.txt +0 -0
  163. {modal-0.73.47 → modal-0.73.49}/modal.egg-info/top_level.txt +0 -0
  164. {modal-0.73.47 → modal-0.73.49}/modal_docs/__init__.py +0 -0
  165. {modal-0.73.47 → modal-0.73.49}/modal_docs/gen_cli_docs.py +0 -0
  166. {modal-0.73.47 → modal-0.73.49}/modal_docs/gen_reference_docs.py +0 -0
  167. {modal-0.73.47 → modal-0.73.49}/modal_proto/__init__.py +0 -0
  168. {modal-0.73.47 → modal-0.73.49}/modal_proto/api_grpc.py +0 -0
  169. {modal-0.73.47 → modal-0.73.49}/modal_proto/api_pb2_grpc.py +0 -0
  170. {modal-0.73.47 → modal-0.73.49}/modal_proto/api_pb2_grpc.pyi +0 -0
  171. {modal-0.73.47 → modal-0.73.49}/modal_proto/modal_api_grpc.py +0 -0
  172. {modal-0.73.47 → modal-0.73.49}/modal_proto/modal_options_grpc.py +0 -0
  173. {modal-0.73.47 → modal-0.73.49}/modal_proto/options.proto +0 -0
  174. {modal-0.73.47 → modal-0.73.49}/modal_proto/options_grpc.py +0 -0
  175. {modal-0.73.47 → modal-0.73.49}/modal_proto/options_pb2.py +0 -0
  176. {modal-0.73.47 → modal-0.73.49}/modal_proto/options_pb2.pyi +0 -0
  177. {modal-0.73.47 → modal-0.73.49}/modal_proto/options_pb2_grpc.py +0 -0
  178. {modal-0.73.47 → modal-0.73.49}/modal_proto/options_pb2_grpc.pyi +0 -0
  179. {modal-0.73.47 → modal-0.73.49}/modal_proto/py.typed +0 -0
  180. {modal-0.73.47 → modal-0.73.49}/modal_version/__init__.py +0 -0
  181. {modal-0.73.47 → modal-0.73.49}/modal_version/__main__.py +0 -0
  182. {modal-0.73.47 → modal-0.73.49}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: modal
3
- Version: 0.73.47
3
+ Version: 0.73.49
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -862,6 +862,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
862
862
  warm_pool_size=function_definition.warm_pool_size,
863
863
  concurrency_limit=function_definition.concurrency_limit,
864
864
  task_idle_timeout_secs=function_definition.task_idle_timeout_secs,
865
+ autoscaler_settings=function_definition.autoscaler_settings,
865
866
  worker_id=function_definition.worker_id,
866
867
  timeout_secs=function_definition.timeout_secs,
867
868
  web_url=function_definition.web_url,
@@ -27,7 +27,7 @@ class _Client:
27
27
  _snapshotted: bool
28
28
 
29
29
  def __init__(
30
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.47"
30
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.49"
31
31
  ): ...
32
32
  def is_closed(self) -> bool: ...
33
33
  @property
@@ -85,7 +85,7 @@ class Client:
85
85
  _snapshotted: bool
86
86
 
87
87
  def __init__(
88
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.47"
88
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.49"
89
89
  ): ...
90
90
  def is_closed(self) -> bool: ...
91
91
  @property
@@ -200,11 +200,11 @@ class Function(
200
200
 
201
201
  _call_generator_nowait: ___call_generator_nowait_spec[typing_extensions.Self]
202
202
 
203
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
203
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
204
204
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
205
205
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
206
206
 
207
- remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
207
+ remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
208
208
 
209
209
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
210
210
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -219,19 +219,19 @@ class Function(
219
219
  self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
220
220
  ) -> modal._functions.OriginalReturnType: ...
221
221
 
222
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
222
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
223
223
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
224
224
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
225
225
 
226
226
  _experimental_spawn: ___experimental_spawn_spec[
227
- modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
227
+ modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
228
228
  ]
229
229
 
230
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
230
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
231
231
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
232
232
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
233
233
 
234
- spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
234
+ spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
235
235
 
236
236
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
237
237
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: modal
3
- Version: 0.73.47
3
+ Version: 0.73.49
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -156,6 +156,9 @@ modal/requirements/base-images.json
156
156
  modal_docs/__init__.py
157
157
  modal_docs/gen_cli_docs.py
158
158
  modal_docs/gen_reference_docs.py
159
+ modal_docs/mdmd/__init__.py
160
+ modal_docs/mdmd/mdmd.py
161
+ modal_docs/mdmd/signatures.py
159
162
  modal_proto/__init__.py
160
163
  modal_proto/api.proto
161
164
  modal_proto/api_grpc.py
@@ -0,0 +1 @@
1
+ # Copyright Modal Labs 2023
@@ -0,0 +1,195 @@
1
+ # Copyright Modal Labs 2023
2
+ """mdmd - MoDal MarkDown"""
3
+
4
+ import inspect
5
+ import warnings
6
+ from enum import Enum, EnumMeta
7
+ from types import ModuleType
8
+ from typing import Callable
9
+
10
+ import synchronicity.synchronizer
11
+
12
+ from .signatures import get_signature
13
+
14
+
15
+ def format_docstring(docstring: str):
16
+ if docstring is None:
17
+ docstring = ""
18
+ else:
19
+ docstring = inspect.cleandoc(docstring)
20
+
21
+ if docstring and not docstring.endswith("\n"):
22
+ docstring += "\n"
23
+
24
+ return docstring
25
+
26
+
27
+ def function_str(name: str, func):
28
+ signature = get_signature(name, func)
29
+ decl = f"""```python
30
+ {signature}
31
+ ```\n\n"""
32
+ docstring = format_docstring(func.__doc__)
33
+ return decl + docstring
34
+
35
+
36
+ def class_str(name, obj, title_level="##"):
37
+ def qual_name(cls):
38
+ if cls.__module__ == "builtins":
39
+ return cls.__name__
40
+ return f"{cls.__module__}.{cls.__name__}"
41
+
42
+ bases = [qual_name(b) for b in obj.__bases__]
43
+ bases_str = f"({', '.join(bases)})" if bases else ""
44
+ decl = f"""```python
45
+ class {name}{bases_str}
46
+ ```\n\n"""
47
+ parts = [decl]
48
+ docstring = format_docstring(obj.__doc__)
49
+
50
+ if isinstance(obj, EnumMeta) and not docstring:
51
+ # Python 3.11 removed the docstring from enums
52
+ docstring = "An enumeration.\n"
53
+
54
+ if docstring:
55
+ parts.append(docstring + "\n")
56
+
57
+ if isinstance(obj, EnumMeta):
58
+ enum_vals = "\n".join(f"* `{k}`" for k in obj.__members__.keys())
59
+ parts.append(f"The possible values are:\n\n{enum_vals}\n")
60
+
61
+ else:
62
+ init = inspect.unwrap(obj.__init__)
63
+
64
+ if (inspect.isfunction(init) or inspect.ismethod(init)) and not object_is_private("constructor", init):
65
+ parts.append(function_str("__init__", init))
66
+
67
+ member_title_level = title_level + "#"
68
+
69
+ entries = {}
70
+
71
+ def rec_update_attributes(cls):
72
+ # first bases, then class itself
73
+ for base_cls in cls.__bases__:
74
+ rec_update_attributes(base_cls)
75
+ entries.update(cls.__dict__)
76
+
77
+ rec_update_attributes(obj)
78
+
79
+ for member_name, member in entries.items():
80
+ if isinstance(member, classmethod) or isinstance(member, staticmethod):
81
+ # get the original function definition instead of the descriptor object
82
+ member = getattr(obj, member_name)
83
+ elif isinstance(member, property):
84
+ member = member.fget
85
+ elif isinstance(member, (synchronicity.synchronizer.FunctionWithAio, synchronicity.synchronizer.MethodWithAio)):
86
+ member = member._func
87
+
88
+ if object_is_private(member_name, member):
89
+ continue
90
+
91
+ if callable(member):
92
+ parts.append(f"{member_title_level} {member_name}\n\n")
93
+ parts.append(function_str(member_name, member))
94
+
95
+ return "".join(parts)
96
+
97
+
98
+ def module_str(header, module, title_level="#", filter_items: Callable[[ModuleType, str], bool] = None):
99
+ header = [f"{title_level} {header}\n\n"]
100
+ docstring = format_docstring(module.__doc__)
101
+ if docstring:
102
+ header.append(docstring + "\n")
103
+
104
+ object_docs = []
105
+ member_title_level = title_level + "#"
106
+ for qual_name, name, item in module_items(module, filter_items):
107
+ try:
108
+ if hasattr(item, "__wrapped__"):
109
+ item = item.__wrapped__
110
+ except KeyError:
111
+ pass
112
+ except:
113
+ print("failed on", qual_name, name, item)
114
+ raise
115
+ if inspect.isclass(item):
116
+ classdoc = class_str(name, item, title_level=member_title_level)
117
+ object_docs.append(f"{member_title_level} {qual_name}\n\n")
118
+ object_docs.append(classdoc)
119
+ elif callable(item):
120
+ funcdoc = function_str(name, item)
121
+ object_docs.append(f"{member_title_level} {qual_name}\n\n")
122
+ object_docs.append(funcdoc)
123
+ else:
124
+ item_doc = getattr(module, f"__doc__{name}", None)
125
+ if item_doc:
126
+ # variable documentation
127
+ object_docs.append(f"{member_title_level} {qual_name}\n\n")
128
+ object_docs.append(item_doc)
129
+ else:
130
+ warnings.warn(f"Not sure how to document: {name} ({item}")
131
+
132
+ if object_docs:
133
+ return "".join(header + object_docs)
134
+ return ""
135
+
136
+
137
+ def object_is_private(name, obj):
138
+ docstring = inspect.getdoc(obj)
139
+ if docstring is None:
140
+ docstring = ""
141
+ module = getattr(obj, "__module__", None) # obj is class
142
+ if not module:
143
+ cls = getattr(obj, "__class__", None) # obj is instance
144
+ if cls:
145
+ module = getattr(cls, "__module__", None)
146
+ if module == "builtins":
147
+ return True
148
+
149
+ if docstring.lstrip().startswith("mdmd:hidden") or name.startswith("_"):
150
+ return True
151
+
152
+ return False
153
+
154
+
155
+ def default_filter(module, item_name):
156
+ """Include non-private objects defined in the module itself"""
157
+ item = getattr(module, item_name)
158
+ if object_is_private(item_name, item) or inspect.ismodule(item):
159
+ return False
160
+ member_module = getattr(item, "__module__", type(item).__module__)
161
+ return member_module == module.__name__
162
+
163
+
164
+ def package_filter(module_prefix: str):
165
+ """Include non-private objects defined in any module with the prefix `module_prefix`"""
166
+
167
+ def return_filter(module, item_name):
168
+ item = getattr(module, item_name)
169
+ if object_is_private(item_name, item) or inspect.ismodule(item):
170
+ return False
171
+ member_module = getattr(item, "__module__", type(item).__module__)
172
+ return member_module.startswith(module_prefix)
173
+
174
+ return return_filter
175
+
176
+
177
+ def module_items(module, filter_items: Callable[[ModuleType, str], bool] = None):
178
+ """Returns filtered members of module"""
179
+ if filter_items is None:
180
+ # default filter is to only include classes and functions declared (or whose type is declared) in the file
181
+ filter_items = default_filter
182
+
183
+ for member_name, member in inspect.getmembers(module):
184
+ # only modal items
185
+ if not filter_items(module, member_name):
186
+ continue
187
+
188
+ qual_name = f"{module.__name__}.{member_name}"
189
+ yield qual_name, member_name, member
190
+
191
+
192
+ class Category(Enum):
193
+ FUNCTION = "function"
194
+ CLASS = "class"
195
+ MODULE = "module"
@@ -0,0 +1,76 @@
1
+ # Copyright Modal Labs 2023
2
+ import ast
3
+ import inspect
4
+ import re
5
+ import textwrap
6
+ import warnings
7
+
8
+ from synchronicity.synchronizer import FunctionWithAio
9
+
10
+
11
+ def _signature_from_ast(func) -> tuple[str, str]:
12
+ """Get function signature, including decorators and comments, from source code
13
+
14
+ Traverses functools.wraps-wrappings to get source of underlying function.
15
+
16
+ Has the advantage over inspect.signature that it can get decorators, default arguments and comments verbatim
17
+ from the function definition.
18
+ """
19
+ src = inspect.getsource(func)
20
+ src = textwrap.dedent(src)
21
+
22
+ def get_source_segment(src, fromline, fromcol, toline, tocol) -> str:
23
+ lines = src.split("\n")
24
+ lines = lines[fromline - 1 : toline]
25
+ lines[-1] = lines[-1][:tocol]
26
+ lines[0] = lines[0][fromcol:]
27
+ return "\n".join(lines)
28
+
29
+ tree = ast.parse(src)
30
+ func_def = list(ast.iter_child_nodes(tree))[0]
31
+ assert isinstance(func_def, (ast.FunctionDef, ast.AsyncFunctionDef))
32
+ decorator_starts = [(item.lineno, item.col_offset - 1) for item in func_def.decorator_list]
33
+ declaration_start = min([(func_def.lineno, func_def.col_offset)] + decorator_starts)
34
+ body_start = min((item.lineno, item.col_offset) for item in func_def.body)
35
+
36
+ return (
37
+ func_def.name,
38
+ get_source_segment(src, declaration_start[0], declaration_start[1], body_start[0], body_start[1] - 1).strip(),
39
+ )
40
+
41
+
42
+ def get_signature(name, callable) -> str:
43
+ """A problem with using *only* this method is that the wrapping method signature will not be respected.
44
+ TODO: use source parsing *only* to extract default arguments, comments (and possibly decorators) and "merge"
45
+ that definition with the outer-most definition."""
46
+
47
+ if not (inspect.isfunction(callable) or inspect.ismethod(callable) or isinstance(callable, FunctionWithAio)):
48
+ assert hasattr(callable, "__call__")
49
+ callable = callable.__call__
50
+
51
+ try:
52
+ original_name, definition_source = _signature_from_ast(callable)
53
+ except Exception:
54
+ warnings.warn(f"Could not get source signature for {name}. Using fallback.")
55
+ original_name = name
56
+ definition_source = f"def {name}{inspect.signature(callable)}"
57
+
58
+ if original_name != name:
59
+ # ugly name and definition replacement hack when needed
60
+ definition_source = definition_source.replace(f"def {original_name}", f"def {name}")
61
+
62
+ if (
63
+ "async def" in definition_source
64
+ and not inspect.iscoroutinefunction(callable)
65
+ and not inspect.isasyncgenfunction(callable)
66
+ ):
67
+ # hack to "reset" signature to a blocking one if the underlying source definition is async
68
+ # but the wrapper function isn't (like when synchronicity wraps an async function as a blocking one)
69
+ definition_source = definition_source.replace("async def", "def")
70
+ definition_source = definition_source.replace("asynccontextmanager", "contextmanager")
71
+ definition_source = definition_source.replace("AsyncIterator", "Iterator")
72
+
73
+ # remove any synchronicity-internal decorators
74
+ definition_source, _ = re.subn(r"^\s*@synchronizer\..*\n", "", definition_source)
75
+
76
+ return definition_source
@@ -1435,6 +1435,9 @@ message FunctionData {
1435
1435
  bool untrusted = 27; // If set, the function will be run in an untrusted environment.
1436
1436
  bool snapshot_debug = 28; // For internal debugging use only.
1437
1437
  bool runtime_perf_record = 29; // For internal debugging use only.
1438
+
1439
+ AutoscalerSettings autoscaler_settings = 31; // Bundle of parameters related to autoscaling
1440
+
1438
1441
  }
1439
1442
 
1440
1443
  message FunctionExtended {