From 2b626b189f244deb2b34eafec32ba3136baf860e Mon Sep 17 00:00:00 2001 From: pi3c Date: Mon, 15 Apr 2024 04:02:47 +0300 Subject: [PATCH] sync --- .pre-commit-config.yaml | 4 +-- Dockerfile | 21 ++++++++++++ compose.yml | 35 +++++++++++++++++++ flask_demo_api/config.py | 8 +++++ flask_demo_api/ioc.py | 47 ++++++++++++++++++++++++++ flask_demo_api/main.py | 9 ++++- flask_demo_api/protocols/repository.py | 2 +- flask_demo_api/repository/config.py | 6 ++++ flask_demo_api/repository/redis.py | 7 ++-- flask_demo_api/usecase/get.py | 4 +-- poetry.lock | 22 ++++++++++-- pyproject.toml | 3 +- 12 files changed, 154 insertions(+), 14 deletions(-) create mode 100644 Dockerfile create mode 100644 compose.yml create mode 100644 flask_demo_api/config.py create mode 100644 flask_demo_api/ioc.py create mode 100644 flask_demo_api/repository/config.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e38d4fb..fd55ede 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: rev: v3.15.2 hooks: - id: pyupgrade - args: [ --py311-plus ] + args: [ --py310-plus ] # Форматирует код под PEP8 - repo: https://github.com/pre-commit/mirrors-autopep8 @@ -46,7 +46,7 @@ repos: rev: 24.3.0 hooks: - id: black - language_version: python3.11 + language_version: python3.10 args: [ "--line-length=120" ] # Проверка статических типов с помощью mypy diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..00b97c7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM python:3.10-slim + +ENV PYTHONDONTWRITEBYTECODE 1 + +ENV PYTHONUNBUFFERED 1 + +RUN pip install --upgrade pip + +RUN pip install poetry + +RUN poetry config virtualenvs.create false + +RUN mkdir -p /usr/src/flask-demo-api/flask_demo_api + +WORKDIR /usr/src/flask-demo-api + +COPY ./poetry.lock . + +COPY ./pyproject.toml . + +RUN poetry install diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..01f310b --- /dev/null +++ b/compose.yml @@ -0,0 +1,35 @@ +version: "3.8" +services: + redis: + container_name: redis_demo + + image: redis:7.2.4-alpine3.19 + + ports: + - '6380:6379' + + healthcheck: + test: [ "CMD", "redis-cli","ping" ] + interval: 10s + timeout: 5s + retries: 5 + + app: + container_name: flask_demo + + build: + context: . + + ports: + - 8080:5000 + + depends_on: + redis: + condition: service_healthy + + restart: always + + volumes: + - ./flask_demo_api:/usr/src/flask-demo-api/flask_demo_api + + command: /bin/bash -c 'poetry run python flask_demo_api/main.py' diff --git a/flask_demo_api/config.py b/flask_demo_api/config.py new file mode 100644 index 0000000..f2ee44b --- /dev/null +++ b/flask_demo_api/config.py @@ -0,0 +1,8 @@ +from dataclasses import dataclass + +from repository.config import RedisSettings + + +@dataclass(frozen=True) +class Settings: + redis: RedisSettings diff --git a/flask_demo_api/ioc.py b/flask_demo_api/ioc.py new file mode 100644 index 0000000..dece842 --- /dev/null +++ b/flask_demo_api/ioc.py @@ -0,0 +1,47 @@ +import redis # type: ignore +from config import Settings +from dishka import Container, Provider, Scope, make_container, provide +from protocols.repository import Repository +from repository.config import RedisSettings +from repository.redis import RedisRepository +from usecase.get import GetKey + + +class RedisSettingsProvider(Provider): + @provide(scope=Scope.APP) + def redis_settings(self) -> RedisSettings: + return RedisSettings() + + +class SettingsProvider(Provider): + @provide(scope=Scope.APP) + def main_settings(self, redis_settings: RedisSettings) -> Settings: + return Settings(redis=redis_settings) + + +class RedisPoolProvider(Provider): + @provide(scope=Scope.APP) + def get_redis_pool(self, redis_settings: RedisSettings) -> redis.Redis: + return redis.from_url(redis_settings.url, decode_responses=False) + + +class RepositoryProvider(Provider): + @provide(scope=Scope.REQUEST) + def get_db(self, redis_pool: redis.Redis) -> Repository: + return RedisRepository(redis_pool=redis_pool) + + +class UseCasesProvider(Provider): + scope = Scope.REQUEST + + get = provide(GetKey) + + +def create_container() -> Container: + return make_container( + RedisSettingsProvider(), + SettingsProvider(), + RedisPoolProvider(), + RepositoryProvider(), + UseCasesProvider(), + ) diff --git a/flask_demo_api/main.py b/flask_demo_api/main.py index 7baa107..0f41ffa 100644 --- a/flask_demo_api/main.py +++ b/flask_demo_api/main.py @@ -1,4 +1,6 @@ +from dishka.integrations.flask import setup_dishka from flask import Flask +from ioc import create_container from routers.key import key_bp @@ -10,4 +12,9 @@ def app_factory() -> Flask: if __name__ == "__main__": app = app_factory() - app.run(debug=True) + container = create_container() + setup_dishka(container=container, app=app, auto_inject=True) + try: + app.run(debug=True, host="0.0.0.0") + finally: + container.close() diff --git a/flask_demo_api/protocols/repository.py b/flask_demo_api/protocols/repository.py index 988906f..c7f2ba7 100644 --- a/flask_demo_api/protocols/repository.py +++ b/flask_demo_api/protocols/repository.py @@ -1,7 +1,7 @@ from abc import abstractmethod from typing import Protocol -from flask_demo_api.protocols.models import KeyDTO +from protocols.models import KeyDTO class Repository(Protocol): diff --git a/flask_demo_api/repository/config.py b/flask_demo_api/repository/config.py new file mode 100644 index 0000000..0a6bd45 --- /dev/null +++ b/flask_demo_api/repository/config.py @@ -0,0 +1,6 @@ +from dataclasses import dataclass + + +@dataclass(frozen=True) +class RedisSettings: + url: str = "redis://redis:6379/0" diff --git a/flask_demo_api/repository/redis.py b/flask_demo_api/repository/redis.py index de58d1e..627833c 100644 --- a/flask_demo_api/repository/redis.py +++ b/flask_demo_api/repository/redis.py @@ -1,7 +1,6 @@ -import redis - -from flask_demo_api.protocols.models import KeyDTO -from flask_demo_api.protocols.repository import Repository +import redis # type: ignore +from protocols.models import KeyDTO +from protocols.repository import Repository class RedisRepository(Repository): diff --git a/flask_demo_api/usecase/get.py b/flask_demo_api/usecase/get.py index 3804c3c..f382e19 100644 --- a/flask_demo_api/usecase/get.py +++ b/flask_demo_api/usecase/get.py @@ -1,5 +1,5 @@ -from flask_demo_api.protocols.models import KeyDTO -from flask_demo_api.protocols.repository import Repository +from protocols.models import KeyDTO +from protocols.repository import Repository class GetKey: diff --git a/poetry.lock b/poetry.lock index 5180ea4..b13211b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -69,6 +69,9 @@ files = [ {file = "dishka-1.0.0.tar.gz", hash = "sha256:faed0353e43515d3485557037ce4cb63a3acf747e32f6c6b3bf1ff286cbf689b"}, ] +[package.dependencies] +exceptiongroup = {version = ">=1.1.3", markers = "python_version < \"3.11\""} + [[package]] name = "distlib" version = "0.3.8" @@ -80,6 +83,20 @@ files = [ {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "filelock" version = "3.13.4" @@ -301,7 +318,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -409,5 +425,5 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.0" -python-versions = "^3.11" -content-hash = "1e2a8795b8f7a080a95a4983bef9fd54096d0ce2668526045de78c8808678987" +python-versions = "^3.10" +content-hash = "0277ac9aaa4b3c1aafbf05157381b1af16f56a8d7ce4a47c5a20f7bac3978189" diff --git a/pyproject.toml b/pyproject.toml index a91fec4..2d8d64f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,10 +6,11 @@ authors = ["Sergey Vanyushkin "] readme = "README.md" [tool.poetry.dependencies] -python = "^3.11" +python = "^3.10" flask = "^3.0.3" redis = "^5.0.3" dishka = "^1.0.0" +exceptiongroup = "^1.2.0" [tool.poetry.group.dev.dependencies]