fal 1.8.3__tar.gz → 1.9.0__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 fal might be problematic. Click here for more details.

Files changed (171) hide show
  1. {fal-1.8.3/fal.egg-info → fal-1.9.0}/PKG-INFO +2 -2
  2. {fal-1.8.3 → fal-1.9.0/fal.egg-info}/PKG-INFO +2 -2
  3. {fal-1.8.3 → fal-1.9.0}/fal.egg-info/requires.txt +1 -1
  4. {fal-1.8.3 → fal-1.9.0}/pyproject.toml +1 -1
  5. {fal-1.8.3 → fal-1.9.0}/src/fal/_fal_version.py +2 -2
  6. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/apps.py +27 -0
  7. {fal-1.8.3 → fal-1.9.0}/src/fal/sdk.py +7 -0
  8. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/file/file.py +13 -7
  9. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/file/providers/fal.py +27 -4
  10. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/file/providers/gcp.py +4 -0
  11. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/file/providers/r2.py +4 -0
  12. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/file/providers/s3.py +4 -0
  13. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/file/types.py +12 -1
  14. {fal-1.8.3 → fal-1.9.0}/tests/test_stability.py +7 -0
  15. {fal-1.8.3 → fal-1.9.0}/.gitignore +0 -0
  16. {fal-1.8.3 → fal-1.9.0}/Makefile +0 -0
  17. {fal-1.8.3 → fal-1.9.0}/README.md +0 -0
  18. {fal-1.8.3 → fal-1.9.0}/docs/conf.py +0 -0
  19. {fal-1.8.3 → fal-1.9.0}/docs/index.rst +0 -0
  20. {fal-1.8.3 → fal-1.9.0}/fal.egg-info/SOURCES.txt +0 -0
  21. {fal-1.8.3 → fal-1.9.0}/fal.egg-info/dependency_links.txt +0 -0
  22. {fal-1.8.3 → fal-1.9.0}/fal.egg-info/entry_points.txt +0 -0
  23. {fal-1.8.3 → fal-1.9.0}/fal.egg-info/top_level.txt +0 -0
  24. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/README.md +0 -0
  25. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
  26. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
  27. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
  28. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
  29. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
  30. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
  31. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
  32. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
  33. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
  34. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
  35. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
  36. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
  37. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
  38. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
  39. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
  40. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
  41. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
  42. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
  43. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
  44. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
  45. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
  46. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
  47. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
  48. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
  49. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
  50. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
  51. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
  52. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
  53. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
  54. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
  55. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
  56. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
  57. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
  58. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
  59. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
  60. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
  61. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
  62. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
  63. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
  64. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
  65. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
  66. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
  67. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
  68. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
  69. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
  70. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
  71. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
  72. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
  73. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
  74. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
  75. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
  76. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
  77. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
  78. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
  79. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
  80. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
  81. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
  82. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
  83. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
  84. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
  85. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
  86. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
  87. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
  88. {fal-1.8.3 → fal-1.9.0}/openapi-fal-rest/pyproject.toml +0 -0
  89. {fal-1.8.3 → fal-1.9.0}/openapi_rest.config.yaml +0 -0
  90. {fal-1.8.3 → fal-1.9.0}/setup.cfg +0 -0
  91. {fal-1.8.3 → fal-1.9.0}/src/fal/__init__.py +0 -0
  92. {fal-1.8.3 → fal-1.9.0}/src/fal/__main__.py +0 -0
  93. {fal-1.8.3 → fal-1.9.0}/src/fal/_serialization.py +0 -0
  94. {fal-1.8.3 → fal-1.9.0}/src/fal/_version.py +0 -0
  95. {fal-1.8.3 → fal-1.9.0}/src/fal/api.py +0 -0
  96. {fal-1.8.3 → fal-1.9.0}/src/fal/app.py +0 -0
  97. {fal-1.8.3 → fal-1.9.0}/src/fal/apps.py +0 -0
  98. {fal-1.8.3 → fal-1.9.0}/src/fal/auth/__init__.py +0 -0
  99. {fal-1.8.3 → fal-1.9.0}/src/fal/auth/auth0.py +0 -0
  100. {fal-1.8.3 → fal-1.9.0}/src/fal/auth/local.py +0 -0
  101. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/__init__.py +0 -0
  102. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/_utils.py +0 -0
  103. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/auth.py +0 -0
  104. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/create.py +0 -0
  105. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/debug.py +0 -0
  106. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/deploy.py +0 -0
  107. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/doctor.py +0 -0
  108. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/keys.py +0 -0
  109. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/main.py +0 -0
  110. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/parser.py +0 -0
  111. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/run.py +0 -0
  112. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/runners.py +0 -0
  113. {fal-1.8.3 → fal-1.9.0}/src/fal/cli/secrets.py +0 -0
  114. {fal-1.8.3 → fal-1.9.0}/src/fal/config.py +0 -0
  115. {fal-1.8.3 → fal-1.9.0}/src/fal/console/__init__.py +0 -0
  116. {fal-1.8.3 → fal-1.9.0}/src/fal/console/icons.py +0 -0
  117. {fal-1.8.3 → fal-1.9.0}/src/fal/console/ux.py +0 -0
  118. {fal-1.8.3 → fal-1.9.0}/src/fal/container.py +0 -0
  119. {fal-1.8.3 → fal-1.9.0}/src/fal/exceptions/__init__.py +0 -0
  120. {fal-1.8.3 → fal-1.9.0}/src/fal/exceptions/_base.py +0 -0
  121. {fal-1.8.3 → fal-1.9.0}/src/fal/exceptions/_cuda.py +0 -0
  122. {fal-1.8.3 → fal-1.9.0}/src/fal/exceptions/auth.py +0 -0
  123. {fal-1.8.3 → fal-1.9.0}/src/fal/files.py +0 -0
  124. {fal-1.8.3 → fal-1.9.0}/src/fal/flags.py +0 -0
  125. {fal-1.8.3 → fal-1.9.0}/src/fal/logging/__init__.py +0 -0
  126. {fal-1.8.3 → fal-1.9.0}/src/fal/logging/isolate.py +0 -0
  127. {fal-1.8.3 → fal-1.9.0}/src/fal/logging/style.py +0 -0
  128. {fal-1.8.3 → fal-1.9.0}/src/fal/logging/trace.py +0 -0
  129. {fal-1.8.3 → fal-1.9.0}/src/fal/logging/user.py +0 -0
  130. {fal-1.8.3 → fal-1.9.0}/src/fal/py.typed +0 -0
  131. {fal-1.8.3 → fal-1.9.0}/src/fal/rest_client.py +0 -0
  132. {fal-1.8.3 → fal-1.9.0}/src/fal/sync.py +0 -0
  133. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/__init__.py +0 -0
  134. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/exceptions.py +0 -0
  135. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/file/__init__.py +0 -0
  136. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/image/__init__.py +0 -0
  137. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/image/image.py +0 -0
  138. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
  139. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
  140. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
  141. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
  142. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
  143. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/image/safety_checker.py +0 -0
  144. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/optimize.py +0 -0
  145. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/types.py +0 -0
  146. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/utils/__init__.py +0 -0
  147. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/utils/download_utils.py +0 -0
  148. {fal-1.8.3 → fal-1.9.0}/src/fal/toolkit/utils/retry.py +0 -0
  149. {fal-1.8.3 → fal-1.9.0}/src/fal/utils.py +0 -0
  150. {fal-1.8.3 → fal-1.9.0}/src/fal/workflows.py +0 -0
  151. {fal-1.8.3 → fal-1.9.0}/tests/__init__.py +0 -0
  152. {fal-1.8.3 → fal-1.9.0}/tests/assets/cat.png +0 -0
  153. {fal-1.8.3 → fal-1.9.0}/tests/cli/__init__.py +0 -0
  154. {fal-1.8.3 → fal-1.9.0}/tests/cli/test_apps.py +0 -0
  155. {fal-1.8.3 → fal-1.9.0}/tests/cli/test_auth.py +0 -0
  156. {fal-1.8.3 → fal-1.9.0}/tests/cli/test_deploy.py +0 -0
  157. {fal-1.8.3 → fal-1.9.0}/tests/cli/test_keys.py +0 -0
  158. {fal-1.8.3 → fal-1.9.0}/tests/cli/test_run.py +0 -0
  159. {fal-1.8.3 → fal-1.9.0}/tests/cli/test_secrets.py +0 -0
  160. {fal-1.8.3 → fal-1.9.0}/tests/conftest.py +0 -0
  161. {fal-1.8.3 → fal-1.9.0}/tests/integration_test.py +0 -0
  162. {fal-1.8.3 → fal-1.9.0}/tests/mainify_package/__init__.py +0 -0
  163. {fal-1.8.3 → fal-1.9.0}/tests/mainify_package/impl.py +0 -0
  164. {fal-1.8.3 → fal-1.9.0}/tests/mainify_package/utils.py +0 -0
  165. {fal-1.8.3 → fal-1.9.0}/tests/mainify_target.py +0 -0
  166. {fal-1.8.3 → fal-1.9.0}/tests/test_apps.py +0 -0
  167. {fal-1.8.3 → fal-1.9.0}/tests/toolkit/file_test.py +0 -0
  168. {fal-1.8.3 → fal-1.9.0}/tests/toolkit/image_test.py +0 -0
  169. {fal-1.8.3 → fal-1.9.0}/tests/toolkit/test_types.py +0 -0
  170. {fal-1.8.3 → fal-1.9.0}/tests/toolkit/utils/retry.py +0 -0
  171. {fal-1.8.3 → fal-1.9.0}/tools/demo_script.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fal
3
- Version: 1.8.3
3
+ Version: 1.9.0
4
4
  Summary: fal is an easy-to-use Serverless Python Framework
5
5
  Author: Features & Labels <support@fal.ai>
6
6
  Requires-Python: >=3.8
@@ -39,7 +39,7 @@ Requires-Dist: uvicorn<1,>=0.29.0
39
39
  Requires-Dist: cookiecutter
40
40
  Requires-Dist: tomli
41
41
  Provides-Extra: docs
42
- Requires-Dist: sphinx; extra == "docs"
42
+ Requires-Dist: sphinx<8.2.0; extra == "docs"
43
43
  Requires-Dist: sphinx-rtd-theme; extra == "docs"
44
44
  Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
45
45
  Provides-Extra: test
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fal
3
- Version: 1.8.3
3
+ Version: 1.9.0
4
4
  Summary: fal is an easy-to-use Serverless Python Framework
5
5
  Author: Features & Labels <support@fal.ai>
6
6
  Requires-Python: >=3.8
@@ -39,7 +39,7 @@ Requires-Dist: uvicorn<1,>=0.29.0
39
39
  Requires-Dist: cookiecutter
40
40
  Requires-Dist: tomli
41
41
  Provides-Extra: docs
42
- Requires-Dist: sphinx; extra == "docs"
42
+ Requires-Dist: sphinx<8.2.0; extra == "docs"
43
43
  Requires-Dist: sphinx-rtd-theme; extra == "docs"
44
44
  Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
45
45
  Provides-Extra: test
@@ -39,7 +39,7 @@ fal[docs,test]
39
39
  openapi-python-client<1,>=0.14.1
40
40
 
41
41
  [docs]
42
- sphinx
42
+ sphinx<8.2.0
43
43
  sphinx-rtd-theme
44
44
  sphinx-autodoc-typehints
45
45
 
@@ -62,7 +62,7 @@ dependencies = [
62
62
 
63
63
  [project.optional-dependencies]
64
64
  docs = [
65
- "sphinx",
65
+ "sphinx<8.2.0",
66
66
  "sphinx-rtd-theme",
67
67
  "sphinx-autodoc-typehints",
68
68
  ]
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.8.3'
16
- __version_tuple__ = version_tuple = (1, 8, 3)
15
+ __version__ = version = '1.9.0'
16
+ __version_tuple__ = version_tuple = (1, 9, 0)
@@ -128,6 +128,7 @@ def _scale(args):
128
128
  and args.min_concurrency is None
129
129
  and args.request_timeout is None
130
130
  and args.startup_timeout is None
131
+ and args.machine_types is None
131
132
  ):
132
133
  args.console.log("No parameters for update were provided, ignoring.")
133
134
  return
@@ -140,6 +141,7 @@ def _scale(args):
140
141
  min_concurrency=args.min_concurrency,
141
142
  request_timeout=args.request_timeout,
142
143
  startup_timeout=args.startup_timeout,
144
+ machine_types=args.machine_types,
143
145
  )
144
146
  table = _apps_table([alias_info])
145
147
 
@@ -188,6 +190,13 @@ def _add_scale_parser(subparsers, parents):
188
190
  type=int,
189
191
  help="Startup timeout (seconds).",
190
192
  )
193
+ parser.add_argument(
194
+ "--machine-type",
195
+ type=str,
196
+ action="append",
197
+ dest="machine_types",
198
+ help="Machine type.",
199
+ )
191
200
  parser.set_defaults(func=_scale)
192
201
 
193
202
 
@@ -255,6 +264,24 @@ def _runners(args):
255
264
 
256
265
  args.console.print(table)
257
266
 
267
+ requests_table = Table()
268
+ requests_table.add_column("Runner ID")
269
+ requests_table.add_column("Request ID")
270
+ requests_table.add_column("Caller ID")
271
+
272
+ for runner in runners:
273
+ for lease in runner.external_metadata.get("leases", []):
274
+ if not (req_id := lease.get("request_id")):
275
+ continue
276
+
277
+ requests_table.add_row(
278
+ runner.runner_id,
279
+ req_id,
280
+ lease.get("caller_user_id") or "",
281
+ )
282
+
283
+ args.console.print(requests_table)
284
+
258
285
 
259
286
  def _add_runners_parser(subparsers, parents):
260
287
  runners_help = "List application runners."
@@ -11,6 +11,7 @@ import grpc
11
11
  import isolate_proto
12
12
  from isolate.connections.common import is_agent
13
13
  from isolate.logs import Log
14
+ from isolate.server import definitions as worker_definitions
14
15
  from isolate.server.interface import from_grpc, to_serialized_object, to_struct
15
16
  from isolate_proto.configuration import GRPC_OPTIONS
16
17
 
@@ -222,6 +223,7 @@ class RunnerInfo:
222
223
  in_flight_requests: int
223
224
  expiration_countdown: Optional[int]
224
225
  uptime: timedelta
226
+ external_metadata: dict[str, Any]
225
227
 
226
228
 
227
229
  @dataclass
@@ -353,6 +355,7 @@ def _from_grpc_alias_info(message: isolate_proto.AliasInfo) -> AliasInfo:
353
355
 
354
356
  @from_grpc.register(isolate_proto.RunnerInfo)
355
357
  def _from_grpc_runner_info(message: isolate_proto.RunnerInfo) -> RunnerInfo:
358
+ external_metadata = worker_definitions.struct_to_dict(message.external_metadata)
356
359
  return RunnerInfo(
357
360
  runner_id=message.runner_id,
358
361
  in_flight_requests=message.in_flight_requests,
@@ -360,6 +363,7 @@ def _from_grpc_runner_info(message: isolate_proto.RunnerInfo) -> RunnerInfo:
360
363
  if message.HasField("expiration_countdown")
361
364
  else None,
362
365
  uptime=timedelta(seconds=message.uptime),
366
+ external_metadata=external_metadata,
363
367
  )
364
368
 
365
369
 
@@ -578,7 +582,9 @@ class FalServerlessConnection:
578
582
  min_concurrency: int | None = None,
579
583
  request_timeout: int | None = None,
580
584
  startup_timeout: int | None = None,
585
+ machine_types: list[str] | None = None,
581
586
  ) -> AliasInfo:
587
+ print(machine_types)
582
588
  request = isolate_proto.UpdateApplicationRequest(
583
589
  application_name=application_name,
584
590
  keep_alive=keep_alive,
@@ -587,6 +593,7 @@ class FalServerlessConnection:
587
593
  min_concurrency=min_concurrency,
588
594
  request_timeout=request_timeout,
589
595
  startup_timeout=startup_timeout,
596
+ machine_types=machine_types,
590
597
  )
591
598
  res: isolate_proto.UpdateApplicationResult = self.stub.UpdateApplication(
592
599
  request
@@ -156,6 +156,9 @@ class File(BaseModel):
156
156
  save_kwargs.setdefault(
157
157
  "object_lifecycle_preference", object_lifecycle_preference
158
158
  )
159
+ fallback_save_kwargs.setdefault(
160
+ "object_lifecycle_preference", object_lifecycle_preference
161
+ )
159
162
 
160
163
  try:
161
164
  url = repo.save(fdata, **save_kwargs)
@@ -165,9 +168,7 @@ class File(BaseModel):
165
168
 
166
169
  fallback_repo = get_builtin_repository(fallback_repository)
167
170
 
168
- url = fallback_repo.save(
169
- fdata, object_lifecycle_preference, **fallback_save_kwargs
170
- )
171
+ url = fallback_repo.save(fdata, **fallback_save_kwargs)
171
172
 
172
173
  return cls(
173
174
  url=url,
@@ -204,13 +205,20 @@ class File(BaseModel):
204
205
  object_lifecycle_preference = (
205
206
  request_lifecycle_preference(request) or LIFECYCLE_PREFERENCE.get()
206
207
  )
208
+ save_kwargs.setdefault(
209
+ "object_lifecycle_preference", object_lifecycle_preference
210
+ )
211
+ fallback_save_kwargs.setdefault(
212
+ "object_lifecycle_preference", object_lifecycle_preference
213
+ )
214
+
215
+ save_kwargs.setdefault("multipart", multipart)
216
+ fallback_save_kwargs.setdefault("multipart", multipart)
207
217
 
208
218
  try:
209
219
  url, data = repo.save_file(
210
220
  file_path,
211
221
  content_type=content_type,
212
- multipart=multipart,
213
- object_lifecycle_preference=object_lifecycle_preference,
214
222
  **save_kwargs,
215
223
  )
216
224
  except Exception:
@@ -222,8 +230,6 @@ class File(BaseModel):
222
230
  url, data = fallback_repo.save_file(
223
231
  file_path,
224
232
  content_type=content_type,
225
- multipart=multipart,
226
- object_lifecycle_preference=object_lifecycle_preference,
227
233
  **fallback_save_kwargs,
228
234
  )
229
235
 
@@ -185,7 +185,13 @@ class FalFileRepositoryBase(FileRepository):
185
185
  @dataclass
186
186
  class FalFileRepository(FalFileRepositoryBase):
187
187
  def save(
188
- self, file: FileData, object_lifecycle_preference: dict[str, str] | None = None
188
+ self,
189
+ file: FileData,
190
+ multipart: bool | None = None,
191
+ multipart_threshold: int | None = None,
192
+ multipart_chunk_size: int | None = None,
193
+ multipart_max_concurrency: int | None = None,
194
+ object_lifecycle_preference: dict[str, str] | None = None,
189
195
  ) -> str:
190
196
  return self._save(file, "gcs")
191
197
 
@@ -834,7 +840,10 @@ class FalFileRepositoryV2(FalFileRepositoryBase):
834
840
  content_type=content_type,
835
841
  file_name=os.path.basename(file_path),
836
842
  )
837
- url = self.save(data, object_lifecycle_preference)
843
+ url = self.save(
844
+ data,
845
+ object_lifecycle_preference=object_lifecycle_preference,
846
+ )
838
847
 
839
848
  return url, data
840
849
 
@@ -844,6 +853,10 @@ class InMemoryRepository(FileRepository):
844
853
  def save(
845
854
  self,
846
855
  file: FileData,
856
+ multipart: bool | None = None,
857
+ multipart_threshold: int | None = None,
858
+ multipart_chunk_size: int | None = None,
859
+ multipart_max_concurrency: int | None = None,
847
860
  object_lifecycle_preference: dict[str, str] | None = None,
848
861
  ) -> str:
849
862
  return f'data:{file.content_type};base64,{b64encode(file.data).decode("utf-8")}'
@@ -865,6 +878,10 @@ class FalCDNFileRepository(FileRepository):
865
878
  def save(
866
879
  self,
867
880
  file: FileData,
881
+ multipart: bool | None = None,
882
+ multipart_threshold: int | None = None,
883
+ multipart_chunk_size: int | None = None,
884
+ multipart_max_concurrency: int | None = None,
868
885
  object_lifecycle_preference: dict[str, str] | None = None,
869
886
  ) -> str:
870
887
  headers = {
@@ -1013,7 +1030,10 @@ class FalFileRepositoryV3(FileRepository):
1013
1030
  content_type=content_type,
1014
1031
  file_name=os.path.basename(file_path),
1015
1032
  )
1016
- url = self.save(data, object_lifecycle_preference)
1033
+ url = self.save(
1034
+ data,
1035
+ object_lifecycle_preference=object_lifecycle_preference,
1036
+ )
1017
1037
 
1018
1038
  return url, data
1019
1039
 
@@ -1119,6 +1139,9 @@ class InternalFalFileRepositoryV3(FileRepository):
1119
1139
  content_type=content_type,
1120
1140
  file_name=os.path.basename(file_path),
1121
1141
  )
1122
- url = self.save(data, object_lifecycle_preference)
1142
+ url = self.save(
1143
+ data,
1144
+ object_lifecycle_preference=object_lifecycle_preference,
1145
+ )
1123
1146
 
1124
1147
  return url, data
@@ -56,6 +56,10 @@ class GoogleStorageRepository(FileRepository):
56
56
  def save(
57
57
  self,
58
58
  data: FileData,
59
+ multipart: bool | None = None,
60
+ multipart_threshold: int | None = None,
61
+ multipart_chunk_size: int | None = None,
62
+ multipart_max_concurrency: int | None = None,
59
63
  object_lifecycle_preference: Optional[dict[str, str]] = None,
60
64
  ) -> str:
61
65
  destination_path = posixpath.join(
@@ -73,6 +73,10 @@ class R2Repository(FileRepository):
73
73
  def save(
74
74
  self,
75
75
  data: FileData,
76
+ multipart: bool | None = None,
77
+ multipart_threshold: int | None = None,
78
+ multipart_chunk_size: int | None = None,
79
+ multipart_max_concurrency: int | None = None,
76
80
  object_lifecycle_preference: Optional[dict[str, str]] = None,
77
81
  ) -> str:
78
82
  destination_path = posixpath.join(
@@ -57,6 +57,10 @@ class S3Repository(FileRepository):
57
57
  def save(
58
58
  self,
59
59
  data: FileData,
60
+ multipart: bool | None = None,
61
+ multipart_threshold: int | None = None,
62
+ multipart_chunk_size: int | None = None,
63
+ multipart_max_concurrency: int | None = None,
60
64
  object_lifecycle_preference: Optional[dict[str, str]] = None,
61
65
  key: Optional[str] = None,
62
66
  ) -> str:
@@ -39,6 +39,10 @@ class FileRepository:
39
39
  def save(
40
40
  self,
41
41
  data: FileData,
42
+ multipart: bool | None = None,
43
+ multipart_threshold: int | None = None,
44
+ multipart_chunk_size: int | None = None,
45
+ multipart_max_concurrency: int | None = None,
42
46
  object_lifecycle_preference: Optional[dict[str, str]] = None,
43
47
  ) -> str:
44
48
  raise NotImplementedError()
@@ -59,4 +63,11 @@ class FileRepository:
59
63
  with open(file_path, "rb") as fobj:
60
64
  data = FileData(fobj.read(), content_type, Path(file_path).name)
61
65
 
62
- return self.save(data, object_lifecycle_preference), data
66
+ return self.save(
67
+ data,
68
+ multipart=multipart,
69
+ multipart_threshold=multipart_threshold,
70
+ multipart_chunk_size=multipart_chunk_size,
71
+ multipart_max_concurrency=multipart_max_concurrency,
72
+ object_lifecycle_preference=object_lifecycle_preference,
73
+ ), data
@@ -603,6 +603,13 @@ def test_fal_storage(isolated_client, repo_type, url_prefix):
603
603
  return File.from_bytes(
604
604
  b"Hello fal storage from isolated",
605
605
  repository=repo_type,
606
+ save_kwargs={
607
+ "multipart": False,
608
+ "multipart_threshold": 1024 * 1024,
609
+ "multipart_chunk_size": 1024 * 1024,
610
+ "multipart_max_concurrency": 10,
611
+ "object_lifecycle_preference": {},
612
+ },
606
613
  fallback_repository=None,
607
614
  )
608
615
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes