fal 1.4.1__tar.gz → 1.5.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 (162) hide show
  1. {fal-1.4.1 → fal-1.5.0}/PKG-INFO +2 -2
  2. {fal-1.4.1 → fal-1.5.0}/fal.egg-info/PKG-INFO +2 -2
  3. {fal-1.4.1 → fal-1.5.0}/fal.egg-info/requires.txt +1 -1
  4. {fal-1.4.1 → fal-1.5.0}/pyproject.toml +1 -1
  5. {fal-1.4.1 → fal-1.5.0}/src/fal/_fal_version.py +2 -2
  6. {fal-1.4.1 → fal-1.5.0}/src/fal/api.py +11 -0
  7. {fal-1.4.1 → fal-1.5.0}/src/fal/app.py +7 -1
  8. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/_utils.py +2 -1
  9. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/deploy.py +13 -5
  10. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/run.py +1 -1
  11. {fal-1.4.1 → fal-1.5.0}/src/fal/sdk.py +3 -0
  12. {fal-1.4.1 → fal-1.5.0}/tests/cli/test_deploy.py +98 -4
  13. {fal-1.4.1 → fal-1.5.0}/.gitignore +0 -0
  14. {fal-1.4.1 → fal-1.5.0}/README.md +0 -0
  15. {fal-1.4.1 → fal-1.5.0}/fal.egg-info/SOURCES.txt +0 -0
  16. {fal-1.4.1 → fal-1.5.0}/fal.egg-info/dependency_links.txt +0 -0
  17. {fal-1.4.1 → fal-1.5.0}/fal.egg-info/entry_points.txt +0 -0
  18. {fal-1.4.1 → fal-1.5.0}/fal.egg-info/top_level.txt +0 -0
  19. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/README.md +0 -0
  20. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
  21. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
  22. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
  23. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
  24. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
  25. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
  26. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
  27. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
  28. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
  29. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
  30. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
  31. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
  32. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
  33. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
  34. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
  35. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
  36. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
  37. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
  38. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
  39. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
  40. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
  41. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
  42. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
  43. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
  44. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
  45. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
  46. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
  47. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
  48. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
  49. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
  50. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
  51. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
  52. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
  53. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
  54. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
  55. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
  56. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
  57. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
  58. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
  59. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
  60. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
  61. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
  62. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
  63. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
  64. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
  65. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
  66. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
  67. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
  68. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
  69. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
  70. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
  71. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
  72. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
  73. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
  74. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
  75. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
  76. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
  77. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
  78. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
  79. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
  80. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
  81. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
  82. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
  83. {fal-1.4.1 → fal-1.5.0}/openapi-fal-rest/pyproject.toml +0 -0
  84. {fal-1.4.1 → fal-1.5.0}/openapi_rest.config.yaml +0 -0
  85. {fal-1.4.1 → fal-1.5.0}/setup.cfg +0 -0
  86. {fal-1.4.1 → fal-1.5.0}/src/fal/__init__.py +0 -0
  87. {fal-1.4.1 → fal-1.5.0}/src/fal/__main__.py +0 -0
  88. {fal-1.4.1 → fal-1.5.0}/src/fal/_serialization.py +0 -0
  89. {fal-1.4.1 → fal-1.5.0}/src/fal/_version.py +0 -0
  90. {fal-1.4.1 → fal-1.5.0}/src/fal/apps.py +0 -0
  91. {fal-1.4.1 → fal-1.5.0}/src/fal/auth/__init__.py +0 -0
  92. {fal-1.4.1 → fal-1.5.0}/src/fal/auth/auth0.py +0 -0
  93. {fal-1.4.1 → fal-1.5.0}/src/fal/auth/local.py +0 -0
  94. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/__init__.py +0 -0
  95. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/apps.py +0 -0
  96. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/auth.py +0 -0
  97. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/create.py +0 -0
  98. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/debug.py +0 -0
  99. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/doctor.py +0 -0
  100. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/keys.py +0 -0
  101. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/main.py +0 -0
  102. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/parser.py +0 -0
  103. {fal-1.4.1 → fal-1.5.0}/src/fal/cli/secrets.py +0 -0
  104. {fal-1.4.1 → fal-1.5.0}/src/fal/console/__init__.py +0 -0
  105. {fal-1.4.1 → fal-1.5.0}/src/fal/console/icons.py +0 -0
  106. {fal-1.4.1 → fal-1.5.0}/src/fal/console/ux.py +0 -0
  107. {fal-1.4.1 → fal-1.5.0}/src/fal/container.py +0 -0
  108. {fal-1.4.1 → fal-1.5.0}/src/fal/exceptions/__init__.py +0 -0
  109. {fal-1.4.1 → fal-1.5.0}/src/fal/exceptions/_base.py +0 -0
  110. {fal-1.4.1 → fal-1.5.0}/src/fal/exceptions/_cuda.py +0 -0
  111. {fal-1.4.1 → fal-1.5.0}/src/fal/exceptions/auth.py +0 -0
  112. {fal-1.4.1 → fal-1.5.0}/src/fal/files.py +0 -0
  113. {fal-1.4.1 → fal-1.5.0}/src/fal/flags.py +0 -0
  114. {fal-1.4.1 → fal-1.5.0}/src/fal/logging/__init__.py +0 -0
  115. {fal-1.4.1 → fal-1.5.0}/src/fal/logging/isolate.py +0 -0
  116. {fal-1.4.1 → fal-1.5.0}/src/fal/logging/style.py +0 -0
  117. {fal-1.4.1 → fal-1.5.0}/src/fal/logging/trace.py +0 -0
  118. {fal-1.4.1 → fal-1.5.0}/src/fal/logging/user.py +0 -0
  119. {fal-1.4.1 → fal-1.5.0}/src/fal/py.typed +0 -0
  120. {fal-1.4.1 → fal-1.5.0}/src/fal/rest_client.py +0 -0
  121. {fal-1.4.1 → fal-1.5.0}/src/fal/sync.py +0 -0
  122. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/__init__.py +0 -0
  123. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/exceptions.py +0 -0
  124. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/file/__init__.py +0 -0
  125. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/file/file.py +0 -0
  126. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/file/providers/fal.py +0 -0
  127. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/file/providers/gcp.py +0 -0
  128. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/file/providers/r2.py +0 -0
  129. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/file/types.py +0 -0
  130. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/image/__init__.py +0 -0
  131. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/image/image.py +0 -0
  132. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
  133. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
  134. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
  135. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
  136. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
  137. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/image/safety_checker.py +0 -0
  138. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/optimize.py +0 -0
  139. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/utils/__init__.py +0 -0
  140. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/utils/download_utils.py +0 -0
  141. {fal-1.4.1 → fal-1.5.0}/src/fal/toolkit/utils/retry.py +0 -0
  142. {fal-1.4.1 → fal-1.5.0}/src/fal/utils.py +0 -0
  143. {fal-1.4.1 → fal-1.5.0}/src/fal/workflows.py +0 -0
  144. {fal-1.4.1 → fal-1.5.0}/tests/__init__.py +0 -0
  145. {fal-1.4.1 → fal-1.5.0}/tests/cli/__init__.py +0 -0
  146. {fal-1.4.1 → fal-1.5.0}/tests/cli/test_apps.py +0 -0
  147. {fal-1.4.1 → fal-1.5.0}/tests/cli/test_auth.py +0 -0
  148. {fal-1.4.1 → fal-1.5.0}/tests/cli/test_keys.py +0 -0
  149. {fal-1.4.1 → fal-1.5.0}/tests/cli/test_run.py +0 -0
  150. {fal-1.4.1 → fal-1.5.0}/tests/cli/test_secrets.py +0 -0
  151. {fal-1.4.1 → fal-1.5.0}/tests/conftest.py +0 -0
  152. {fal-1.4.1 → fal-1.5.0}/tests/integration_test.py +0 -0
  153. {fal-1.4.1 → fal-1.5.0}/tests/mainify_package/__init__.py +0 -0
  154. {fal-1.4.1 → fal-1.5.0}/tests/mainify_package/impl.py +0 -0
  155. {fal-1.4.1 → fal-1.5.0}/tests/mainify_package/utils.py +0 -0
  156. {fal-1.4.1 → fal-1.5.0}/tests/mainify_target.py +0 -0
  157. {fal-1.4.1 → fal-1.5.0}/tests/test_apps.py +0 -0
  158. {fal-1.4.1 → fal-1.5.0}/tests/test_stability.py +0 -0
  159. {fal-1.4.1 → fal-1.5.0}/tests/toolkit/file_test.py +0 -0
  160. {fal-1.4.1 → fal-1.5.0}/tests/toolkit/image_test.py +0 -0
  161. {fal-1.4.1 → fal-1.5.0}/tests/toolkit/utils/retry.py +0 -0
  162. {fal-1.4.1 → fal-1.5.0}/tools/demo_script.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fal
3
- Version: 1.4.1
3
+ Version: 1.5.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
7
7
  Description-Content-Type: text/markdown
8
8
  Requires-Dist: isolate[build]<1.14.0,>=0.13.0
9
- Requires-Dist: isolate-proto==0.5.3
9
+ Requires-Dist: isolate-proto==0.5.4
10
10
  Requires-Dist: grpcio==1.64.0
11
11
  Requires-Dist: dill==0.3.7
12
12
  Requires-Dist: cloudpickle==3.0.0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fal
3
- Version: 1.4.1
3
+ Version: 1.5.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
7
7
  Description-Content-Type: text/markdown
8
8
  Requires-Dist: isolate[build]<1.14.0,>=0.13.0
9
- Requires-Dist: isolate-proto==0.5.3
9
+ Requires-Dist: isolate-proto==0.5.4
10
10
  Requires-Dist: grpcio==1.64.0
11
11
  Requires-Dist: dill==0.3.7
12
12
  Requires-Dist: cloudpickle==3.0.0
@@ -1,5 +1,5 @@
1
1
  isolate[build]<1.14.0,>=0.13.0
2
- isolate-proto==0.5.3
2
+ isolate-proto==0.5.4
3
3
  grpcio==1.64.0
4
4
  dill==0.3.7
5
5
  cloudpickle==3.0.0
@@ -23,7 +23,7 @@ readme = "README.md"
23
23
  requires-python = ">=3.8"
24
24
  dependencies = [
25
25
  "isolate[build]>=0.13.0,<1.14.0",
26
- "isolate-proto==0.5.3",
26
+ "isolate-proto==0.5.4",
27
27
  "grpcio==1.64.0",
28
28
  "dill==0.3.7",
29
29
  "cloudpickle==3.0.0",
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.4.1'
16
- __version_tuple__ = version_tuple = (1, 4, 1)
15
+ __version__ = version = '1.5.0'
16
+ __version_tuple__ = version_tuple = (1, 5, 0)
@@ -397,6 +397,7 @@ class FalServerlessHost(Host):
397
397
  "max_multiplexing",
398
398
  "setup_function",
399
399
  "metadata",
400
+ "request_timeout",
400
401
  "_base_image",
401
402
  "_scheduler",
402
403
  "_scheduler_options",
@@ -444,6 +445,7 @@ class FalServerlessHost(Host):
444
445
  scheduler = options.host.get("_scheduler", None)
445
446
  scheduler_options = options.host.get("_scheduler_options", None)
446
447
  exposed_port = options.get_exposed_port()
448
+ request_timeout = options.host.get("request_timeout")
447
449
 
448
450
  machine_requirements = MachineRequirements(
449
451
  machine_types=machine_type, # type: ignore
@@ -456,6 +458,7 @@ class FalServerlessHost(Host):
456
458
  max_multiplexing=max_multiplexing,
457
459
  max_concurrency=max_concurrency,
458
460
  min_concurrency=min_concurrency,
461
+ request_timeout=request_timeout,
459
462
  )
460
463
 
461
464
  partial_func = _prepare_partial_func(func)
@@ -516,6 +519,7 @@ class FalServerlessHost(Host):
516
519
  scheduler_options = options.host.get("_scheduler_options", None)
517
520
  exposed_port = options.get_exposed_port()
518
521
  setup_function = options.host.get("setup_function", None)
522
+ request_timeout = options.host.get("request_timeout")
519
523
 
520
524
  machine_requirements = MachineRequirements(
521
525
  machine_types=machine_type, # type: ignore
@@ -528,6 +532,7 @@ class FalServerlessHost(Host):
528
532
  max_multiplexing=max_multiplexing,
529
533
  max_concurrency=max_concurrency,
530
534
  min_concurrency=min_concurrency,
535
+ request_timeout=request_timeout,
531
536
  )
532
537
 
533
538
  return_value = _UNSET
@@ -693,6 +698,7 @@ def function(
693
698
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
694
699
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
695
700
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
701
+ request_timeout: int | None = None,
696
702
  setup_function: Callable[..., None] | None = None,
697
703
  _base_image: str | None = None,
698
704
  _scheduler: str | None = None,
@@ -719,6 +725,7 @@ def function(
719
725
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
720
726
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
721
727
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
728
+ request_timeout: int | None = None,
722
729
  setup_function: Callable[..., None] | None = None,
723
730
  _base_image: str | None = None,
724
731
  _scheduler: str | None = None,
@@ -795,6 +802,7 @@ def function(
795
802
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
796
803
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
797
804
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
805
+ request_timeout: int | None = None,
798
806
  setup_function: Callable[..., None] | None = None,
799
807
  _base_image: str | None = None,
800
808
  _scheduler: str | None = None,
@@ -826,6 +834,7 @@ def function(
826
834
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
827
835
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
828
836
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
837
+ request_timeout: int | None = None,
829
838
  setup_function: Callable[..., None] | None = None,
830
839
  _base_image: str | None = None,
831
840
  _scheduler: str | None = None,
@@ -851,6 +860,7 @@ def function(
851
860
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
852
861
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
853
862
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
863
+ request_timeout: int | None = None,
854
864
  setup_function: Callable[..., None] | None = None,
855
865
  _base_image: str | None = None,
856
866
  _scheduler: str | None = None,
@@ -876,6 +886,7 @@ def function(
876
886
  keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
877
887
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
878
888
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
889
+ request_timeout: int | None = None,
879
890
  setup_function: Callable[..., None] | None = None,
880
891
  _base_image: str | None = None,
881
892
  _scheduler: str | None = None,
@@ -189,11 +189,17 @@ class App(fal.api.BaseServable):
189
189
  }
190
190
  app_name: ClassVar[str]
191
191
  app_auth: ClassVar[Literal["private", "public", "shared"]] = "private"
192
+ version: ClassVar[str] = "unknown"
193
+ request_timeout: ClassVar[int | None] = None
192
194
 
193
195
  def __init_subclass__(cls, **kwargs):
194
196
  app_name = kwargs.pop("name", None) or _to_fal_app_name(cls.__name__)
195
197
  parent_settings = getattr(cls, "host_kwargs", {})
196
198
  cls.host_kwargs = {**parent_settings, **kwargs}
199
+
200
+ if cls.request_timeout is not None:
201
+ cls.host_kwargs["request_timeout"] = cls.request_timeout
202
+
197
203
  cls.app_name = getattr(cls, "app_name", app_name)
198
204
 
199
205
  if cls.__init__ is not App.__init__:
@@ -232,7 +238,7 @@ class App(fal.api.BaseServable):
232
238
  await _call_any_fn(self.teardown)
233
239
 
234
240
  def health(self):
235
- return {}
241
+ return {"version": self.version}
236
242
 
237
243
  def setup(self):
238
244
  """Setup the application before serving."""
@@ -34,5 +34,6 @@ def get_app_data_from_toml(app_name):
34
34
  app_ref = str(project_root / app_ref)
35
35
 
36
36
  app_auth = app_data.get("auth", "private")
37
+ app_deployment_strategy = app_data.get("deployment_strategy", "recreate")
37
38
 
38
- return app_ref, app_auth
39
+ return app_ref, app_auth, app_deployment_strategy
@@ -65,8 +65,9 @@ def _get_user() -> User:
65
65
  def _deploy_from_reference(
66
66
  app_ref: Tuple[Optional[Union[Path, str]], ...],
67
67
  app_name: str,
68
- auth: Literal["public", "shared", "private"],
69
68
  args,
69
+ auth: Optional[Literal["public", "shared", "private"]] = None,
70
+ deployment_strategy: Optional[Literal["recreate", "rolling"]] = None,
70
71
  ):
71
72
  from fal.api import FalServerlessError, FalServerlessHost
72
73
  from fal.utils import load_function_from
@@ -96,7 +97,7 @@ def _deploy_from_reference(
96
97
  isolated_function = loaded.function
97
98
  app_name = app_name or loaded.app_name # type: ignore
98
99
  app_auth = auth or loaded.app_auth or "private"
99
- deployment_strategy = args.strategy or "recreate"
100
+ deployment_strategy = deployment_strategy or "recreate"
100
101
 
101
102
  app_id = host.register(
102
103
  func=isolated_function.func,
@@ -137,7 +138,7 @@ def _deploy(args):
137
138
  raise ValueError("Cannot use --app-name or --auth with app name reference.")
138
139
 
139
140
  app_name = args.app_ref[0]
140
- app_ref, app_auth = get_app_data_from_toml(app_name)
141
+ app_ref, app_auth, app_deployment_strategy = get_app_data_from_toml(app_name)
141
142
  file_path, func_name = RefAction.split_ref(app_ref)
142
143
 
143
144
  # path/to/myfile.py::MyApp
@@ -145,8 +146,15 @@ def _deploy(args):
145
146
  file_path, func_name = args.app_ref
146
147
  app_name = args.app_name
147
148
  app_auth = args.auth
148
-
149
- _deploy_from_reference((file_path, func_name), app_name, app_auth, args)
149
+ app_deployment_strategy = args.strategy
150
+
151
+ _deploy_from_reference(
152
+ (file_path, func_name),
153
+ app_name,
154
+ args,
155
+ app_auth,
156
+ app_deployment_strategy,
157
+ )
150
158
 
151
159
 
152
160
  def add_parser(main_subparsers, parents):
@@ -10,7 +10,7 @@ def _run(args):
10
10
 
11
11
  if is_app_name(args.func_ref):
12
12
  app_name = args.func_ref[0]
13
- app_ref, _ = get_app_data_from_toml(app_name)
13
+ app_ref, _, _ = get_app_data_from_toml(app_name)
14
14
  file_path, func_name = RefAction.split_ref(app_ref)
15
15
  else:
16
16
  file_path, func_name = args.func_ref
@@ -399,6 +399,7 @@ class MachineRequirements:
399
399
  max_concurrency: int | None = None
400
400
  max_multiplexing: int | None = None
401
401
  min_concurrency: int | None = None
402
+ request_timeout: int | None = None
402
403
 
403
404
  def __post_init__(self):
404
405
  if isinstance(self.machine_types, str):
@@ -514,6 +515,7 @@ class FalServerlessConnection:
514
515
  max_concurrency=machine_requirements.max_concurrency,
515
516
  min_concurrency=machine_requirements.min_concurrency,
516
517
  max_multiplexing=machine_requirements.max_multiplexing,
518
+ request_timeout=machine_requirements.request_timeout,
517
519
  )
518
520
  else:
519
521
  wrapped_requirements = None
@@ -607,6 +609,7 @@ class FalServerlessConnection:
607
609
  max_concurrency=machine_requirements.max_concurrency,
608
610
  max_multiplexing=machine_requirements.max_multiplexing,
609
611
  min_concurrency=machine_requirements.min_concurrency,
612
+ request_timeout=machine_requirements.request_timeout,
610
613
  )
611
614
  else:
612
615
  wrapped_requirements = None
@@ -20,8 +20,8 @@ def mock_parse_pyproject_toml():
20
20
  "my-app": {
21
21
  "ref": "src/my_app/inference.py::MyApp",
22
22
  "auth": "shared",
23
+ "deployment_strategy": "rolling",
23
24
  },
24
- # auth is not provided for another-app
25
25
  "another-app": {
26
26
  "ref": "src/another_app/inference.py::AnotherApp",
27
27
  },
@@ -30,13 +30,17 @@ def mock_parse_pyproject_toml():
30
30
 
31
31
 
32
32
  def mock_args(
33
- app_ref: tuple[str], app_name: Optional[str] = None, auth: Optional[str] = None
33
+ app_ref: tuple[str],
34
+ app_name: Optional[str] = None,
35
+ auth: Optional[str] = None,
36
+ strategy: Optional[str] = None,
34
37
  ):
35
38
  args = MagicMock()
36
39
 
37
40
  args.app_ref = app_ref
38
41
  args.app_name = app_name
39
42
  args.auth = auth
43
+ args.strategy = strategy
40
44
 
41
45
  return args
42
46
 
@@ -60,8 +64,9 @@ def test_deploy_with_toml_success(
60
64
  mock_deploy_ref.assert_called_once_with(
61
65
  (f"{project_root / 'src/my_app/inference.py'}", "MyApp"),
62
66
  "my-app",
63
- "shared",
64
67
  args,
68
+ "shared",
69
+ "rolling",
65
70
  )
66
71
 
67
72
 
@@ -84,8 +89,9 @@ def test_deploy_with_toml_no_auth(
84
89
  mock_deploy_ref.assert_called_once_with(
85
90
  (f"{project_root / 'src/another_app/inference.py'}", "AnotherApp"),
86
91
  "another-app",
87
- "private",
88
92
  args,
93
+ "private",
94
+ "recreate",
89
95
  )
90
96
 
91
97
 
@@ -157,3 +163,91 @@ def test_deploy_with_toml_only_app_name_is_provided(
157
163
  ValueError, match="Cannot use --app-name or --auth with app name reference."
158
164
  ):
159
165
  _deploy(args)
166
+
167
+
168
+ @patch("fal.cli._utils.find_pyproject_toml", return_value="pyproject.toml")
169
+ @patch("fal.cli._utils.parse_pyproject_toml")
170
+ @patch("fal.cli.deploy._deploy_from_reference")
171
+ def test_deploy_with_toml_deployment_strategy(
172
+ mock_deploy_ref, mock_parse_toml, mock_find_toml, mock_parse_pyproject_toml
173
+ ):
174
+ mock_parse_toml.return_value = mock_parse_pyproject_toml
175
+
176
+ args = mock_args(app_ref=("my-app", None), strategy="rolling")
177
+
178
+ _deploy(args)
179
+
180
+ project_root, _ = find_project_root(None)
181
+
182
+ mock_deploy_ref.assert_called_once_with(
183
+ (f"{project_root / 'src/my_app/inference.py'}", "MyApp"),
184
+ "my-app",
185
+ args,
186
+ "shared",
187
+ "rolling",
188
+ )
189
+
190
+
191
+ @patch("fal.cli._utils.find_pyproject_toml", return_value="pyproject.toml")
192
+ @patch("fal.cli._utils.parse_pyproject_toml")
193
+ @patch("fal.cli.deploy._deploy_from_reference")
194
+ def test_deploy_with_toml_default_deployment_strategy(
195
+ mock_deploy_ref, mock_parse_toml, mock_find_toml, mock_parse_pyproject_toml
196
+ ):
197
+ mock_parse_toml.return_value = mock_parse_pyproject_toml
198
+
199
+ args = mock_args(app_ref=("another-app", None))
200
+
201
+ _deploy(args)
202
+
203
+ project_root, _ = find_project_root(None)
204
+
205
+ mock_deploy_ref.assert_called_once_with(
206
+ (f"{project_root / 'src/another_app/inference.py'}", "AnotherApp"),
207
+ "another-app",
208
+ args,
209
+ "private",
210
+ "recreate",
211
+ )
212
+
213
+
214
+ @patch("fal.cli._utils.find_pyproject_toml", return_value="pyproject.toml")
215
+ @patch("fal.cli._utils.parse_pyproject_toml")
216
+ @patch("fal.cli.deploy._deploy_from_reference")
217
+ def test_deploy_with_cli_auth(
218
+ mock_deploy_ref, mock_parse_toml, mock_find_toml, mock_parse_pyproject_toml
219
+ ):
220
+ mock_parse_toml.return_value = mock_parse_pyproject_toml
221
+
222
+ args = mock_args(app_ref=("src/my_app/inference.py", "MyApp"), auth="shared")
223
+
224
+ _deploy(args)
225
+
226
+ mock_deploy_ref.assert_called_once_with(
227
+ ("src/my_app/inference.py", "MyApp"),
228
+ None,
229
+ args,
230
+ "shared",
231
+ None,
232
+ )
233
+
234
+
235
+ @patch("fal.cli._utils.find_pyproject_toml", return_value="pyproject.toml")
236
+ @patch("fal.cli._utils.parse_pyproject_toml")
237
+ @patch("fal.cli.deploy._deploy_from_reference")
238
+ def test_deploy_with_cli_deployment_strategy(
239
+ mock_deploy_ref, mock_parse_toml, mock_find_toml, mock_parse_pyproject_toml
240
+ ):
241
+ mock_parse_toml.return_value = mock_parse_pyproject_toml
242
+
243
+ args = mock_args(app_ref=("src/my_app/inference.py", "MyApp"), strategy="rolling")
244
+
245
+ _deploy(args)
246
+
247
+ mock_deploy_ref.assert_called_once_with(
248
+ ("src/my_app/inference.py", "MyApp"),
249
+ None,
250
+ args,
251
+ None,
252
+ "rolling",
253
+ )
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