diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f2c9595..e615f9ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,6 +6,13 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: 'v0.3.4' hooks: + - id: ruff-format + files: | + (?x)( + ^projects/fal/src/| + ^projects/fal/tests/| + ^projects/fal_client/ + ) - id: ruff args: [--fix, --exit-non-zero-on-fix] files: | diff --git a/projects/fal/src/fal/_serialization.py b/projects/fal/src/fal/_serialization.py index 152d5721..643b1911 100644 --- a/projects/fal/src/fal/_serialization.py +++ b/projects/fal/src/fal/_serialization.py @@ -186,8 +186,8 @@ def create_rlock(count: int, owner: int) -> RLockType: def pickle_rlock(obj: RLockType) -> tuple[Callable, tuple]: r = obj.__repr__() - count = int(r.split('count=')[1].split()[0].rstrip('>')) - owner = int(r.split('owner=')[1].split()[0]) + count = int(r.split("count=")[1].split()[0].rstrip(">")) + owner = int(r.split("owner=")[1].split()[0]) return create_rlock, (count, owner) @@ -209,7 +209,7 @@ def pickle_locals(obj: ConsoleThreadLocals) -> tuple[Callable, tuple]: "buffer": obj.buffer, "buffer_index": obj.buffer_index, } - return create_locals, (kwargs, ) + return create_locals, (kwargs,) _register(ConsoleThreadLocals, pickle_locals) @@ -231,4 +231,3 @@ def patch_pickle() -> None: _patch_exceptions() _register_pickle_by_value("fal") - diff --git a/projects/fal/src/fal/apps.py b/projects/fal/src/fal/apps.py index e6b791d4..8a12c895 100644 --- a/projects/fal/src/fal/apps.py +++ b/projects/fal/src/fal/apps.py @@ -24,8 +24,7 @@ def _backwards_compatible_app_id(app_id: str) -> str: @dataclass -class _Status: - ... +class _Status: ... @dataclass diff --git a/projects/fal/src/fal/cli/apps.py b/projects/fal/src/fal/cli/apps.py index 7164901c..2a27e4e9 100644 --- a/projects/fal/src/fal/cli/apps.py +++ b/projects/fal/src/fal/cli/apps.py @@ -203,7 +203,6 @@ def _runners(args): from fal.sdk import FalServerlessClient - client = FalServerlessClient(args.host) with client.connect() as connection: runners = connection.list_alias_runners(alias=args.app_name) diff --git a/projects/fal/src/fal/cli/debug.py b/projects/fal/src/fal/cli/debug.py index 16e437f4..516190eb 100644 --- a/projects/fal/src/fal/cli/debug.py +++ b/projects/fal/src/fal/cli/debug.py @@ -47,11 +47,7 @@ def debugtools(args): def get_debug_parser(): parser = FalParser(add_help=False) group = parser.add_argument_group(title="Debug") - group.add_argument( - "--debug", - action="store_true", - help="Show verbose errors." - ) + group.add_argument("--debug", action="store_true", help="Show verbose errors.") group.add_argument( "--pdb", action="store_true", diff --git a/projects/fal/src/fal/cli/deploy.py b/projects/fal/src/fal/cli/deploy.py index 6d048e6b..1f8ebe42 100644 --- a/projects/fal/src/fal/cli/deploy.py +++ b/projects/fal/src/fal/cli/deploy.py @@ -69,9 +69,7 @@ def _deploy(args): # Try to find a python file in the current directory options = list(Path(".").glob("*.py")) if len(options) == 0: - raise FalServerlessError( - "No python files found in the current directory" - ) + raise FalServerlessError("No python files found in the current directory") elif len(options) > 1: raise FalServerlessError( "Multiple python files found in the current directory. " @@ -107,8 +105,12 @@ def _deploy(args): "Registered a new revision for function " f"'{app_name}' (revision='{app_id}')." ) - args.console.print(f"Playground: https://fal.ai/models/{user.username}/{app_name}") - args.console.print(f"Endpoint: https://{gateway_host}/{user.username}/{app_name}") + args.console.print( + f"Playground: https://fal.ai/models/{user.username}/{app_name}" + ) + args.console.print( + f"Endpoint: https://{gateway_host}/{user.username}/{app_name}" + ) def add_parser(main_subparsers, parents): @@ -139,8 +141,7 @@ def valid_auth_option(option): nargs="?", action=RefAction, help=( - "Application reference. " - "For example: `myfile.py::MyApp`, `myfile.py`." + "Application reference. " "For example: `myfile.py::MyApp`, `myfile.py`." ), ) parser.add_argument( diff --git a/projects/fal/src/fal/cli/keys.py b/projects/fal/src/fal/cli/keys.py index 289c8697..3416bf53 100644 --- a/projects/fal/src/fal/cli/keys.py +++ b/projects/fal/src/fal/cli/keys.py @@ -56,7 +56,10 @@ def _list(args): keys = connection.list_user_keys() for key in keys: table.add_row( - key.key_id, str(key.created_at), str(key.scope.value), key.alias, + key.key_id, + str(key.created_at), + str(key.scope.value), + key.alias, ) args.console.print(table) diff --git a/projects/fal/src/fal/cli/run.py b/projects/fal/src/fal/cli/run.py index 5e7fdc21..4c25e1a3 100644 --- a/projects/fal/src/fal/cli/run.py +++ b/projects/fal/src/fal/cli/run.py @@ -14,10 +14,7 @@ def _run(args): def add_parser(main_subparsers, parents): run_help = "Run fal function." - epilog = ( - "Examples:\n" - " fal run path/to/myfile.py::myfunc" - ) + epilog = "Examples:\n" " fal run path/to/myfile.py::myfunc" parser = main_subparsers.add_parser( "run", description=run_help, diff --git a/projects/fal/src/fal/cli/secrets.py b/projects/fal/src/fal/cli/secrets.py index d448c27c..3104c350 100644 --- a/projects/fal/src/fal/cli/secrets.py +++ b/projects/fal/src/fal/cli/secrets.py @@ -1,9 +1,9 @@ - from .parser import DictAction, FalClientParser def _set(args): from fal.sdk import FalServerlessClient + client = FalServerlessClient(args.host) with client.connect() as connection: for name, value in args.secrets.items(): @@ -12,10 +12,7 @@ def _set(args): def _add_set_parser(subparsers, parents): set_help = "Set a secret." - epilog = ( - "Examples:\n" - " fal secrets set HF_TOKEN=hf_***" - ) + epilog = "Examples:\n" " fal secrets set HF_TOKEN=hf_***" parser = subparsers.add_parser( "set", @@ -64,6 +61,7 @@ def _add_list_parser(subparsers, parents): def _unset(args): from fal.sdk import FalServerlessClient + client = FalServerlessClient(args.host) with client.connect() as connection: connection.delete_secret(args.secret) diff --git a/projects/fal/src/fal/exceptions/_base.py b/projects/fal/src/fal/exceptions/_base.py index 885a2f94..086b72c2 100644 --- a/projects/fal/src/fal/exceptions/_base.py +++ b/projects/fal/src/fal/exceptions/_base.py @@ -3,4 +3,5 @@ class FalServerlessException(Exception): """Base exception type for fal Serverless related flows and APIs.""" + pass diff --git a/projects/fal/src/fal/logging/isolate.py b/projects/fal/src/fal/logging/isolate.py index 3a21f46b..f50bbae9 100644 --- a/projects/fal/src/fal/logging/isolate.py +++ b/projects/fal/src/fal/logging/isolate.py @@ -13,7 +13,6 @@ class IsolateLogPrinter: - debug: bool def __init__(self, debug: bool = False) -> None: diff --git a/projects/fal/src/fal/sdk.py b/projects/fal/src/fal/sdk.py index f1696516..362db471 100644 --- a/projects/fal/src/fal/sdk.py +++ b/projects/fal/src/fal/sdk.py @@ -277,7 +277,7 @@ def from_proto( @from_grpc.register(isolate_proto.ApplicationInfo) def _from_grpc_application_info( - message: isolate_proto.ApplicationInfo + message: isolate_proto.ApplicationInfo, ) -> ApplicationInfo: return ApplicationInfo( application_id=message.application_id, diff --git a/projects/fal/src/fal/toolkit/file/file.py b/projects/fal/src/fal/toolkit/file/file.py index 66766695..de64cb43 100644 --- a/projects/fal/src/fal/toolkit/file/file.py +++ b/projects/fal/src/fal/toolkit/file/file.py @@ -15,6 +15,7 @@ else: from pydantic import GetCoreSchemaHandler from pydantic_core import CoreSchema, core_schema + IS_PYDANTIC_V2 = True from pydantic import BaseModel, Field diff --git a/projects/fal/src/fal/toolkit/file/providers/fal.py b/projects/fal/src/fal/toolkit/file/providers/fal.py index 65ceb611..e8826a77 100644 --- a/projects/fal/src/fal/toolkit/file/providers/fal.py +++ b/projects/fal/src/fal/toolkit/file/providers/fal.py @@ -41,7 +41,9 @@ def _save(self, file: FileData, storage_type: str) -> str: grpc_host = os.environ.get("FAL_HOST", "api.alpha.fal.ai") rest_host = grpc_host.replace("api", "rest", 1) - storage_url = f"https://{rest_host}/storage/upload/initiate?storage_type={storage_type}" + storage_url = ( + f"https://{rest_host}/storage/upload/initiate?storage_type={storage_type}" + ) try: req = Request( diff --git a/projects/fal/src/fal/toolkit/image/image.py b/projects/fal/src/fal/toolkit/image/image.py index 6fd6f7f0..9c778b81 100644 --- a/projects/fal/src/fal/toolkit/image/image.py +++ b/projects/fal/src/fal/toolkit/image/image.py @@ -44,6 +44,7 @@ class ImageSize(BaseModel): ImageSizeInput = Union[ImageSize, ImageSizePreset] + def get_image_size(source: ImageSizeInput) -> ImageSize: if isinstance(source, ImageSize): return source @@ -62,7 +63,8 @@ class Image(File): """ width: Optional[int] = Field( - None, description="The width of the image in pixels.", + None, + description="The width of the image in pixels.", examples=[1024], ) height: Optional[int] = Field( @@ -84,8 +86,8 @@ def from_bytes( # type: ignore[override] file_name=file_name, repository=repository, ) - obj.width=size.width if size else None - obj.height=size.height if size else None + obj.width = size.width if size else None + obj.height = size.height if size else None return obj @classmethod @@ -120,9 +122,7 @@ def to_pil(self, mode: str = "RGB") -> PILImage.Image: from PIL import Image as PILImage from PIL import ImageOps except ImportError: - raise ImportError( - "The PIL package is required to use Image.to_pil()." - ) + raise ImportError("The PIL package is required to use Image.to_pil().") # Stream the image data from url to a temp file and convert it to a PIL image with NamedTemporaryFile() as temp_file: @@ -134,4 +134,3 @@ def to_pil(self, mode: str = "RGB") -> PILImage.Image: img = ImageOps.exif_transpose(img) return img - diff --git a/projects/fal/src/fal/utils.py b/projects/fal/src/fal/utils.py index f9ce2a04..85dc8f2d 100644 --- a/projects/fal/src/fal/utils.py +++ b/projects/fal/src/fal/utils.py @@ -51,4 +51,3 @@ def load_function_from( f"Function '{function_name}' is not a fal.function or a fal.App" ) return target, app_name - diff --git a/projects/fal/tests/cli/test_apps.py b/projects/fal/tests/cli/test_apps.py index 4e1dc1eb..c84ea7ee 100644 --- a/projects/fal/tests/cli/test_apps.py +++ b/projects/fal/tests/cli/test_apps.py @@ -31,11 +31,17 @@ def test_set_rev(): def test_scale(): args = parse_args( [ - "apps", "scale", "myapp", - "--keep-alive", "123", - "--max-multiplexing", "321", - "--min-concurrency", "7", - "--max-concurrency", "10", + "apps", + "scale", + "myapp", + "--keep-alive", + "123", + "--max-multiplexing", + "321", + "--min-concurrency", + "7", + "--max-concurrency", + "10", ] ) assert args.func == _scale @@ -61,4 +67,3 @@ def test_delete_rev(): args = parse_args(["apps", "delete-rev", "myrev"]) assert args.func == _delete_rev assert args.app_rev == "myrev" - diff --git a/projects/fal/tests/cli/test_auth.py b/projects/fal/tests/cli/test_auth.py index 97d3011a..e7a5b39a 100644 --- a/projects/fal/tests/cli/test_auth.py +++ b/projects/fal/tests/cli/test_auth.py @@ -6,6 +6,7 @@ def test_login(): args = parse_args(["auth", "login"]) assert args.func == _login + def test_logout(): args = parse_args(["auth", "logout"]) assert args.func == _logout @@ -14,4 +15,3 @@ def test_logout(): def test_whoami(): args = parse_args(["auth", "whoami"]) assert args.func == _whoami - diff --git a/projects/fal/tests/cli/test_keys.py b/projects/fal/tests/cli/test_keys.py index 3c4fd140..111e4057 100644 --- a/projects/fal/tests/cli/test_keys.py +++ b/projects/fal/tests/cli/test_keys.py @@ -7,8 +7,10 @@ def test_create(): [ "keys", "create", - "--scope", "API", - "--desc", "My test key", + "--scope", + "API", + "--desc", + "My test key", ] ) assert args.func == _create diff --git a/projects/fal/tests/integration_test.py b/projects/fal/tests/integration_test.py index 5357aa41..7988fee2 100644 --- a/projects/fal/tests/integration_test.py +++ b/projects/fal/tests/integration_test.py @@ -556,7 +556,6 @@ def init_compressed_file_on_fal(input: TestInput) -> int: def test_fal_cdn(isolated_client): - @isolated_client(requirements=[f"pydantic=={pydantic_version}"]) def upload_to_fal_cdn() -> FalImage: return FalImage.from_bytes(b"0", "jpeg", repository="cdn") diff --git a/projects/fal/tests/test_stability.py b/projects/fal/tests/test_stability.py index 8ad056c1..1566d6ad 100644 --- a/projects/fal/tests/test_stability.py +++ b/projects/fal/tests/test_stability.py @@ -56,7 +56,10 @@ def mult(a, b): assert mult(5, 2) == 10 -@pytest.mark.xfail(reason="The support needs to be deployed. See https://github.com/fal-ai/isolate-cloud/pull/1809") + +@pytest.mark.xfail( + reason="The support needs to be deployed. See https://github.com/fal-ai/isolate-cloud/pull/1809" +) def test_regular_function_in_a_container(isolated_client): @isolated_client("container") def regular_function(): @@ -70,7 +73,10 @@ def mult(a, b): assert mult(5, 2) == 10 -@pytest.mark.xfail(reason="The support needs to be deployed. See https://github.com/fal-ai/isolate-cloud/pull/1809") + +@pytest.mark.xfail( + reason="The support needs to be deployed. See https://github.com/fal-ai/isolate-cloud/pull/1809" +) def test_regular_function_in_a_container_with_custom_image(isolated_client): @isolated_client( "container", @@ -557,11 +563,14 @@ def get_env_var(name: str) -> str | None: @pytest.mark.parametrize( - "repo_type, url_prefix", - [ - ("fal", "https://storage.googleapis.com/isolate-dev-smiling-shark_toolkit_bucket/"), - ("fal_v2", "https://v2.fal.media/files"), - ] + "repo_type, url_prefix", + [ + ( + "fal", + "https://storage.googleapis.com/isolate-dev-smiling-shark_toolkit_bucket/", + ), + ("fal_v2", "https://v2.fal.media/files"), + ], ) def test_fal_storage(isolated_client, repo_type, url_prefix): file = File.from_bytes(b"Hello fal storage from local", repository=repo_type) diff --git a/projects/fal/tests/toolkit/file_test.py b/projects/fal/tests/toolkit/file_test.py index 8d164d7e..6dbe639c 100644 --- a/projects/fal/tests/toolkit/file_test.py +++ b/projects/fal/tests/toolkit/file_test.py @@ -96,8 +96,8 @@ def test_uniqueness_of_file_name(repo: RepositoryId | FileRepository): host_and_path = file.url.split("?")[0] last_path = host_and_path.split("/")[-1] - assert ( - last_path.endswith(".py") + assert last_path.endswith( + ".py" ), f"The file name {last_path} should end with the same extension" assert ( len(last_path) > 10 diff --git a/projects/fal_client/tests/test_async_client.py b/projects/fal_client/tests/test_async_client.py index 675e818a..21a12881 100644 --- a/projects/fal_client/tests/test_async_client.py +++ b/projects/fal_client/tests/test_async_client.py @@ -44,7 +44,7 @@ async def test_fal_client(client: fal_client.AsyncClient): arguments={ "prompt": "a cat", }, - hint="lora:a" + hint="lora:a", ) assert len(output["images"]) == 1 diff --git a/projects/fal_client/tests/unit/test_client.py b/projects/fal_client/tests/unit/test_client.py index e42904de..1ede8782 100644 --- a/projects/fal_client/tests/unit/test_client.py +++ b/projects/fal_client/tests/unit/test_client.py @@ -22,16 +22,22 @@ False, ), ( - {"status": "COMPLETED", "logs": [{"msg": "foo"}, {"msg": "bar"}], "metrics": {"m1": "v1", "m2": "v2"}}, - Completed(logs=[{"msg": "foo"}, {"msg": "bar"}], metrics={"m1": "v1", "m2": "v2"}), + { + "status": "COMPLETED", + "logs": [{"msg": "foo"}, {"msg": "bar"}], + "metrics": {"m1": "v1", "m2": "v2"}, + }, + Completed( + logs=[{"msg": "foo"}, {"msg": "bar"}], metrics={"m1": "v1", "m2": "v2"} + ), False, ), ( {"status": "FOO"}, ValueError, True, - ) - ] + ), + ], ) def test_parse_status(data, result, raised): handle = _BaseRequestHandle("foo", "bar", "baz", "qux")