fal 1.10.0__tar.gz → 1.11.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 (174) hide show
  1. {fal-1.10.0/fal.egg-info → fal-1.11.0}/PKG-INFO +2 -2
  2. {fal-1.10.0 → fal-1.11.0/fal.egg-info}/PKG-INFO +2 -2
  3. {fal-1.10.0 → fal-1.11.0}/src/fal/_fal_version.py +2 -2
  4. {fal-1.10.0 → fal-1.11.0}/src/fal/container.py +6 -0
  5. {fal-1.10.0 → fal-1.11.0}/tests/test_apps.py +26 -21
  6. {fal-1.10.0 → fal-1.11.0}/.gitignore +0 -0
  7. {fal-1.10.0 → fal-1.11.0}/Makefile +0 -0
  8. {fal-1.10.0 → fal-1.11.0}/README.md +0 -0
  9. {fal-1.10.0 → fal-1.11.0}/docs/conf.py +0 -0
  10. {fal-1.10.0 → fal-1.11.0}/docs/index.rst +0 -0
  11. {fal-1.10.0 → fal-1.11.0}/fal.egg-info/SOURCES.txt +0 -0
  12. {fal-1.10.0 → fal-1.11.0}/fal.egg-info/dependency_links.txt +0 -0
  13. {fal-1.10.0 → fal-1.11.0}/fal.egg-info/entry_points.txt +0 -0
  14. {fal-1.10.0 → fal-1.11.0}/fal.egg-info/requires.txt +0 -0
  15. {fal-1.10.0 → fal-1.11.0}/fal.egg-info/top_level.txt +0 -0
  16. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/README.md +0 -0
  17. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
  18. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
  19. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
  20. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
  21. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
  22. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
  23. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
  24. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
  25. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
  26. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
  27. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
  28. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
  29. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
  30. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
  31. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
  32. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
  33. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
  34. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
  35. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
  36. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
  37. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
  38. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
  39. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
  40. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
  41. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
  42. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
  43. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
  44. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
  45. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
  46. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
  47. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
  48. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
  49. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
  50. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
  51. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
  52. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
  53. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
  54. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
  55. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
  56. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
  57. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
  58. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
  59. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
  60. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
  61. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
  62. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
  63. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
  64. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
  65. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
  66. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
  67. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
  68. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
  69. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
  70. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
  71. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
  72. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
  73. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
  74. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
  75. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
  76. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
  77. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
  78. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
  79. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
  80. {fal-1.10.0 → fal-1.11.0}/openapi-fal-rest/pyproject.toml +0 -0
  81. {fal-1.10.0 → fal-1.11.0}/openapi_rest.config.yaml +0 -0
  82. {fal-1.10.0 → fal-1.11.0}/pyproject.toml +0 -0
  83. {fal-1.10.0 → fal-1.11.0}/setup.cfg +0 -0
  84. {fal-1.10.0 → fal-1.11.0}/src/fal/__init__.py +0 -0
  85. {fal-1.10.0 → fal-1.11.0}/src/fal/__main__.py +0 -0
  86. {fal-1.10.0 → fal-1.11.0}/src/fal/_serialization.py +0 -0
  87. {fal-1.10.0 → fal-1.11.0}/src/fal/_version.py +0 -0
  88. {fal-1.10.0 → fal-1.11.0}/src/fal/api.py +0 -0
  89. {fal-1.10.0 → fal-1.11.0}/src/fal/app.py +0 -0
  90. {fal-1.10.0 → fal-1.11.0}/src/fal/apps.py +0 -0
  91. {fal-1.10.0 → fal-1.11.0}/src/fal/auth/__init__.py +0 -0
  92. {fal-1.10.0 → fal-1.11.0}/src/fal/auth/auth0.py +0 -0
  93. {fal-1.10.0 → fal-1.11.0}/src/fal/auth/local.py +0 -0
  94. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/__init__.py +0 -0
  95. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/_utils.py +0 -0
  96. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/api.py +0 -0
  97. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/apps.py +0 -0
  98. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/auth.py +0 -0
  99. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/cli_nested_json.py +0 -0
  100. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/create.py +0 -0
  101. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/debug.py +0 -0
  102. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/deploy.py +0 -0
  103. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/doctor.py +0 -0
  104. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/keys.py +0 -0
  105. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/main.py +0 -0
  106. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/parser.py +0 -0
  107. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/profile.py +0 -0
  108. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/run.py +0 -0
  109. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/runners.py +0 -0
  110. {fal-1.10.0 → fal-1.11.0}/src/fal/cli/secrets.py +0 -0
  111. {fal-1.10.0 → fal-1.11.0}/src/fal/config.py +0 -0
  112. {fal-1.10.0 → fal-1.11.0}/src/fal/console/__init__.py +0 -0
  113. {fal-1.10.0 → fal-1.11.0}/src/fal/console/icons.py +0 -0
  114. {fal-1.10.0 → fal-1.11.0}/src/fal/console/ux.py +0 -0
  115. {fal-1.10.0 → fal-1.11.0}/src/fal/exceptions/__init__.py +0 -0
  116. {fal-1.10.0 → fal-1.11.0}/src/fal/exceptions/_base.py +0 -0
  117. {fal-1.10.0 → fal-1.11.0}/src/fal/exceptions/_cuda.py +0 -0
  118. {fal-1.10.0 → fal-1.11.0}/src/fal/exceptions/auth.py +0 -0
  119. {fal-1.10.0 → fal-1.11.0}/src/fal/files.py +0 -0
  120. {fal-1.10.0 → fal-1.11.0}/src/fal/flags.py +0 -0
  121. {fal-1.10.0 → fal-1.11.0}/src/fal/logging/__init__.py +0 -0
  122. {fal-1.10.0 → fal-1.11.0}/src/fal/logging/isolate.py +0 -0
  123. {fal-1.10.0 → fal-1.11.0}/src/fal/logging/style.py +0 -0
  124. {fal-1.10.0 → fal-1.11.0}/src/fal/logging/trace.py +0 -0
  125. {fal-1.10.0 → fal-1.11.0}/src/fal/logging/user.py +0 -0
  126. {fal-1.10.0 → fal-1.11.0}/src/fal/py.typed +0 -0
  127. {fal-1.10.0 → fal-1.11.0}/src/fal/rest_client.py +0 -0
  128. {fal-1.10.0 → fal-1.11.0}/src/fal/sdk.py +0 -0
  129. {fal-1.10.0 → fal-1.11.0}/src/fal/sync.py +0 -0
  130. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/__init__.py +0 -0
  131. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/exceptions.py +0 -0
  132. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/file/__init__.py +0 -0
  133. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/file/file.py +0 -0
  134. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/file/providers/fal.py +0 -0
  135. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/file/providers/gcp.py +0 -0
  136. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/file/providers/r2.py +0 -0
  137. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/file/providers/s3.py +0 -0
  138. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/file/types.py +0 -0
  139. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/image/__init__.py +0 -0
  140. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/image/image.py +0 -0
  141. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
  142. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
  143. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
  144. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
  145. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
  146. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/image/safety_checker.py +0 -0
  147. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/optimize.py +0 -0
  148. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/types.py +0 -0
  149. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/utils/__init__.py +0 -0
  150. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/utils/download_utils.py +0 -0
  151. {fal-1.10.0 → fal-1.11.0}/src/fal/toolkit/utils/retry.py +0 -0
  152. {fal-1.10.0 → fal-1.11.0}/src/fal/utils.py +0 -0
  153. {fal-1.10.0 → fal-1.11.0}/src/fal/workflows.py +0 -0
  154. {fal-1.10.0 → fal-1.11.0}/tests/__init__.py +0 -0
  155. {fal-1.10.0 → fal-1.11.0}/tests/assets/cat.png +0 -0
  156. {fal-1.10.0 → fal-1.11.0}/tests/cli/__init__.py +0 -0
  157. {fal-1.10.0 → fal-1.11.0}/tests/cli/test_apps.py +0 -0
  158. {fal-1.10.0 → fal-1.11.0}/tests/cli/test_auth.py +0 -0
  159. {fal-1.10.0 → fal-1.11.0}/tests/cli/test_deploy.py +0 -0
  160. {fal-1.10.0 → fal-1.11.0}/tests/cli/test_keys.py +0 -0
  161. {fal-1.10.0 → fal-1.11.0}/tests/cli/test_run.py +0 -0
  162. {fal-1.10.0 → fal-1.11.0}/tests/cli/test_secrets.py +0 -0
  163. {fal-1.10.0 → fal-1.11.0}/tests/conftest.py +0 -0
  164. {fal-1.10.0 → fal-1.11.0}/tests/integration_test.py +0 -0
  165. {fal-1.10.0 → fal-1.11.0}/tests/mainify_package/__init__.py +0 -0
  166. {fal-1.10.0 → fal-1.11.0}/tests/mainify_package/impl.py +0 -0
  167. {fal-1.10.0 → fal-1.11.0}/tests/mainify_package/utils.py +0 -0
  168. {fal-1.10.0 → fal-1.11.0}/tests/mainify_target.py +0 -0
  169. {fal-1.10.0 → fal-1.11.0}/tests/test_stability.py +0 -0
  170. {fal-1.10.0 → fal-1.11.0}/tests/toolkit/file_test.py +0 -0
  171. {fal-1.10.0 → fal-1.11.0}/tests/toolkit/image_test.py +0 -0
  172. {fal-1.10.0 → fal-1.11.0}/tests/toolkit/test_types.py +0 -0
  173. {fal-1.10.0 → fal-1.11.0}/tests/toolkit/utils/retry.py +0 -0
  174. {fal-1.10.0 → fal-1.11.0}/tools/demo_script.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: fal
3
- Version: 1.10.0
3
+ Version: 1.11.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
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: fal
3
- Version: 1.10.0
3
+ Version: 1.11.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
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '1.10.0'
21
- __version_tuple__ = version_tuple = (1, 10, 0)
20
+ __version__ = version = '1.11.0'
21
+ __version_tuple__ = version_tuple = (1, 11, 0)
@@ -4,6 +4,8 @@ from typing import Dict, Literal
4
4
  Builder = Literal["depot", "service", "worker"]
5
5
  BUILDERS = {"depot", "service", "worker"}
6
6
  DEFAULT_BUILDER: Builder = "depot"
7
+ DEFAULT_COMPRESSION: str = "gzip"
8
+ DEFAULT_FORCE_COMPRESSION: bool = False
7
9
 
8
10
 
9
11
  @dataclass
@@ -16,6 +18,8 @@ class ContainerImage:
16
18
  build_args: Dict[str, str] = field(default_factory=dict)
17
19
  registries: Dict[str, Dict[str, str]] = field(default_factory=dict)
18
20
  builder: Builder = field(default=DEFAULT_BUILDER)
21
+ compression: str = DEFAULT_COMPRESSION
22
+ force_compression: bool = DEFAULT_FORCE_COMPRESSION
19
23
 
20
24
  def __post_init__(self) -> None:
21
25
  if self.registries:
@@ -46,4 +50,6 @@ class ContainerImage:
46
50
  "build_args": self.build_args,
47
51
  "registries": self.registries,
48
52
  "builder": self.builder,
53
+ "compression": self.compression,
54
+ "force_compression": self.force_compression,
49
55
  }
@@ -3,8 +3,9 @@ import json
3
3
  import secrets
4
4
  import subprocess
5
5
  import time
6
+ import uuid
6
7
  from contextlib import contextmanager, suppress
7
- from datetime import datetime
8
+ from datetime import datetime, timedelta
8
9
  from typing import Generator, List, Tuple
9
10
 
10
11
  import httpx
@@ -295,8 +296,6 @@ class RealtimeApp(fal.App, keep_alive=300, max_concurrency=1):
295
296
  def aliased_app() -> Generator[Tuple[str, str], None, None]:
296
297
  # Create a temporary app, register it, and return the ID of it.
297
298
 
298
- import uuid
299
-
300
299
  app_alias = str(uuid.uuid4()) + "-alias"
301
300
  app_revision = addition_app.host.register(
302
301
  func=addition_app.func,
@@ -514,8 +513,6 @@ def test_app_cancellation(test_app: str, test_cancellable_app: str):
514
513
 
515
514
  @pytest.mark.flaky(max_runs=3)
516
515
  def test_app_client_async():
517
- import uuid
518
-
519
516
  app_alias = str(uuid.uuid4()) + "-client-async-alias"
520
517
 
521
518
  app = fal.wrap_app(SleepApp)
@@ -548,11 +545,11 @@ def test_app_client_async():
548
545
  elif isinstance(event, apps.Queued):
549
546
  assert event.position == 0
550
547
 
551
- status = handle.status(logs=True)
552
- assert isinstance(status, apps.Completed)
553
- if not status.logs:
554
- # Sometimes fetching logs times out to get faster results
548
+ for _ in range(10):
555
549
  status = handle.status(logs=True)
550
+ assert isinstance(status, apps.Completed)
551
+ if status.logs:
552
+ break
556
553
 
557
554
  assert status.logs, "Logs missing from Completed status"
558
555
  assert any("sleeping..." in log["message"] for log in status.logs)
@@ -609,7 +606,6 @@ def test_404_response(test_app: str, request: pytest.FixtureRequest):
609
606
 
610
607
 
611
608
  def test_app_deploy_scale(aliased_app: Tuple[str, str]):
612
- import uuid
613
609
  from dataclasses import replace
614
610
 
615
611
  app_alias = str(uuid.uuid4()) + "-alias"
@@ -823,8 +819,10 @@ def test_workflows(test_app: str):
823
819
  assert data["result"] == 10
824
820
 
825
821
 
822
+ # If the logging subsystem is not working for some nodes, this test will flake
823
+ @pytest.mark.flaky(max_runs=5)
826
824
  def test_traceback_logs(test_exception_app: AppClient):
827
- date = datetime.utcnow().isoformat()
825
+ date = (datetime.utcnow() - timedelta(seconds=1)).isoformat()
828
826
 
829
827
  with pytest.raises(AppClientError):
830
828
  test_exception_app.fail({})
@@ -835,16 +833,25 @@ def test_traceback_logs(test_exception_app: AppClient):
835
833
  timeout=300,
836
834
  ) as client:
837
835
  # Give some time for logs to propagate through the logging subsystem.
838
- time.sleep(5)
839
- response = client.get(
840
- REST_CLIENT.base_url + f"/logs/?traceback=true&since={date}"
841
- )
842
- for log in json.loads(response.text):
843
- assert log["message"].count("\n") > 1, "Logs are multi-line"
844
- assert '{"traceback":' not in log["message"], "Logs are not JSON-wrapped"
836
+ for _ in range(10):
837
+ time.sleep(2)
838
+ response = client.get(
839
+ REST_CLIENT.base_url + f"/logs/?traceback=true&since={date}"
840
+ )
841
+
842
+ logs = response.json()
843
+ if len(logs) > 0:
844
+ break
845
+
846
+ assert len(logs) > 0
847
+ for log in logs:
848
+ assert log["message"].count("\n") > 1, "Logs should be multi-line"
849
+ assert (
850
+ '{"traceback":' not in log["message"]
851
+ ), "Logs should not be JSON-wrapped"
845
852
  assert (
846
853
  "this app is designed to fail" in log["message"]
847
- ), "Logs contain the traceback message"
854
+ ), "Logs should contain the traceback message"
848
855
 
849
856
 
850
857
  def test_app_exceptions(test_exception_app: AppClient):
@@ -866,8 +873,6 @@ def test_app_exceptions(test_exception_app: AppClient):
866
873
 
867
874
 
868
875
  def test_kill_runner():
869
- import uuid
870
-
871
876
  app_alias = str(uuid.uuid4()) + "-sleep-alias"
872
877
  app = fal.wrap_app(SleepApp)
873
878
  app_revision = app.host.register(
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
File without changes
File without changes