From 766260aa7f246710912e454c9ddb32ca22afc020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Antonio=20Perdiguero=20L=C3=B3pez?= Date: Tue, 11 Feb 2025 22:09:21 +0100 Subject: [PATCH] :sparkles: Remove black and isort in favor of ruff format --- .github/workflows/test_and_publish.yaml | 29 ++- .../workflows/test_pull_request_branch.yaml | 17 +- .pre-commit-config.yaml | 56 +++-- Makefile | 24 +-- examples/error.py | 9 +- flama/applications.py | 2 +- flama/asgi.py | 2 +- flama/authentication/exceptions.py | 18 +- flama/authentication/middleware.py | 4 +- flama/cli/config/app.py | 3 +- flama/cli/config/config.py | 3 +- flama/cli/config/uvicorn.py | 8 +- flama/codecs/base.py | 9 +- flama/config/config.py | 18 +- flama/config/loaders.py | 2 +- flama/ddd/exceptions.py | 6 +- flama/ddd/repositories/base.py | 3 +- flama/ddd/workers/http.py | 6 +- flama/debug/data_structures.py | 2 +- flama/debug/middleware.py | 6 +- flama/exceptions.py | 9 +- flama/injection/exceptions.py | 3 +- flama/injection/injector.py | 12 +- flama/injection/resolver.py | 3 +- flama/lifespan.py | 3 +- flama/middleware.py | 6 +- flama/models/base.py | 3 +- flama/models/resource.py | 2 +- flama/modules.py | 11 +- flama/pagination/__init__.py | 2 +- flama/pagination/decorators.py | 6 +- flama/pagination/paginator.py | 17 +- flama/resources/crud.py | 3 +- flama/routing/routes/base.py | 3 +- flama/routing/routes/http.py | 2 +- flama/schemas/_libs/marshmallow/adapter.py | 2 +- flama/schemas/adapter.py | 45 ++-- flama/schemas/data_structures.py | 21 +- flama/serialize/base.py | 12 +- flama/serialize/serializers/tensorflow.py | 2 +- flama/types/asgi.py | 12 +- flama/types/endpoints.py | 27 +-- flama/url.py | 12 +- flama/validation.py | 12 +- poetry.lock | 141 +++---------- pyproject.toml | 193 ++++++++---------- scripts/format | 12 ++ scripts/lint | 25 +-- scripts/ruff | 12 -- scripts/{pyright => types} | 0 tests/ddd/repositories/test_http.py | 3 +- tests/ddd/repositories/test_sqlalchemy.py | 3 +- tests/ddd/test_components.py | 18 +- tests/ddd/workers/test_base.py | 33 +-- tests/ddd/workers/test_worker.py | 3 +- tests/debug/test_data_structures.py | 24 ++- tests/debug/test_middleware.py | 38 ++-- tests/endpoints/test_base.py | 6 +- tests/endpoints/test_http.py | 9 +- tests/endpoints/test_websocket.py | 3 +- tests/resources/test_workers.py | 9 +- tests/routing/routes/test_base.py | 21 +- tests/routing/routes/test_http.py | 21 +- tests/routing/routes/test_mount.py | 3 +- tests/routing/routes/test_websocket.py | 9 +- tests/routing/test_router.py | 15 +- tests/schemas/test_routing.py | 15 +- tests/schemas/test_setup.py | 11 +- tests/schemas/test_validation.py | 6 +- tests/test_applications.py | 27 +-- tests/test_client.py | 43 +++- tests/test_concurrency.py | 18 +- tests/test_http.py | 24 ++- tests/test_lifespan.py | 6 +- tests/test_middleware.py | 6 +- tests/test_modules.py | 3 +- tests/test_pagination.py | 12 +- tests/validation/test_schemas.py | 8 +- 78 files changed, 478 insertions(+), 759 deletions(-) create mode 100755 scripts/format delete mode 100755 scripts/ruff rename scripts/{pyright => types} (100%) diff --git a/.github/workflows/test_and_publish.yaml b/.github/workflows/test_and_publish.yaml index b6d26cf5..60071928 100644 --- a/.github/workflows/test_and_publish.yaml +++ b/.github/workflows/test_and_publish.yaml @@ -5,11 +5,11 @@ on: branches: - master paths-ignore: - - 'examples/**' - - '.github/**' - - 'docs/**' - - 'scripts/**' - - 'Dockerfiles/**' + - "examples/**" + - ".github/**" + - "docs/**" + - "scripts/**" + - "Dockerfiles/**" env: DEFAULT_LINUX: "slim" @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: [ "3.9", "3.10", "3.11", "3.12", "3.13" ] + python: ["3.9", "3.10", "3.11", "3.12", "3.13"] container: image: python:${{ matrix.python }} steps: @@ -40,18 +40,15 @@ jobs: run: | pip install pip poetry --upgrade ./scripts/install - - id: black + - id: format name: Code format checking - run: ./scripts/black --check . - - id: isort - name: Imports order checking - run: ./scripts/isort --check . - - id: ruff - name: Code style (ruff) - run: ./scripts/ruff . - - id: pyright + run: ./scripts/format --check . + - id: lint + name: Code linting + run: ./scripts/lint --output-format=github . + - id: types name: Static types check - run: ./scripts/pyright + run: ./scripts/types - id: tests name: Tests run: ./scripts/test diff --git a/.github/workflows/test_pull_request_branch.yaml b/.github/workflows/test_pull_request_branch.yaml index dc417bb4..30992572 100644 --- a/.github/workflows/test_pull_request_branch.yaml +++ b/.github/workflows/test_pull_request_branch.yaml @@ -28,18 +28,15 @@ jobs: run: | pip install pip poetry --upgrade ./scripts/install - - id: black + - id: format name: Code format checking - run: ./scripts/black --check . - - id: isort - name: Imports order checking - run: ./scripts/isort --check . - - id: ruff - name: Code style (ruff) - run: ./scripts/ruff . - - id: pyright + run: ./scripts/format --check . + - id: lint + name: Code linting + run: ./scripts/lint --output-format=github . + - id: types name: Static types check - run: ./scripts/pyright + run: ./scripts/types - id: tests name: Tests run: ./scripts/test diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8a173101..c2b751b8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,56 +1,46 @@ fail_fast: true repos: -- repo: git@github.com:pre-commit/pre-commit-hooks + - repo: git@github.com:pre-commit/pre-commit-hooks rev: v4.2.0 hooks: - - id: check-added-large-files + - id: check-added-large-files args: - - --maxkb=2000 - - id: check-merge-conflict - - id: check-xml - - id: check-yaml - - id: debug-statements - - id: name-tests-test + - --maxkb=2000 + - id: check-merge-conflict + - id: check-xml + - id: check-yaml + - id: debug-statements + - id: name-tests-test args: - - --django + - --django exclude: "asserts.py|utils.py" - - id: pretty-format-json + - id: pretty-format-json args: - - --autofix - - --indent=2 + - --autofix + - --indent=2 exclude: "templates/.+\\.json" -- repo: git@github.com:alessandrojcm/commitlint-pre-commit-hook + - repo: git@github.com:alessandrojcm/commitlint-pre-commit-hook rev: v8.0.0 hooks: - id: commitlint stages: [commit-msg] -- repo: local + - repo: local hooks: - - id: black - name: Black - Code Style - entry: ./scripts/black - args: - - -q - - --safe - - --line-length=120 - language: system - types: [file, python] - exclude: "make" - - id: isort - name: Isort - Sort Imports - entry: ./scripts/isort + - id: format + name: Code formatting + entry: ./scripts/format language: system types: [file, python] exclude: "make" - - id: ruff - name: Ruff - Code Linter - entry: ./scripts/ruff --fix + - id: lint + name: Code linting + entry: ./scripts/lint --fix language: system types: [file, python] exclude: "make" - - id: pyright - name: Pyright - Static types check - entry: ./scripts/pyright + - id: types + name: Static types check + entry: ./scripts/types language: system types: [file, python] exclude: "(make|tests/|examples/)" diff --git a/Makefile b/Makefile index 28d2c1ab..977baa13 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,6 @@ install: ## Installs the package, JS requirements, and build templates needed build: ## Builds the package, and templates needed @./scripts/build -lint: ## Runs a linting pipeline: black, isort, ruff, and mypy - @./scripts/lint - -lint-fix: ## Runs a linting pipeline with auto fixing: black, isort, ruff, and mypy - @./scripts/lint --fix - test: ## Runs all tests of the repository @./scripts/test @@ -27,22 +21,22 @@ publish: ## Publishes the package in PiPy if user and passwords are correct version: ## Gets the current version of the package @./scripts/version -isort: ## Runs isort on Flama - @./scripts/isort . +format: ## Runs code formatting + @./scripts/format . -black: ## Runs black on Flama - @./scripts/black . +lint: ## Runs code linting + @./scripts/lint . -ruff: ## Runs ruff on Flama - @./scripts/ruff . +lint-fix: ## Runs code linting with autofixing + @./scripts/lint --fix . -pyright: ## Runs pyright on Flama - @./scripts/pyright +types: ## Runs static types checking + @./scripts/types docker_push: ## Push docker images to registry @./scripts/docker_push . -.PHONY: help check clean install build lint tests publish version isort black ruff pyright docker_push +.PHONY: help check clean install build tests publish version format lint lint-fix types docker_push .DEFAULT_GOAL := help help: diff --git a/examples/error.py b/examples/error.py index 51b7f479..c08b5e2a 100755 --- a/examples/error.py +++ b/examples/error.py @@ -29,8 +29,7 @@ def home(): error_app = flama.Router() -class FooException(Exception): - ... +class FooException(Exception): ... @error_app.route("/500") @@ -56,13 +55,11 @@ def error_500(): @bar_app.route("/foobar/") -def foobar(): - ... +def foobar(): ... @bar_app.route("/barfoo/") -def barfoo(): - ... +def barfoo(): ... foo_app = flama.Router() diff --git a/flama/applications.py b/flama/applications.py index b66ad26e..6926b6a8 100644 --- a/flama/applications.py +++ b/flama/applications.py @@ -15,7 +15,7 @@ try: from flama.resources.workers import FlamaWorker -except exceptions.DependencyNotInstalled: +except exceptions.DependencyNotInstalled: # pragma: no cover FlamaWorker = None if t.TYPE_CHECKING: diff --git a/flama/asgi.py b/flama/asgi.py index cd612154..7c94dacb 100644 --- a/flama/asgi.py +++ b/flama/asgi.py @@ -101,7 +101,7 @@ async def resolve(self, receive: types.Receive) -> types.Body: body = b"" while True: message = await receive() - if not message["type"] == "http.request": + if not message["type"] == "http.request": # pragma: no cover raise Exception(f"Unexpected ASGI message type '{message['type']}'.") body += message.get("body", b"") if not message.get("more_body", False): diff --git a/flama/authentication/exceptions.py b/flama/authentication/exceptions.py index 916d88d7..8eec19e7 100644 --- a/flama/authentication/exceptions.py +++ b/flama/authentication/exceptions.py @@ -8,28 +8,22 @@ ] -class AuthenticationException(Exception): - ... +class AuthenticationException(Exception): ... -class Unauthorized(AuthenticationException): - ... +class Unauthorized(AuthenticationException): ... -class Forbidden(AuthenticationException): - ... +class Forbidden(AuthenticationException): ... -class JWTException(AuthenticationException): - ... +class JWTException(AuthenticationException): ... -class JWTDecodeException(JWTException): - ... +class JWTDecodeException(JWTException): ... -class JWTValidateException(JWTException): - ... +class JWTValidateException(JWTException): ... class JWTClaimValidateException(JWTValidateException): diff --git a/flama/authentication/middleware.py b/flama/authentication/middleware.py index 92f9b489..7591c477 100644 --- a/flama/authentication/middleware.py +++ b/flama/authentication/middleware.py @@ -19,7 +19,7 @@ class AuthenticationMiddleware: def __init__(self, app: "types.App"): - self.app: "Flama" = t.cast("Flama", app) + self.app: Flama = t.cast("Flama", app) async def __call__(self, scope: "types.Scope", receive: "types.Receive", send: "types.Send") -> None: if scope["type"] not in ("http", "websocket"): @@ -34,7 +34,7 @@ def _get_permissions(self, route: "BaseRoute") -> set[str]: return set(route.tags.get("permissions", [])) async def _get_response(self, scope: "types.Scope", receive: "types.Receive") -> t.Union["Response", "Flama"]: - app: "Flama" = scope["app"] + app: Flama = scope["app"] route, _ = app.router.resolve_route(scope) diff --git a/flama/cli/config/app.py b/flama/cli/config/app.py index 895a58a2..c11af381 100644 --- a/flama/cli/config/app.py +++ b/flama/cli/config/app.py @@ -78,8 +78,7 @@ class App(metaclass=abc.ABCMeta): @property # type: ignore @abc.abstractmethod @contextlib.contextmanager - def context(self) -> t.Generator[_AppContext, None, None]: - ... + def context(self) -> t.Generator[_AppContext, None, None]: ... @classmethod def build(cls, app: t.Union[str, dict[str, t.Any], "Flama"]) -> "App": diff --git a/flama/cli/config/config.py b/flama/cli/config/config.py index b6f2b2b2..97c00837 100644 --- a/flama/cli/config/config.py +++ b/flama/cli/config/config.py @@ -63,8 +63,7 @@ def build(cls, mode: str) -> "ExampleConfig": @classmethod @abc.abstractmethod - def dumps(cls) -> str: - ... + def dumps(cls) -> str: ... class SimpleExample(ExampleConfig): diff --git a/flama/cli/config/uvicorn.py b/flama/cli/config/uvicorn.py index 0216181c..41743bc1 100644 --- a/flama/cli/config/uvicorn.py +++ b/flama/cli/config/uvicorn.py @@ -47,7 +47,7 @@ click.option( "--server-reload-dirs", multiple=True, - help="Set reload directories explicitly, instead of using the current working" " directory.", + help="Set reload directories explicitly, instead of using the current working directory.", type=click.Path(exists=True), ), click.option( @@ -70,7 +70,7 @@ type=float, default=0.25, show_default=True, - help="Delay between previous and next check if application needs to be." " Defaults to 0.25s.", + help="Delay between previous and next check if application needs to be. Defaults to 0.25s.", ), click.option( "--server-workers", @@ -179,7 +179,7 @@ "--server-proxy-headers/--server-no-proxy-headers", is_flag=True, default=True, - help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to " "populate remote address info.", + help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info.", ), click.option( "--server-server-header/--server-no-server-header", @@ -210,7 +210,7 @@ "--server-limit-concurrency", type=int, default=None, - help="Maximum number of concurrent connections or tasks to allow, before issuing" " HTTP 503 responses.", + help="Maximum number of concurrent connections or tasks to allow, before issuing HTTP 503 responses.", ), click.option( "--server-backlog", diff --git a/flama/codecs/base.py b/flama/codecs/base.py index 96d7c9e0..41ef8bca 100644 --- a/flama/codecs/base.py +++ b/flama/codecs/base.py @@ -7,21 +7,18 @@ class Codec(metaclass=abc.ABCMeta): @abc.abstractmethod - async def decode(self, item: t.Any, **options) -> t.Any: - ... + async def decode(self, item: t.Any, **options) -> t.Any: ... class HTTPCodec(Codec): media_type: t.Optional[str] = None @abc.abstractmethod - async def decode(self, item: "http.Request", **options) -> t.Any: - ... + async def decode(self, item: "http.Request", **options) -> t.Any: ... class WebsocketsCodec(Codec): encoding: t.Optional[str] = None @abc.abstractmethod - async def decode(self, item: "types.Message", **options) -> t.Any: - ... + async def decode(self, item: "types.Message", **options) -> t.Any: ... diff --git a/flama/config/config.py b/flama/config/config.py index 11042ea4..24746db7 100644 --- a/flama/config/config.py +++ b/flama/config/config.py @@ -112,28 +112,22 @@ def _build_dataclass(self, data: t.Any, dataclass: type[R]) -> R: raise exceptions.ConfigError("Cannot create config dataclass") from e @t.overload - def __call__(self, key: str) -> t.Any: - ... + def __call__(self, key: str) -> t.Any: ... @t.overload - def __call__(self, key: str, *, default: t.Union[R, types.UnknownType]) -> R: - ... + def __call__(self, key: str, *, default: t.Union[R, types.UnknownType]) -> R: ... @t.overload - def __call__(self, key: str, *, cast: type[R]) -> R: - ... + def __call__(self, key: str, *, cast: type[R]) -> R: ... @t.overload - def __call__(self, key: str, *, default: t.Union[R, types.UnknownType], cast: type[R]) -> R: - ... + def __call__(self, key: str, *, default: t.Union[R, types.UnknownType], cast: type[R]) -> R: ... @t.overload - def __call__(self, key: str, *, cast: t.Callable[[t.Any], R]) -> R: - ... + def __call__(self, key: str, *, cast: t.Callable[[t.Any], R]) -> R: ... @t.overload - def __call__(self, key: str, *, default: t.Union[R, types.UnknownType], cast: t.Callable[[t.Any], R]) -> R: - ... + def __call__(self, key: str, *, default: t.Union[R, types.UnknownType], cast: t.Callable[[t.Any], R]) -> R: ... def __call__( self, diff --git a/flama/config/loaders.py b/flama/config/loaders.py index f3b89430..f8d3915f 100644 --- a/flama/config/loaders.py +++ b/flama/config/loaders.py @@ -80,7 +80,7 @@ def load(self, f: t.Union[str, os.PathLike]) -> dict[str, t.Any]: :return: Dict with the file contents. """ if compat.tomllib is None: # PORT: Replace compat when stop supporting 3.10 - raise exceptions.DependencyNotInstalled( + raise exceptions.DependencyNotInstalled( # pragma: no cover dependency=exceptions.DependencyNotInstalled.Dependency.tomli, dependant=f"{self.__class__.__module__}.{self.__class__.__name__}", msg="for Python versions lower than 3.11", diff --git a/flama/ddd/exceptions.py b/flama/ddd/exceptions.py index 7c4df90c..a8cc470f 100644 --- a/flama/ddd/exceptions.py +++ b/flama/ddd/exceptions.py @@ -10,12 +10,10 @@ ] -class Empty(Exception): - ... +class Empty(Exception): ... -class RepositoryException(Exception): - ... +class RepositoryException(Exception): ... class ResourceException(RepositoryException): diff --git a/flama/ddd/repositories/base.py b/flama/ddd/repositories/base.py index 21e09fc5..e21a9725 100644 --- a/flama/ddd/repositories/base.py +++ b/flama/ddd/repositories/base.py @@ -6,8 +6,7 @@ class AbstractRepository(abc.ABC): """Abstract class for repositories.""" - def __init__(self, *args, **kwargs): - ... + def __init__(self, *args, **kwargs): ... class BaseRepository(AbstractRepository): diff --git a/flama/ddd/workers/http.py b/flama/ddd/workers/http.py index 94b21ba2..ad26a323 100644 --- a/flama/ddd/workers/http.py +++ b/flama/ddd/workers/http.py @@ -74,8 +74,6 @@ async def repository_params(self) -> tuple[list[t.Any], dict[str, t.Any]]: """ return [self.client], {} - async def commit(self) -> None: - ... + async def commit(self) -> None: ... - async def rollback(self) -> None: - ... + async def rollback(self) -> None: ... diff --git a/flama/debug/data_structures.py b/flama/debug/data_structures.py index ea5256c5..9dac7a0c 100644 --- a/flama/debug/data_structures.py +++ b/flama/debug/data_structures.py @@ -150,7 +150,7 @@ class App: @classmethod def from_app(cls, app: t.Any, path: str = "/", name: t.Optional[str] = None) -> "App": - urls: list[t.Union[Endpoint, "App"]] = [] + urls: list[t.Union[Endpoint, App]] = [] for route in app.routes: try: urls.append(App.from_app(route.app, path=route.path.path, name=route.name)) diff --git a/flama/debug/middleware.py b/flama/debug/middleware.py index 7a80d539..b37e03d0 100644 --- a/flama/debug/middleware.py +++ b/flama/debug/middleware.py @@ -46,8 +46,7 @@ async def sender(message: types.Message) -> None: @abc.abstractmethod async def process_exception( self, scope: types.Scope, receive: types.Receive, send: types.Send, exc: Exception, response_started: bool - ) -> None: - ... + ) -> None: ... class ServerErrorMiddleware(BaseErrorMiddleware): @@ -92,8 +91,7 @@ def error_handler( ) -> http.Response: return http.PlainTextResponse("Internal Server Error", status_code=500) - def noop_handler(self, scope: types.Scope, receive: types.Receive, send: types.Send, exc: Exception) -> None: - ... + def noop_handler(self, scope: types.Scope, receive: types.Receive, send: types.Send, exc: Exception) -> None: ... class ExceptionMiddleware(BaseErrorMiddleware): diff --git a/flama/exceptions.py b/flama/exceptions.py index 25dd53c9..f4a33d22 100644 --- a/flama/exceptions.py +++ b/flama/exceptions.py @@ -22,8 +22,7 @@ ] -class ApplicationError(Exception): - ... +class ApplicationError(Exception): ... class DependencyNotInstalled(ApplicationError): @@ -66,8 +65,7 @@ def __repr__(self) -> str: return f"{self.__class__.__name__}({formatted_params})" -class SQLAlchemyError(ApplicationError): - ... +class SQLAlchemyError(ApplicationError): ... class DecodeError(Exception): @@ -82,8 +80,7 @@ def __init__(self, message, marker=None, base_format=None) -> None: self.base_format = base_format -class NoCodecAvailable(Exception): - ... +class NoCodecAvailable(Exception): ... class WebSocketException(starlette.exceptions.WebSocketException): diff --git a/flama/injection/exceptions.py b/flama/injection/exceptions.py index 0de5ecfe..24e9566a 100644 --- a/flama/injection/exceptions.py +++ b/flama/injection/exceptions.py @@ -7,8 +7,7 @@ __all__ = ["ComponentError", "ComponentNotFound"] -class ComponentError(Exception): - ... +class ComponentError(Exception): ... class ComponentNotFound(ComponentError): diff --git a/flama/injection/injector.py b/flama/injection/injector.py index 88e385fa..8c0d0cdd 100644 --- a/flama/injection/injector.py +++ b/flama/injection/injector.py @@ -69,20 +69,16 @@ def resolver(self): self._resolver = None @t.overload - def resolve(self, annotation: t.Any) -> "ResolutionTree": - ... + def resolve(self, annotation: t.Any) -> "ResolutionTree": ... @t.overload - def resolve(self, annotation: t.Any, *, name: str) -> "ResolutionTree": - ... + def resolve(self, annotation: t.Any, *, name: str) -> "ResolutionTree": ... @t.overload - def resolve(self, annotation: t.Any, *, default: t.Any) -> "ResolutionTree": - ... + def resolve(self, annotation: t.Any, *, default: t.Any) -> "ResolutionTree": ... @t.overload - def resolve(self, annotation: t.Any, *, name: str, default: t.Any) -> "ResolutionTree": - ... + def resolve(self, annotation: t.Any, *, name: str, default: t.Any) -> "ResolutionTree": ... def resolve( self, annotation: t.Optional[t.Any] = None, *, name: t.Optional[str] = None, default: t.Any = EMPTY diff --git a/flama/injection/resolver.py b/flama/injection/resolver.py index 56de6594..775fa698 100644 --- a/flama/injection/resolver.py +++ b/flama/injection/resolver.py @@ -56,8 +56,7 @@ class ResolutionNode(abc.ABC): nodes: list["ResolutionNode"] @abc.abstractmethod - async def value(self, context: dict[str, t.Any]) -> t.Any: - ... + async def value(self, context: dict[str, t.Any]) -> t.Any: ... def components(self) -> list[tuple[str, "Component"]]: return [] diff --git a/flama/lifespan.py b/flama/lifespan.py index 8a43e33a..61ba0961 100644 --- a/flama/lifespan.py +++ b/flama/lifespan.py @@ -95,8 +95,7 @@ async def _child_propagation(self, app: "Flama", scope: types.Scope, message: ty async def child_receive() -> types.Message: return message - async def child_send(message: types.Message) -> None: - ... + async def child_send(message: types.Message) -> None: ... if app.routes: await concurrency.run_task_group(*(route(scope, child_receive, child_send) for route in app.routes)) diff --git a/flama/middleware.py b/flama/middleware.py index 7c327160..101c4b68 100644 --- a/flama/middleware.py +++ b/flama/middleware.py @@ -114,10 +114,8 @@ def __init__(self, app: "Flama", middleware: t.Sequence[Middleware], debug: bool self.app = app self.middleware = list(reversed(middleware)) self.debug = debug - self._exception_handlers: dict[ - t.Union[int, type[Exception]], t.Callable[["Request", Exception], "Response"] - ] = {} - self._stack: t.Optional[t.Union["types.MiddlewareClass", "types.App"]] = None + self._exception_handlers: dict[t.Union[int, type[Exception]], t.Callable[[Request, Exception], Response]] = {} + self._stack: t.Optional[t.Union[types.MiddlewareClass, types.App]] = None @property def stack( diff --git a/flama/models/base.py b/flama/models/base.py index ad8ba952..de98b05e 100644 --- a/flama/models/base.py +++ b/flama/models/base.py @@ -17,5 +17,4 @@ def inspect(self) -> t.Any: return {"meta": self.meta.to_dict(), "artifacts": self.artifacts} @abc.abstractmethod - def predict(self, x: t.Any) -> t.Any: - ... + def predict(self, x: t.Any) -> t.Any: ... diff --git a/flama/models/resource.py b/flama/models/resource.py index 8488975a..b0830ba2 100644 --- a/flama/models/resource.py +++ b/flama/models/resource.py @@ -104,7 +104,7 @@ def _is_abstract(namespace: dict[str, t.Any]) -> bool: @classmethod def _get_model_component(cls, bases: t.Sequence[t.Any], namespace: dict[str, t.Any]) -> "ModelComponent": try: - component: "ModelComponent" = cls._get_attribute("component", bases, namespace, metadata_namespace="model") + component: ModelComponent = cls._get_attribute("component", bases, namespace, metadata_namespace="model") return component except AttributeError: ... diff --git a/flama/modules.py b/flama/modules.py index 3e514640..cbc98b4f 100644 --- a/flama/modules.py +++ b/flama/modules.py @@ -12,13 +12,11 @@ class _BaseModule: name: str def __init__(self) -> None: - self.app: "Flama" + self.app: Flama - async def on_startup(self) -> None: - ... + async def on_startup(self) -> None: ... - async def on_shutdown(self) -> None: - ... + async def on_shutdown(self) -> None: ... class _ModuleMeta(abc.ABCMeta): @@ -28,8 +26,7 @@ def __new__(mcs, name, bases, namespace): return super().__new__(mcs, name, bases, namespace) -class Module(_BaseModule, metaclass=_ModuleMeta): - ... +class Module(_BaseModule, metaclass=_ModuleMeta): ... class Modules(dict[str, Module]): diff --git a/flama/pagination/__init__.py b/flama/pagination/__init__.py index f7c3b712..bc48afb2 100644 --- a/flama/pagination/__init__.py +++ b/flama/pagination/__init__.py @@ -1 +1 @@ -from flama.pagination.paginator import paginator # noqa +from flama.pagination.paginator import * # noqa diff --git a/flama/pagination/decorators.py b/flama/pagination/decorators.py index 75061be7..8e46e63a 100644 --- a/flama/pagination/decorators.py +++ b/flama/pagination/decorators.py @@ -29,10 +29,8 @@ def decorate(cls, func: t.Callable, schema: t.Any) -> t.Callable: @classmethod @abc.abstractmethod - def _decorate_async(cls, func: t.Callable, schema: t.Any) -> t.Callable: - ... + def _decorate_async(cls, func: t.Callable, schema: t.Any) -> t.Callable: ... @classmethod @abc.abstractmethod - def _decorate_sync(cls, func: t.Callable, schema: t.Any) -> t.Callable: - ... + def _decorate_sync(cls, func: t.Callable, schema: t.Any) -> t.Callable: ... diff --git a/flama/pagination/paginator.py b/flama/pagination/paginator.py index ce0f6b4e..b47a3341 100644 --- a/flama/pagination/paginator.py +++ b/flama/pagination/paginator.py @@ -1,19 +1,24 @@ import typing as t -from flama.pagination import mixins, types +from flama import compat +from flama.pagination.mixins import LimitOffsetMixin, PageNumberMixin +from flama.pagination.types import PaginationType __all__ = ["paginator"] +P = compat.ParamSpec("P") # PORT: Replace compat when stop supporting 3.9 +R = t.TypeVar("R", covariant=True) -class Paginator(mixins.LimitOffsetMixin, mixins.PageNumberMixin): + +class Paginator(LimitOffsetMixin, PageNumberMixin): def __init__(self): self.schemas = {} - def paginate(self, pagination: t.Union[str, types.PaginationType], func: t.Callable) -> t.Callable: + def paginate(self, pagination: t.Union[str, PaginationType], func: t.Callable[P, R]) -> t.Callable[P, R]: return { - types.PaginationType.limit_offset: self._paginate_limit_offset, - types.PaginationType.page_number: self._paginate_page_number, - }[types.PaginationType[pagination]](func) + PaginationType.limit_offset: self._paginate_limit_offset, + PaginationType.page_number: self._paginate_page_number, + }[PaginationType[pagination]](func) paginator = Paginator() diff --git a/flama/resources/crud.py b/flama/resources/crud.py index 226da285..fb49b6a1 100644 --- a/flama/resources/crud.py +++ b/flama/resources/crud.py @@ -417,5 +417,4 @@ def _is_abstract(namespace: dict[str, t.Any]) -> bool: return namespace.get("__module__") == "flama.resources.crud" and namespace.get("__qualname__") == "CRUDResource" -class CRUDResource(RESTResource, metaclass=CRUDResourceType): - ... +class CRUDResource(RESTResource, metaclass=CRUDResourceType): ... diff --git a/flama/routing/routes/base.py b/flama/routing/routes/base.py index b7df8f12..dfe3de38 100644 --- a/flama/routing/routes/base.py +++ b/flama/routing/routes/base.py @@ -79,8 +79,7 @@ def __init__( super().__init__() @abc.abstractmethod - async def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send) -> None: - ... + async def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send) -> None: ... def __eq__(self, other: t.Any) -> bool: return ( diff --git a/flama/routing/routes/http.py b/flama/routing/routes/http.py index 20774f44..799e349d 100644 --- a/flama/routing/routes/http.py +++ b/flama/routing/routes/http.py @@ -138,7 +138,7 @@ def __repr__(self) -> str: @staticmethod def is_endpoint( - x: t.Union[t.Callable, type[endpoints.HTTPEndpoint]] + x: t.Union[t.Callable, type[endpoints.HTTPEndpoint]], ) -> compat.TypeGuard[type[endpoints.HTTPEndpoint]]: # PORT: Replace compat when stop supporting 3.9 return inspect.isclass(x) and issubclass(x, endpoints.HTTPEndpoint) diff --git a/flama/schemas/_libs/marshmallow/adapter.py b/flama/schemas/_libs/marshmallow/adapter.py index c22275df..e1105768 100644 --- a/flama/schemas/_libs/marshmallow/adapter.py +++ b/flama/schemas/_libs/marshmallow/adapter.py @@ -101,7 +101,7 @@ def to_json_schema(self, schema: t.Union[type[Schema], type[Field], Schema, Fiel try: plugin = MarshmallowPlugin(schema_name_resolver=lambda x: t.cast(type, resolve_schema_cls(x)).__name__) APISpec("", "", "3.1.0", [plugin]) - converter: "OpenAPIConverter" = t.cast("OpenAPIConverter", plugin.converter) + converter: OpenAPIConverter = t.cast("OpenAPIConverter", plugin.converter) if (inspect.isclass(schema) and issubclass(schema, Field)) or isinstance(schema, Field): json_schema = converter.field2property(t.cast(marshmallow.fields.Field, schema)) diff --git a/flama/schemas/adapter.py b/flama/schemas/adapter.py index 25e16a7d..d7b62e27 100644 --- a/flama/schemas/adapter.py +++ b/flama/schemas/adapter.py @@ -21,30 +21,25 @@ def build_field( default: t.Any = None, multiple: bool = False, **kwargs: t.Any, - ) -> _T_Field: - ... + ) -> _T_Field: ... @t.overload @abc.abstractmethod - def build_schema(self, *, name: t.Optional[str] = None, fields: dict[str, t.Any]) -> t.Any: - ... + def build_schema(self, *, name: t.Optional[str] = None, fields: dict[str, t.Any]) -> t.Any: ... @t.overload @abc.abstractmethod - def build_schema(self, *, name: t.Optional[str] = None, schema: t.Any) -> t.Any: - ... + def build_schema(self, *, name: t.Optional[str] = None, schema: t.Any) -> t.Any: ... @t.overload @abc.abstractmethod - def build_schema(self, *, name: t.Optional[str] = None, schema: t.Any, partial: bool) -> t.Any: - ... + def build_schema(self, *, name: t.Optional[str] = None, schema: t.Any, partial: bool) -> t.Any: ... @t.overload @abc.abstractmethod def build_schema( self, *, name: t.Optional[str] = None, schema: t.Any, fields: t.Optional[dict[str, t.Any]] - ) -> t.Any: - ... + ) -> t.Any: ... @abc.abstractmethod def build_schema( @@ -54,46 +49,36 @@ def build_schema( schema: t.Optional[t.Any] = None, fields: t.Optional[dict[str, t.Any]] = None, partial: bool = False, - ) -> t.Any: - ... + ) -> t.Any: ... @abc.abstractmethod - def validate(self, schema: t.Any, values: dict[str, t.Any], *, partial: bool = False) -> dict[str, t.Any]: - ... + def validate(self, schema: t.Any, values: dict[str, t.Any], *, partial: bool = False) -> dict[str, t.Any]: ... @abc.abstractmethod - def load(self, schema: t.Any, value: dict[str, t.Any]) -> _T_Schema: - ... + def load(self, schema: t.Any, value: dict[str, t.Any]) -> _T_Schema: ... @abc.abstractmethod - def dump(self, schema: t.Any, value: dict[str, t.Any]) -> dict[str, t.Any]: - ... + def dump(self, schema: t.Any, value: dict[str, t.Any]) -> dict[str, t.Any]: ... @t.overload @abc.abstractmethod - def name(self, schema: t.Any) -> str: - ... + def name(self, schema: t.Any) -> str: ... @t.overload @abc.abstractmethod - def name(self, schema: t.Any, *, prefix: str) -> str: - ... + def name(self, schema: t.Any, *, prefix: str) -> str: ... @abc.abstractmethod - def name(self, schema: t.Any, *, prefix: t.Optional[str] = None) -> str: - ... + def name(self, schema: t.Any, *, prefix: t.Optional[str] = None) -> str: ... @abc.abstractmethod - def to_json_schema(self, schema: t.Any) -> JSONSchema: - ... + def to_json_schema(self, schema: t.Any) -> JSONSchema: ... @abc.abstractmethod - def unique_schema(self, schema: t.Any) -> t.Any: - ... + def unique_schema(self, schema: t.Any) -> t.Any: ... @abc.abstractmethod - def schema_fields(self, schema: t.Any) -> dict[str, t.Any]: - ... + def schema_fields(self, schema: t.Any) -> dict[str, t.Any]: ... @abc.abstractmethod def is_schema(self, obj: t.Any) -> compat.TypeGuard[t.Any]: # PORT: Replace compat when stop supporting 3.9 diff --git a/flama/schemas/data_structures.py b/flama/schemas/data_structures.py index 78a8226f..291f31fe 100644 --- a/flama/schemas/data_structures.py +++ b/flama/schemas/data_structures.py @@ -189,16 +189,13 @@ def nested_schemas(self, schema: t.Any = UNKNOWN) -> list[t.Any]: return [] @t.overload - def validate(self, values: None, *, partial: bool = False) -> dict[str, t.Any]: - ... + def validate(self, values: None, *, partial: bool = False) -> dict[str, t.Any]: ... @t.overload - def validate(self, values: dict[str, t.Any], *, partial: bool = False) -> dict[str, t.Any]: - ... + def validate(self, values: dict[str, t.Any], *, partial: bool = False) -> dict[str, t.Any]: ... @t.overload - def validate(self, values: list[dict[str, t.Any]], *, partial: bool = False) -> list[dict[str, t.Any]]: - ... + def validate(self, values: list[dict[str, t.Any]], *, partial: bool = False) -> list[dict[str, t.Any]]: ... def validate(self, values: t.Union[dict[str, t.Any], list[dict[str, t.Any]], None], *, partial=False): if isinstance(values, (list, tuple)): @@ -207,12 +204,10 @@ def validate(self, values: t.Union[dict[str, t.Any], list[dict[str, t.Any]], Non return schemas.adapter.validate(self.schema, values or {}, partial=partial) @t.overload - def load(self, values: dict[str, t.Any]) -> t.Any: - ... + def load(self, values: dict[str, t.Any]) -> t.Any: ... @t.overload - def load(self, values: list[dict[str, t.Any]]) -> list[t.Any]: - ... + def load(self, values: list[dict[str, t.Any]]) -> list[t.Any]: ... def load(self, values): if isinstance(values, (list, tuple)): @@ -221,12 +216,10 @@ def load(self, values): return schemas.adapter.load(self.schema, values) @t.overload - def dump(self, values: dict[str, t.Any]) -> dict[str, t.Any]: - ... + def dump(self, values: dict[str, t.Any]) -> dict[str, t.Any]: ... @t.overload - def dump(self, values: list[dict[str, t.Any]]) -> list[dict[str, t.Any]]: - ... + def dump(self, values: list[dict[str, t.Any]]) -> list[dict[str, t.Any]]: ... def dump(self, values): if isinstance(values, (list, tuple)): diff --git a/flama/serialize/base.py b/flama/serialize/base.py index 96119922..667ccc1d 100644 --- a/flama/serialize/base.py +++ b/flama/serialize/base.py @@ -13,17 +13,13 @@ class Serializer(metaclass=abc.ABCMeta): lib: t.ClassVar[Framework] @abc.abstractmethod - def dump(self, obj: t.Any, **kwargs) -> bytes: - ... + def dump(self, obj: t.Any, **kwargs) -> bytes: ... @abc.abstractmethod - def load(self, model: bytes, **kwargs) -> t.Any: - ... + def load(self, model: bytes, **kwargs) -> t.Any: ... @abc.abstractmethod - def info(self, model: t.Any) -> t.Optional["JSONSchema"]: - ... + def info(self, model: t.Any) -> t.Optional["JSONSchema"]: ... @abc.abstractmethod - def version(self) -> str: - ... + def version(self) -> str: ... diff --git a/flama/serialize/serializers/tensorflow.py b/flama/serialize/serializers/tensorflow.py index 5918dee7..3c8fb768 100644 --- a/flama/serialize/serializers/tensorflow.py +++ b/flama/serialize/serializers/tensorflow.py @@ -37,7 +37,7 @@ def load(self, model: bytes, **kwargs) -> t.Any: return tf.keras.models.load_model(tmp_file.name) # type: ignore def info(self, model: t.Any) -> t.Optional["JSONSchema"]: - model_info: "JSONSchema" = json.loads(model.to_json()) + model_info: JSONSchema = json.loads(model.to_json()) return model_info def version(self) -> str: diff --git a/flama/types/asgi.py b/flama/types/asgi.py index a9a81b74..1f7a842e 100644 --- a/flama/types/asgi.py +++ b/flama/types/asgi.py @@ -29,20 +29,17 @@ class Receive(t.Protocol): - async def __call__(self) -> Message: - ... + async def __call__(self) -> Message: ... class Send(t.Protocol): - async def __call__(self, message: Message) -> None: - ... + async def __call__(self, message: Message) -> None: ... # Applications @t.runtime_checkable class AppClass(t.Protocol): - def __call__(self, scope: Scope, receive: Receive, send: Send) -> t.Union[None, t.Awaitable[None]]: - ... + def __call__(self, scope: Scope, receive: Receive, send: Send) -> t.Union[None, t.Awaitable[None]]: ... AppFunction = t.Callable[[Scope, Receive, Send], t.Union[None, t.Awaitable[None]]] @@ -52,8 +49,7 @@ def __call__(self, scope: Scope, receive: Receive, send: Send) -> t.Union[None, # Middleware @t.runtime_checkable class MiddlewareClass(AppClass, t.Protocol[P, R]): - def __init__(self, app: App, *args: P.args, **kwargs: P.kwargs): - ... + def __init__(self, app: App, *args: P.args, **kwargs: P.kwargs): ... MiddlewareFunction = t.Callable[compat.Concatenate[App, P], App] # PORT: Replace compat when stop supporting 3.9 diff --git a/flama/types/endpoints.py b/flama/types/endpoints.py index bf06a5e3..239524d6 100644 --- a/flama/types/endpoints.py +++ b/flama/types/endpoints.py @@ -7,38 +7,29 @@ class EndpointProtocol(t.Protocol): - def __init__(self, scope: "types.Scope", receive: "types.Receive", send: "types.Send") -> None: - ... + def __init__(self, scope: "types.Scope", receive: "types.Receive", send: "types.Send") -> None: ... - def __await__(self) -> t.Generator: - ... + def __await__(self) -> t.Generator: ... @classmethod - def allowed_handlers(cls) -> dict[str, t.Callable]: - ... + def allowed_handlers(cls) -> dict[str, t.Callable]: ... - async def dispatch(self) -> None: - ... + async def dispatch(self) -> None: ... class HTTPEndpointProtocol(EndpointProtocol, t.Protocol): @classmethod - def allowed_methods(cls) -> set[str]: - ... + def allowed_methods(cls) -> set[str]: ... @property - def handler(self) -> t.Callable: - ... + def handler(self) -> t.Callable: ... class WebSocketEndpointProtocol(EndpointProtocol, t.Protocol): encoding: t.Union["types.Encoding", None] = None - async def on_connect(self, websocket: "websockets.WebSocket") -> None: - ... + async def on_connect(self, websocket: "websockets.WebSocket") -> None: ... - async def on_receive(self, websocket: "websockets.WebSocket", data: "types.Data") -> None: - ... + async def on_receive(self, websocket: "websockets.WebSocket", data: "types.Data") -> None: ... - async def on_disconnect(self, websocket: "websockets.WebSocket", websocket_code: "types.Code") -> None: - ... + async def on_disconnect(self, websocket: "websockets.WebSocket", websocket_code: "types.Code") -> None: ... diff --git a/flama/url.py b/flama/url.py index 131469d2..38034a49 100644 --- a/flama/url.py +++ b/flama/url.py @@ -18,12 +18,10 @@ class Serializer(t.Generic[T], metaclass=abc.ABCMeta): type: t.ClassVar[type] @abc.abstractmethod - def load(self, value: str) -> T: - ... + def load(self, value: str) -> T: ... @abc.abstractmethod - def dump(self, value: T) -> str: - ... + def dump(self, value: T) -> str: ... def __eq__(self, other): return type(other) == type(self) @@ -114,13 +112,11 @@ def build(cls, fragment: str) -> "_Fragment": @property @abc.abstractmethod - def regex(self) -> re.Pattern: - ... + def regex(self) -> re.Pattern: ... @property @abc.abstractmethod - def template(self) -> str: - ... + def template(self) -> str: ... @dataclasses.dataclass diff --git a/flama/validation.py b/flama/validation.py index db267a83..aee02fee 100644 --- a/flama/validation.py +++ b/flama/validation.py @@ -74,9 +74,9 @@ class ValidateRequestDataComponent(Component): def resolve(self, request: http.Request, route: routing.BaseRoute, data: types.RequestData) -> ValidatedRequestData: body_param = route.parameters.body[request.method] - assert ( - body_param is not None - ), f"Body schema parameter not defined for route '{route}' and method '{request.method}'" + assert body_param is not None, ( + f"Body schema parameter not defined for route '{route}' and method '{request.method}'" + ) try: return ValidatedRequestData(body_param.schema.validate(dict(data))) @@ -108,9 +108,9 @@ def can_handle_parameter(self, parameter: Parameter): def resolve(self, parameter: Parameter, request: http.Request, route: routing.BaseRoute, data: types.RequestData): body_param = route.parameters.body[request.method] - assert ( - body_param is not None - ), f"Body schema parameter not defined for route '{route}' and method '{request.method}'" + assert body_param is not None, ( + f"Body schema parameter not defined for route '{route}' and method '{request.method}'" + ) try: return body_param.schema.validate(data, partial=schemas.is_schema_partial(parameter.annotation)) diff --git a/poetry.lock b/poetry.lock index 8e4b0ec0..a12f7737 100644 --- a/poetry.lock +++ b/poetry.lock @@ -127,54 +127,6 @@ files = [ six = ">=1.6.1,<2.0" wheel = ">=0.23.0,<1.0" -[[package]] -name = "black" -version = "23.12.1" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, - {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, - {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, - {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, - {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, - {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, - {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, - {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, - {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, - {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, - {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, - {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, - {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, - {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, - {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, - {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, - {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, - {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, - {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, - {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, - {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, - {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "certifi" version = "2024.12.14" @@ -391,7 +343,7 @@ version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] +groups = ["main"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, @@ -408,11 +360,11 @@ description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["main", "dev"] -markers = "(python_version <= \"3.11\" or python_version >= \"3.12\") and (platform_system == \"Windows\" or sys_platform == \"win32\")" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "(python_version <= \"3.11\" or python_version >= \"3.12\") and (platform_system == \"Windows\" or sys_platform == \"win32\")", dev = "(python_version <= \"3.11\" or python_version >= \"3.12\") and sys_platform == \"win32\""} [[package]] name = "coverage" @@ -1178,22 +1130,6 @@ qtconsole = ["qtconsole"] test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["dev"] -markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - [[package]] name = "jedi" version = "0.19.2" @@ -1517,19 +1453,6 @@ docs = ["sphinx"] gmpy = ["gmpy2 (>=2.1.0a4)"] tests = ["pytest (>=4.6)"] -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -groups = ["dev"] -markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - [[package]] name = "namex" version = "0.0.8" @@ -1956,19 +1879,6 @@ files = [ qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["docopt", "pytest"] -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - [[package]] name = "pexpect" version = "4.9.0" @@ -2306,15 +2216,15 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyright" -version = "1.1.391" +version = "1.1.393" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" groups = ["dev"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "pyright-1.1.391-py3-none-any.whl", hash = "sha256:54fa186f8b3e8a55a44ebfa842636635688670c6896dcf6cf4a7fc75062f4d15"}, - {file = "pyright-1.1.391.tar.gz", hash = "sha256:66b2d42cdf5c3cbab05f2f4b76e8bec8aa78e679bfa0b6ad7b923d9e027cadb2"}, + {file = "pyright-1.1.393-py3-none-any.whl", hash = "sha256:8320629bb7a44ca90944ba599390162bf59307f3d9fb6e27da3b7011b8c17ae5"}, + {file = "pyright-1.1.393.tar.gz", hash = "sha256:aeeb7ff4e0364775ef416a80111613f91a05c8e01e58ecfefc370ca0db7aed9c"}, ] [package.dependencies] @@ -2571,30 +2481,31 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.0.292" -description = "An extremely fast Python linter, written in Rust." +version = "0.9.6" +description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "ruff-0.0.292-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:02f29db018c9d474270c704e6c6b13b18ed0ecac82761e4fcf0faa3728430c96"}, - {file = "ruff-0.0.292-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:69654e564342f507edfa09ee6897883ca76e331d4bbc3676d8a8403838e9fade"}, - {file = "ruff-0.0.292-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c3c91859a9b845c33778f11902e7b26440d64b9d5110edd4e4fa1726c41e0a4"}, - {file = "ruff-0.0.292-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4476f1243af2d8c29da5f235c13dca52177117935e1f9393f9d90f9833f69e4"}, - {file = "ruff-0.0.292-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be8eb50eaf8648070b8e58ece8e69c9322d34afe367eec4210fdee9a555e4ca7"}, - {file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9889bac18a0c07018aac75ef6c1e6511d8411724d67cb879103b01758e110a81"}, - {file = "ruff-0.0.292-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bdfabd4334684a4418b99b3118793f2c13bb67bf1540a769d7816410402a205"}, - {file = "ruff-0.0.292-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7c77c53bfcd75dbcd4d1f42d6cabf2485d2e1ee0678da850f08e1ab13081a8"}, - {file = "ruff-0.0.292-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e087b24d0d849c5c81516ec740bf4fd48bf363cfb104545464e0fca749b6af9"}, - {file = "ruff-0.0.292-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f160b5ec26be32362d0774964e218f3fcf0a7da299f7e220ef45ae9e3e67101a"}, - {file = "ruff-0.0.292-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ac153eee6dd4444501c4bb92bff866491d4bfb01ce26dd2fff7ca472c8df9ad0"}, - {file = "ruff-0.0.292-py3-none-musllinux_1_2_i686.whl", hash = "sha256:87616771e72820800b8faea82edd858324b29bb99a920d6aa3d3949dd3f88fb0"}, - {file = "ruff-0.0.292-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b76deb3bdbea2ef97db286cf953488745dd6424c122d275f05836c53f62d4016"}, - {file = "ruff-0.0.292-py3-none-win32.whl", hash = "sha256:e854b05408f7a8033a027e4b1c7f9889563dd2aca545d13d06711e5c39c3d003"}, - {file = "ruff-0.0.292-py3-none-win_amd64.whl", hash = "sha256:f27282bedfd04d4c3492e5c3398360c9d86a295be00eccc63914438b4ac8a83c"}, - {file = "ruff-0.0.292-py3-none-win_arm64.whl", hash = "sha256:7f67a69c8f12fbc8daf6ae6d36705037bde315abf8b82b6e1f4c9e74eb750f68"}, - {file = "ruff-0.0.292.tar.gz", hash = "sha256:1093449e37dd1e9b813798f6ad70932b57cf614e5c2b5c51005bf67d55db33ac"}, + {file = "ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"}, + {file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"}, + {file = "ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656"}, + {file = "ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d"}, + {file = "ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa"}, + {file = "ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a"}, + {file = "ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9"}, ] [[package]] @@ -3804,4 +3715,4 @@ typesystem = ["typesystem"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<3.14" -content-hash = "fd6c26f28556b679b9c3f34fa1ddd22c97e3378501f395fb3356daf9b0f87075" +content-hash = "f9bdd6617b7294e6607e55f95225c5e663f82b2f6821722f914d2e826a22aa3a" diff --git a/pyproject.toml b/pyproject.toml index 926625b9..1cbe4790 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,20 +11,32 @@ license = { text = "Apache-2.0" } readme = "README.md" authors = [ { name = "José Antonio Perdiguero López", email = "perdy@perdy.io" }, - { name = "Miguel A. Durán Olivencia", email = "migduroli@gmail.com" } + { name = "Miguel A. Durán Olivencia", email = "migduroli@gmail.com" }, ] maintainers = [ { name = "José Antonio Perdiguero López", email = "perdy@perdy.io" }, - { name = "Miguel A. Durán Olivencia", email = "migduroli@gmail.com" } + { name = "Miguel A. Durán Olivencia", email = "migduroli@gmail.com" }, +] +keywords = [ + "machine-learning", + "ml", + "ml-ops", + "mlops", + "api", + "rest", + "restful", + "openapi", + "tensorflow", + "pytorch", + "sklearn", ] -keywords = ["machine-learning", "ml", "ml-ops", "mlops", "api", "rest", "restful", "openapi", "tensorflow", "pytorch", "sklearn"] classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "Topic :: Internet :: WWW/HTTP :: HTTP Servers", - "Topic :: Software Development", - "Topic :: Software Development :: Libraries", - "Topic :: Software Development :: Libraries :: Application Frameworks" + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Topic :: Internet :: WWW/HTTP :: HTTP Servers", + "Topic :: Software Development", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Libraries :: Application Frameworks", ] dependencies = [ "starlette (>=0.31,<1.0.0)", @@ -41,29 +53,18 @@ homepage = "https://flama.dev" documentation = "https://flama.dev/docs/" [project.optional-dependencies] -pydantic = [ - "pydantic (>=2.0,<3.0)" -] -typesystem = [ - "typesystem (>=0.4.1,<1.0)" -] -marshmallow = [ - "marshmallow (>=3.0,<4.0)", - "apispec (>=6.0,<7.0)" -] -database = [ - "SQLAlchemy[asyncio] (>=2.0,<3.0)" -] -client = [ - "httpx (>=0.25,<1.0)" -] +pydantic = ["pydantic (>=2.0,<3.0)"] +typesystem = ["typesystem (>=0.4.1,<1.0)"] +marshmallow = ["marshmallow (>=3.0,<4.0)", "apispec (>=6.0,<7.0)"] +database = ["SQLAlchemy[asyncio] (>=2.0,<3.0)"] +client = ["httpx (>=0.25,<1.0)"] full = [ "pydantic (>=2.0,<3.0)", "typesystem (>=0.4.1,<1.0)", "marshmallow (>=3.0,<4.0)", "apispec (>=6.0,<7.0)", "SQLAlchemy[asyncio] (>=2.0,<3.0)", - "httpx (>=0.25,<1.0)" + "httpx (>=0.25,<1.0)", ] [project.scripts] @@ -71,8 +72,14 @@ flama = 'flama.cli.__main__:cli' [tool.poetry] include = [ - { path = "flama", format = ["sdist", "wheel"] }, - { path = "flama/templates/**/*", format = ["sdist", "wheel"] } + { path = "flama", format = [ + "sdist", + "wheel", + ] }, + { path = "flama/templates/**/*", format = [ + "sdist", + "wheel", + ] }, ] exclude = [] @@ -85,9 +92,8 @@ pytest-xdist = { version = "^3.3", extras = ["psutil"] } pytest-cov = "^6.0" pytest-asyncio = "^0.24" ipython = "^8.0" -isort = "^5.12" -ruff = "^0.0.292" -black = "^23.9" +ruff = "^0.9.6" +pyright = "^1.1.393" pre-commit = "^3.4" python-multipart = "^0.0.6" httpx = ">=0.25,<1.0.0" @@ -95,7 +101,6 @@ aiosqlite = ">=0.19.0,<1.0.0" Faker = "^8.2" SQLAlchemy = { version = "^2.0", extras = ["asyncio"] } gevent = "^23.9.1" -pyright = "^1.1.386" [tool.poetry.group.schemas] optional = true @@ -109,125 +114,95 @@ typesystem = "^0.4" [tool.poetry.group.ml] optional = true -[tool.poetry.group.ml.dependencies] # Only testable on linux and before 3.13, because numpy old versions are not providing binaries +[tool.poetry.group.ml.dependencies] # Only testable on linux and before 3.13, because numpy old versions are not providing binaries scikit-learn = { version = "~1.5.2", platform = "linux", python = ">=3.9,<3.13" } tensorflow-cpu = { version = "~2.17.0", platform = "linux", python = ">=3.9,<3.13" } torch = { version = "~2.5.0", platform = "linux", python = ">=3.9,<3.13" } -[tool.black] +[tool.ruff] line-length = 120 -include = '\.pyi?$' -exclude = ''' -/( - \.git - | \.venv - | build - | dist -)/ -''' - -[tool.isort] -profile = "black" -atomic = true -multi_line_output = 3 -include_trailing_comma = true -line_length = 120 -skip_glob = [ - "*/.venv/**", - "*/docs/**", - "*/build/**", - "*/dist/**", +exclude = [ + ".git", + ".pytest_cache", + ".mypy_cache", + ".ruff_cache", + ".venv", + "buck-out", + "build", + "dist", + "node_modules", ] -[tool.ruff] -line-length = 120 -# Enable Pyflakes and pycodestyle rules. +[tool.ruff.format] +docstring-code-format = true + +[tool.ruff.lint] select = ["C90", "E", "F", "G", "I", "W", "T", "UP"] ignore = ["E721"] -exclude = [ - ".git", - ".pytest_cache", - ".mypy_cache", - ".ruff_cache", - ".venv", - "buck-out", - "build", - "dist", - "node_modules", -] # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "__init__.py" = ["E402"] -[tool.ruff.mccabe] +[tool.ruff.lint.mccabe] # Unlike Flake8, default to a complexity level of 10. max-complexity = 10 [tool.pyright] include = ["flama"] -exclude = [ - "**/node_modules", - "**/__pycache__", -] +exclude = ["**/node_modules", "**/__pycache__"] reportWildcardImportFromLibrary = false reportPrivateImportUsage = false [tool.pytest.ini_options] minversion = 3 addopts = "--dist=loadfile --junitxml=./test-results/pytest/results.xml --no-cov-on-fail --cov-report=html --cov-report=xml --cov-report=term-missing --cov-config=pyproject.toml --cov=. --pdbcls=IPython.terminal.debugger:TerminalPdb -nauto" -norecursedirs = [ - "*settings*", - "*urls*", - "*docs*", -] +norecursedirs = ["*settings*", "*urls*", "*docs*"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "session" [tool.coverage.run] -source = [ - "flama" -] +source = ["flama"] branch = true omit = [ - ".venv*", - "*settings*", - "*__init__.py", - "*__main__.py", - "tests/*", - "examples/*", - "flama/cli/*", - "flama/types/*", - "flama/*/types.py", - "build.py", + ".venv*", + "*settings*", + "*__init__.py", + "*__main__.py", + "tests/*", + "examples/*", + "flama/compat.py", + "flama/cli/*", + "flama/types/*", + "flama/*/types.py", + "build.py", ] concurrency = ["thread", "multiprocessing"] [tool.coverage.report] show_missing = true +skip_covered = true ignore_errors = true fail_under = 90 exclude_lines = [ - "noqa", - "pragma: no cover", - "pass", - "\\.\\.\\.", - "raise AssertionError", - "raise NotImplementedError", - "if 0:", - "if __name__ == .__main__.:", - "def __repr__", - "def __str__", - "if cls\\.debug", - "if settings\\.DEBUG", - "if (typing\\.|t\\.)?TYPE_CHECKING:", + "noqa", + "pragma: no cover", + "pass", + "\\.\\.\\.", + "raise AssertionError", + "raise NotImplementedError", + "if 0:", + "if __name__ == .__main__.:", + "def __repr__", + "def __str__", + "if cls\\.debug", + "if settings\\.DEBUG", + "if (typing\\.|t\\.)?TYPE_CHECKING:", ] [tool.coverage.paths] -source = [ - "./" -] +source = ["./"] [tool.coverage.html] directory = "./test-results/coverage_html/" diff --git a/scripts/format b/scripts/format new file mode 100755 index 00000000..1fd12f43 --- /dev/null +++ b/scripts/format @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e + +run_format() { + echo "• Run format:" + poetry run ruff format "$@" + echo "↳ Format done" +} + +if [[ "${#BASH_SOURCE[@]}" -eq 1 ]]; then + run_format "$@" +fi diff --git a/scripts/lint b/scripts/lint index d5a98d85..73d9e190 100755 --- a/scripts/lint +++ b/scripts/lint @@ -1,27 +1,12 @@ #!/usr/bin/env bash set -e -source scripts/black -source scripts/isort -source scripts/ruff -source scripts/pyright - -run_lint() { - echo "🧹 Code lint using multiple tools:" - - local fix="$1" - if [[ "$fix" == "-f" || "$fix" == "--fix" ]]; then - run_black . - run_isort . - run_ruff --fix . - else - run_black --check . - run_isort --check . - run_ruff . - fi - run_pyright +run_ruff() { + echo "• Run Ruff code analysis:" + poetry run ruff check "$@" + echo "↳ Ruff done" } if [[ "${#BASH_SOURCE[@]}" -eq 1 ]]; then - run_lint "$@" + run_ruff "$@" fi diff --git a/scripts/ruff b/scripts/ruff deleted file mode 100755 index 010d38d2..00000000 --- a/scripts/ruff +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -set -e - -run_ruff() { - echo "• Run Ruff code analysis:" - poetry run ruff "$@" - echo "↳ Ruff done" -} - -if [[ "${#BASH_SOURCE[@]}" -eq 1 ]]; then - run_ruff "$@" -fi diff --git a/scripts/pyright b/scripts/types similarity index 100% rename from scripts/pyright rename to scripts/types diff --git a/tests/ddd/repositories/test_http.py b/tests/ddd/repositories/test_http.py index 2bfb5302..1f36ca4f 100644 --- a/tests/ddd/repositories/test_http.py +++ b/tests/ddd/repositories/test_http.py @@ -23,8 +23,7 @@ def client(self): return Mock(spec=Client) async def test_init(self, client): - class Repository(HTTPRepository): - ... + class Repository(HTTPRepository): ... repository = Repository(client) diff --git a/tests/ddd/repositories/test_sqlalchemy.py b/tests/ddd/repositories/test_sqlalchemy.py index 02d3a55f..97325c16 100644 --- a/tests/ddd/repositories/test_sqlalchemy.py +++ b/tests/ddd/repositories/test_sqlalchemy.py @@ -64,8 +64,7 @@ def connection(self): return Mock(spec=AsyncConnection) async def test_init(self, connection): - class Repository(SQLAlchemyRepository): - ... + class Repository(SQLAlchemyRepository): ... repository = Repository(connection) diff --git a/tests/ddd/test_components.py b/tests/ddd/test_components.py index fcf60fa2..0acbcd3c 100644 --- a/tests/ddd/test_components.py +++ b/tests/ddd/test_components.py @@ -10,8 +10,7 @@ class TestCaseWorkerComponent: @pytest.fixture(scope="function") def repository(self): - class FooRepository(BaseRepository): - ... + class FooRepository(BaseRepository): ... return FooRepository @@ -20,20 +19,16 @@ def worker(self, repository): class FooWorker(BaseWorker): foo: repository - async def set_up(self): - ... + async def set_up(self): ... - async def tear_down(self, *, rollback: bool = False): - ... + async def tear_down(self, *, rollback: bool = False): ... async def repository_params(self): return [], {} - async def commit(self): - ... + async def commit(self): ... - async def rollback(self): - ... + async def rollback(self): ... return FooWorker() @@ -64,8 +59,7 @@ def test_can_handle_parameter(self, component, param_name, param_type, parameter assert component.can_handle_parameter(Parameter(param_name, parameter_types[param_type])) == expected def test_resolve(self, component, worker): - class App: - ... + class App: ... foo = App() bar = App() diff --git a/tests/ddd/workers/test_base.py b/tests/ddd/workers/test_base.py index 77419ce8..3e7eee3a 100644 --- a/tests/ddd/workers/test_base.py +++ b/tests/ddd/workers/test_base.py @@ -9,8 +9,7 @@ @pytest.fixture(scope="function") def repository(): - class FooRepository(BaseRepository): - ... + class FooRepository(BaseRepository): ... return FooRepository @@ -19,17 +18,13 @@ class TestCaseAbstractWorker: @pytest.fixture(scope="function") def worker(self): class FooWorker(AbstractWorker): - async def begin(self): - ... + async def begin(self): ... - async def end(self, *, rollback: bool = False): - ... + async def end(self, *, rollback: bool = False): ... - async def commit(self): - ... + async def commit(self): ... - async def rollback(self): - ... + async def rollback(self): ... return FooWorker() @@ -64,26 +59,20 @@ def worker(self, repository): class FooWorker(BaseWorker): foo: repository - async def set_up(self): - ... + async def set_up(self): ... - async def tear_down(self, *, rollback: bool = False): - ... + async def tear_down(self, *, rollback: bool = False): ... async def repository_params(self): return [], {} - async def begin(self): - ... + async def begin(self): ... - async def end(self, *, rollback: bool = False): - ... + async def end(self, *, rollback: bool = False): ... - async def commit(self): - ... + async def commit(self): ... - async def rollback(self): - ... + async def rollback(self): ... return FooWorker() diff --git a/tests/ddd/workers/test_worker.py b/tests/ddd/workers/test_worker.py index d38e4ef5..28fcd151 100644 --- a/tests/ddd/workers/test_worker.py +++ b/tests/ddd/workers/test_worker.py @@ -6,8 +6,7 @@ class TestCaseWorker: @pytest.fixture(scope="function") def worker(self, client): - class FooWorker(Worker): - ... + class FooWorker(Worker): ... return FooWorker(client.app) diff --git a/tests/debug/test_data_structures.py b/tests/debug/test_data_structures.py index 85fc2031..27f5f5e6 100644 --- a/tests/debug/test_data_structures.py +++ b/tests/debug/test_data_structures.py @@ -63,11 +63,9 @@ def test_from_system(self): class TestCaseApp: def test_from_app(self): - def foo_handler(): - ... + def foo_handler(): ... - def bar_handler(): - ... + def bar_handler(): ... app = Flama( routes=[ @@ -100,7 +98,7 @@ def bar_handler(): "path": "/", "module": "tests.debug.test_data_structures", "file": "tests/debug/test_data_structures.py", - "line": 69, + "line": 68, "endpoint": "bar_handler", "name": "bar", } @@ -116,9 +114,11 @@ def test_build(self): environment_mock = MagicMock(Environment) error_mock = MagicMock(Error) - with patch.object(Request, "from_request", return_value=request_mock), patch.object( - Environment, "from_system", return_value=environment_mock - ), patch.object(Error, "from_exception", return_value=error_mock): + with ( + patch.object(Request, "from_request", return_value=request_mock), + patch.object(Environment, "from_system", return_value=environment_mock), + patch.object(Error, "from_exception", return_value=error_mock), + ): context = dataclasses.asdict(ErrorContext.build(MagicMock(), MagicMock())) assert context == {"request": request_mock, "environment": environment_mock, "error": error_mock} @@ -130,9 +130,11 @@ def test_build(self): environment_mock = MagicMock(Environment) app_mock = MagicMock(App) - with patch.object(Request, "from_request", return_value=request_mock), patch.object( - Environment, "from_system", return_value=environment_mock - ), patch.object(App, "from_app", return_value=app_mock): + with ( + patch.object(Request, "from_request", return_value=request_mock), + patch.object(Environment, "from_system", return_value=environment_mock), + patch.object(App, "from_app", return_value=app_mock), + ): context = dataclasses.asdict(NotFoundContext.build(MagicMock(), MagicMock())) assert context == {"request": request_mock, "environment": environment_mock, "app": app_mock} diff --git a/tests/debug/test_middleware.py b/tests/debug/test_middleware.py index f0c7c386..c5e3d6bd 100644 --- a/tests/debug/test_middleware.py +++ b/tests/debug/test_middleware.py @@ -20,8 +20,7 @@ async def process_exception( send: types.Send, exc: Exception, response_started: bool, - ) -> None: - ... + ) -> None: ... return FooMiddleware @@ -97,9 +96,10 @@ async def test_process_exception(self, middleware, asgi_scope, asgi_receive, asg middleware.debug = debug response_method = "debug_handler" if debug else "error_handler" exc = ValueError("Foo") - with patch.object( - ServerErrorMiddleware, response_method, new=MagicMock(return_value=AsyncMock()) - ) as response, pytest.raises(ValueError, match="Foo"): + with ( + patch.object(ServerErrorMiddleware, response_method, new=MagicMock(return_value=AsyncMock())) as response, + pytest.raises(ValueError, match="Foo"), + ): await middleware.process_exception(asgi_scope, asgi_receive, asgi_send, exc, response_started) if debug: @@ -116,11 +116,11 @@ def test_debug_response_html(self, middleware, asgi_scope, asgi_receive, asgi_se asgi_scope["headers"].append((b"accept", b"text/html")) exc = ValueError() error_context_mock, context_mock = MagicMock(), MagicMock() - with patch( - "flama.debug.middleware.dataclasses.asdict", return_value=context_mock - ) as dataclasses_dict, patch.object(ErrorContext, "build", return_value=error_context_mock), patch.object( - http._FlamaTemplateResponse, "__init__", return_value=None - ) as response_mock: + with ( + patch("flama.debug.middleware.dataclasses.asdict", return_value=context_mock) as dataclasses_dict, + patch.object(ErrorContext, "build", return_value=error_context_mock), + patch.object(http._FlamaTemplateResponse, "__init__", return_value=None) as response_mock, + ): response = middleware.debug_handler(asgi_scope, asgi_receive, asgi_send, exc) assert ErrorContext.build.call_count == 1 assert dataclasses_dict.call_args_list == [call(error_context_mock)] @@ -149,8 +149,7 @@ def middleware(self): @pytest.fixture def handler(self): - def _handler(): - ... + def _handler(): ... return _handler @@ -245,9 +244,11 @@ async def test_process_exception( asgi_scope["type"] = request_type handler_mock = MagicMock() response_mock = AsyncMock() if request_type == "http" else None - with exception, patch.object(middleware, "_get_handler", return_value=handler_mock), patch( - "flama.debug.middleware.concurrency.run", new=AsyncMock(return_value=response_mock) - ) as run_mock: + with ( + exception, + patch.object(middleware, "_get_handler", return_value=handler_mock), + patch("flama.debug.middleware.concurrency.run", new=AsyncMock(return_value=response_mock)) as run_mock, + ): await middleware.process_exception(asgi_scope, asgi_receive, asgi_send, expected_exc, response_started) if request_type == "http": @@ -317,9 +318,10 @@ def test_http_exception_handler( if response_class == http.APIErrorResponse: response_params["exception"] = exc - with patch( - f"flama.debug.middleware.http.{response_class.__name__}", spec=response_class - ) as response_mock, patch("flama.debug.middleware.dataclasses.asdict", return_value={}): + with ( + patch(f"flama.debug.middleware.http.{response_class.__name__}", spec=response_class) as response_mock, + patch("flama.debug.middleware.dataclasses.asdict", return_value={}), + ): response = middleware.http_exception_handler(asgi_scope, asgi_receive, asgi_send, exc) assert isinstance(response, response_class) diff --git a/tests/endpoints/test_base.py b/tests/endpoints/test_base.py index 1db6826a..e42691db 100644 --- a/tests/endpoints/test_base.py +++ b/tests/endpoints/test_base.py @@ -21,11 +21,9 @@ def route(self): def endpoint(self): class _Endpoint(endpoints.BaseEndpoint): @classmethod - def allowed_handlers(cls) -> dict[str, t.Callable]: - ... + def allowed_handlers(cls) -> dict[str, t.Callable]: ... - async def dispatch(self) -> None: - ... + async def dispatch(self) -> None: ... return _Endpoint diff --git a/tests/endpoints/test_http.py b/tests/endpoints/test_http.py index 77216edd..d0981a6a 100644 --- a/tests/endpoints/test_http.py +++ b/tests/endpoints/test_http.py @@ -28,8 +28,7 @@ def app(self, app): def endpoint(self, app, asgi_scope, asgi_receive, asgi_send): @app.route("/") class FooEndpoint(endpoints.HTTPEndpoint): - def get(self): - ... + def get(self): ... asgi_scope["app"] = app asgi_scope["root_app"] = app @@ -87,8 +86,7 @@ def test_init(self, app, asgi_scope, asgi_receive, asgi_send): with patch("flama.http.Request") as request_mock: class FooEndpoint(endpoints.HTTPEndpoint): - def get(self): - ... + def get(self): ... route = app.add_route("/", FooEndpoint) asgi_scope = types.Scope( @@ -121,8 +119,7 @@ def test_allowed_methods(self, endpoint): assert endpoint.allowed_methods() == {"GET", "HEAD"} class BarEndpoint(endpoints.HTTPEndpoint): - def post(self): - ... + def post(self): ... assert BarEndpoint.allowed_methods() == {"POST"} diff --git a/tests/endpoints/test_websocket.py b/tests/endpoints/test_websocket.py index 4d410474..ddf43ddf 100644 --- a/tests/endpoints/test_websocket.py +++ b/tests/endpoints/test_websocket.py @@ -24,8 +24,7 @@ def app(self, app): def endpoint(self, app, asgi_scope, asgi_receive, asgi_send): @app.websocket_route("/") class FooEndpoint(endpoints.WebSocketEndpoint): - def get(self): - ... + def get(self): ... asgi_scope["app"] = app asgi_scope["root_app"] = app diff --git a/tests/resources/test_workers.py b/tests/resources/test_workers.py index 2a10c702..f11264bd 100644 --- a/tests/resources/test_workers.py +++ b/tests/resources/test_workers.py @@ -18,22 +18,19 @@ async def app(self): @pytest.fixture(scope="function") def worker(self): - class FooWorker(FlamaWorker): - ... + class FooWorker(FlamaWorker): ... return FooWorker() @pytest.fixture(scope="function") def sqlalchemy_repository(self): - class FooRepository(SQLAlchemyRepository): - ... + class FooRepository(SQLAlchemyRepository): ... return FooRepository @pytest.fixture(scope="function") def http_repository(self): - class BarRepository(HTTPRepository): - ... + class BarRepository(HTTPRepository): ... return BarRepository diff --git a/tests/routing/routes/test_base.py b/tests/routing/routes/test_base.py index 82bd3593..737fb3c4 100644 --- a/tests/routing/routes/test_base.py +++ b/tests/routing/routes/test_base.py @@ -12,15 +12,13 @@ class TestCaseBaseEndpointWrapper: @pytest.fixture(scope="function") def wrapper_cls(self): class _Wrapper(routing.BaseEndpointWrapper): - async def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send) -> None: - ... + async def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send) -> None: ... return _Wrapper @pytest.fixture(scope="function") def handler(self): - async def foo(): - ... + async def foo(): ... return foo @@ -51,8 +49,7 @@ class Foo: assert isinstance(Foo.endpoint, functools.partial) def test_eq(self, wrapper_cls, handler): - async def bar(): - ... + async def bar(): ... endpoint = wrapper_cls(handler) endpoint_foo = wrapper_cls(handler) @@ -67,8 +64,7 @@ class TestCaseBaseRoute: @pytest.fixture(scope="function") def wrapper_cls(self): class _Wrapper(routing.BaseEndpointWrapper): - async def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send) -> None: - ... + async def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send) -> None: ... return _Wrapper @@ -85,8 +81,7 @@ def route(self, route_cls, wrapper_cls): return route_cls("/", wrapper_cls(lambda: None), name="foo", include_in_schema=False) def test_init(self, route_cls): - def foo(): - ... + def foo(): ... app = foo route = route_cls( @@ -105,15 +100,13 @@ def foo(): assert route.tags == {"tag": "tag", "list_tag": ["foo", "bar"], "dict_tag": {"foo": "bar"}} def test_eq(self, route_cls): - def foo(): - ... + def foo(): ... assert route_cls("/", foo, name="foo") == route_cls("/", foo, name="foo") assert route_cls("/", foo, name="foo") != route_cls("/", foo, name="bar") def test_repr(self, route_cls): - def foo(): - ... + def foo(): ... assert repr(route_cls("/", foo, name="foo")) == "_Route(path='/', name='foo')" diff --git a/tests/routing/routes/test_http.py b/tests/routing/routes/test_http.py index 8f6802d0..e6815a7c 100644 --- a/tests/routing/routes/test_http.py +++ b/tests/routing/routes/test_http.py @@ -19,8 +19,7 @@ async def foo(): @pytest.fixture(scope="function") def wrapper_cls(self): class _Wrapper(BaseHTTPEndpointWrapper): - async def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send) -> None: - ... + async def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send) -> None: ... return _Wrapper @@ -127,19 +126,16 @@ def route(self): def endpoint(self, request): if request.param == "function": - def foo(): - ... + def foo(): ... return foo elif request.param == "endpoint": class FooEndpoint(endpoints.HTTPEndpoint): - def get(self): - ... + def get(self): ... - def post(self): - ... + def post(self): ... return FooEndpoint elif request.param is None: @@ -246,15 +242,13 @@ async def test_call(self, route, asgi_scope, asgi_receive, asgi_send, scope_type assert handle.call_args_list == expected_calls def test_eq(self): - def foo(): - ... + def foo(): ... assert Route("/", foo, methods={"GET"}) == Route("/", foo, methods={"GET"}) assert Route("/", foo, methods={"GET"}) != Route("/", foo, methods={"POST"}) def test_repr(self): - def foo(): - ... + def foo(): ... assert repr(Route("/", foo)) == "Route(path='/', name='foo', methods=['GET', 'HEAD'])" @@ -298,8 +292,7 @@ def test_endpoint_handlers(self, endpoint, methods, expected_methods): ), ) def test_match(self, scope_type, scope_method, path_match_return, result, asgi_scope): - def foo(): - ... + def foo(): ... route = Route("/", foo, methods={"GET"}) diff --git a/tests/routing/routes/test_mount.py b/tests/routing/routes/test_mount.py index cac5e3ab..c310fb80 100644 --- a/tests/routing/routes/test_mount.py +++ b/tests/routing/routes/test_mount.py @@ -138,8 +138,7 @@ async def test_handle(self, mount, asgi_scope, asgi_receive, asgi_send): ), ) def test_route_scope(self, mount, asgi_scope, app, used): - def bar(): - ... + def bar(): ... mount.app = app mount.app.add_route("/bar", bar) diff --git a/tests/routing/routes/test_websocket.py b/tests/routing/routes/test_websocket.py index 1c543766..4b264732 100644 --- a/tests/routing/routes/test_websocket.py +++ b/tests/routing/routes/test_websocket.py @@ -87,8 +87,7 @@ def route(self): def endpoint(self, request): if request.param == "function": - def foo(): - ... + def foo(): ... return foo @@ -144,8 +143,7 @@ async def test_call(self, route, asgi_scope, asgi_receive, asgi_send, scope_type assert handle.call_args_list == expected_calls def test_eq(self): - def foo(): - ... + def foo(): ... assert WebSocketRoute("/", foo, name="foo") == WebSocketRoute("/", foo, name="foo") assert WebSocketRoute("/", foo, name="foo") != WebSocketRoute("/", foo, name="bar") @@ -185,8 +183,7 @@ def test_endpoint_handlers(self, endpoint, expected_handlers): ), ) def test_match(self, scope_type, path_match_return, result, asgi_scope): - def foo(): - ... + def foo(): ... route = WebSocketRoute("/", foo) diff --git a/tests/routing/test_router.py b/tests/routing/test_router.py index d9737164..218da470 100644 --- a/tests/routing/test_router.py +++ b/tests/routing/test_router.py @@ -68,8 +68,7 @@ def mount(app): endpoint = foo elif request.param == "websocket_endpoint": - class FooWebSocketEndpoint(WebSocketEndpoint): - ... + class FooWebSocketEndpoint(WebSocketEndpoint): ... def mount(app): app.add_websocket_route("/foo/", FooWebSocketEndpoint) @@ -113,8 +112,7 @@ def mount(app): endpoint = foo elif request.param == "wrong": - class Foo: - ... + class Foo: ... def mount(app): app.add_route("/wrong/", Foo) @@ -380,14 +378,11 @@ def test_mount_router(self, app, component_mock, tags): assert app.components == default_components def test_mount_declarative(self, component_mock, tags): - def root(): - ... + def root(): ... - def foo(): - ... + def foo(): ... - def foo_view(): - ... + def foo_view(): ... routes = [ Route("/", root, tags=tags), diff --git a/tests/schemas/test_routing.py b/tests/schemas/test_routing.py index 987981fa..c096e4d6 100644 --- a/tests/schemas/test_routing.py +++ b/tests/schemas/test_routing.py @@ -11,8 +11,7 @@ from flama.schemas.data_structures import Parameter, ParameterLocation -class Custom: - ... +class Custom: ... class TestCaseRouteFieldsMixin: @@ -55,8 +54,7 @@ def foo( z: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(foo_schema)], x: int = 1, y: t.Optional[str] = None, - ) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(foo_schema)]: - ... + ) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(foo_schema)]: ... return routing.Route("/foo/{w:int}/", endpoint=foo, methods=["GET"]) @@ -70,8 +68,7 @@ def get( z: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(foo_schema)], x: int = 1, y: t.Optional[str] = None, - ) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(foo_schema)]: - ... + ) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(foo_schema)]: ... return routing.Route("/bar/{w:int}/", endpoint=FooEndpoint, methods=["GET"]) @@ -85,8 +82,7 @@ def bar( z: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(foo_schema)], x: int = 1, y: t.Optional[str] = None, - ) -> None: - ... + ) -> None: ... return routing.WebSocketRoute("/foo/{w:int}/", endpoint=bar) @@ -102,8 +98,7 @@ async def on_receive( z: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(foo_schema)], x: int = 1, y: t.Optional[str] = None, - ) -> None: - ... + ) -> None: ... return routing.WebSocketRoute("/foo/{w:int}/", endpoint=FooWebsocket) else: diff --git a/tests/schemas/test_setup.py b/tests/schemas/test_setup.py index 5f05a242..b7fd0d61 100644 --- a/tests/schemas/test_setup.py +++ b/tests/schemas/test_setup.py @@ -40,9 +40,12 @@ def test_setup_marshmallow(self): def test_setup_no_lib_installed(self): from flama import schemas - with patch("flama.schemas.Module.available", PropertyMock(return_value=iter(()))), pytest.raises( - exceptions.DependencyNotInstalled, - match="No schema library is installed. Install one of your preference following instructions from: " - "https://flama.dev/docs/getting-started/installation#extras", + with ( + patch("flama.schemas.Module.available", PropertyMock(return_value=iter(()))), + pytest.raises( + exceptions.DependencyNotInstalled, + match="No schema library is installed. Install one of your preference following instructions from: " + "https://flama.dev/docs/getting-started/installation#extras", + ), ): schemas._module.setup() diff --git a/tests/schemas/test_validation.py b/tests/schemas/test_validation.py index 818ab394..9cb4318c 100644 --- a/tests/schemas/test_validation.py +++ b/tests/schemas/test_validation.py @@ -85,8 +85,7 @@ def validate_many_products() -> product_schema: def output_validation_error() -> product_schema: return {"name": "foo", "rating": -1} - class CustomValidationError(exceptions.ValidationError): - ... + class CustomValidationError(exceptions.ValidationError): ... @app.route("/custom-error") @output_validation(error_cls=CustomValidationError, error_status_code=502) @@ -167,5 +166,4 @@ def test_function_without_return_schema(self): with pytest.raises(TypeError, match=r"Invalid return signature for function .*"): @output_validation() - def foo(): - ... + def foo(): ... diff --git a/tests/test_applications.py b/tests/test_applications.py index 7d30003e..6edb0a86 100644 --- a/tests/test_applications.py +++ b/tests/test_applications.py @@ -161,8 +161,7 @@ def test_routes(self, app): assert routes == expected_routes def test_add_route(self, app, tags): - def foo(): - ... + def foo(): ... with patch.object(app, "router", spec=routing.Router) as router_mock: router_mock.add_route.return_value = foo @@ -187,16 +186,14 @@ def test_route(self, app, tags): with patch.object(app, "router", spec=routing.Router) as router_mock: @app.route("/", tags=tags) - def foo(): - ... + def foo(): ... assert router_mock.route.call_args_list == [ call("/", methods=None, name=None, include_in_schema=True, root=app, pagination=None, tags=tags) ] def test_add_websocket_route(self, app, tags): - def foo(): - ... + def foo(): ... with patch.object(app, "router", spec=routing.Router) as router_mock: router_mock.add_websocket_route.return_value = foo @@ -211,8 +208,7 @@ def test_websocket_route(self, app, tags): with patch.object(app, "router", spec=routing.Router) as router_mock: @app.websocket_route("/", tags=tags) - def foo(): - ... + def foo(): ... assert router_mock.websocket_route.call_args_list == [ call("/", name=None, root=app, pagination=None, tags=tags) @@ -236,8 +232,7 @@ def test_injector(self, app): def test_add_event_handler(self, app): handlers_before = app.events.startup.copy() - def handler(): - ... + def handler(): ... app.add_event_handler("startup", handler) @@ -247,8 +242,7 @@ def test_on_event(self, app): handlers_before = app.events.startup.copy() @app.on_event("startup") - def handler(): - ... + def handler(): ... assert app.events.startup == [*handlers_before, handler] @@ -265,11 +259,9 @@ def test_add_exception_handler(self, app, key, handler): def test_add_middleware(self, app): class FooMiddleware: - def __init__(self, app: types.App) -> None: - ... + def __init__(self, app: types.App) -> None: ... - def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send): - ... + def __call__(self, scope: types.Scope, receive: types.Receive, send: types.Send): ... kwargs = {"foo": "bar"} @@ -319,8 +311,7 @@ class PuppyResource(Resource): verbose_name = "Puppy" @resource_method("/custom") - def custom(self): - ... + def custom(self): ... with exception: assert app.resolve_url(resolve, **path_params) == resolution diff --git a/tests/test_client.py b/tests/test_client.py index 7f74c807..598cdf36 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -96,17 +96,36 @@ async def test_app_task(self, exception, lifespan_context_manager): assert lifespan_context_manager._shutdown_complete.set.call_args_list == [call()] @pytest.mark.parametrize( - ["exception"], + ["startup_mock", "shutdown_mock", "exception"], ( - pytest.param(None, id="ok"), - pytest.param(Exception("foo"), id="exception"), + pytest.param( + AsyncMock(), + AsyncMock(), + None, + id="ok", + ), + pytest.param( + AsyncMock(side_effect=Exception("foo")), + AsyncMock(), + Exception("foo"), + id="startup_exception", + ), + pytest.param( + AsyncMock(), + AsyncMock(side_effect=Exception("foo")), + Exception("foo"), + id="shutdown_exception", + ), ), indirect=["exception"], ) - async def test_context(self, lifespan_context_manager, exception): - with exception, patch.object(lifespan_context_manager, "_app_task"), patch.object( - lifespan_context_manager, "_startup", side_effect=exception.exception - ), patch.object(lifespan_context_manager, "_shutdown"): + async def test_context(self, lifespan_context_manager, startup_mock, shutdown_mock, exception): + with ( + exception, + patch.object(lifespan_context_manager, "_app_task"), + patch.object(lifespan_context_manager, "_startup", startup_mock), + patch.object(lifespan_context_manager, "_shutdown", shutdown_mock), + ): async with lifespan_context_manager: assert lifespan_context_manager._app_task.call_args_list == [call()] assert lifespan_context_manager._startup.await_args_list == [call()] @@ -160,12 +179,14 @@ async def test_context_no_app(self): assert aexit_mock.await_args_list == [call(None, None, None)] async def test_model_request(self, app): - with patch("flama.client.Flama", return_value=app), patch("builtins.super"), patch( - "importlib.metadata.version", return_value="x.y.z" + with ( + patch("flama.client.Flama", return_value=app), + patch("builtins.super"), + patch("importlib.metadata.version", return_value="x.y.z"), ): client = Client(models=[("foo", "/foo/", "model_foo.flm")]) - with patch.object(client, "request"): + with patch.object(client, "request") as request_mock: await client.model_request("foo", "GET", "/") - assert client.request.call_args_list == [call("GET", "/foo/")] + assert request_mock.call_args_list == [call("GET", "/foo/")] diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py index 84bc14e6..61779917 100644 --- a/tests/test_concurrency.py +++ b/tests/test_concurrency.py @@ -17,35 +17,29 @@ async def async_event_task(event): class TestCaseIsAsync: def test_function(self): - def foo_sync(): - ... + def foo_sync(): ... - async def foo_async(): - ... + async def foo_async(): ... assert not concurrency.is_async(foo_sync) assert concurrency.is_async(foo_async) def test_callable(self): class FooSync: - def __call__(self): - ... + def __call__(self): ... class FooAsync: - async def __call__(self): - ... + async def __call__(self): ... assert not concurrency.is_async(FooSync) assert concurrency.is_async(FooAsync) def test_partial(self): - def foo_sync(x: int): - ... + def foo_sync(x: int): ... partial_foo_sync = functools.partial(foo_sync, x=1) - async def foo_async(x: int): - ... + async def foo_async(x: int): ... partial_foo_async = functools.partial(foo_async, x=1) diff --git a/tests/test_http.py b/tests/test_http.py index e420c678..f36b3549 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -240,9 +240,10 @@ def test_init(self): def test_init_error(self): error_detail = "Foo error" - with patch("builtins.open", side_effect=ValueError(error_detail)), pytest.raises( - exceptions.HTTPException - ) as exc: + with ( + patch("builtins.open", side_effect=ValueError(error_detail)), + pytest.raises(exceptions.HTTPException) as exc, + ): http.HTMLFileResponse("foo.html") assert exc.status_code == 500 @@ -351,9 +352,10 @@ def test_init(self, context): template_mock.render.return_value = "foo" environment_mock = MagicMock(spec=jinja2.Environment) environment_mock.get_template.return_value = template_mock - with patch.object(http.HTMLTemplateResponse, "templates", new=environment_mock), patch.object( - http.HTMLResponse, "__init__", return_value=None - ) as super_mock: + with ( + patch.object(http.HTMLTemplateResponse, "templates", new=environment_mock), + patch.object(http.HTMLResponse, "__init__", return_value=None) as super_mock, + ): http.HTMLTemplateResponse("foo.html", context) assert super_mock.call_args_list == [call("foo")] @@ -388,9 +390,13 @@ class TestCaseFlamaLoader: indirect=["exception"], ) def test_init(self, import_mock, path_exists_mock, mkdir_call, exception): - with exception, patch("jinja2.PackageLoader.__init__"), patch("importlib.util", import_mock), patch.object( - pathlib.Path, "exists", return_value=path_exists_mock - ), patch.object(pathlib.Path, "mkdir") as mkdir_mock: + with ( + exception, + patch("jinja2.PackageLoader.__init__"), + patch("importlib.util", import_mock), + patch.object(pathlib.Path, "exists", return_value=path_exists_mock), + patch.object(pathlib.Path, "mkdir") as mkdir_mock, + ): http._FlamaLoader() if mkdir_call: diff --git a/tests/test_lifespan.py b/tests/test_lifespan.py index f7f5f6cc..78f2b8e9 100644 --- a/tests/test_lifespan.py +++ b/tests/test_lifespan.py @@ -285,8 +285,10 @@ async def send(message: types.Message) -> None: lifespan = app.router.lifespan - with exception, patch.object(lifespan, "_startup", side_effect=startup_side_effect), patch.object( - lifespan, "_shutdown", side_effect=shutdown_side_effect + with ( + exception, + patch.object(lifespan, "_startup", side_effect=startup_side_effect), + patch.object(lifespan, "_shutdown", side_effect=shutdown_side_effect), ): for receive_messages, send_messages, app_status in states: for m in receive_messages: diff --git a/tests/test_middleware.py b/tests/test_middleware.py index 81732b78..7b1c726b 100644 --- a/tests/test_middleware.py +++ b/tests/test_middleware.py @@ -11,8 +11,7 @@ class TestCaseMiddlewareStack: @pytest.fixture def middleware(self): class FooMiddleware: - def __init__(self, *args, **kwargs): - ... + def __init__(self, *args, **kwargs): ... def __call__(self, *args, **kwargs): return None @@ -42,8 +41,7 @@ def test_stack(self, stack): assert isinstance(stack._stack.app, ExceptionMiddleware) def test_add_exception_handler(self, stack): - def handler(request: http.Request, exc: Exception) -> http.Response: - ... + def handler(request: http.Request, exc: Exception) -> http.Response: ... assert stack._stack is None assert stack.stack diff --git a/tests/test_modules.py b/tests/test_modules.py index 68bd28ff..fb5e137c 100644 --- a/tests/test_modules.py +++ b/tests/test_modules.py @@ -26,8 +26,7 @@ class FooModule(Module): def test_new_module_no_name(self): with pytest.raises(AssertionError, match="Module 'FooModule' does not have a 'name' attribute."): - class FooModule(Module): - ... + class FooModule(Module): ... def test_init(self, module): m = module() diff --git a/tests/test_pagination.py b/tests/test_pagination.py index 0f95a51b..e984161d 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -60,15 +60,13 @@ def test_invalid_view(self, output_schema): with pytest.raises(TypeError, match=r"Paginated views must define \*\*kwargs param"): @paginator._paginate_page_number - def invalid() -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(output_schema.schema)]: - ... + def invalid() -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(output_schema.schema)]: ... def test_invalid_response(self): with pytest.raises(ValueError, match=r"Wrong schema type"): @paginator._paginate_page_number - def invalid(): - ... + def invalid(): ... def test_pagination_schema_parameters(self, app): schema = app.schema.schema["paths"]["/page-number/"]["get"] @@ -202,15 +200,13 @@ def test_invalid_view(self, output_schema): with pytest.raises(TypeError, match=r"Paginated views must define \*\*kwargs param"): @paginator._paginate_limit_offset - def invalid() -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(output_schema.schema)]: - ... + def invalid() -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(output_schema.schema)]: ... def test_invalid_response(self): with pytest.raises(ValueError, match=r"Wrong schema type"): @paginator._paginate_limit_offset - def invalid(): - ... + def invalid(): ... def test_pagination_schema_parameters(self, app): schema = app.schema.schema["paths"]["/limit-offset/"]["get"] diff --git a/tests/validation/test_schemas.py b/tests/validation/test_schemas.py index 1e254811..1b8fb153 100644 --- a/tests/validation/test_schemas.py +++ b/tests/validation/test_schemas.py @@ -126,7 +126,7 @@ def place_schema(self, app, location_schema): def add_endpoints(self, app, product_schema, reviewed_product_schema, place_schema): @app.route("/product", methods=["POST"]) def product_identity( - product: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(product_schema)] + product: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(product_schema)], ) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(product_schema)]: return product @@ -138,19 +138,19 @@ def reviewed_product_identity( @app.route("/place", methods=["POST"]) def place_identity( - place: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(place_schema)] + place: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(place_schema)], ) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(place_schema)]: return place @app.route("/many-products", methods=["GET"]) def many_products( - products: t.Annotated[list[schemas.SchemaType], schemas.SchemaMetadata(product_schema)] + products: t.Annotated[list[schemas.SchemaType], schemas.SchemaMetadata(product_schema)], ) -> t.Annotated[list[schemas.SchemaType], schemas.SchemaMetadata(product_schema)]: return products @app.route("/partial-product", methods=["GET"]) def partial_product( - product: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(product_schema, partial=True)] + product: t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(product_schema, partial=True)], ) -> t.Annotated[schemas.SchemaType, schemas.SchemaMetadata(product_schema, partial=True)]: return product