fal 1.50.2__tar.gz → 1.59.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.
- {fal-1.50.2/fal.egg-info → fal-1.59.0}/PKG-INFO +6 -6
- {fal-1.50.2 → fal-1.59.0}/README.md +1 -1
- {fal-1.50.2 → fal-1.59.0/fal.egg-info}/PKG-INFO +6 -6
- {fal-1.50.2 → fal-1.59.0}/fal.egg-info/SOURCES.txt +23 -23
- {fal-1.50.2 → fal-1.59.0}/fal.egg-info/requires.txt +4 -4
- {fal-1.50.2 → fal-1.59.0}/pyproject.toml +5 -4
- {fal-1.50.2 → fal-1.59.0}/src/fal/__init__.py +2 -1
- {fal-1.50.2 → fal-1.59.0}/src/fal/_fal_version.py +2 -2
- {fal-1.50.2 → fal-1.59.0}/src/fal/api/api.py +33 -2
- {fal-1.50.2 → fal-1.59.0}/src/fal/api/apps.py +23 -1
- {fal-1.50.2 → fal-1.59.0}/src/fal/api/client.py +66 -1
- {fal-1.50.2 → fal-1.59.0}/src/fal/api/deploy.py +16 -28
- fal-1.59.0/src/fal/api/keys.py +31 -0
- fal-1.59.0/src/fal/api/secrets.py +29 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/app.py +72 -15
- {fal-1.50.2 → fal-1.59.0}/src/fal/apps.py +1 -1
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/_utils.py +11 -3
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/api.py +4 -2
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/apps.py +56 -2
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/deploy.py +17 -3
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/files.py +16 -24
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/keys.py +47 -50
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/queue.py +12 -10
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/run.py +11 -7
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/runners.py +51 -24
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/secrets.py +28 -30
- {fal-1.50.2 → fal-1.59.0}/src/fal/files.py +31 -8
- fal-1.59.0/src/fal/flags.py +50 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/sdk.py +113 -23
- {fal-1.50.2 → fal-1.59.0}/src/fal/sync.py +22 -12
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/__init__.py +10 -0
- fal-1.59.0/src/fal/toolkit/compilation.py +220 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/file/file.py +10 -9
- fal-1.59.0/src/fal/utils.py +111 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/workflows.py +6 -2
- {fal-1.50.2/tests → fal-1.59.0/tests/e2e}/test_apps.py +118 -20
- fal-1.50.2/tests/integration_test.py → fal-1.59.0/tests/integration/test.py +2 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/integration}/test_stability.py +2 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/cli/test_apps.py +3 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/cli/test_deploy.py +137 -0
- fal-1.59.0/tests/unit/cli/test_run.py +221 -0
- fal-1.59.0/tests/unit/distributed/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/tests/unit/test_app.py +71 -1
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/test_file_sync.py +5 -1
- fal-1.59.0/tests/unit/test_utils.py +108 -0
- fal-1.50.2/src/fal/flags.py +0 -36
- fal-1.50.2/src/fal/rest_client.py +0 -25
- fal-1.50.2/src/fal/utils.py +0 -77
- fal-1.50.2/tests/cli/test_run.py +0 -114
- fal-1.50.2/tests/mainify_package/__init__.py +0 -1
- fal-1.50.2/tests/mainify_package/impl.py +0 -8
- fal-1.50.2/tests/mainify_package/utils.py +0 -2
- fal-1.50.2/tests/mainify_target.py +0 -22
- {fal-1.50.2 → fal-1.59.0}/.gitignore +0 -0
- {fal-1.50.2 → fal-1.59.0}/Makefile +0 -0
- {fal-1.50.2 → fal-1.59.0}/docs/conf.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/docs/index.rst +0 -0
- {fal-1.50.2 → fal-1.59.0}/fal.egg-info/dependency_links.txt +0 -0
- {fal-1.50.2 → fal-1.59.0}/fal.egg-info/entry_points.txt +0 -0
- {fal-1.50.2 → fal-1.59.0}/fal.egg-info/top_level.txt +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/README.md +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/create_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/delete_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/get_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/list_user_workflows.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/comfy/update_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/users/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/users/get_current_user.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/list_user_workflows.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/api/workflows/update_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_detail.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_item.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_extra_data.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_fal_inputs_dev_info.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/comfy_workflow_schema_prompt.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/current_user.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/page_comfy_workflow_item.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/team_role.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/typed_comfy_workflow_update.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow_update.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/user_member.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_metadata.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi-fal-rest/pyproject.toml +0 -0
- {fal-1.50.2 → fal-1.59.0}/openapi_rest.config.yaml +0 -0
- {fal-1.50.2 → fal-1.59.0}/setup.cfg +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/__main__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/_serialization.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/_version.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/api/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/api/runners.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/auth/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/auth/auth0.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/auth/local.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/auth.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/cli_nested_json.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/create.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/debug.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/doctor.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/main.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/parser.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/profile.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/cli/teams.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/config.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/console/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/console/icons.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/console/ux.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/container.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/distributed/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/distributed/utils.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/distributed/worker.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/exceptions/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/exceptions/_base.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/exceptions/_cuda.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/exceptions/auth.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/file_sync.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/logging/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/logging/isolate.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/logging/style.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/logging/trace.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/project.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/py.typed +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/audio/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/audio/audio.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/exceptions.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/file/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/file/providers/fal.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/file/providers/gcp.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/file/providers/r2.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/file/providers/s3.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/file/types.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/image/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/image/image.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/image/nsfw_filter/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/image/nsfw_filter/env.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/image/nsfw_filter/inference.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/image/nsfw_filter/model.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/image/nsfw_filter/requirements.txt +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/image/safety_checker.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/kv.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/optimize.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/types.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/utils/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/utils/download_utils.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/utils/endpoint.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/utils/retry.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/utils/setup_utils.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/video/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/src/fal/toolkit/video/video.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/tests/__init__.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/tests/assets/cat.png +0 -0
- {fal-1.50.2 → fal-1.59.0}/tests/conftest.py +0 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/integration}/test_files.py +0 -0
- /fal-1.50.2/tests/toolkit/image_test.py → /fal-1.59.0/tests/integration/toolkit/test_image.py +0 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/integration/toolkit}/test_kv.py +0 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/cli/__init__.py +0 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/cli/test_auth.py +0 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/cli/test_keys.py +0 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/cli/test_secrets.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/tests/unit/distributed/test_integration.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/tests/unit/distributed/test_utils.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/tests/unit/distributed/test_worker.py +0 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/toolkit/file/providers/test_fal_retry.py +0 -0
- /fal-1.50.2/tests/toolkit/file_test.py → /fal-1.59.0/tests/unit/toolkit/test_file.py +0 -0
- {fal-1.50.2/tests → fal-1.59.0/tests/unit}/toolkit/test_types.py +0 -0
- /fal-1.50.2/tests/toolkit/utils/retry.py → /fal-1.59.0/tests/unit/toolkit/utils/test_retry.py +0 -0
- {fal-1.50.2 → fal-1.59.0}/tools/demo_script.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fal
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.59.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
|
-
Requires-Dist: isolate[build]<0.
|
|
9
|
-
Requires-Dist: isolate-proto
|
|
8
|
+
Requires-Dist: isolate[build]<0.22.0,>=0.18.0
|
|
9
|
+
Requires-Dist: isolate-proto>=0.29.2
|
|
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
|
|
@@ -21,8 +21,8 @@ Requires-Dist: rich<15,>=13.3.2
|
|
|
21
21
|
Requires-Dist: rich_argparse
|
|
22
22
|
Requires-Dist: packaging>=21.3
|
|
23
23
|
Requires-Dist: pathspec<1,>=0.11.1
|
|
24
|
-
Requires-Dist: pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4
|
|
25
|
-
Requires-Dist: fastapi<
|
|
24
|
+
Requires-Dist: pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*
|
|
25
|
+
Requires-Dist: fastapi<0.119,>=0.99.1
|
|
26
26
|
Requires-Dist: starlette-exporter>=0.21.0
|
|
27
27
|
Requires-Dist: httpx>=0.15.4
|
|
28
28
|
Requires-Dist: httpx-sse
|
|
@@ -60,7 +60,7 @@ Requires-Dist: fal[docs,test]; extra == "dev"
|
|
|
60
60
|
Requires-Dist: openapi-python-client<1,>=0.14.1; extra == "dev"
|
|
61
61
|
|
|
62
62
|
[](https://pypi.org/project/fal)
|
|
63
|
-
[](https://github.com/fal-ai/fal/actions)
|
|
64
64
|
|
|
65
65
|
# fal
|
|
66
66
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[](https://pypi.org/project/fal)
|
|
2
|
-
[](https://github.com/fal-ai/fal/actions)
|
|
3
3
|
|
|
4
4
|
# fal
|
|
5
5
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fal
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.59.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
|
-
Requires-Dist: isolate[build]<0.
|
|
9
|
-
Requires-Dist: isolate-proto
|
|
8
|
+
Requires-Dist: isolate[build]<0.22.0,>=0.18.0
|
|
9
|
+
Requires-Dist: isolate-proto>=0.29.2
|
|
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
|
|
@@ -21,8 +21,8 @@ Requires-Dist: rich<15,>=13.3.2
|
|
|
21
21
|
Requires-Dist: rich_argparse
|
|
22
22
|
Requires-Dist: packaging>=21.3
|
|
23
23
|
Requires-Dist: pathspec<1,>=0.11.1
|
|
24
|
-
Requires-Dist: pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4
|
|
25
|
-
Requires-Dist: fastapi<
|
|
24
|
+
Requires-Dist: pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*
|
|
25
|
+
Requires-Dist: fastapi<0.119,>=0.99.1
|
|
26
26
|
Requires-Dist: starlette-exporter>=0.21.0
|
|
27
27
|
Requires-Dist: httpx>=0.15.4
|
|
28
28
|
Requires-Dist: httpx-sse
|
|
@@ -60,7 +60,7 @@ Requires-Dist: fal[docs,test]; extra == "dev"
|
|
|
60
60
|
Requires-Dist: openapi-python-client<1,>=0.14.1; extra == "dev"
|
|
61
61
|
|
|
62
62
|
[](https://pypi.org/project/fal)
|
|
63
|
-
[](https://github.com/fal-ai/fal/actions)
|
|
64
64
|
|
|
65
65
|
# fal
|
|
66
66
|
|
|
@@ -90,7 +90,6 @@ src/fal/files.py
|
|
|
90
90
|
src/fal/flags.py
|
|
91
91
|
src/fal/project.py
|
|
92
92
|
src/fal/py.typed
|
|
93
|
-
src/fal/rest_client.py
|
|
94
93
|
src/fal/sdk.py
|
|
95
94
|
src/fal/sync.py
|
|
96
95
|
src/fal/utils.py
|
|
@@ -100,7 +99,9 @@ src/fal/api/api.py
|
|
|
100
99
|
src/fal/api/apps.py
|
|
101
100
|
src/fal/api/client.py
|
|
102
101
|
src/fal/api/deploy.py
|
|
102
|
+
src/fal/api/keys.py
|
|
103
103
|
src/fal/api/runners.py
|
|
104
|
+
src/fal/api/secrets.py
|
|
104
105
|
src/fal/auth/__init__.py
|
|
105
106
|
src/fal/auth/auth0.py
|
|
106
107
|
src/fal/auth/local.py
|
|
@@ -139,6 +140,7 @@ src/fal/logging/isolate.py
|
|
|
139
140
|
src/fal/logging/style.py
|
|
140
141
|
src/fal/logging/trace.py
|
|
141
142
|
src/fal/toolkit/__init__.py
|
|
143
|
+
src/fal/toolkit/compilation.py
|
|
142
144
|
src/fal/toolkit/exceptions.py
|
|
143
145
|
src/fal/toolkit/kv.py
|
|
144
146
|
src/fal/toolkit/optimize.py
|
|
@@ -169,31 +171,29 @@ src/fal/toolkit/video/__init__.py
|
|
|
169
171
|
src/fal/toolkit/video/video.py
|
|
170
172
|
tests/__init__.py
|
|
171
173
|
tests/conftest.py
|
|
172
|
-
tests/integration_test.py
|
|
173
|
-
tests/mainify_target.py
|
|
174
|
-
tests/test_apps.py
|
|
175
|
-
tests/test_file_sync.py
|
|
176
|
-
tests/test_files.py
|
|
177
|
-
tests/test_kv.py
|
|
178
|
-
tests/test_stability.py
|
|
179
174
|
tests/assets/cat.png
|
|
180
|
-
tests/
|
|
181
|
-
tests/
|
|
182
|
-
tests/
|
|
183
|
-
tests/
|
|
184
|
-
tests/
|
|
185
|
-
tests/
|
|
186
|
-
tests/cli/test_secrets.py
|
|
187
|
-
tests/mainify_package/__init__.py
|
|
188
|
-
tests/mainify_package/impl.py
|
|
189
|
-
tests/mainify_package/utils.py
|
|
190
|
-
tests/toolkit/file_test.py
|
|
191
|
-
tests/toolkit/image_test.py
|
|
192
|
-
tests/toolkit/test_types.py
|
|
193
|
-
tests/toolkit/file/providers/test_fal_retry.py
|
|
194
|
-
tests/toolkit/utils/retry.py
|
|
175
|
+
tests/e2e/test_apps.py
|
|
176
|
+
tests/integration/test.py
|
|
177
|
+
tests/integration/test_files.py
|
|
178
|
+
tests/integration/test_stability.py
|
|
179
|
+
tests/integration/toolkit/test_image.py
|
|
180
|
+
tests/integration/toolkit/test_kv.py
|
|
195
181
|
tests/unit/test_app.py
|
|
182
|
+
tests/unit/test_file_sync.py
|
|
183
|
+
tests/unit/test_utils.py
|
|
184
|
+
tests/unit/cli/__init__.py
|
|
185
|
+
tests/unit/cli/test_apps.py
|
|
186
|
+
tests/unit/cli/test_auth.py
|
|
187
|
+
tests/unit/cli/test_deploy.py
|
|
188
|
+
tests/unit/cli/test_keys.py
|
|
189
|
+
tests/unit/cli/test_run.py
|
|
190
|
+
tests/unit/cli/test_secrets.py
|
|
191
|
+
tests/unit/distributed/__init__.py
|
|
196
192
|
tests/unit/distributed/test_integration.py
|
|
197
193
|
tests/unit/distributed/test_utils.py
|
|
198
194
|
tests/unit/distributed/test_worker.py
|
|
195
|
+
tests/unit/toolkit/test_file.py
|
|
196
|
+
tests/unit/toolkit/test_types.py
|
|
197
|
+
tests/unit/toolkit/file/providers/test_fal_retry.py
|
|
198
|
+
tests/unit/toolkit/utils/test_retry.py
|
|
199
199
|
tools/demo_script.py
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
isolate[build]<0.
|
|
2
|
-
isolate-proto
|
|
1
|
+
isolate[build]<0.22.0,>=0.18.0
|
|
2
|
+
isolate-proto>=0.29.2
|
|
3
3
|
grpcio<2,>=1.64.0
|
|
4
4
|
dill==0.3.7
|
|
5
5
|
cloudpickle==3.0.0
|
|
@@ -14,8 +14,8 @@ rich<15,>=13.3.2
|
|
|
14
14
|
rich_argparse
|
|
15
15
|
packaging>=21.3
|
|
16
16
|
pathspec<1,>=0.11.1
|
|
17
|
-
pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4
|
|
18
|
-
fastapi<
|
|
17
|
+
pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*
|
|
18
|
+
fastapi<0.119,>=0.99.1
|
|
19
19
|
starlette-exporter>=0.21.0
|
|
20
20
|
httpx>=0.15.4
|
|
21
21
|
httpx-sse
|
|
@@ -22,8 +22,8 @@ authors = [{ name = "Features & Labels <support@fal.ai>"}]
|
|
|
22
22
|
readme = "README.md"
|
|
23
23
|
requires-python = ">=3.8"
|
|
24
24
|
dependencies = [
|
|
25
|
-
"isolate[build]>=0.18.0,<0.
|
|
26
|
-
"isolate-proto>=0.
|
|
25
|
+
"isolate[build]>=0.18.0,<0.22.0",
|
|
26
|
+
"isolate-proto>=0.29.2",
|
|
27
27
|
"grpcio>=1.64.0,<2",
|
|
28
28
|
"dill==0.3.7",
|
|
29
29
|
"cloudpickle==3.0.0",
|
|
@@ -38,9 +38,10 @@ dependencies = [
|
|
|
38
38
|
"rich_argparse",
|
|
39
39
|
"packaging>=21.3",
|
|
40
40
|
"pathspec>=0.11.1,<1",
|
|
41
|
-
"pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4
|
|
41
|
+
"pydantic!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*,!=2.4.*",
|
|
42
42
|
# serve=True dependencies
|
|
43
|
-
|
|
43
|
+
# https://github.com/fastapi/fastapi/issues/14221
|
|
44
|
+
"fastapi>=0.99.1,<0.119",
|
|
44
45
|
"starlette-exporter>=0.21.0",
|
|
45
46
|
# rest-api-client dependencies
|
|
46
47
|
"httpx>=0.15.4",
|
|
@@ -5,7 +5,7 @@ from fal.api import FalServerlessHost, LocalHost, cached, function
|
|
|
5
5
|
from fal.api import function as isolated # noqa: F401
|
|
6
6
|
from fal.app import App, endpoint, realtime, wrap_app # noqa: F401
|
|
7
7
|
from fal.container import ContainerImage
|
|
8
|
-
from fal.sdk import FalServerlessKeyCredentials
|
|
8
|
+
from fal.sdk import FalServerlessKeyCredentials, HealthCheck
|
|
9
9
|
from fal.sync import sync_dir
|
|
10
10
|
|
|
11
11
|
from ._version import __version__, version_tuple # noqa: F401
|
|
@@ -23,6 +23,7 @@ __all__ = [
|
|
|
23
23
|
"endpoint",
|
|
24
24
|
"realtime",
|
|
25
25
|
# "wrap_app",
|
|
26
|
+
"HealthCheck",
|
|
26
27
|
"FalServerlessKeyCredentials",
|
|
27
28
|
"sync_dir",
|
|
28
29
|
"__version__",
|
|
@@ -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.
|
|
32
|
-
__version_tuple__ = version_tuple = (1,
|
|
31
|
+
__version__ = version = '1.59.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 59, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -66,8 +66,10 @@ from fal.sdk import (
|
|
|
66
66
|
FalServerlessClient,
|
|
67
67
|
FalServerlessConnection,
|
|
68
68
|
File,
|
|
69
|
+
HealthCheck,
|
|
69
70
|
HostedRunState,
|
|
70
71
|
MachineRequirements,
|
|
72
|
+
RegisterApplicationResult,
|
|
71
73
|
get_agent_credentials,
|
|
72
74
|
get_default_credentials,
|
|
73
75
|
)
|
|
@@ -84,6 +86,7 @@ _UNSET = object()
|
|
|
84
86
|
SERVE_REQUIREMENTS = [
|
|
85
87
|
f"fastapi=={fastapi_version}",
|
|
86
88
|
f"pydantic=={pydantic_version}",
|
|
89
|
+
f"tblib=={tblib.__version__}",
|
|
87
90
|
"uvicorn",
|
|
88
91
|
"starlette_exporter",
|
|
89
92
|
# workaround for prometheus_client 0.23.0
|
|
@@ -426,12 +429,14 @@ class FalServerlessHost(Host):
|
|
|
426
429
|
{
|
|
427
430
|
"machine_type",
|
|
428
431
|
"machine_types",
|
|
432
|
+
"regions",
|
|
429
433
|
"num_gpus",
|
|
430
434
|
"keep_alive",
|
|
431
435
|
"max_concurrency",
|
|
432
436
|
"min_concurrency",
|
|
433
437
|
"concurrency_buffer",
|
|
434
438
|
"concurrency_buffer_perc",
|
|
439
|
+
"scaling_delay",
|
|
435
440
|
"max_multiplexing",
|
|
436
441
|
"setup_function",
|
|
437
442
|
"metadata",
|
|
@@ -444,6 +449,7 @@ class FalServerlessHost(Host):
|
|
|
444
449
|
"app_files",
|
|
445
450
|
"app_files_ignore",
|
|
446
451
|
"app_files_context_dir",
|
|
452
|
+
"health_check_config",
|
|
447
453
|
}
|
|
448
454
|
)
|
|
449
455
|
|
|
@@ -518,7 +524,7 @@ class FalServerlessHost(Host):
|
|
|
518
524
|
metadata: Optional[dict[str, Any]] = None,
|
|
519
525
|
deployment_strategy: DeploymentStrategyLiteral,
|
|
520
526
|
scale: bool = True,
|
|
521
|
-
) -> Optional[
|
|
527
|
+
) -> Optional[RegisterApplicationResult]:
|
|
522
528
|
from isolate.backends.common import active_python
|
|
523
529
|
|
|
524
530
|
environment_options = options.environment.copy()
|
|
@@ -536,10 +542,12 @@ class FalServerlessHost(Host):
|
|
|
536
542
|
min_concurrency = options.host.get("min_concurrency")
|
|
537
543
|
concurrency_buffer = options.host.get("concurrency_buffer")
|
|
538
544
|
concurrency_buffer_perc = options.host.get("concurrency_buffer_perc")
|
|
545
|
+
scaling_delay = options.host.get("scaling_delay")
|
|
539
546
|
max_multiplexing = options.host.get("max_multiplexing")
|
|
540
547
|
exposed_port = options.get_exposed_port()
|
|
541
548
|
request_timeout = options.host.get("request_timeout")
|
|
542
549
|
startup_timeout = options.host.get("startup_timeout")
|
|
550
|
+
regions = options.host.get("regions")
|
|
543
551
|
machine_requirements = MachineRequirements(
|
|
544
552
|
machine_types=machine_type, # type: ignore
|
|
545
553
|
num_gpus=options.host.get("num_gpus"),
|
|
@@ -553,10 +561,14 @@ class FalServerlessHost(Host):
|
|
|
553
561
|
min_concurrency=min_concurrency,
|
|
554
562
|
concurrency_buffer=concurrency_buffer,
|
|
555
563
|
concurrency_buffer_perc=concurrency_buffer_perc,
|
|
564
|
+
scaling_delay=scaling_delay,
|
|
556
565
|
request_timeout=request_timeout,
|
|
557
566
|
startup_timeout=startup_timeout,
|
|
567
|
+
valid_regions=regions,
|
|
558
568
|
)
|
|
559
569
|
|
|
570
|
+
health_check_config = options.host.get("health_check_config")
|
|
571
|
+
|
|
560
572
|
app_files = self._app_files_sync(options)
|
|
561
573
|
|
|
562
574
|
partial_func = _prepare_partial_func(func)
|
|
@@ -580,6 +592,7 @@ class FalServerlessHost(Host):
|
|
|
580
592
|
metadata=metadata,
|
|
581
593
|
deployment_strategy=deployment_strategy,
|
|
582
594
|
scale=scale,
|
|
595
|
+
health_check_config=health_check_config,
|
|
583
596
|
# By default, logs are public
|
|
584
597
|
private_logs=options.host.get("private_logs", False),
|
|
585
598
|
files=app_files,
|
|
@@ -588,7 +601,7 @@ class FalServerlessHost(Host):
|
|
|
588
601
|
self._log_printer.print(log)
|
|
589
602
|
|
|
590
603
|
if partial_result.result:
|
|
591
|
-
return partial_result
|
|
604
|
+
return partial_result
|
|
592
605
|
|
|
593
606
|
return None
|
|
594
607
|
|
|
@@ -615,6 +628,7 @@ class FalServerlessHost(Host):
|
|
|
615
628
|
min_concurrency = options.host.get("min_concurrency")
|
|
616
629
|
concurrency_buffer = options.host.get("concurrency_buffer")
|
|
617
630
|
concurrency_buffer_perc = options.host.get("concurrency_buffer_perc")
|
|
631
|
+
scaling_delay = options.host.get("scaling_delay")
|
|
618
632
|
max_multiplexing = options.host.get("max_multiplexing")
|
|
619
633
|
base_image = options.host.get("_base_image", None)
|
|
620
634
|
scheduler = options.host.get("_scheduler", None)
|
|
@@ -636,6 +650,7 @@ class FalServerlessHost(Host):
|
|
|
636
650
|
min_concurrency=min_concurrency,
|
|
637
651
|
concurrency_buffer=concurrency_buffer,
|
|
638
652
|
concurrency_buffer_perc=concurrency_buffer_perc,
|
|
653
|
+
scaling_delay=scaling_delay,
|
|
639
654
|
request_timeout=request_timeout,
|
|
640
655
|
startup_timeout=startup_timeout,
|
|
641
656
|
)
|
|
@@ -824,12 +839,14 @@ def function(
|
|
|
824
839
|
# FalServerlessHost options
|
|
825
840
|
metadata: dict[str, Any] | None = None,
|
|
826
841
|
machine_type: str | list[str] = FAL_SERVERLESS_DEFAULT_MACHINE_TYPE,
|
|
842
|
+
regions: list[str] | None = None,
|
|
827
843
|
num_gpus: int | None = None,
|
|
828
844
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
829
845
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
830
846
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
831
847
|
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
832
848
|
concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
|
|
849
|
+
scaling_delay: int | None = None,
|
|
833
850
|
request_timeout: int | None = None,
|
|
834
851
|
startup_timeout: int | None = None,
|
|
835
852
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -855,12 +872,14 @@ def function(
|
|
|
855
872
|
# FalServerlessHost options
|
|
856
873
|
metadata: dict[str, Any] | None = None,
|
|
857
874
|
machine_type: str | list[str] = FAL_SERVERLESS_DEFAULT_MACHINE_TYPE,
|
|
875
|
+
regions: list[str] | None = None,
|
|
858
876
|
num_gpus: int | None = None,
|
|
859
877
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
860
878
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
861
879
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
862
880
|
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
863
881
|
concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
|
|
882
|
+
scaling_delay: int | None = None,
|
|
864
883
|
request_timeout: int | None = None,
|
|
865
884
|
startup_timeout: int | None = None,
|
|
866
885
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -938,12 +957,14 @@ def function(
|
|
|
938
957
|
# FalServerlessHost options
|
|
939
958
|
metadata: dict[str, Any] | None = None,
|
|
940
959
|
machine_type: str | list[str] = FAL_SERVERLESS_DEFAULT_MACHINE_TYPE,
|
|
960
|
+
regions: list[str] | None = None,
|
|
941
961
|
num_gpus: int | None = None,
|
|
942
962
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
943
963
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
944
964
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
945
965
|
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
946
966
|
concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
|
|
967
|
+
scaling_delay: int | None = None,
|
|
947
968
|
request_timeout: int | None = None,
|
|
948
969
|
startup_timeout: int | None = None,
|
|
949
970
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -974,12 +995,14 @@ def function(
|
|
|
974
995
|
# FalServerlessHost options
|
|
975
996
|
metadata: dict[str, Any] | None = None,
|
|
976
997
|
machine_type: str | list[str] = FAL_SERVERLESS_DEFAULT_MACHINE_TYPE,
|
|
998
|
+
regions: list[str] | None = None,
|
|
977
999
|
num_gpus: int | None = None,
|
|
978
1000
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
979
1001
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
980
1002
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
981
1003
|
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
982
1004
|
concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
|
|
1005
|
+
scaling_delay: int | None = None,
|
|
983
1006
|
request_timeout: int | None = None,
|
|
984
1007
|
startup_timeout: int | None = None,
|
|
985
1008
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -1004,12 +1027,14 @@ def function(
|
|
|
1004
1027
|
# FalServerlessHost options
|
|
1005
1028
|
metadata: dict[str, Any] | None = None,
|
|
1006
1029
|
machine_type: str | list[str] = FAL_SERVERLESS_DEFAULT_MACHINE_TYPE,
|
|
1030
|
+
regions: list[str] | None = None,
|
|
1007
1031
|
num_gpus: int | None = None,
|
|
1008
1032
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
1009
1033
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
1010
1034
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
1011
1035
|
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
1012
1036
|
concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
|
|
1037
|
+
scaling_delay: int | None = None,
|
|
1013
1038
|
request_timeout: int | None = None,
|
|
1014
1039
|
startup_timeout: int | None = None,
|
|
1015
1040
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -1034,12 +1059,14 @@ def function(
|
|
|
1034
1059
|
# FalServerlessHost options
|
|
1035
1060
|
metadata: dict[str, Any] | None = None,
|
|
1036
1061
|
machine_type: str | list[str] = FAL_SERVERLESS_DEFAULT_MACHINE_TYPE,
|
|
1062
|
+
regions: list[str] | None = None,
|
|
1037
1063
|
num_gpus: int | None = None,
|
|
1038
1064
|
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
1039
1065
|
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
1040
1066
|
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
1041
1067
|
concurrency_buffer: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER,
|
|
1042
1068
|
concurrency_buffer_perc: int = FAL_SERVERLESS_DEFAULT_CONCURRENCY_BUFFER_PERC,
|
|
1069
|
+
scaling_delay: int | None = None,
|
|
1043
1070
|
request_timeout: int | None = None,
|
|
1044
1071
|
startup_timeout: int | None = None,
|
|
1045
1072
|
setup_function: Callable[..., None] | None = None,
|
|
@@ -1065,6 +1092,9 @@ def function( # type: ignore
|
|
|
1065
1092
|
if config.get("image"):
|
|
1066
1093
|
kind = "container"
|
|
1067
1094
|
|
|
1095
|
+
if kind == "container" and config.get("app_files"):
|
|
1096
|
+
raise ValueError("app_files is not supported for container apps.")
|
|
1097
|
+
|
|
1068
1098
|
options = host.parse_options(kind=kind, **config)
|
|
1069
1099
|
|
|
1070
1100
|
def wrapper(func: Callable[ArgsT, ReturnT]):
|
|
@@ -1141,6 +1171,7 @@ class FalFastAPI(FastAPI):
|
|
|
1141
1171
|
class RouteSignature(NamedTuple):
|
|
1142
1172
|
path: str
|
|
1143
1173
|
is_websocket: bool = False
|
|
1174
|
+
health_check: HealthCheck | None = None
|
|
1144
1175
|
input_modal: type | None = None
|
|
1145
1176
|
buffering: int | None = None
|
|
1146
1177
|
session_timeout: float | None = None
|
|
@@ -34,7 +34,14 @@ def apps_runners(
|
|
|
34
34
|
|
|
35
35
|
if state and "all" not in set(state):
|
|
36
36
|
states = set(state)
|
|
37
|
-
alias_runners = [
|
|
37
|
+
alias_runners = [
|
|
38
|
+
r
|
|
39
|
+
for r in alias_runners
|
|
40
|
+
if r.state.value.lower() in states
|
|
41
|
+
or (
|
|
42
|
+
"terminated" in states and r.state.value.lower() == "dead"
|
|
43
|
+
) # TODO for backwards compatibility. remove later
|
|
44
|
+
]
|
|
38
45
|
return alias_runners
|
|
39
46
|
|
|
40
47
|
|
|
@@ -48,6 +55,7 @@ def scale_app(
|
|
|
48
55
|
min_concurrency: int | None = None,
|
|
49
56
|
concurrency_buffer: int | None = None,
|
|
50
57
|
concurrency_buffer_perc: int | None = None,
|
|
58
|
+
scaling_delay: int | None = None,
|
|
51
59
|
request_timeout: int | None = None,
|
|
52
60
|
startup_timeout: int | None = None,
|
|
53
61
|
machine_types: list[str] | None = None,
|
|
@@ -62,8 +70,22 @@ def scale_app(
|
|
|
62
70
|
min_concurrency=min_concurrency,
|
|
63
71
|
concurrency_buffer=concurrency_buffer,
|
|
64
72
|
concurrency_buffer_perc=concurrency_buffer_perc,
|
|
73
|
+
scaling_delay=scaling_delay,
|
|
65
74
|
request_timeout=request_timeout,
|
|
66
75
|
startup_timeout=startup_timeout,
|
|
67
76
|
machine_types=machine_types,
|
|
68
77
|
valid_regions=regions,
|
|
69
78
|
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def rollout_app(
|
|
82
|
+
client: SyncServerlessClient,
|
|
83
|
+
app_name: str,
|
|
84
|
+
*,
|
|
85
|
+
force: bool = False,
|
|
86
|
+
) -> None:
|
|
87
|
+
with FalServerlessClient(client._grpc_host, client._credentials).connect() as conn:
|
|
88
|
+
conn.rollout_application(
|
|
89
|
+
application_name=app_name,
|
|
90
|
+
force=force,
|
|
91
|
+
)
|
|
@@ -2,18 +2,26 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import List, Optional
|
|
5
|
+
from typing import TYPE_CHECKING, List, Optional
|
|
6
6
|
|
|
7
7
|
from fal.api import FAL_SERVERLESS_DEFAULT_URL, FalServerlessHost
|
|
8
8
|
from fal.sdk import (
|
|
9
9
|
AliasInfo,
|
|
10
10
|
Credentials,
|
|
11
|
+
KeyScope,
|
|
11
12
|
RunnerInfo,
|
|
13
|
+
ServerlessSecret,
|
|
14
|
+
UserKeyInfo,
|
|
12
15
|
)
|
|
13
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from openapi_fal_rest.client import Client
|
|
19
|
+
|
|
14
20
|
from . import apps as apps_api
|
|
15
21
|
from . import deploy as deploy_api
|
|
22
|
+
from . import keys as keys_api
|
|
16
23
|
from . import runners as runners_api
|
|
24
|
+
from . import secrets as secrets_api
|
|
17
25
|
|
|
18
26
|
|
|
19
27
|
class _AppsNamespace:
|
|
@@ -38,6 +46,7 @@ class _AppsNamespace:
|
|
|
38
46
|
min_concurrency: int | None = None,
|
|
39
47
|
concurrency_buffer: int | None = None,
|
|
40
48
|
concurrency_buffer_perc: int | None = None,
|
|
49
|
+
scaling_delay: int | None = None,
|
|
41
50
|
request_timeout: int | None = None,
|
|
42
51
|
startup_timeout: int | None = None,
|
|
43
52
|
machine_types: List[str] | None = None,
|
|
@@ -52,12 +61,16 @@ class _AppsNamespace:
|
|
|
52
61
|
min_concurrency=min_concurrency,
|
|
53
62
|
concurrency_buffer=concurrency_buffer,
|
|
54
63
|
concurrency_buffer_perc=concurrency_buffer_perc,
|
|
64
|
+
scaling_delay=scaling_delay,
|
|
55
65
|
request_timeout=request_timeout,
|
|
56
66
|
startup_timeout=startup_timeout,
|
|
57
67
|
machine_types=machine_types,
|
|
58
68
|
regions=regions,
|
|
59
69
|
)
|
|
60
70
|
|
|
71
|
+
def rollout(self, app_name: str, *, force: bool = False) -> None:
|
|
72
|
+
return apps_api.rollout_app(self.client, app_name, force=force)
|
|
73
|
+
|
|
61
74
|
|
|
62
75
|
class _RunnersNamespace:
|
|
63
76
|
def __init__(self, client: SyncServerlessClient):
|
|
@@ -73,6 +86,36 @@ class _RunnersNamespace:
|
|
|
73
86
|
return runners_api.kill_runner(self.client, runner_id)
|
|
74
87
|
|
|
75
88
|
|
|
89
|
+
class _KeysNamespace:
|
|
90
|
+
def __init__(self, client: SyncServerlessClient):
|
|
91
|
+
self.client = client
|
|
92
|
+
|
|
93
|
+
def create(
|
|
94
|
+
self, *, scope: KeyScope, description: str | None = None
|
|
95
|
+
) -> tuple[str, str]:
|
|
96
|
+
return keys_api.create_key(self.client, scope=scope, description=description)
|
|
97
|
+
|
|
98
|
+
def list(self) -> List[UserKeyInfo]:
|
|
99
|
+
return keys_api.list_keys(self.client)
|
|
100
|
+
|
|
101
|
+
def revoke(self, key_id: str) -> None:
|
|
102
|
+
return keys_api.revoke_key(self.client, key_id)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class _SecretsNamespace:
|
|
106
|
+
def __init__(self, client: SyncServerlessClient):
|
|
107
|
+
self.client = client
|
|
108
|
+
|
|
109
|
+
def set(self, name: str, value: str) -> None:
|
|
110
|
+
return secrets_api.set_secret(self.client, name, value)
|
|
111
|
+
|
|
112
|
+
def list(self) -> List[ServerlessSecret]:
|
|
113
|
+
return secrets_api.list_secrets(self.client)
|
|
114
|
+
|
|
115
|
+
def unset(self, name: str) -> None:
|
|
116
|
+
return secrets_api.unset_secret(self.client, name)
|
|
117
|
+
|
|
118
|
+
|
|
76
119
|
@dataclass
|
|
77
120
|
class SyncServerlessClient:
|
|
78
121
|
host: Optional[str] = None
|
|
@@ -83,6 +126,8 @@ class SyncServerlessClient:
|
|
|
83
126
|
def __post_init__(self) -> None:
|
|
84
127
|
self.apps = _AppsNamespace(self)
|
|
85
128
|
self.runners = _RunnersNamespace(self)
|
|
129
|
+
self.keys = _KeysNamespace(self)
|
|
130
|
+
self.secrets = _SecretsNamespace(self)
|
|
86
131
|
|
|
87
132
|
# Top-level verbs
|
|
88
133
|
def deploy(self, *args, **kwargs):
|
|
@@ -93,6 +138,12 @@ class SyncServerlessClient:
|
|
|
93
138
|
def _grpc_host(self) -> str:
|
|
94
139
|
return self.host or FAL_SERVERLESS_DEFAULT_URL
|
|
95
140
|
|
|
141
|
+
@property
|
|
142
|
+
def _rest_url(self) -> str:
|
|
143
|
+
from fal.flags import REST_SCHEME
|
|
144
|
+
|
|
145
|
+
return f"{REST_SCHEME}://{self._grpc_host.replace('api', 'rest', 1)}"
|
|
146
|
+
|
|
96
147
|
@property
|
|
97
148
|
def _credentials(self) -> Credentials:
|
|
98
149
|
from fal.sdk import FalServerlessKeyCredentials, get_default_credentials
|
|
@@ -127,3 +178,17 @@ class SyncServerlessClient:
|
|
|
127
178
|
local_file_path=local_file_path,
|
|
128
179
|
credentials=self._credentials,
|
|
129
180
|
)
|
|
181
|
+
|
|
182
|
+
def _create_rest_client(self) -> Client:
|
|
183
|
+
from openapi_fal_rest.client import Client
|
|
184
|
+
|
|
185
|
+
import fal.flags as flags
|
|
186
|
+
|
|
187
|
+
return Client(
|
|
188
|
+
self._rest_url,
|
|
189
|
+
headers=self._credentials.to_headers(),
|
|
190
|
+
timeout=30,
|
|
191
|
+
verify_ssl=not flags.TEST_MODE,
|
|
192
|
+
raise_on_unexpected_status=False,
|
|
193
|
+
follow_redirects=True,
|
|
194
|
+
)
|