From e7f29dd3cd3e18acef94e0d63908b28abcf219e6 Mon Sep 17 00:00:00 2001 From: Matteo Ferrando Date: Wed, 30 Oct 2024 08:33:59 -0400 Subject: [PATCH 1/8] fix: add 3.8 tests --- .github/workflows/integration_tests.yaml | 5 +++-- .github/workflows/tests-fal-client.yml | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml index cc2ffd74..2a05369e 100644 --- a/.github/workflows/integration_tests.yaml +++ b/.github/workflows/integration_tests.yaml @@ -25,6 +25,7 @@ jobs: fail-fast: false matrix: deps: ["pydantic==1.10.12", "pydantic==2.5.0"] + python: ["3.8", "3.13"] steps: - uses: actions/checkout@v3 with: @@ -32,8 +33,8 @@ jobs: - uses: actions/setup-python@v4 with: - python-version: "3.9" - cache: 'pip' + python-version: ${{ matrix.python }} + cache: pip - name: Install dependencies run: | diff --git a/.github/workflows/tests-fal-client.yml b/.github/workflows/tests-fal-client.yml index d7244333..fac0daf5 100644 --- a/.github/workflows/tests-fal-client.yml +++ b/.github/workflows/tests-fal-client.yml @@ -10,13 +10,17 @@ on: jobs: tests: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python: ["3.8", "3.13"] steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - uses: actions/setup-python@v4 with: - python-version: "3.12" + python-version: ${{ matrix.python }} - name: Install dependencies run: | pip install --upgrade pip wheel @@ -25,4 +29,4 @@ jobs: env: FAL_KEY: ${{ secrets.FAL_KEY_PROD }} run: | - pytest projects/fal_client/tests \ No newline at end of file + pytest projects/fal_client/tests From f2d32503a8bd51b0367a51932cffecf78c9e8963 Mon Sep 17 00:00:00 2001 From: Matteo Ferrando Date: Wed, 30 Oct 2024 08:35:14 -0400 Subject: [PATCH 2/8] fix types --- projects/fal/tests/cli/test_deploy.py | 4 ++-- projects/fal_client/src/fal_client/client.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/fal/tests/cli/test_deploy.py b/projects/fal/tests/cli/test_deploy.py index 5c23ff2f..fd30342b 100644 --- a/projects/fal/tests/cli/test_deploy.py +++ b/projects/fal/tests/cli/test_deploy.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Tuple from unittest.mock import MagicMock, patch import pytest @@ -30,7 +30,7 @@ def mock_parse_pyproject_toml(): def mock_args( - app_ref: tuple[str], + app_ref: Tuple[str, Optional[str]], app_name: Optional[str] = None, auth: Optional[str] = None, strategy: Optional[str] = None, diff --git a/projects/fal_client/src/fal_client/client.py b/projects/fal_client/src/fal_client/client.py index cb2c122b..c70f93e0 100644 --- a/projects/fal_client/src/fal_client/client.py +++ b/projects/fal_client/src/fal_client/client.py @@ -10,7 +10,7 @@ from datetime import datetime, timezone from dataclasses import dataclass, field from functools import cached_property -from typing import Any, AsyncIterator, Iterator, TYPE_CHECKING, Optional, Literal +from typing import Any, AsyncIterator, Dict, Iterator, TYPE_CHECKING, Optional, Literal from urllib.parse import urlencode import httpx @@ -20,7 +20,7 @@ if TYPE_CHECKING: from PIL import Image -AnyJSON = dict[str, Any] +AnyJSON = Dict[str, Any] Priority = Literal["normal", "low"] RUN_URL_FORMAT = f"https://{FAL_RUN_HOST}/" From dfac930f7acf062f02d94454e1e48a0be9c31be8 Mon Sep 17 00:00:00 2001 From: Matteo Ferrando Date: Wed, 30 Oct 2024 08:49:10 -0400 Subject: [PATCH 3/8] back to 3.12 for tests for now --- .github/workflows/integration_tests.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml index 2a05369e..bd77119d 100644 --- a/.github/workflows/integration_tests.yaml +++ b/.github/workflows/integration_tests.yaml @@ -25,7 +25,8 @@ jobs: fail-fast: false matrix: deps: ["pydantic==1.10.12", "pydantic==2.5.0"] - python: ["3.8", "3.13"] + # TODO: Test Python 3.13 + python: ["3.8", "3.12"] steps: - uses: actions/checkout@v3 with: From 4e0628cee8c484da1d9a1cc26fff78501f142f64 Mon Sep 17 00:00:00 2001 From: Matteo Ferrando Date: Wed, 30 Oct 2024 09:17:27 -0400 Subject: [PATCH 4/8] type --- projects/fal/src/fal/workflows.py | 6 +++--- projects/fal/tests/cli/test_run.py | 3 ++- projects/fal/tests/test_apps.py | 12 ++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/projects/fal/src/fal/workflows.py b/projects/fal/src/fal/workflows.py index 087814a1..f193d52a 100644 --- a/projects/fal/src/fal/workflows.py +++ b/projects/fal/src/fal/workflows.py @@ -5,7 +5,7 @@ from argparse import ArgumentParser from collections import Counter from dataclasses import dataclass, field -from typing import Any, Iterator, Union, cast +from typing import Any, Dict, Iterator, List, Union, cast import graphlib import rich @@ -21,8 +21,8 @@ from fal.exceptions import FalServerlessException from fal.rest_client import REST_CLIENT -JSONType = Union[dict[str, Any], list[Any], str, int, float, bool, None, "Leaf"] -SchemaType = dict[str, Any] +JSONType = Union[Dict[str, Any], List[Any], str, int, float, bool, None, "Leaf"] +SchemaType = Dict[str, Any] VARIABLE_PREFIX = "$" INPUT_VARIABLE_NAME = "input" diff --git a/projects/fal/tests/cli/test_run.py b/projects/fal/tests/cli/test_run.py index 05c88e34..542087e6 100644 --- a/projects/fal/tests/cli/test_run.py +++ b/projects/fal/tests/cli/test_run.py @@ -1,3 +1,4 @@ +from typing import Optional, Tuple from unittest.mock import MagicMock, patch import pytest @@ -34,7 +35,7 @@ def mocked_fal_serverless_host(host): return mock -def mock_args(host, func_ref: tuple[str]): +def mock_args(host, func_ref: Tuple[str, Optional[str]]): args = MagicMock() args.host = host args.func_ref = func_ref diff --git a/projects/fal/tests/test_apps.py b/projects/fal/tests/test_apps.py index 6e17a5a1..4a6fa73b 100644 --- a/projects/fal/tests/test_apps.py +++ b/projects/fal/tests/test_apps.py @@ -5,7 +5,7 @@ import time from contextlib import contextmanager, suppress from datetime import datetime -from typing import Generator +from typing import Generator, List, Tuple import fal import fal.api as api @@ -224,7 +224,7 @@ class RTOutput(BaseModel): class RTOutputs(BaseModel): - texts: list[str] + texts: List[str] class RealtimeApp(fal.App, keep_alive=300, max_concurrency=1): @@ -252,7 +252,7 @@ def generate_rt_batched(self, input: RTInput, *inputs: RTInput) -> RTOutputs: @pytest.fixture(scope="module") -def aliased_app() -> Generator[tuple[str, str], None, None]: +def aliased_app() -> Generator[Tuple[str, str], None, None]: # Create a temporary app, register it, and return the ID of it. import uuid @@ -516,7 +516,7 @@ def test_404_response(test_app: str, request: pytest.FixtureRequest): apps.run(test_app, path="/other", arguments={"lhs": 1, "rhs": 2}) -def test_app_deploy_scale(aliased_app: tuple[str, str]): +def test_app_deploy_scale(aliased_app: Tuple[str, str]): import uuid from dataclasses import replace @@ -558,7 +558,7 @@ def test_app_deploy_scale(aliased_app: tuple[str, str]): assert found.max_multiplexing == 30 -def test_app_update_app(aliased_app: tuple[str, str]): +def test_app_update_app(aliased_app: Tuple[str, str]): app_revision, app_alias = aliased_app host: api.FalServerlessHost = addition_app.host # type: ignore @@ -608,7 +608,7 @@ def test_app_update_app(aliased_app: tuple[str, str]): assert res.max_multiplexing == new_max_multiplexing -def test_app_set_delete_alias(aliased_app: tuple[str, str]): +def test_app_set_delete_alias(aliased_app: Tuple[str, str]): app_revision, app_alias = aliased_app host: api.FalServerlessHost = addition_app.host # type: ignore From b5f3f4239b1815d4750308259257271ded095a45 Mon Sep 17 00:00:00 2001 From: Matteo Ferrando Date: Wed, 30 Oct 2024 09:26:37 -0400 Subject: [PATCH 5/8] flaky --- projects/fal/tests/test_apps.py | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/fal/tests/test_apps.py b/projects/fal/tests/test_apps.py index 4a6fa73b..3b85ef27 100644 --- a/projects/fal/tests/test_apps.py +++ b/projects/fal/tests/test_apps.py @@ -418,6 +418,7 @@ def test_stateful_app_client(test_stateful_app: str): assert response["result"] == 0 +@pytest.mark.flaky(max_runs=3) def test_app_cancellation(test_app: str, test_cancellable_app: str): request_handle = apps.submit( test_cancellable_app, arguments={"lhs": 1, "rhs": 2, "wait_time": 10} From 67b9f842d74e779ce18e871e9395d06006aea725 Mon Sep 17 00:00:00 2001 From: Matteo Ferrando Date: Wed, 30 Oct 2024 09:29:47 -0400 Subject: [PATCH 6/8] graphlib --- .github/workflows/integration_tests.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml index bd77119d..2aa2de49 100644 --- a/.github/workflows/integration_tests.yaml +++ b/.github/workflows/integration_tests.yaml @@ -40,7 +40,8 @@ jobs: - name: Install dependencies run: | pip install --upgrade pip wheel - pip install -e 'projects/fal[test]' ${{ matrix.deps }} + # TODO: should we include graphlib as a project dependency? + pip install -e 'projects/fal[test]' graphlib ${{ matrix.deps }} - name: Run integration tests env: From 0c903b0151f018e44738a8ec78b707ca2f287963 Mon Sep 17 00:00:00 2001 From: Matteo Ferrando Date: Wed, 30 Oct 2024 09:38:02 -0400 Subject: [PATCH 7/8] removeprefix --- projects/fal/src/fal/apps.py | 6 ++++-- projects/fal/src/fal/workflows.py | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/projects/fal/src/fal/apps.py b/projects/fal/src/fal/apps.py index ba1465f5..208b7491 100644 --- a/projects/fal/src/fal/apps.py +++ b/projects/fal/src/fal/apps.py @@ -173,7 +173,8 @@ def submit(app_id: str, arguments: dict[str, Any], *, path: str = "") -> Request app_id = _backwards_compatible_app_id(app_id) url = _QUEUE_URL_FORMAT.format(app_id=app_id) if path: - url += "/" + path.removeprefix("/") + _path = path[len("/") :] if path.startswith("/") else path + url += "/" + _path creds = get_default_credentials() @@ -235,7 +236,8 @@ def _connect(app_id: str, *, path: str = "/realtime") -> Iterator[_RealtimeConne app_id = _backwards_compatible_app_id(app_id) url = _REALTIME_URL_FORMAT.format(app_id=app_id) if path: - url += "/" + path.removeprefix("/") + _path = path[len("/") :] if path.startswith("/") else path + url += "/" + _path creds = get_default_credentials() diff --git a/projects/fal/src/fal/workflows.py b/projects/fal/src/fal/workflows.py index f193d52a..62c50ebf 100644 --- a/projects/fal/src/fal/workflows.py +++ b/projects/fal/src/fal/workflows.py @@ -50,7 +50,13 @@ def parse_leaf(raw_leaf: str) -> Leaf: f"Invalid leaf: {raw_leaf} (must start with a reference)" ) - leaf: Leaf = ReferenceLeaf(reference.removeprefix(VARIABLE_PREFIX)) + # remove the $ prefix + _reference = ( + reference[len(VARIABLE_PREFIX) :] + if reference.startswith(VARIABLE_PREFIX) + else reference + ) + leaf: Leaf = ReferenceLeaf(_reference) for raw_part in raw_parts: if raw_part.isdigit(): leaf = IndexLeaf(leaf, int(raw_part)) From fbdb59f49ad2d850a20d735821ffafc5f5eeed4a Mon Sep 17 00:00:00 2001 From: Matteo Ferrando Date: Wed, 30 Oct 2024 09:40:39 -0400 Subject: [PATCH 8/8] pydantic --- .github/workflows/integration_tests.yaml | 2 +- projects/fal/tests/test_apps.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml index 2aa2de49..b8d4b947 100644 --- a/.github/workflows/integration_tests.yaml +++ b/.github/workflows/integration_tests.yaml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - deps: ["pydantic==1.10.12", "pydantic==2.5.0"] + deps: ["pydantic==1.10.18", "pydantic==2.5.0"] # TODO: Test Python 3.13 python: ["3.8", "3.12"] steps: diff --git a/projects/fal/tests/test_apps.py b/projects/fal/tests/test_apps.py index 3b85ef27..aedebb56 100644 --- a/projects/fal/tests/test_apps.py +++ b/projects/fal/tests/test_apps.py @@ -92,7 +92,7 @@ def container_addition_app(input: Input) -> Output: @fal.function( keep_alive=300, - requirements=["fastapi", "uvicorn", "pydantic==1.10.12"], + requirements=["fastapi", "uvicorn", "pydantic==1.10.18"], machine_type="S", max_concurrency=1, max_multiplexing=30,