fal 1.26.2__tar.gz → 1.26.4__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.
- {fal-1.26.2/fal.egg-info → fal-1.26.4}/PKG-INFO +1 -1
- {fal-1.26.2 → fal-1.26.4/fal.egg-info}/PKG-INFO +1 -1
- {fal-1.26.2 → fal-1.26.4}/src/fal/_fal_version.py +2 -2
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/profile.py +65 -8
- {fal-1.26.2 → fal-1.26.4}/src/fal/config.py +21 -17
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/file/providers/fal.py +24 -32
- {fal-1.26.2 → fal-1.26.4}/tests/test_apps.py +5 -5
- {fal-1.26.2 → fal-1.26.4}/.gitignore +0 -0
- {fal-1.26.2 → fal-1.26.4}/Makefile +0 -0
- {fal-1.26.2 → fal-1.26.4}/README.md +0 -0
- {fal-1.26.2 → fal-1.26.4}/docs/conf.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/docs/index.rst +0 -0
- {fal-1.26.2 → fal-1.26.4}/fal.egg-info/SOURCES.txt +0 -0
- {fal-1.26.2 → fal-1.26.4}/fal.egg-info/dependency_links.txt +0 -0
- {fal-1.26.2 → fal-1.26.4}/fal.egg-info/entry_points.txt +0 -0
- {fal-1.26.2 → fal-1.26.4}/fal.egg-info/requires.txt +0 -0
- {fal-1.26.2 → fal-1.26.4}/fal.egg-info/top_level.txt +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/README.md +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/pyproject.toml +0 -0
- {fal-1.26.2 → fal-1.26.4}/openapi_rest.config.yaml +0 -0
- {fal-1.26.2 → fal-1.26.4}/pyproject.toml +0 -0
- {fal-1.26.2 → fal-1.26.4}/setup.cfg +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/__main__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/_serialization.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/_version.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/api.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/app.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/apps.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/auth/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/auth/auth0.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/auth/local.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/_utils.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/api.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/apps.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/auth.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/cli_nested_json.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/create.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/debug.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/deploy.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/doctor.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/files.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/keys.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/main.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/parser.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/run.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/runners.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/secrets.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/cli/teams.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/console/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/console/icons.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/console/ux.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/container.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/exceptions/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/exceptions/_base.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/exceptions/_cuda.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/exceptions/auth.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/files.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/flags.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/logging/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/logging/isolate.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/logging/style.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/logging/trace.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/logging/user.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/project.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/py.typed +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/rest_client.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/sdk.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/sync.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/audio/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/audio/audio.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/exceptions.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/file/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/file/file.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/file/providers/gcp.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/file/providers/r2.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/file/providers/s3.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/file/types.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/image/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/image/image.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/image/safety_checker.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/kv.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/optimize.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/types.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/utils/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/utils/download_utils.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/utils/endpoint.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/utils/retry.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/video/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/toolkit/video/video.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/utils.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/src/fal/workflows.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/assets/cat.png +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/cli/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/cli/test_apps.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/cli/test_auth.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/cli/test_deploy.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/cli/test_keys.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/cli/test_run.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/cli/test_secrets.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/conftest.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/integration_test.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/mainify_package/__init__.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/mainify_package/impl.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/mainify_package/utils.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/mainify_target.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/test_kv.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/test_stability.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/toolkit/file/providers/test_fal_retry.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/toolkit/file_test.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/toolkit/image_test.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/toolkit/test_types.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tests/toolkit/utils/retry.py +0 -0
- {fal-1.26.2 → fal-1.26.4}/tools/demo_script.py +0 -0
|
@@ -23,14 +23,38 @@ def _list(args):
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _set(args):
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
config = Config()
|
|
27
|
+
|
|
28
|
+
# Check if the profile exists
|
|
29
|
+
if args.PROFILE not in config._config:
|
|
30
|
+
# Profile doesn't exist, offer to create it
|
|
31
|
+
args.console.print(f"Profile [cyan]{args.PROFILE}[/] does not exist.")
|
|
32
|
+
create_profile = input("Would you like to create it? (y/N): ").strip().lower()
|
|
33
|
+
|
|
34
|
+
if create_profile in ["y", "yes"]:
|
|
35
|
+
# Create the profile by setting it
|
|
36
|
+
with config.edit() as config:
|
|
37
|
+
config.set_internal("profile", args.PROFILE)
|
|
38
|
+
config._config[args.PROFILE] = {}
|
|
39
|
+
config._profile = args.PROFILE
|
|
31
40
|
args.console.print(
|
|
32
|
-
"
|
|
41
|
+
f"Profile [cyan]{args.PROFILE}[/] created and set as default."
|
|
33
42
|
)
|
|
43
|
+
else:
|
|
44
|
+
args.console.print("Profile creation cancelled.")
|
|
45
|
+
return
|
|
46
|
+
else:
|
|
47
|
+
# Profile exists, just set it as default
|
|
48
|
+
with config.edit() as config:
|
|
49
|
+
config.set_internal("profile", args.PROFILE)
|
|
50
|
+
config._profile = args.PROFILE
|
|
51
|
+
args.console.print(f"Default profile set to [cyan]{args.PROFILE}[/].")
|
|
52
|
+
|
|
53
|
+
# Check if key is set for the profile
|
|
54
|
+
if not config.get("key"):
|
|
55
|
+
args.console.print(
|
|
56
|
+
"No key set for profile. Use [bold]fal profile key[/] to set a key."
|
|
57
|
+
)
|
|
34
58
|
|
|
35
59
|
|
|
36
60
|
def _unset(args, config: Config | None = None):
|
|
@@ -42,6 +66,8 @@ def _unset(args, config: Config | None = None):
|
|
|
42
66
|
|
|
43
67
|
|
|
44
68
|
def _key_set(args):
|
|
69
|
+
config = Config(validate_profile=True)
|
|
70
|
+
|
|
45
71
|
while True:
|
|
46
72
|
key = input("Enter the key: ")
|
|
47
73
|
if ":" in key:
|
|
@@ -50,7 +76,7 @@ def _key_set(args):
|
|
|
50
76
|
"[red]Invalid key. The key must be in the format [bold]key:value[/].[/]"
|
|
51
77
|
)
|
|
52
78
|
|
|
53
|
-
with
|
|
79
|
+
with config.edit():
|
|
54
80
|
config.set("key", key)
|
|
55
81
|
args.console.print(f"Key set for profile [cyan]{config.profile}[/].")
|
|
56
82
|
|
|
@@ -61,6 +87,24 @@ def _host_set(args):
|
|
|
61
87
|
args.console.print(f"Fal host set to [cyan]{args.HOST}[/].")
|
|
62
88
|
|
|
63
89
|
|
|
90
|
+
def _create(args):
|
|
91
|
+
config = Config()
|
|
92
|
+
|
|
93
|
+
# Check if the profile already exists
|
|
94
|
+
if args.PROFILE in config._config:
|
|
95
|
+
args.console.print(f"Profile [cyan]{args.PROFILE}[/] already exists.")
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
# Create the profile
|
|
99
|
+
with config.edit() as config:
|
|
100
|
+
config._config[args.PROFILE] = {}
|
|
101
|
+
|
|
102
|
+
args.console.print(f"Profile [cyan]{args.PROFILE}[/] created.")
|
|
103
|
+
args.console.print(
|
|
104
|
+
f"Use [bold]fal profile set {args.PROFILE}[/] to set it as default."
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
64
108
|
def _delete(args):
|
|
65
109
|
with Config().edit() as config:
|
|
66
110
|
if config.profile == args.PROFILE:
|
|
@@ -96,7 +140,7 @@ def add_parser(main_subparsers, parents):
|
|
|
96
140
|
)
|
|
97
141
|
list_parser.set_defaults(func=_list)
|
|
98
142
|
|
|
99
|
-
set_help = "Set default profile."
|
|
143
|
+
set_help = "Set default profile. If the profile doesn't exist, you'll be prompted to create it." # noqa: E501
|
|
100
144
|
set_parser = subparsers.add_parser(
|
|
101
145
|
"set",
|
|
102
146
|
description=set_help,
|
|
@@ -140,6 +184,19 @@ def add_parser(main_subparsers, parents):
|
|
|
140
184
|
)
|
|
141
185
|
host_set_parser.set_defaults(func=_host_set)
|
|
142
186
|
|
|
187
|
+
create_help = "Create a new profile. Use 'fal profile set <name>' to set it as default after creation." # noqa: E501
|
|
188
|
+
create_parser = subparsers.add_parser(
|
|
189
|
+
"create",
|
|
190
|
+
description=create_help,
|
|
191
|
+
help=create_help,
|
|
192
|
+
parents=parents,
|
|
193
|
+
)
|
|
194
|
+
create_parser.add_argument(
|
|
195
|
+
"PROFILE",
|
|
196
|
+
help="Profile name.",
|
|
197
|
+
)
|
|
198
|
+
create_parser.set_defaults(func=_create)
|
|
199
|
+
|
|
143
200
|
delete_help = "Delete profile."
|
|
144
201
|
delete_parser = subparsers.add_parser(
|
|
145
202
|
"delete",
|
|
@@ -4,8 +4,9 @@ import os
|
|
|
4
4
|
from contextlib import contextmanager
|
|
5
5
|
from typing import Dict, Iterator, List, Optional
|
|
6
6
|
|
|
7
|
-
SETTINGS_SECTION = "__internal__"
|
|
8
|
-
|
|
7
|
+
SETTINGS_SECTION = "__internal__"
|
|
8
|
+
|
|
9
|
+
NO_PROFILE_ERROR = ValueError("No profile set.")
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class Config:
|
|
@@ -15,7 +16,7 @@ class Config:
|
|
|
15
16
|
|
|
16
17
|
DEFAULT_CONFIG_PATH = "~/.fal/config.toml"
|
|
17
18
|
|
|
18
|
-
def __init__(self):
|
|
19
|
+
def __init__(self, *, validate_profile: bool = False):
|
|
19
20
|
import tomli
|
|
20
21
|
|
|
21
22
|
self.config_path = os.path.expanduser(
|
|
@@ -28,11 +29,17 @@ class Config:
|
|
|
28
29
|
except FileNotFoundError:
|
|
29
30
|
self._config = {}
|
|
30
31
|
|
|
31
|
-
profile = (
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
profile = os.getenv("FAL_PROFILE") or self.get_internal("profile")
|
|
33
|
+
|
|
34
|
+
# Try to set the profile, but don't fail if it doesn't exist
|
|
35
|
+
try:
|
|
36
|
+
self.profile = profile
|
|
37
|
+
except ValueError:
|
|
38
|
+
# Profile doesn't exist, set to None
|
|
39
|
+
self._profile = None
|
|
34
40
|
|
|
35
|
-
self.profile
|
|
41
|
+
if validate_profile and not self.profile:
|
|
42
|
+
raise NO_PROFILE_ERROR
|
|
36
43
|
|
|
37
44
|
@property
|
|
38
45
|
def profile(self) -> Optional[str]:
|
|
@@ -41,9 +48,10 @@ class Config:
|
|
|
41
48
|
@profile.setter
|
|
42
49
|
def profile(self, value: Optional[str]) -> None:
|
|
43
50
|
if value and value not in self._config:
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
# Don't automatically create profiles - they should be created explicitly
|
|
52
|
+
raise ValueError(
|
|
53
|
+
f"Profile '{value}' does not exist. Create it first or use the profile set command." # noqa: E501
|
|
54
|
+
)
|
|
47
55
|
elif not value:
|
|
48
56
|
self.unset_internal("profile")
|
|
49
57
|
|
|
@@ -53,11 +61,7 @@ class Config:
|
|
|
53
61
|
keys: List[str] = []
|
|
54
62
|
for key in self._config:
|
|
55
63
|
if key != SETTINGS_SECTION:
|
|
56
|
-
|
|
57
|
-
# Add it at the beginning
|
|
58
|
-
keys.insert(0, key)
|
|
59
|
-
else:
|
|
60
|
-
keys.append(key)
|
|
64
|
+
keys.append(key)
|
|
61
65
|
|
|
62
66
|
return keys
|
|
63
67
|
|
|
@@ -75,13 +79,13 @@ class Config:
|
|
|
75
79
|
|
|
76
80
|
def set(self, key: str, value: str) -> None:
|
|
77
81
|
if not self.profile:
|
|
78
|
-
raise
|
|
82
|
+
raise NO_PROFILE_ERROR
|
|
79
83
|
|
|
80
84
|
self._config[self.profile][key] = value
|
|
81
85
|
|
|
82
86
|
def unset(self, key: str) -> None:
|
|
83
87
|
if not self.profile:
|
|
84
|
-
raise
|
|
88
|
+
raise NO_PROFILE_ERROR
|
|
85
89
|
|
|
86
90
|
self._config.get(self.profile, {}).pop(key, None)
|
|
87
91
|
|
|
@@ -9,7 +9,7 @@ from contextlib import contextmanager
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
10
|
from datetime import datetime, timezone
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Any, Generator, Generic, TypeVar
|
|
12
|
+
from typing import Any, Dict, Generator, Generic, TypeVar
|
|
13
13
|
from urllib.error import HTTPError
|
|
14
14
|
from urllib.parse import urlparse, urlunparse
|
|
15
15
|
from urllib.request import Request, urlopen
|
|
@@ -45,6 +45,9 @@ def _should_retry(exc: Exception) -> bool:
|
|
|
45
45
|
if isinstance(exc, HTTPError) and exc.code in RETRY_CODES:
|
|
46
46
|
return True
|
|
47
47
|
|
|
48
|
+
if isinstance(exc, TimeoutError):
|
|
49
|
+
return True
|
|
50
|
+
|
|
48
51
|
return False
|
|
49
52
|
|
|
50
53
|
|
|
@@ -66,6 +69,19 @@ def _maybe_retry_request(
|
|
|
66
69
|
yield response
|
|
67
70
|
|
|
68
71
|
|
|
72
|
+
def _object_lifecycle_headers(
|
|
73
|
+
headers: dict[str, str],
|
|
74
|
+
object_lifecycle_preference: dict[str, str] | None,
|
|
75
|
+
):
|
|
76
|
+
if object_lifecycle_preference:
|
|
77
|
+
# Used by V3 CDN
|
|
78
|
+
headers["X-Fal-Object-Lifecycle"] = json.dumps(object_lifecycle_preference)
|
|
79
|
+
# Used by V1 CDN
|
|
80
|
+
headers["X-Fal-Object-Lifecycle-Preference"] = json.dumps(
|
|
81
|
+
object_lifecycle_preference
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
69
85
|
@dataclass
|
|
70
86
|
class FalV2Token:
|
|
71
87
|
token: str
|
|
@@ -448,14 +464,6 @@ class MultipartUploadGCS:
|
|
|
448
464
|
|
|
449
465
|
@dataclass
|
|
450
466
|
class FalFileRepository(FalFileRepositoryBase):
|
|
451
|
-
def _object_lifecycle_headers(
|
|
452
|
-
self,
|
|
453
|
-
headers: dict[str, str],
|
|
454
|
-
object_lifecycle_preference: dict[str, str] | None,
|
|
455
|
-
):
|
|
456
|
-
if object_lifecycle_preference:
|
|
457
|
-
headers["X-Fal-Object-Lifecycle"] = json.dumps(object_lifecycle_preference)
|
|
458
|
-
|
|
459
467
|
def save(
|
|
460
468
|
self,
|
|
461
469
|
file: FileData,
|
|
@@ -476,9 +484,8 @@ class FalFileRepository(FalFileRepositoryBase):
|
|
|
476
484
|
max_concurrency=multipart_max_concurrency,
|
|
477
485
|
)
|
|
478
486
|
|
|
479
|
-
headers = {}
|
|
480
|
-
|
|
481
|
-
headers["X-Fal-Object-Lifecycle"] = json.dumps(object_lifecycle_preference)
|
|
487
|
+
headers: Dict[str, str] = {}
|
|
488
|
+
_object_lifecycle_headers(headers, object_lifecycle_preference)
|
|
482
489
|
|
|
483
490
|
return self._save(file, "gcs", headers=headers)
|
|
484
491
|
|
|
@@ -1121,6 +1128,8 @@ class FalFileRepositoryV2(FalFileRepositoryBase):
|
|
|
1121
1128
|
"Content-Type": file.content_type,
|
|
1122
1129
|
}
|
|
1123
1130
|
|
|
1131
|
+
_object_lifecycle_headers(headers, object_lifecycle_preference)
|
|
1132
|
+
|
|
1124
1133
|
storage_url = f"{token.base_upload_url}/upload"
|
|
1125
1134
|
|
|
1126
1135
|
try:
|
|
@@ -1192,16 +1201,6 @@ class InMemoryRepository(FileRepository):
|
|
|
1192
1201
|
|
|
1193
1202
|
@dataclass
|
|
1194
1203
|
class FalCDNFileRepository(FileRepository):
|
|
1195
|
-
def _object_lifecycle_headers(
|
|
1196
|
-
self,
|
|
1197
|
-
headers: dict[str, str],
|
|
1198
|
-
object_lifecycle_preference: dict[str, str] | None,
|
|
1199
|
-
):
|
|
1200
|
-
if object_lifecycle_preference:
|
|
1201
|
-
headers["X-Fal-Object-Lifecycle-Preference"] = json.dumps(
|
|
1202
|
-
object_lifecycle_preference
|
|
1203
|
-
)
|
|
1204
|
-
|
|
1205
1204
|
def save(
|
|
1206
1205
|
self,
|
|
1207
1206
|
file: FileData,
|
|
@@ -1218,7 +1217,7 @@ class FalCDNFileRepository(FileRepository):
|
|
|
1218
1217
|
"X-Fal-File-Name": file.file_name,
|
|
1219
1218
|
}
|
|
1220
1219
|
|
|
1221
|
-
|
|
1220
|
+
_object_lifecycle_headers(headers, object_lifecycle_preference)
|
|
1222
1221
|
|
|
1223
1222
|
url = os.getenv("FAL_CDN_HOST", _FAL_CDN) + "/files/upload"
|
|
1224
1223
|
request = Request(url, headers=headers, method="POST", data=file.data)
|
|
@@ -1285,6 +1284,7 @@ class FalFileRepositoryV3(FileRepository):
|
|
|
1285
1284
|
"Accept": "application/json",
|
|
1286
1285
|
"Content-Type": "application/json",
|
|
1287
1286
|
}
|
|
1287
|
+
_object_lifecycle_headers(headers, object_lifecycle_preference)
|
|
1288
1288
|
|
|
1289
1289
|
grpc_host = os.environ.get("FAL_HOST", "api.alpha.fal.ai")
|
|
1290
1290
|
rest_host = grpc_host.replace("api", "rest", 1)
|
|
@@ -1373,14 +1373,6 @@ class InternalFalFileRepositoryV3(FileRepository):
|
|
|
1373
1373
|
That way it can avoid the need to refresh the token for every upload.
|
|
1374
1374
|
"""
|
|
1375
1375
|
|
|
1376
|
-
def _object_lifecycle_headers(
|
|
1377
|
-
self,
|
|
1378
|
-
headers: dict[str, str],
|
|
1379
|
-
object_lifecycle_preference: dict[str, str] | None,
|
|
1380
|
-
):
|
|
1381
|
-
if object_lifecycle_preference:
|
|
1382
|
-
headers["X-Fal-Object-Lifecycle"] = json.dumps(object_lifecycle_preference)
|
|
1383
|
-
|
|
1384
1376
|
def save(
|
|
1385
1377
|
self,
|
|
1386
1378
|
file: FileData,
|
|
@@ -1410,7 +1402,7 @@ class InternalFalFileRepositoryV3(FileRepository):
|
|
|
1410
1402
|
"X-Fal-File-Name": file.file_name,
|
|
1411
1403
|
}
|
|
1412
1404
|
|
|
1413
|
-
|
|
1405
|
+
_object_lifecycle_headers(headers, object_lifecycle_preference)
|
|
1414
1406
|
|
|
1415
1407
|
url = os.getenv("FAL_CDN_V3_HOST", _FAL_CDN_V3) + "/files/upload"
|
|
1416
1408
|
request = Request(url, headers=headers, method="POST", data=file.data)
|
|
@@ -235,7 +235,7 @@ class ExceptionApp(fal.App, keep_alive=300, max_concurrency=1):
|
|
|
235
235
|
raise RuntimeError("cuDNN error: CUDNN_STATUS_INTERNAL_ERROR")
|
|
236
236
|
|
|
237
237
|
|
|
238
|
-
class CancellableApp(fal.App, keep_alive=300, max_concurrency=1, request_timeout=
|
|
238
|
+
class CancellableApp(fal.App, keep_alive=300, max_concurrency=1, request_timeout=4):
|
|
239
239
|
task = None
|
|
240
240
|
running = 0
|
|
241
241
|
|
|
@@ -514,12 +514,12 @@ def test_stateful_app_client(test_stateful_app: str):
|
|
|
514
514
|
|
|
515
515
|
def test_app_cancellation(test_app: str, test_cancellable_app: str):
|
|
516
516
|
request_handle = apps.submit(
|
|
517
|
-
test_cancellable_app, arguments={"lhs": 1, "rhs": 2, "wait_time":
|
|
517
|
+
test_cancellable_app, arguments={"lhs": 1, "rhs": 2, "wait_time": 6}
|
|
518
518
|
)
|
|
519
519
|
|
|
520
520
|
while True:
|
|
521
521
|
status = request_handle.status()
|
|
522
|
-
time.sleep(0.
|
|
522
|
+
time.sleep(0.05)
|
|
523
523
|
if isinstance(status, apps.InProgress):
|
|
524
524
|
# The app is running
|
|
525
525
|
break
|
|
@@ -534,12 +534,12 @@ def test_app_cancellation(test_app: str, test_cancellable_app: str):
|
|
|
534
534
|
|
|
535
535
|
# normal app should just ignore the cancellation
|
|
536
536
|
request_handle = apps.submit(
|
|
537
|
-
test_app, arguments={"lhs": 1, "rhs": 2, "wait_time":
|
|
537
|
+
test_app, arguments={"lhs": 1, "rhs": 2, "wait_time": 6}
|
|
538
538
|
)
|
|
539
539
|
|
|
540
540
|
while True:
|
|
541
541
|
status = request_handle.status()
|
|
542
|
-
time.sleep(0.
|
|
542
|
+
time.sleep(0.05)
|
|
543
543
|
if isinstance(status, apps.InProgress):
|
|
544
544
|
# The app is running
|
|
545
545
|
break
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py
RENAMED
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py
RENAMED
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py
RENAMED
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py
RENAMED
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py
RENAMED
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py
RENAMED
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fal-1.26.2 → fal-1.26.4}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|