fal 1.41.1__tar.gz → 1.43.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 (188) hide show
  1. {fal-1.41.1/fal.egg-info → fal-1.43.0}/PKG-INFO +3 -2
  2. {fal-1.41.1 → fal-1.43.0/fal.egg-info}/PKG-INFO +3 -2
  3. {fal-1.41.1 → fal-1.43.0}/fal.egg-info/requires.txt +2 -1
  4. {fal-1.41.1 → fal-1.43.0}/pyproject.toml +2 -1
  5. {fal-1.41.1 → fal-1.43.0}/src/fal/_fal_version.py +2 -2
  6. {fal-1.41.1 → fal-1.43.0}/src/fal/api.py +21 -5
  7. {fal-1.41.1 → fal-1.43.0}/src/fal/app.py +3 -2
  8. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/_utils.py +15 -7
  9. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/apps.py +16 -2
  10. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/deploy.py +13 -9
  11. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/parser.py +32 -1
  12. fal-1.43.0/src/fal/cli/runners.py +570 -0
  13. {fal-1.41.1 → fal-1.43.0}/src/fal/sdk.py +15 -4
  14. {fal-1.41.1 → fal-1.43.0}/tests/cli/test_apps.py +3 -0
  15. {fal-1.41.1 → fal-1.43.0}/tests/cli/test_deploy.py +4 -4
  16. {fal-1.41.1 → fal-1.43.0}/tests/test_apps.py +4 -0
  17. fal-1.41.1/src/fal/cli/runners.py +0 -219
  18. {fal-1.41.1 → fal-1.43.0}/.gitignore +0 -0
  19. {fal-1.41.1 → fal-1.43.0}/Makefile +0 -0
  20. {fal-1.41.1 → fal-1.43.0}/README.md +0 -0
  21. {fal-1.41.1 → fal-1.43.0}/docs/conf.py +0 -0
  22. {fal-1.41.1 → fal-1.43.0}/docs/index.rst +0 -0
  23. {fal-1.41.1 → fal-1.43.0}/fal.egg-info/SOURCES.txt +0 -0
  24. {fal-1.41.1 → fal-1.43.0}/fal.egg-info/dependency_links.txt +0 -0
  25. {fal-1.41.1 → fal-1.43.0}/fal.egg-info/entry_points.txt +0 -0
  26. {fal-1.41.1 → fal-1.43.0}/fal.egg-info/top_level.txt +0 -0
  27. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/README.md +0 -0
  28. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
  29. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
  30. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
  31. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
  32. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
  33. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
  34. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
  35. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
  36. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
  37. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
  38. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
  39. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
  40. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
  41. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
  42. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
  43. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
  44. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
  45. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
  46. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
  47. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
  48. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
  49. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
  50. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
  51. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
  52. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
  53. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
  54. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
  55. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
  56. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
  57. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
  58. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
  59. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
  60. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
  61. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
  62. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
  63. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
  64. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
  65. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
  66. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
  67. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
  68. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
  69. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
  70. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
  71. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
  72. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
  73. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
  74. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
  75. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
  76. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
  77. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
  78. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
  79. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
  80. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
  81. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
  82. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
  83. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
  84. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
  85. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
  86. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
  87. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
  88. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
  89. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
  90. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
  91. {fal-1.41.1 → fal-1.43.0}/openapi-fal-rest/pyproject.toml +0 -0
  92. {fal-1.41.1 → fal-1.43.0}/openapi_rest.config.yaml +0 -0
  93. {fal-1.41.1 → fal-1.43.0}/setup.cfg +0 -0
  94. {fal-1.41.1 → fal-1.43.0}/src/fal/__init__.py +0 -0
  95. {fal-1.41.1 → fal-1.43.0}/src/fal/__main__.py +0 -0
  96. {fal-1.41.1 → fal-1.43.0}/src/fal/_serialization.py +0 -0
  97. {fal-1.41.1 → fal-1.43.0}/src/fal/_version.py +0 -0
  98. {fal-1.41.1 → fal-1.43.0}/src/fal/apps.py +0 -0
  99. {fal-1.41.1 → fal-1.43.0}/src/fal/auth/__init__.py +0 -0
  100. {fal-1.41.1 → fal-1.43.0}/src/fal/auth/auth0.py +0 -0
  101. {fal-1.41.1 → fal-1.43.0}/src/fal/auth/local.py +0 -0
  102. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/__init__.py +0 -0
  103. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/api.py +0 -0
  104. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/auth.py +0 -0
  105. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/cli_nested_json.py +0 -0
  106. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/create.py +0 -0
  107. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/debug.py +0 -0
  108. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/doctor.py +0 -0
  109. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/files.py +0 -0
  110. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/keys.py +0 -0
  111. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/main.py +0 -0
  112. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/profile.py +0 -0
  113. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/queue.py +0 -0
  114. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/run.py +0 -0
  115. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/secrets.py +0 -0
  116. {fal-1.41.1 → fal-1.43.0}/src/fal/cli/teams.py +0 -0
  117. {fal-1.41.1 → fal-1.43.0}/src/fal/config.py +0 -0
  118. {fal-1.41.1 → fal-1.43.0}/src/fal/console/__init__.py +0 -0
  119. {fal-1.41.1 → fal-1.43.0}/src/fal/console/icons.py +0 -0
  120. {fal-1.41.1 → fal-1.43.0}/src/fal/console/ux.py +0 -0
  121. {fal-1.41.1 → fal-1.43.0}/src/fal/container.py +0 -0
  122. {fal-1.41.1 → fal-1.43.0}/src/fal/exceptions/__init__.py +0 -0
  123. {fal-1.41.1 → fal-1.43.0}/src/fal/exceptions/_base.py +0 -0
  124. {fal-1.41.1 → fal-1.43.0}/src/fal/exceptions/_cuda.py +0 -0
  125. {fal-1.41.1 → fal-1.43.0}/src/fal/exceptions/auth.py +0 -0
  126. {fal-1.41.1 → fal-1.43.0}/src/fal/files.py +0 -0
  127. {fal-1.41.1 → fal-1.43.0}/src/fal/flags.py +0 -0
  128. {fal-1.41.1 → fal-1.43.0}/src/fal/logging/__init__.py +0 -0
  129. {fal-1.41.1 → fal-1.43.0}/src/fal/logging/isolate.py +0 -0
  130. {fal-1.41.1 → fal-1.43.0}/src/fal/logging/style.py +0 -0
  131. {fal-1.41.1 → fal-1.43.0}/src/fal/logging/trace.py +0 -0
  132. {fal-1.41.1 → fal-1.43.0}/src/fal/project.py +0 -0
  133. {fal-1.41.1 → fal-1.43.0}/src/fal/py.typed +0 -0
  134. {fal-1.41.1 → fal-1.43.0}/src/fal/rest_client.py +0 -0
  135. {fal-1.41.1 → fal-1.43.0}/src/fal/sync.py +0 -0
  136. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/__init__.py +0 -0
  137. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/audio/__init__.py +0 -0
  138. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/audio/audio.py +0 -0
  139. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/exceptions.py +0 -0
  140. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/file/__init__.py +0 -0
  141. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/file/file.py +0 -0
  142. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/file/providers/fal.py +0 -0
  143. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/file/providers/gcp.py +0 -0
  144. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/file/providers/r2.py +0 -0
  145. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/file/providers/s3.py +0 -0
  146. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/file/types.py +0 -0
  147. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/image/__init__.py +0 -0
  148. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/image/image.py +0 -0
  149. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
  150. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
  151. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
  152. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
  153. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
  154. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/image/safety_checker.py +0 -0
  155. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/kv.py +0 -0
  156. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/optimize.py +0 -0
  157. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/types.py +0 -0
  158. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/utils/__init__.py +0 -0
  159. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/utils/download_utils.py +0 -0
  160. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/utils/endpoint.py +0 -0
  161. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/utils/retry.py +0 -0
  162. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/utils/setup_utils.py +0 -0
  163. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/video/__init__.py +0 -0
  164. {fal-1.41.1 → fal-1.43.0}/src/fal/toolkit/video/video.py +0 -0
  165. {fal-1.41.1 → fal-1.43.0}/src/fal/utils.py +0 -0
  166. {fal-1.41.1 → fal-1.43.0}/src/fal/workflows.py +0 -0
  167. {fal-1.41.1 → fal-1.43.0}/tests/__init__.py +0 -0
  168. {fal-1.41.1 → fal-1.43.0}/tests/assets/cat.png +0 -0
  169. {fal-1.41.1 → fal-1.43.0}/tests/cli/__init__.py +0 -0
  170. {fal-1.41.1 → fal-1.43.0}/tests/cli/test_auth.py +0 -0
  171. {fal-1.41.1 → fal-1.43.0}/tests/cli/test_keys.py +0 -0
  172. {fal-1.41.1 → fal-1.43.0}/tests/cli/test_run.py +0 -0
  173. {fal-1.41.1 → fal-1.43.0}/tests/cli/test_secrets.py +0 -0
  174. {fal-1.41.1 → fal-1.43.0}/tests/conftest.py +0 -0
  175. {fal-1.41.1 → fal-1.43.0}/tests/integration_test.py +0 -0
  176. {fal-1.41.1 → fal-1.43.0}/tests/mainify_package/__init__.py +0 -0
  177. {fal-1.41.1 → fal-1.43.0}/tests/mainify_package/impl.py +0 -0
  178. {fal-1.41.1 → fal-1.43.0}/tests/mainify_package/utils.py +0 -0
  179. {fal-1.41.1 → fal-1.43.0}/tests/mainify_target.py +0 -0
  180. {fal-1.41.1 → fal-1.43.0}/tests/test_files.py +0 -0
  181. {fal-1.41.1 → fal-1.43.0}/tests/test_kv.py +0 -0
  182. {fal-1.41.1 → fal-1.43.0}/tests/test_stability.py +0 -0
  183. {fal-1.41.1 → fal-1.43.0}/tests/toolkit/file/providers/test_fal_retry.py +0 -0
  184. {fal-1.41.1 → fal-1.43.0}/tests/toolkit/file_test.py +0 -0
  185. {fal-1.41.1 → fal-1.43.0}/tests/toolkit/image_test.py +0 -0
  186. {fal-1.41.1 → fal-1.43.0}/tests/toolkit/test_types.py +0 -0
  187. {fal-1.41.1 → fal-1.43.0}/tests/toolkit/utils/retry.py +0 -0
  188. {fal-1.41.1 → fal-1.43.0}/tools/demo_script.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fal
3
- Version: 1.41.1
3
+ Version: 1.43.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]<0.21.0,>=0.18.0
9
- Requires-Dist: isolate-proto<0.18.0,>=0.17.0
9
+ Requires-Dist: isolate-proto<0.19.0,>=0.18.0
10
10
  Requires-Dist: grpcio<2,>=1.64.0
11
11
  Requires-Dist: dill==0.3.7
12
12
  Requires-Dist: cloudpickle==3.0.0
@@ -25,6 +25,7 @@ Requires-Dist: pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<2.11
25
25
  Requires-Dist: fastapi<1,>=0.99.1
26
26
  Requires-Dist: starlette-exporter>=0.21.0
27
27
  Requires-Dist: httpx>=0.15.4
28
+ Requires-Dist: httpx-sse
28
29
  Requires-Dist: attrs>=21.3.0
29
30
  Requires-Dist: python-dateutil<3,>=2.8.0
30
31
  Requires-Dist: types-python-dateutil<3,>=2.8.0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fal
3
- Version: 1.41.1
3
+ Version: 1.43.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]<0.21.0,>=0.18.0
9
- Requires-Dist: isolate-proto<0.18.0,>=0.17.0
9
+ Requires-Dist: isolate-proto<0.19.0,>=0.18.0
10
10
  Requires-Dist: grpcio<2,>=1.64.0
11
11
  Requires-Dist: dill==0.3.7
12
12
  Requires-Dist: cloudpickle==3.0.0
@@ -25,6 +25,7 @@ Requires-Dist: pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<2.11
25
25
  Requires-Dist: fastapi<1,>=0.99.1
26
26
  Requires-Dist: starlette-exporter>=0.21.0
27
27
  Requires-Dist: httpx>=0.15.4
28
+ Requires-Dist: httpx-sse
28
29
  Requires-Dist: attrs>=21.3.0
29
30
  Requires-Dist: python-dateutil<3,>=2.8.0
30
31
  Requires-Dist: types-python-dateutil<3,>=2.8.0
@@ -1,5 +1,5 @@
1
1
  isolate[build]<0.21.0,>=0.18.0
2
- isolate-proto<0.18.0,>=0.17.0
2
+ isolate-proto<0.19.0,>=0.18.0
3
3
  grpcio<2,>=1.64.0
4
4
  dill==0.3.7
5
5
  cloudpickle==3.0.0
@@ -18,6 +18,7 @@ pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*,<2.11
18
18
  fastapi<1,>=0.99.1
19
19
  starlette-exporter>=0.21.0
20
20
  httpx>=0.15.4
21
+ httpx-sse
21
22
  attrs>=21.3.0
22
23
  python-dateutil<3,>=2.8.0
23
24
  types-python-dateutil<3,>=2.8.0
@@ -23,7 +23,7 @@ readme = "README.md"
23
23
  requires-python = ">=3.8"
24
24
  dependencies = [
25
25
  "isolate[build]>=0.18.0,<0.21.0",
26
- "isolate-proto>=0.17.0,<0.18.0",
26
+ "isolate-proto>=0.18.0,<0.19.0",
27
27
  "grpcio>=1.64.0,<2",
28
28
  "dill==0.3.7",
29
29
  "cloudpickle==3.0.0",
@@ -44,6 +44,7 @@ dependencies = [
44
44
  "starlette-exporter>=0.21.0",
45
45
  # rest-api-client dependencies
46
46
  "httpx>=0.15.4",
47
+ "httpx-sse",
47
48
  "attrs>=21.3.0",
48
49
  "python-dateutil>=2.8.0,<3",
49
50
  "types-python-dateutil>=2.8.0,<3",
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.41.1'
32
- __version_tuple__ = version_tuple = (1, 41, 1)
31
+ __version__ = version = '1.43.0'
32
+ __version_tuple__ = version_tuple = (1, 43, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -21,6 +21,7 @@ from typing import (
21
21
  Iterator,
22
22
  Literal,
23
23
  NamedTuple,
24
+ Optional,
24
25
  TypeVar,
25
26
  cast,
26
27
  overload,
@@ -53,10 +54,13 @@ from fal.exceptions._cuda import _is_cuda_oom_exception
53
54
  from fal.logging.isolate import IsolateLogPrinter
54
55
  from fal.sdk import (
55
56
  FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
57
+ FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
56
58
  FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
57
59
  FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
58
60
  FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
61
+ AuthModeLiteral,
59
62
  Credentials,
63
+ DeploymentStrategyLiteral,
60
64
  FalServerlessClient,
61
65
  FalServerlessConnection,
62
66
  HostedRunState,
@@ -424,6 +428,7 @@ class FalServerlessHost(Host):
424
428
  "max_concurrency",
425
429
  "min_concurrency",
426
430
  "concurrency_buffer",
431
+ "concurrency_buffer_perc",
427
432
  "max_multiplexing",
428
433
  "setup_function",
429
434
  "metadata",
@@ -465,12 +470,13 @@ class FalServerlessHost(Host):
465
470
  self,
466
471
  func: Callable[ArgsT, ReturnT],
467
472
  options: Options,
468
- application_name: str | None = None,
469
- application_auth_mode: Literal["public", "shared", "private"] | None = None,
470
- metadata: dict[str, Any] | None = None,
471
- deployment_strategy: Literal["recreate", "rolling"] = "recreate",
473
+ *,
474
+ application_name: Optional[str] = None,
475
+ application_auth_mode: Optional[AuthModeLiteral] = None,
476
+ metadata: Optional[dict[str, Any]] = None,
477
+ deployment_strategy: DeploymentStrategyLiteral,
472
478
  scale: bool = True,
473
- ) -> str | None:
479
+ ) -> Optional[str]:
474
480
  from isolate.backends.common import active_python
475
481
 
476
482
  environment_options = options.environment.copy()
@@ -487,6 +493,7 @@ class FalServerlessHost(Host):
487
493
  max_concurrency = options.host.get("max_concurrency")
488
494
  min_concurrency = options.host.get("min_concurrency")
489
495
  concurrency_buffer = options.host.get("concurrency_buffer")
496
+ concurrency_buffer_perc = options.host.get("concurrency_buffer_perc")
490
497
  max_multiplexing = options.host.get("max_multiplexing")
491
498
  exposed_port = options.get_exposed_port()
492
499
  request_timeout = options.host.get("request_timeout")
@@ -503,6 +510,7 @@ class FalServerlessHost(Host):
503
510
  max_concurrency=max_concurrency,
504
511
  min_concurrency=min_concurrency,
505
512
  concurrency_buffer=concurrency_buffer,
513
+ concurrency_buffer_perc=concurrency_buffer_perc,
506
514
  request_timeout=request_timeout,
507
515
  startup_timeout=startup_timeout,
508
516
  )
@@ -560,6 +568,7 @@ class FalServerlessHost(Host):
560
568
  max_concurrency = options.host.get("max_concurrency")
561
569
  min_concurrency = options.host.get("min_concurrency")
562
570
  concurrency_buffer = options.host.get("concurrency_buffer")
571
+ concurrency_buffer_perc = options.host.get("concurrency_buffer_perc")
563
572
  max_multiplexing = options.host.get("max_multiplexing")
564
573
  base_image = options.host.get("_base_image", None)
565
574
  scheduler = options.host.get("_scheduler", None)
@@ -580,6 +589,7 @@ class FalServerlessHost(Host):
580
589
  max_concurrency=max_concurrency,
581
590
  min_concurrency=min_concurrency,
582
591
  concurrency_buffer=concurrency_buffer,
592
+ concurrency_buffer_perc=concurrency_buffer_perc,
583
593
  request_timeout=request_timeout,
584
594
  startup_timeout=startup_timeout,
585
595
  )
@@ -770,6 +780,7 @@ def function(
770
780
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
771
781
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
772
782
  concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
783
+ concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
773
784
  request_timeout: int | None = None,
774
785
  startup_timeout: int | None = None,
775
786
  setup_function: Callable[..., None] | None = None,
@@ -800,6 +811,7 @@ def function(
800
811
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
801
812
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
802
813
  concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
814
+ concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
803
815
  request_timeout: int | None = None,
804
816
  startup_timeout: int | None = None,
805
817
  setup_function: Callable[..., None] | None = None,
@@ -882,6 +894,7 @@ def function(
882
894
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
883
895
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
884
896
  concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
897
+ concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
885
898
  request_timeout: int | None = None,
886
899
  startup_timeout: int | None = None,
887
900
  setup_function: Callable[..., None] | None = None,
@@ -917,6 +930,7 @@ def function(
917
930
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
918
931
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
919
932
  concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
933
+ concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
920
934
  request_timeout: int | None = None,
921
935
  startup_timeout: int | None = None,
922
936
  setup_function: Callable[..., None] | None = None,
@@ -946,6 +960,7 @@ def function(
946
960
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
947
961
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
948
962
  concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
963
+ concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
949
964
  request_timeout: int | None = None,
950
965
  startup_timeout: int | None = None,
951
966
  setup_function: Callable[..., None] | None = None,
@@ -975,6 +990,7 @@ def function(
975
990
  max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
976
991
  min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
977
992
  concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
993
+ concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
978
994
  request_timeout: int | None = None,
979
995
  startup_timeout: int | None = None,
980
996
  setup_function: Callable[..., None] | None = None,
@@ -11,7 +11,7 @@ import time
11
11
  import typing
12
12
  from contextlib import asynccontextmanager, contextmanager
13
13
  from dataclasses import dataclass
14
- from typing import Any, Callable, ClassVar, Literal, TypeVar
14
+ from typing import Any, Callable, ClassVar, Optional, TypeVar
15
15
 
16
16
  import fastapi
17
17
  import grpc.aio as async_grpc
@@ -29,6 +29,7 @@ from fal.api import (
29
29
  )
30
30
  from fal.exceptions import FalServerlessException, RequestCancelledException
31
31
  from fal.logging import get_logger
32
+ from fal.sdk import AuthModeLiteral
32
33
  from fal.toolkit.file import request_lifecycle_preference
33
34
  from fal.toolkit.file.providers.fal import LIFECYCLE_PREFERENCE
34
35
 
@@ -311,7 +312,7 @@ class App(BaseServable):
311
312
  "keep_alive": 60,
312
313
  }
313
314
  app_name: ClassVar[str]
314
- app_auth: ClassVar[Literal["private", "public", "shared", None]] = None
315
+ app_auth: ClassVar[Optional[AuthModeLiteral]] = None
315
316
  request_timeout: ClassVar[int | None] = None
316
317
  startup_timeout: ClassVar[int | None] = None
317
318
 
@@ -1,10 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from typing import Any, Optional
4
+
3
5
  from fal.project import find_project_root, find_pyproject_toml, parse_pyproject_toml
6
+ from fal.sdk import AuthModeLiteral, DeploymentStrategyLiteral
4
7
 
5
8
 
6
9
  def get_client(host: str, team: str | None = None):
7
- from fal.sdk import FalServerlessClient, get_default_credentials
10
+ from fal.sdk import FalServerlessClient, get_default_credentials # noqa: PLC0415
8
11
 
9
12
  credentials = get_default_credentials(team=team)
10
13
  return FalServerlessClient(host, credentials)
@@ -17,7 +20,9 @@ def is_app_name(app_ref: tuple[str, str | None]) -> bool:
17
20
  return is_single_file and not is_python_file
18
21
 
19
22
 
20
- def get_app_data_from_toml(app_name):
23
+ def get_app_data_from_toml(
24
+ app_name,
25
+ ) -> tuple[str, Optional[AuthModeLiteral], Optional[DeploymentStrategyLiteral], bool]:
21
26
  toml_path = find_pyproject_toml()
22
27
 
23
28
  if toml_path is None:
@@ -27,12 +32,12 @@ def get_app_data_from_toml(app_name):
27
32
  apps = fal_data.get("apps", {})
28
33
 
29
34
  try:
30
- app_data = apps[app_name]
35
+ app_data: dict[str, Any] = apps[app_name]
31
36
  except KeyError:
32
37
  raise ValueError(f"App {app_name} not found in pyproject.toml")
33
38
 
34
39
  try:
35
- app_ref = app_data.pop("ref")
40
+ app_ref: str = app_data.pop("ref")
36
41
  except KeyError:
37
42
  raise ValueError(f"App {app_name} does not have a ref key in pyproject.toml")
38
43
 
@@ -40,12 +45,15 @@ def get_app_data_from_toml(app_name):
40
45
  project_root, _ = find_project_root(None)
41
46
  app_ref = str(project_root / app_ref)
42
47
 
43
- app_auth = app_data.pop("auth", "private")
44
- app_deployment_strategy = app_data.pop("deployment_strategy", "recreate")
48
+ app_auth: Optional[AuthModeLiteral] = app_data.pop("auth", None)
49
+ app_deployment_strategy: Optional[DeploymentStrategyLiteral] = app_data.pop(
50
+ "deployment_strategy", None
51
+ )
45
52
 
53
+ app_reset_scale: bool
46
54
  if "no_scale" in app_data:
47
55
  # Deprecated
48
- app_no_scale = app_data.pop("no_scale")
56
+ app_no_scale: bool = app_data.pop("no_scale")
49
57
  print("[WARNING] no_scale is deprecated, use app_scale_settings instead")
50
58
  app_reset_scale = not app_no_scale
51
59
  else:
@@ -33,13 +33,20 @@ def _apps_table(apps: list[AliasInfo]):
33
33
  table.add_column("Regions")
34
34
 
35
35
  for app in apps:
36
+ if app.concurrency_buffer_perc > 0:
37
+ concurrency_buffer_str = (
38
+ f"{app.concurrency_buffer_perc}%, min {app.concurrency_buffer}"
39
+ )
40
+ else:
41
+ concurrency_buffer_str = str(app.concurrency_buffer)
42
+
36
43
  table.add_row(
37
44
  app.alias,
38
45
  app.revision,
39
46
  app.auth_mode,
40
47
  str(app.min_concurrency),
41
48
  str(app.max_concurrency),
42
- str(app.concurrency_buffer),
49
+ concurrency_buffer_str,
43
50
  str(app.max_multiplexing),
44
51
  str(app.keep_alive),
45
52
  str(app.request_timeout),
@@ -165,6 +172,7 @@ def _scale(args):
165
172
  and args.max_concurrency is None
166
173
  and args.min_concurrency is None
167
174
  and args.concurrency_buffer is None
175
+ and args.concurrency_buffer_perc is None
168
176
  and args.request_timeout is None
169
177
  and args.startup_timeout is None
170
178
  and args.machine_types is None
@@ -180,6 +188,7 @@ def _scale(args):
180
188
  max_concurrency=args.max_concurrency,
181
189
  min_concurrency=args.min_concurrency,
182
190
  concurrency_buffer=args.concurrency_buffer,
191
+ concurrency_buffer_perc=args.concurrency_buffer_perc,
183
192
  request_timeout=args.request_timeout,
184
193
  startup_timeout=args.startup_timeout,
185
194
  machine_types=args.machine_types,
@@ -225,7 +234,12 @@ def _add_scale_parser(subparsers, parents):
225
234
  parser.add_argument(
226
235
  "--concurrency-buffer",
227
236
  type=int,
228
- help="Concurrency buffer",
237
+ help="Concurrency buffer (min)",
238
+ )
239
+ parser.add_argument(
240
+ "--concurrency-buffer-perc",
241
+ type=int,
242
+ help="Concurrency buffer %",
229
243
  )
230
244
  parser.add_argument(
231
245
  "--request-timeout",
@@ -2,7 +2,9 @@ import argparse
2
2
  import json
3
3
  from collections import namedtuple
4
4
  from pathlib import Path
5
- from typing import Literal, Optional, Tuple, Union
5
+ from typing import Optional, Tuple, Union, cast
6
+
7
+ from fal.sdk import AuthModeLiteral, DeploymentStrategyLiteral
6
8
 
7
9
  from ._utils import get_app_data_from_toml, is_app_name
8
10
  from .parser import FalClientParser, RefAction, get_output_parser
@@ -67,8 +69,8 @@ def _deploy_from_reference(
67
69
  app_ref: Tuple[Optional[Union[Path, str]], ...],
68
70
  app_name: str,
69
71
  args,
70
- auth: Optional[Literal["public", "shared", "private"]],
71
- deployment_strategy: Optional[Literal["recreate", "rolling"]],
72
+ auth: Optional[AuthModeLiteral],
73
+ deployment_strategy: Optional[DeploymentStrategyLiteral],
72
74
  scale: bool,
73
75
  ):
74
76
  from fal.api import FalServerlessError, FalServerlessHost
@@ -99,7 +101,7 @@ def _deploy_from_reference(
99
101
  isolated_function = loaded.function
100
102
  app_name = app_name or loaded.app_name # type: ignore
101
103
  app_auth = auth or loaded.app_auth
102
- deployment_strategy = deployment_strategy or "recreate"
104
+ deployment_strategy = deployment_strategy or "rolling"
103
105
 
104
106
  app_id = host.register(
105
107
  func=isolated_function.func,
@@ -172,10 +174,12 @@ def _deploy(args):
172
174
  # path/to/myfile.py::MyApp
173
175
  else:
174
176
  file_path, func_name = args.app_ref
175
- app_name = args.app_name
176
- app_auth = args.auth
177
- app_deployment_strategy = args.strategy
178
- app_scale_settings = args.app_scale_settings
177
+ app_name = cast(str, args.app_name)
178
+ # default to be set in the backend
179
+ app_auth = cast(Optional[AuthModeLiteral], args.auth)
180
+ # default comes from the CLI
181
+ app_deployment_strategy = cast(DeploymentStrategyLiteral, args.strategy)
182
+ app_scale_settings = cast(bool, args.app_scale_settings)
179
183
 
180
184
  _deploy_from_reference(
181
185
  (file_path, func_name),
@@ -251,7 +255,7 @@ def add_parser(main_subparsers, parents):
251
255
  "--strategy",
252
256
  choices=["recreate", "rolling"],
253
257
  help="Deployment strategy.",
254
- default="recreate",
258
+ default="rolling",
255
259
  )
256
260
  parser.add_argument(
257
261
  "--no-scale",
@@ -86,6 +86,37 @@ class SinceAction(argparse.Action):
86
86
 
87
87
  super().__init__(*args, **kwargs)
88
88
 
89
+ # If a default is provided as a string like "1h ago", parse it into a datetime
90
+ # so callers can rely on receiving a datetime even when the flag isn't passed.
91
+ default_value = getattr(self, "default", None)
92
+ if default_value is not None and default_value is not argparse.SUPPRESS:
93
+ if isinstance(default_value, str):
94
+ dt = self._parse_since(default_value)
95
+ if not dt:
96
+ raise ValueError(
97
+ f"Invalid 'default' value for SinceAction: {default_value!r}"
98
+ )
99
+ if (
100
+ self._limit
101
+ and self._limit_dt is not None
102
+ and dt < self._limit_dt - self.LIMIT_LEEWAY
103
+ ):
104
+ raise ValueError(
105
+ "Default since value is older than the allowed limit "
106
+ f"{self._limit}."
107
+ )
108
+ self.default = dt
109
+ elif isinstance(default_value, datetime):
110
+ if (
111
+ self._limit
112
+ and self._limit_dt is not None
113
+ and default_value < self._limit_dt - self.LIMIT_LEEWAY
114
+ ):
115
+ raise ValueError(
116
+ "Default since value is older than the allowed limit "
117
+ f"{self._limit}."
118
+ )
119
+
89
120
  def __call__(self, parser, args, values, option_string=None): # noqa: ARG002
90
121
  if values is None:
91
122
  setattr(args, self.dest, None)
@@ -102,7 +133,7 @@ class SinceAction(argparse.Action):
102
133
  ),
103
134
  )
104
135
 
105
- if self._limit_dt is not None:
136
+ if self._limit and self._limit_dt is not None:
106
137
  if dt < self._limit_dt - self.LIMIT_LEEWAY:
107
138
  raise argparse.ArgumentError(
108
139
  self,