fal 1.0.4__tar.gz → 1.0.5__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.0.4 → fal-1.0.5}/PKG-INFO +4 -4
- {fal-1.0.4 → fal-1.0.5}/fal.egg-info/PKG-INFO +4 -4
- {fal-1.0.4 → fal-1.0.5}/fal.egg-info/SOURCES.txt +1 -0
- {fal-1.0.4 → fal-1.0.5}/fal.egg-info/requires.txt +3 -3
- {fal-1.0.4 → fal-1.0.5}/pyproject.toml +3 -3
- {fal-1.0.4 → fal-1.0.5}/src/fal/__init__.py +2 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/_fal_version.py +2 -2
- {fal-1.0.4 → fal-1.0.5}/src/fal/api.py +54 -4
- {fal-1.0.4 → fal-1.0.5}/src/fal/app.py +2 -1
- fal-1.0.5/src/fal/container.py +19 -0
- {fal-1.0.4 → fal-1.0.5}/tests/test_apps.py +32 -0
- {fal-1.0.4 → fal-1.0.5}/tests/test_stability.py +37 -1
- {fal-1.0.4 → fal-1.0.5}/.gitignore +0 -0
- {fal-1.0.4 → fal-1.0.5}/README.md +0 -0
- {fal-1.0.4 → fal-1.0.5}/fal.egg-info/dependency_links.txt +0 -0
- {fal-1.0.4 → fal-1.0.5}/fal.egg-info/entry_points.txt +0 -0
- {fal-1.0.4 → fal-1.0.5}/fal.egg-info/top_level.txt +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/README.md +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/applications/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/applications/app_metadata.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/billing/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/billing/get_user_details.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/files/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/files/check_dir_hash.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/files/upload_local_file.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/workflows/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/workflows/create_or_update_workflow_workflows_post.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/workflows/delete_workflow_workflows_user_id_workflow_name_delete.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/workflows/execute_workflow_workflows_user_id_workflow_name_post.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflow_workflows_user_id_workflow_name_get.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/api/workflows/get_workflows_workflows_get.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/client.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/errors.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/app_metadata_response_app_metadata.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/body_upload_local_file.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/customer_details.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/execute_workflow_workflows_user_id_workflow_name_post_json_body_type_0.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/execute_workflow_workflows_user_id_workflow_name_post_response_200_type_0.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/hash_check.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/http_validation_error.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/lock_reason.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/page_workflow_item.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/typed_workflow.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/validation_error.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_nodes.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents_type_0.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_item.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_node.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_node_type.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_input.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_schema_output.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/py.typed +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/types.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/pyproject.toml +0 -0
- {fal-1.0.4 → fal-1.0.5}/openapi_rest.config.yaml +0 -0
- {fal-1.0.4 → fal-1.0.5}/setup.cfg +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/__main__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/_serialization.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/_version.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/apps.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/auth/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/auth/auth0.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/auth/local.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/apps.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/auth.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/debug.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/deploy.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/keys.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/main.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/parser.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/run.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/cli/secrets.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/console/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/console/icons.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/console/ux.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/exceptions/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/exceptions/_base.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/exceptions/auth.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/flags.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/logging/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/logging/isolate.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/logging/style.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/logging/trace.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/logging/user.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/py.typed +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/rest_client.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/sdk.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/sync.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/exceptions.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/file/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/file/file.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/file/providers/fal.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/file/providers/gcp.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/file/providers/r2.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/file/types.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/image/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/image/image.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/optimize.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/utils/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/toolkit/utils/download_utils.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/utils.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/src/fal/workflows.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/cli/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/cli/test_apps.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/cli/test_auth.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/cli/test_deploy.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/cli/test_keys.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/cli/test_run.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/cli/test_secrets.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/conftest.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/integration_test.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/mainify_package/__init__.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/mainify_package/impl.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/mainify_package/utils.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/mainify_target.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/toolkit/file_test.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tests/toolkit/image_test.py +0 -0
- {fal-1.0.4 → fal-1.0.5}/tools/demo_script.py +0 -0
{fal-1.0.4 → fal-1.0.5}/PKG-INFO
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fal
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
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]<1.0,>=0.
|
|
9
|
-
Requires-Dist: isolate-proto==0.
|
|
10
|
-
Requires-Dist: grpcio
|
|
8
|
+
Requires-Dist: isolate[build]<1.14.0,>=0.13.0
|
|
9
|
+
Requires-Dist: isolate-proto==0.5.1
|
|
10
|
+
Requires-Dist: grpcio==1.64.0
|
|
11
11
|
Requires-Dist: dill==0.3.7
|
|
12
12
|
Requires-Dist: cloudpickle==3.0.0
|
|
13
13
|
Requires-Dist: typing-extensions<5,>=4.7.1
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fal
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.5
|
|
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]<1.0,>=0.
|
|
9
|
-
Requires-Dist: isolate-proto==0.
|
|
10
|
-
Requires-Dist: grpcio
|
|
8
|
+
Requires-Dist: isolate[build]<1.14.0,>=0.13.0
|
|
9
|
+
Requires-Dist: isolate-proto==0.5.1
|
|
10
|
+
Requires-Dist: grpcio==1.64.0
|
|
11
11
|
Requires-Dist: dill==0.3.7
|
|
12
12
|
Requires-Dist: cloudpickle==3.0.0
|
|
13
13
|
Requires-Dist: typing-extensions<5,>=4.7.1
|
|
@@ -22,9 +22,9 @@ 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.
|
|
26
|
-
"isolate-proto==0.
|
|
27
|
-
"grpcio
|
|
25
|
+
"isolate[build]>=0.13.0,<1.14.0",
|
|
26
|
+
"isolate-proto==0.5.1",
|
|
27
|
+
"grpcio==1.64.0",
|
|
28
28
|
"dill==0.3.7",
|
|
29
29
|
"cloudpickle==3.0.0",
|
|
30
30
|
"typing-extensions>=4.7.1,<5",
|
|
@@ -4,6 +4,7 @@ from fal import apps # noqa: F401
|
|
|
4
4
|
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
|
+
from fal.container import ContainerImage
|
|
7
8
|
from fal.sdk import FalServerlessKeyCredentials
|
|
8
9
|
from fal.sync import sync_dir
|
|
9
10
|
|
|
@@ -26,4 +27,5 @@ __all__ = [
|
|
|
26
27
|
"sync_dir",
|
|
27
28
|
"__version__",
|
|
28
29
|
"version_tuple",
|
|
30
|
+
"ContainerImage",
|
|
29
31
|
]
|
|
@@ -42,6 +42,7 @@ from typing_extensions import Concatenate, ParamSpec
|
|
|
42
42
|
|
|
43
43
|
import fal.flags as flags
|
|
44
44
|
from fal._serialization import include_modules_from, patch_pickle
|
|
45
|
+
from fal.container import ContainerImage
|
|
45
46
|
from fal.exceptions import FalServerlessException
|
|
46
47
|
from fal.logging.isolate import IsolateLogPrinter
|
|
47
48
|
from fal.sdk import (
|
|
@@ -523,9 +524,12 @@ class Options:
|
|
|
523
524
|
pip_requirements = self.environment.setdefault("requirements", [])
|
|
524
525
|
elif kind == "conda":
|
|
525
526
|
pip_requirements = self.environment.setdefault("pip", [])
|
|
527
|
+
elif kind == "container":
|
|
528
|
+
return None
|
|
526
529
|
else:
|
|
527
530
|
raise FalServerlessError(
|
|
528
|
-
"Only conda
|
|
531
|
+
"Only {conda, virtualenv, container} "
|
|
532
|
+
"are supported as environment options."
|
|
529
533
|
)
|
|
530
534
|
|
|
531
535
|
# Already has these.
|
|
@@ -743,8 +747,55 @@ def function(
|
|
|
743
747
|
_scheduler: str | None = None,
|
|
744
748
|
) -> Callable[
|
|
745
749
|
[Callable[Concatenate[ArgsT], ReturnT]], ServedIsolatedFunction[ArgsT, ReturnT]
|
|
746
|
-
]:
|
|
747
|
-
|
|
750
|
+
]: ...
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
@overload
|
|
754
|
+
def function(
|
|
755
|
+
kind: Literal["container"],
|
|
756
|
+
*,
|
|
757
|
+
image: ContainerImage | None = None,
|
|
758
|
+
# Common options
|
|
759
|
+
host: FalServerlessHost = _DEFAULT_HOST,
|
|
760
|
+
serve: Literal[False] = False,
|
|
761
|
+
exposed_port: int | None = None,
|
|
762
|
+
max_concurrency: int | None = None,
|
|
763
|
+
# FalServerlessHost options
|
|
764
|
+
metadata: dict[str, Any] | None = None,
|
|
765
|
+
machine_type: str = FAL_SERVERLESS_DEFAULT_MACHINE_TYPE,
|
|
766
|
+
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
767
|
+
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
768
|
+
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
769
|
+
setup_function: Callable[..., None] | None = None,
|
|
770
|
+
_base_image: str | None = None,
|
|
771
|
+
_scheduler: str | None = None,
|
|
772
|
+
) -> Callable[
|
|
773
|
+
[Callable[Concatenate[ArgsT], ReturnT]], IsolatedFunction[ArgsT, ReturnT]
|
|
774
|
+
]: ...
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
@overload
|
|
778
|
+
def function(
|
|
779
|
+
kind: Literal["container"],
|
|
780
|
+
*,
|
|
781
|
+
image: ContainerImage | None = None,
|
|
782
|
+
# Common options
|
|
783
|
+
host: FalServerlessHost = _DEFAULT_HOST,
|
|
784
|
+
serve: Literal[True],
|
|
785
|
+
exposed_port: int | None = None,
|
|
786
|
+
max_concurrency: int | None = None,
|
|
787
|
+
# FalServerlessHost options
|
|
788
|
+
metadata: dict[str, Any] | None = None,
|
|
789
|
+
machine_type: str = FAL_SERVERLESS_DEFAULT_MACHINE_TYPE,
|
|
790
|
+
keep_alive: int = FAL_SERVERLESS_DEFAULT_KEEP_ALIVE,
|
|
791
|
+
max_multiplexing: int = FAL_SERVERLESS_DEFAULT_MAX_MULTIPLEXING,
|
|
792
|
+
min_concurrency: int = FAL_SERVERLESS_DEFAULT_MIN_CONCURRENCY,
|
|
793
|
+
setup_function: Callable[..., None] | None = None,
|
|
794
|
+
_base_image: str | None = None,
|
|
795
|
+
_scheduler: str | None = None,
|
|
796
|
+
) -> Callable[
|
|
797
|
+
[Callable[Concatenate[ArgsT], ReturnT]], ServedIsolatedFunction[ArgsT, ReturnT]
|
|
798
|
+
]: ...
|
|
748
799
|
|
|
749
800
|
|
|
750
801
|
# implementation
|
|
@@ -1121,4 +1172,3 @@ class Server(uvicorn.Server):
|
|
|
1121
1172
|
|
|
1122
1173
|
def install_signal_handlers(self) -> None:
|
|
1123
1174
|
pass
|
|
1124
|
-
|
|
@@ -47,8 +47,9 @@ def wrap_app(cls: type[App], **kwargs) -> fal.api.IsolatedFunction:
|
|
|
47
47
|
routes = app.collect_routes()
|
|
48
48
|
realtime_app = any(route.is_websocket for route in routes)
|
|
49
49
|
|
|
50
|
+
kind = kwargs.pop("kind", "virtualenv")
|
|
50
51
|
wrapper = fal.api.function(
|
|
51
|
-
|
|
52
|
+
kind,
|
|
52
53
|
requirements=cls.requirements,
|
|
53
54
|
machine_type=cls.machine_type,
|
|
54
55
|
**cls.host_kwargs,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class ContainerImage:
|
|
2
|
+
"""ContainerImage represents a Docker image that can be built
|
|
3
|
+
from a Dockerfile.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
_known_keys = {"dockerfile_str", "build_env", "build_args"}
|
|
7
|
+
|
|
8
|
+
@classmethod
|
|
9
|
+
def from_dockerfile_str(cls, text: str, **kwargs):
|
|
10
|
+
# Check for unknown keys and return them as a dict.
|
|
11
|
+
return dict(
|
|
12
|
+
dockerfile_str=text,
|
|
13
|
+
**{k: v for k, v in kwargs.items() if k in cls._known_keys},
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def from_dockerfile(cls, path: str, **kwargs):
|
|
18
|
+
with open(path) as fobj:
|
|
19
|
+
return cls.from_dockerfile_str(fobj.read(), **kwargs)
|
|
@@ -8,6 +8,7 @@ import fal.api as api
|
|
|
8
8
|
import httpx
|
|
9
9
|
import pytest
|
|
10
10
|
from fal import apps
|
|
11
|
+
from fal.container import ContainerImage
|
|
11
12
|
from fal.rest_client import REST_CLIENT
|
|
12
13
|
from fal.workflows import Workflow
|
|
13
14
|
from fastapi import WebSocket
|
|
@@ -49,6 +50,23 @@ def addition_app(input: Input) -> Output:
|
|
|
49
50
|
|
|
50
51
|
nomad_addition_app = addition_app.on(_scheduler="nomad")
|
|
51
52
|
|
|
53
|
+
@fal.function(
|
|
54
|
+
kind="container",
|
|
55
|
+
image=ContainerImage.from_dockerfile_str("FROM python:3.11"),
|
|
56
|
+
keep_alive=60,
|
|
57
|
+
machine_type="S",
|
|
58
|
+
serve=True,
|
|
59
|
+
max_concurrency=1,
|
|
60
|
+
)
|
|
61
|
+
def container_addition_app(input: Input) -> Output:
|
|
62
|
+
print("starting...")
|
|
63
|
+
for _ in range(input.wait_time):
|
|
64
|
+
print("sleeping...")
|
|
65
|
+
time.sleep(1)
|
|
66
|
+
|
|
67
|
+
return Output(result=input.lhs + input.rhs)
|
|
68
|
+
|
|
69
|
+
|
|
52
70
|
@fal.function(
|
|
53
71
|
keep_alive=300,
|
|
54
72
|
requirements=["fastapi", "uvicorn", "pydantic==1.10.12"],
|
|
@@ -201,6 +219,20 @@ def test_nomad_app():
|
|
|
201
219
|
yield f"{user_id}/{app_revision}"
|
|
202
220
|
|
|
203
221
|
|
|
222
|
+
@pytest.mark.xfail(reason="The support needs to be deployed. See https://github.com/fal-ai/isolate-cloud/pull/1809")
|
|
223
|
+
@pytest.fixture(scope="module")
|
|
224
|
+
def test_container_app():
|
|
225
|
+
# Create a temporary app, register it, and return the ID of it.
|
|
226
|
+
|
|
227
|
+
from fal.cli.deploy import _get_user_id
|
|
228
|
+
|
|
229
|
+
app_revision = container_addition_app.host.register(
|
|
230
|
+
func=container_addition_app.func,
|
|
231
|
+
options=container_addition_app.options,
|
|
232
|
+
)
|
|
233
|
+
user_id = _get_user_id()
|
|
234
|
+
yield f"{user_id}/{app_revision}"
|
|
235
|
+
|
|
204
236
|
@pytest.fixture(scope="module")
|
|
205
237
|
def test_fastapi_app():
|
|
206
238
|
# Create a temporary app, register it, and return the ID of it.
|
|
@@ -5,12 +5,14 @@ from contextlib import suppress
|
|
|
5
5
|
import fal
|
|
6
6
|
import pytest
|
|
7
7
|
from fal.api import FalServerlessError, Options
|
|
8
|
+
from fal.container import ContainerImage
|
|
8
9
|
from fal.toolkit.file.file import File
|
|
9
10
|
from pydantic import __version__ as pydantic_version
|
|
10
11
|
|
|
11
|
-
PACKAGE_NAME = "
|
|
12
|
+
PACKAGE_NAME = "fall"
|
|
12
13
|
|
|
13
14
|
|
|
15
|
+
@pytest.mark.xfail(reason="Temporary mismatch due to grpc version updates. Ping @efiop")
|
|
14
16
|
def test_missing_dependencies_nested_server_error(isolated_client):
|
|
15
17
|
@isolated_client()
|
|
16
18
|
def test1():
|
|
@@ -54,6 +56,40 @@ def test_regular_function_on_nomad(isolated_client):
|
|
|
54
56
|
|
|
55
57
|
assert mult(5, 2) == 10
|
|
56
58
|
|
|
59
|
+
@pytest.mark.xfail(reason="The support needs to be deployed. See https://github.com/fal-ai/isolate-cloud/pull/1809")
|
|
60
|
+
def test_regular_function_in_a_container(isolated_client):
|
|
61
|
+
@isolated_client("container")
|
|
62
|
+
def regular_function():
|
|
63
|
+
return 42
|
|
64
|
+
|
|
65
|
+
assert regular_function() == 42
|
|
66
|
+
|
|
67
|
+
@isolated_client("container")
|
|
68
|
+
def mult(a, b):
|
|
69
|
+
return a * b
|
|
70
|
+
|
|
71
|
+
assert mult(5, 2) == 10
|
|
72
|
+
|
|
73
|
+
@pytest.mark.xfail(reason="The support needs to be deployed. See https://github.com/fal-ai/isolate-cloud/pull/1809")
|
|
74
|
+
def test_regular_function_in_a_container_with_custom_image(isolated_client):
|
|
75
|
+
@isolated_client(
|
|
76
|
+
"container",
|
|
77
|
+
image=ContainerImage.from_dockerfile_str("FROM python:3.9"),
|
|
78
|
+
)
|
|
79
|
+
def regular_function():
|
|
80
|
+
return 42
|
|
81
|
+
|
|
82
|
+
assert regular_function() == 42
|
|
83
|
+
|
|
84
|
+
@isolated_client(
|
|
85
|
+
"container",
|
|
86
|
+
image=ContainerImage.from_dockerfile_str("FROM python:3.9"),
|
|
87
|
+
)
|
|
88
|
+
def mult(a, b):
|
|
89
|
+
return a * b
|
|
90
|
+
|
|
91
|
+
assert mult(5, 2) == 10
|
|
92
|
+
|
|
57
93
|
|
|
58
94
|
def test_function_pipelining(isolated_client):
|
|
59
95
|
@isolated_client("virtualenv")
|
|
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
|
{fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_contents_output.py
RENAMED
|
File without changes
|
|
File without changes
|
{fal-1.0.4 → fal-1.0.5}/openapi-fal-rest/openapi_fal_rest/models/workflow_detail_contents_type_0.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
|