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