fal 1.7.0__tar.gz → 1.7.2__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.7.0/fal.egg-info → fal-1.7.2}/PKG-INFO +1 -1
  2. {fal-1.7.0 → fal-1.7.2/fal.egg-info}/PKG-INFO +1 -1
  3. {fal-1.7.0 → fal-1.7.2}/fal.egg-info/SOURCES.txt +1 -0
  4. {fal-1.7.0 → fal-1.7.2}/src/fal/_fal_version.py +2 -2
  5. {fal-1.7.0 → fal-1.7.2}/src/fal/api.py +1 -0
  6. {fal-1.7.0 → fal-1.7.2}/src/fal/auth/__init__.py +4 -1
  7. fal-1.7.2/src/fal/config.py +23 -0
  8. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/file/file.py +10 -22
  9. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/file/providers/fal.py +15 -12
  10. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/utils/retry.py +3 -0
  11. {fal-1.7.0 → fal-1.7.2}/tests/integration_test.py +6 -6
  12. {fal-1.7.0 → fal-1.7.2}/tests/test_stability.py +3 -1
  13. {fal-1.7.0 → fal-1.7.2}/tests/toolkit/image_test.py +4 -4
  14. {fal-1.7.0 → fal-1.7.2}/.gitignore +0 -0
  15. {fal-1.7.0 → fal-1.7.2}/Makefile +0 -0
  16. {fal-1.7.0 → fal-1.7.2}/README.md +0 -0
  17. {fal-1.7.0 → fal-1.7.2}/docs/conf.py +0 -0
  18. {fal-1.7.0 → fal-1.7.2}/docs/index.rst +0 -0
  19. {fal-1.7.0 → fal-1.7.2}/fal.egg-info/dependency_links.txt +0 -0
  20. {fal-1.7.0 → fal-1.7.2}/fal.egg-info/entry_points.txt +0 -0
  21. {fal-1.7.0 → fal-1.7.2}/fal.egg-info/requires.txt +0 -0
  22. {fal-1.7.0 → fal-1.7.2}/fal.egg-info/top_level.txt +0 -0
  23. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/README.md +0 -0
  24. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
  25. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
  26. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
  27. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
  28. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
  29. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
  30. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
  31. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
  32. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
  33. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
  34. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
  35. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
  36. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
  37. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
  38. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
  39. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
  40. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
  41. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
  42. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
  43. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
  44. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
  45. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
  46. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
  47. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
  48. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
  49. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
  50. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
  51. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
  52. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
  53. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
  54. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
  55. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
  56. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
  57. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
  58. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
  59. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
  60. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
  61. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
  62. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
  63. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
  64. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
  65. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
  66. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
  67. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
  68. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
  69. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
  70. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
  71. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
  72. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
  73. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
  74. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
  75. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
  76. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
  77. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
  78. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
  79. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
  80. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
  81. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
  82. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
  83. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
  84. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
  85. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
  86. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
  87. {fal-1.7.0 → fal-1.7.2}/openapi-fal-rest/pyproject.toml +0 -0
  88. {fal-1.7.0 → fal-1.7.2}/openapi_rest.config.yaml +0 -0
  89. {fal-1.7.0 → fal-1.7.2}/pyproject.toml +0 -0
  90. {fal-1.7.0 → fal-1.7.2}/setup.cfg +0 -0
  91. {fal-1.7.0 → fal-1.7.2}/src/fal/__init__.py +0 -0
  92. {fal-1.7.0 → fal-1.7.2}/src/fal/__main__.py +0 -0
  93. {fal-1.7.0 → fal-1.7.2}/src/fal/_serialization.py +0 -0
  94. {fal-1.7.0 → fal-1.7.2}/src/fal/_version.py +0 -0
  95. {fal-1.7.0 → fal-1.7.2}/src/fal/app.py +0 -0
  96. {fal-1.7.0 → fal-1.7.2}/src/fal/apps.py +0 -0
  97. {fal-1.7.0 → fal-1.7.2}/src/fal/auth/auth0.py +0 -0
  98. {fal-1.7.0 → fal-1.7.2}/src/fal/auth/local.py +0 -0
  99. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/__init__.py +0 -0
  100. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/_utils.py +0 -0
  101. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/apps.py +0 -0
  102. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/auth.py +0 -0
  103. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/create.py +0 -0
  104. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/debug.py +0 -0
  105. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/deploy.py +0 -0
  106. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/doctor.py +0 -0
  107. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/keys.py +0 -0
  108. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/main.py +0 -0
  109. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/parser.py +0 -0
  110. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/run.py +0 -0
  111. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/runners.py +0 -0
  112. {fal-1.7.0 → fal-1.7.2}/src/fal/cli/secrets.py +0 -0
  113. {fal-1.7.0 → fal-1.7.2}/src/fal/console/__init__.py +0 -0
  114. {fal-1.7.0 → fal-1.7.2}/src/fal/console/icons.py +0 -0
  115. {fal-1.7.0 → fal-1.7.2}/src/fal/console/ux.py +0 -0
  116. {fal-1.7.0 → fal-1.7.2}/src/fal/container.py +0 -0
  117. {fal-1.7.0 → fal-1.7.2}/src/fal/exceptions/__init__.py +0 -0
  118. {fal-1.7.0 → fal-1.7.2}/src/fal/exceptions/_base.py +0 -0
  119. {fal-1.7.0 → fal-1.7.2}/src/fal/exceptions/_cuda.py +0 -0
  120. {fal-1.7.0 → fal-1.7.2}/src/fal/exceptions/auth.py +0 -0
  121. {fal-1.7.0 → fal-1.7.2}/src/fal/files.py +0 -0
  122. {fal-1.7.0 → fal-1.7.2}/src/fal/flags.py +0 -0
  123. {fal-1.7.0 → fal-1.7.2}/src/fal/logging/__init__.py +0 -0
  124. {fal-1.7.0 → fal-1.7.2}/src/fal/logging/isolate.py +0 -0
  125. {fal-1.7.0 → fal-1.7.2}/src/fal/logging/style.py +0 -0
  126. {fal-1.7.0 → fal-1.7.2}/src/fal/logging/trace.py +0 -0
  127. {fal-1.7.0 → fal-1.7.2}/src/fal/logging/user.py +0 -0
  128. {fal-1.7.0 → fal-1.7.2}/src/fal/py.typed +0 -0
  129. {fal-1.7.0 → fal-1.7.2}/src/fal/rest_client.py +0 -0
  130. {fal-1.7.0 → fal-1.7.2}/src/fal/sdk.py +0 -0
  131. {fal-1.7.0 → fal-1.7.2}/src/fal/sync.py +0 -0
  132. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/__init__.py +0 -0
  133. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/exceptions.py +0 -0
  134. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/file/__init__.py +0 -0
  135. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/file/providers/gcp.py +0 -0
  136. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/file/providers/r2.py +0 -0
  137. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/file/providers/s3.py +0 -0
  138. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/file/types.py +0 -0
  139. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/image/__init__.py +0 -0
  140. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/image/image.py +0 -0
  141. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
  142. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
  143. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
  144. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
  145. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
  146. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/image/safety_checker.py +0 -0
  147. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/optimize.py +0 -0
  148. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/types.py +0 -0
  149. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/utils/__init__.py +0 -0
  150. {fal-1.7.0 → fal-1.7.2}/src/fal/toolkit/utils/download_utils.py +0 -0
  151. {fal-1.7.0 → fal-1.7.2}/src/fal/utils.py +0 -0
  152. {fal-1.7.0 → fal-1.7.2}/src/fal/workflows.py +0 -0
  153. {fal-1.7.0 → fal-1.7.2}/tests/__init__.py +0 -0
  154. {fal-1.7.0 → fal-1.7.2}/tests/assets/cat.png +0 -0
  155. {fal-1.7.0 → fal-1.7.2}/tests/cli/__init__.py +0 -0
  156. {fal-1.7.0 → fal-1.7.2}/tests/cli/test_apps.py +0 -0
  157. {fal-1.7.0 → fal-1.7.2}/tests/cli/test_auth.py +0 -0
  158. {fal-1.7.0 → fal-1.7.2}/tests/cli/test_deploy.py +0 -0
  159. {fal-1.7.0 → fal-1.7.2}/tests/cli/test_keys.py +0 -0
  160. {fal-1.7.0 → fal-1.7.2}/tests/cli/test_run.py +0 -0
  161. {fal-1.7.0 → fal-1.7.2}/tests/cli/test_secrets.py +0 -0
  162. {fal-1.7.0 → fal-1.7.2}/tests/conftest.py +0 -0
  163. {fal-1.7.0 → fal-1.7.2}/tests/mainify_package/__init__.py +0 -0
  164. {fal-1.7.0 → fal-1.7.2}/tests/mainify_package/impl.py +0 -0
  165. {fal-1.7.0 → fal-1.7.2}/tests/mainify_package/utils.py +0 -0
  166. {fal-1.7.0 → fal-1.7.2}/tests/mainify_target.py +0 -0
  167. {fal-1.7.0 → fal-1.7.2}/tests/test_apps.py +0 -0
  168. {fal-1.7.0 → fal-1.7.2}/tests/toolkit/file_test.py +0 -0
  169. {fal-1.7.0 → fal-1.7.2}/tests/toolkit/test_types.py +0 -0
  170. {fal-1.7.0 → fal-1.7.2}/tests/toolkit/utils/retry.py +0 -0
  171. {fal-1.7.0 → fal-1.7.2}/tools/demo_script.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fal
3
- Version: 1.7.0
3
+ Version: 1.7.2
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
1
  Metadata-Version: 2.2
2
2
  Name: fal
3
- Version: 1.7.0
3
+ Version: 1.7.2
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
@@ -84,6 +84,7 @@ src/fal/_version.py
84
84
  src/fal/api.py
85
85
  src/fal/app.py
86
86
  src/fal/apps.py
87
+ src/fal/config.py
87
88
  src/fal/container.py
88
89
  src/fal/files.py
89
90
  src/fal/flags.py
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.7.0'
16
- __version_tuple__ = version_tuple = (1, 7, 0)
15
+ __version__ = version = '1.7.2'
16
+ __version_tuple__ = version_tuple = (1, 7, 2)
@@ -77,6 +77,7 @@ SERVE_REQUIREMENTS = [
77
77
  "uvicorn",
78
78
  "starlette_exporter",
79
79
  "structlog",
80
+ "tomli",
80
81
  ]
81
82
 
82
83
 
@@ -8,6 +8,7 @@ from typing import Optional
8
8
  import click
9
9
 
10
10
  from fal.auth import auth0, local
11
+ from fal.config import Config
11
12
  from fal.console import console
12
13
  from fal.console.icons import CHECK_ICON
13
14
  from fal.exceptions.auth import UnauthenticatedException
@@ -61,7 +62,9 @@ def key_credentials() -> tuple[str, str] | None:
61
62
  if os.environ.get("FAL_FORCE_AUTH_BY_USER") == "1":
62
63
  return None
63
64
 
64
- key = os.environ.get("FAL_KEY") or get_colab_token()
65
+ config = Config()
66
+
67
+ key = os.environ.get("FAL_KEY") or config.get("key") or get_colab_token()
65
68
  if key:
66
69
  key_id, key_secret = key.split(":", 1)
67
70
  return (key_id, key_secret)
@@ -0,0 +1,23 @@
1
+ import os
2
+
3
+ import tomli
4
+
5
+
6
+ class Config:
7
+ DEFAULT_CONFIG_PATH = "~/.fal/config.toml"
8
+ DEFAULT_PROFILE = "default"
9
+
10
+ def __init__(self):
11
+ self.config_path = os.path.expanduser(
12
+ os.getenv("FAL_CONFIG_PATH", self.DEFAULT_CONFIG_PATH)
13
+ )
14
+ self.profile = os.getenv("FAL_PROFILE", self.DEFAULT_PROFILE)
15
+
16
+ try:
17
+ with open(self.config_path, "rb") as file:
18
+ self.config = tomli.load(file)
19
+ except FileNotFoundError:
20
+ self.config = {}
21
+
22
+ def get(self, key):
23
+ return self.config.get(self.profile, {}).get(key)
@@ -47,7 +47,10 @@ BUILT_IN_REPOSITORIES: dict[RepositoryId, FileRepositoryFactory] = {
47
47
  }
48
48
 
49
49
 
50
- def get_builtin_repository(id: RepositoryId) -> FileRepository:
50
+ def get_builtin_repository(id: RepositoryId | FileRepository) -> FileRepository:
51
+ if isinstance(id, FileRepository):
52
+ return id
53
+
51
54
  if id not in BUILT_IN_REPOSITORIES.keys():
52
55
  raise ValueError(f'"{id}" is not a valid built-in file repository')
53
56
  return BUILT_IN_REPOSITORIES[id]()
@@ -122,7 +125,8 @@ class File(BaseModel):
122
125
  url=url,
123
126
  content_type=None,
124
127
  file_name=None,
125
- repository=DEFAULT_REPOSITORY,
128
+ file_size=None,
129
+ file_data=None,
126
130
  )
127
131
 
128
132
  @classmethod
@@ -139,11 +143,7 @@ class File(BaseModel):
139
143
  save_kwargs: Optional[dict] = None,
140
144
  fallback_save_kwargs: Optional[dict] = None,
141
145
  ) -> File:
142
- repo = (
143
- repository
144
- if isinstance(repository, FileRepository)
145
- else get_builtin_repository(repository)
146
- )
146
+ repo = get_builtin_repository(repository)
147
147
 
148
148
  save_kwargs = save_kwargs or {}
149
149
  fallback_save_kwargs = fallback_save_kwargs or {}
@@ -160,11 +160,7 @@ class File(BaseModel):
160
160
  if not fallback_repository:
161
161
  raise
162
162
 
163
- fallback_repo = (
164
- fallback_repository
165
- if isinstance(fallback_repository, FileRepository)
166
- else get_builtin_repository(fallback_repository)
167
- )
163
+ fallback_repo = get_builtin_repository(fallback_repository)
168
164
 
169
165
  url = fallback_repo.save(
170
166
  fdata, object_lifecycle_preference, **fallback_save_kwargs
@@ -196,11 +192,7 @@ class File(BaseModel):
196
192
  if not file_path.exists():
197
193
  raise FileNotFoundError(f"File {file_path} does not exist")
198
194
 
199
- repo = (
200
- repository
201
- if isinstance(repository, FileRepository)
202
- else get_builtin_repository(repository)
203
- )
195
+ repo = get_builtin_repository(repository)
204
196
 
205
197
  save_kwargs = save_kwargs or {}
206
198
  fallback_save_kwargs = fallback_save_kwargs or {}
@@ -222,11 +214,7 @@ class File(BaseModel):
222
214
  if not fallback_repository:
223
215
  raise
224
216
 
225
- fallback_repo = (
226
- fallback_repository
227
- if isinstance(fallback_repository, FileRepository)
228
- else get_builtin_repository(fallback_repository)
229
- )
217
+ fallback_repo = get_builtin_repository(fallback_repository)
230
218
 
231
219
  url, data = fallback_repo.save_file(
232
220
  file_path,
@@ -159,24 +159,27 @@ class FalFileRepositoryBase(FileRepository):
159
159
  result = json.load(response)
160
160
 
161
161
  upload_url = result["upload_url"]
162
- self._upload_file(upload_url, file)
163
-
164
- return result["file_url"]
165
162
  except HTTPError as e:
166
163
  raise FileUploadException(
167
164
  f"Error initiating upload. Status {e.status}: {e.reason}"
168
165
  )
169
166
 
170
- def _upload_file(self, upload_url: str, file: FileData):
171
- req = Request(
172
- upload_url,
173
- method="PUT",
174
- data=file.data,
175
- headers={"Content-Type": file.content_type},
176
- )
167
+ try:
168
+ req = Request(
169
+ upload_url,
170
+ method="PUT",
171
+ data=file.data,
172
+ headers={"Content-Type": file.content_type},
173
+ )
174
+
175
+ with urlopen(req):
176
+ pass
177
177
 
178
- with urlopen(req):
179
- return
178
+ return result["file_url"]
179
+ except HTTPError as e:
180
+ raise FileUploadException(
181
+ f"Error uploading file. Status {e.status}: {e.reason}"
182
+ )
180
183
 
181
184
 
182
185
  @dataclass
@@ -1,6 +1,7 @@
1
1
  import functools
2
2
  import random
3
3
  import time
4
+ import traceback
4
5
  from typing import Any, Callable, Literal
5
6
 
6
7
  BackoffType = Literal["exponential", "fixed"]
@@ -25,6 +26,8 @@ def retry(
25
26
  print(f"Retrying {retries} of {max_retries}...")
26
27
  if retries == max_retries:
27
28
  print(f"Max retries reached. Raising exception: {e}")
29
+ traceback.print_exc()
30
+
28
31
  raise e
29
32
 
30
33
  if backoff_type == "exponential":
@@ -458,7 +458,7 @@ def fal_file_content_matches(file: File, content: str):
458
458
 
459
459
 
460
460
  def test_fal_file_from_path(isolated_client):
461
- @isolated_client(requirements=[f"pydantic=={pydantic_version}"])
461
+ @isolated_client(requirements=[f"pydantic=={pydantic_version}", "tomli"])
462
462
  def fal_file_from_temp(content: str):
463
463
  with tempfile.NamedTemporaryFile() as temp_file:
464
464
  file_path = temp_file.name
@@ -475,7 +475,7 @@ def test_fal_file_from_path(isolated_client):
475
475
 
476
476
 
477
477
  def test_fal_file_from_bytes(isolated_client):
478
- @isolated_client(requirements=[f"pydantic=={pydantic_version}"])
478
+ @isolated_client(requirements=[f"pydantic=={pydantic_version}", "tomli"])
479
479
  def fal_file_from_bytes(content: str):
480
480
  return File.from_bytes(content.encode(), repository="in_memory")
481
481
 
@@ -486,7 +486,7 @@ def test_fal_file_from_bytes(isolated_client):
486
486
 
487
487
 
488
488
  def test_fal_file_save(isolated_client):
489
- @isolated_client(requirements=[f"pydantic=={pydantic_version}"])
489
+ @isolated_client(requirements=[f"pydantic=={pydantic_version}", "tomli"])
490
490
  def fal_file_to_local_file(content: str):
491
491
  file = File.from_bytes(content.encode(), repository="in_memory")
492
492
 
@@ -521,7 +521,7 @@ def test_fal_file_input(isolated_client, file_url: str, expected_content: str):
521
521
  class TestInput(BaseModel):
522
522
  file: File = Field()
523
523
 
524
- @isolated_client(requirements=[f"pydantic=={pydantic_version}"])
524
+ @isolated_client(requirements=[f"pydantic=={pydantic_version}", "tomli"])
525
525
  def init_file_on_fal(input: TestInput) -> File:
526
526
  return input.file
527
527
 
@@ -542,7 +542,7 @@ def test_fal_compressed_file(isolated_client):
542
542
  class TestInput(BaseModel):
543
543
  files: CompressedFile
544
544
 
545
- @isolated_client(requirements=[f"pydantic=={pydantic_version}"])
545
+ @isolated_client(requirements=[f"pydantic=={pydantic_version}", "tomli"])
546
546
  def init_compressed_file_on_fal(input: TestInput) -> int:
547
547
  extracted_file_paths = [file for file in input.files]
548
548
  return extracted_file_paths
@@ -557,7 +557,7 @@ def test_fal_compressed_file(isolated_client):
557
557
 
558
558
 
559
559
  def test_fal_cdn(isolated_client):
560
- @isolated_client(requirements=[f"pydantic=={pydantic_version}"])
560
+ @isolated_client(requirements=[f"pydantic=={pydantic_version}", "tomli"])
561
561
  def upload_to_fal_cdn() -> FalImage:
562
562
  return FalImage.from_bytes(b"0", "jpeg", repository="cdn")
563
563
 
@@ -595,7 +595,9 @@ def test_fal_storage(isolated_client, repo_type, url_prefix):
595
595
  assert file.url.startswith(url_prefix)
596
596
  assert file.as_bytes().decode().endswith("local")
597
597
 
598
- @isolated_client(serve=True, requirements=[f"pydantic=={pydantic_version}"])
598
+ @isolated_client(
599
+ serve=True, requirements=[f"pydantic=={pydantic_version}", "tomli"]
600
+ )
599
601
  def hello_file():
600
602
  # Run in the isolated environment
601
603
  return File.from_bytes(
@@ -77,7 +77,7 @@ def assert_fal_images_equals(fal_image_1: Image, fal_image_2: Image):
77
77
 
78
78
 
79
79
  def test_fal_image_from_pil(isolated_client):
80
- @isolated_client(requirements=["pillow", f"pydantic=={pydantic_version}"])
80
+ @isolated_client(requirements=["pillow", f"pydantic=={pydantic_version}", "tomli"])
81
81
  def fal_image_from_bytes_remote():
82
82
  pil_image = get_image()
83
83
  return Image.from_pil(pil_image, repository="in_memory")
@@ -87,7 +87,7 @@ def test_fal_image_from_pil(isolated_client):
87
87
 
88
88
 
89
89
  def test_fal_image_from_bytes(isolated_client):
90
- @isolated_client(requirements=["pillow", f"pydantic=={pydantic_version}"])
90
+ @isolated_client(requirements=["pillow", f"pydantic=={pydantic_version}", "tomli"])
91
91
  def fal_image_from_bytes_remote():
92
92
  image_bytes = get_image(as_bytes=True)
93
93
  return Image.from_bytes(image_bytes, repository="in_memory", format="png")
@@ -107,7 +107,7 @@ def test_fal_image_input(isolated_client, image_url):
107
107
  class TestInput(BaseModel):
108
108
  image: Image = Field()
109
109
 
110
- @isolated_client(requirements=["pillow", f"pydantic=={pydantic_version}"])
110
+ @isolated_client(requirements=["pillow", f"pydantic=={pydantic_version}", "tomli"])
111
111
  def init_image_on_fal(input: TestInput) -> Image:
112
112
  return TestInput(image=input.image).image
113
113
 
@@ -127,7 +127,7 @@ def test_fal_image_input_to_pil(isolated_client):
127
127
  class TestInput(BaseModel):
128
128
  image: Image = Field()
129
129
 
130
- @isolated_client(requirements=["pillow", f"pydantic=={pydantic_version}"])
130
+ @isolated_client(requirements=["pillow", f"pydantic=={pydantic_version}", "tomli"])
131
131
  def init_image_on_fal(input: TestInput) -> bytes:
132
132
  input_image = TestInput(image=input.image).image
133
133
  pil_image = input_image.to_pil()
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