From 2655be2c0cf408bfdf001f106faa56be3a4b6f56 Mon Sep 17 00:00:00 2001 From: riroan Date: Sun, 25 Aug 2024 05:31:09 +0900 Subject: [PATCH] =?UTF-8?q?pre-commit=EC=97=90=20black=20=EB=A3=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yaml | 8 + .pre-commit-config.yaml | 7 + app.py | 5 +- db.py | 10 +- depends/__init__.py | 8 +- depends/cart.py | 14 +- depends/like.py | 6 +- depends/product.py | 2 +- dto/like.py | 2 +- exception.py | 5 +- migrations/env.py | 3 +- .../46c6ea277f8a_001_initial_migration.py | 192 ++++++++++++------ orm/base.py | 7 +- presentation/cart.py | 31 ++- presentation/like.py | 4 +- presentation/product.py | 15 +- repository/base.py | 19 +- repository/cart.py | 33 ++- repository/like.py | 33 ++- repository/product.py | 6 +- service/cart.py | 32 +-- service/like.py | 20 +- service/product.py | 9 +- settings.py | 5 +- tests/conftest.py | 39 +--- tests/e2e/test_cart.py | 62 ++---- tests/e2e/test_like.py | 52 ++--- tests/e2e/test_ping.py | 6 +- tests/e2e/test_product.py | 18 +- tests/unit/test_exception.py | 1 - 30 files changed, 278 insertions(+), 376 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c5be715..2075356 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,11 +11,19 @@ on: jobs: test: runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.12] steps: - name: Check out repository code uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2573992..f9683a2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,9 +11,16 @@ repos: rev: 5.13.2 hooks: - id: isort + args: ["--profile=black", "--py=312", "--line-length=80"] - repo: https://github.com/PyCQA/flake8 rev: 7.0.0 hooks: - id: flake8 additional_dependencies: - flake8-bugbear==24.4.21 +- repo: https://github.com/psf/black + rev: 23.9.1 + hooks: + - id: black + language_version: python3.12 + args: ["--line-length=80"] diff --git a/app.py b/app.py index 5768f20..4a72ebc 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,3 @@ - from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware @@ -15,7 +14,9 @@ def create_app(settings: Settings): app.add_middleware( CORSMiddleware, - allow_origins=["*",], + allow_origins=[ + "*", + ], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], diff --git a/db.py b/db.py index c563351..978a70f 100644 --- a/db.py +++ b/db.py @@ -7,19 +7,15 @@ class Database: def __init__(self, settings: Settings): - self.engine = create_engine( - url=settings.get_db_url() - ) + self.engine = create_engine(url=settings.get_db_url()) self.session = sessionmaker( - autocommit=False, - autoflush=False, - bind=self.engine + autocommit=False, autoflush=False, bind=self.engine ) def get_session(self) -> Session: return self.session() def __new__(cls, settings: Settings): - if not hasattr(cls, 'instance'): + if not hasattr(cls, "instance"): cls.instance = super(Database, cls).__new__(cls) return cls.instance diff --git a/depends/__init__.py b/depends/__init__.py index 0a52fe1..ffdcc63 100644 --- a/depends/__init__.py +++ b/depends/__init__.py @@ -18,9 +18,7 @@ async def get_database( return Database(settings) -async def get_session( - database: Annotated[Database, Depends(get_database)] -): +async def get_session(database: Annotated[Database, Depends(get_database)]): session = database.get_session() try: yield session @@ -30,7 +28,5 @@ async def get_session( raise e -async def get_messagebus( - session: Annotated[Session, Depends(get_session)] -): +async def get_messagebus(session: Annotated[Session, Depends(get_session)]): return MessageBus(session) diff --git a/depends/cart.py b/depends/cart.py index 50e6484..afcaf80 100644 --- a/depends/cart.py +++ b/depends/cart.py @@ -3,20 +3,12 @@ async def add_cart_command(cart: CartDto): - return AddCartCommand( - user_id=cart.user_id, - product_id=cart.product_id - ) + return AddCartCommand(user_id=cart.user_id, product_id=cart.product_id) async def update_cart_command(cart: CartUpdateDto, cart_id: int): - return UpdateCartCommand( - cart_id=cart_id, - count=cart.count - ) + return UpdateCartCommand(cart_id=cart_id, count=cart.count) async def delete_cart_command(cart_id: int): - return DeleteCartCommand( - cart_id=cart_id - ) + return DeleteCartCommand(cart_id=cart_id) diff --git a/depends/like.py b/depends/like.py index 7abb5ee..f677cf9 100644 --- a/depends/like.py +++ b/depends/like.py @@ -4,13 +4,11 @@ async def like_command(like_data: LikeDto): return LikeCommand( - user_id=like_data.user_id, - product_id=like_data.product_id + user_id=like_data.user_id, product_id=like_data.product_id ) async def dislike_command(like_data: LikeDto): return DislikeCommand( - user_id=like_data.user_id, - product_id=like_data.product_id + user_id=like_data.user_id, product_id=like_data.product_id ) diff --git a/depends/product.py b/depends/product.py index 0653823..ac2f681 100644 --- a/depends/product.py +++ b/depends/product.py @@ -7,5 +7,5 @@ async def add_product_command(product: ProductDto): name=product.name, image_path=product.image_path, price=product.price, - summary=product.summary + summary=product.summary, ) diff --git a/dto/like.py b/dto/like.py index 0a166e8..3df9a26 100644 --- a/dto/like.py +++ b/dto/like.py @@ -18,5 +18,5 @@ def from_entity(like: Like): return LikeResponseDto( is_like=like.is_like, user_id=like.user_id, - product_id=like.product_id + product_id=like.product_id, ) diff --git a/exception.py b/exception.py index 03bc463..055b01a 100644 --- a/exception.py +++ b/exception.py @@ -16,7 +16,7 @@ class NotFoundException(BaseException): exception_mapper = { BadRequestException: status.HTTP_400_BAD_REQUEST, - NotFoundException: status.HTTP_404_NOT_FOUND + NotFoundException: status.HTTP_404_NOT_FOUND, } @@ -24,7 +24,6 @@ def handle_exception(request: Request, exc: HTTPException): for exception in exception_mapper: if isinstance(exc, exception): return JSONResponse( - status_code=exception_mapper[exception], - content=exc.message + status_code=exception_mapper[exception], content=exc.message ) raise NotImplementedError diff --git a/migrations/env.py b/migrations/env.py index 0a2a8c4..bde3636 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -18,8 +18,7 @@ db_password = os.environ["DB_PASSWORD"] db_port = os.environ["DB_PORT"] url = ( - f"mysql+pymysql://{db_user}:{db_password}" - f"@{db_host}:{db_port}/{db_name}" + f"mysql+pymysql://{db_user}:{db_password}" f"@{db_host}:{db_port}/{db_name}" ) config.set_main_option("sqlalchemy.url", url) diff --git a/migrations/versions/46c6ea277f8a_001_initial_migration.py b/migrations/versions/46c6ea277f8a_001_initial_migration.py index 2626a6c..9b5fb8e 100644 --- a/migrations/versions/46c6ea277f8a_001_initial_migration.py +++ b/migrations/versions/46c6ea277f8a_001_initial_migration.py @@ -11,7 +11,7 @@ from alembic import op # revision identifiers, used by Alembic. -revision: str = '46c6ea277f8a' +revision: str = "46c6ea277f8a" down_revision: Union[str, None] = None branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None @@ -19,75 +19,133 @@ def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - op.create_table('product', - sa.Column('name', sa.String(length=256), nullable=False), - sa.Column('image_path', sa.String( - length=512), nullable=False), - sa.Column('price', sa.Integer(), nullable=False), - sa.Column('summary', sa.Text(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.Column('updated_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_table('user', - sa.Column('email', sa.String(length=256), nullable=False), - sa.Column('password', sa.String( - length=256), nullable=False), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.Column('updated_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - op.create_table('like_history', - sa.Column('is_like', sa.Integer(), nullable=False), - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('product_id', sa.Integer(), nullable=False), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.Column('updated_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.ForeignKeyConstraint(['product_id'], ['product.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_table('review', - sa.Column('product_id', sa.Integer(), nullable=False), - sa.Column('comment', sa.Text(), nullable=False), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.Column('updated_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.ForeignKeyConstraint(['product_id'], ['product.id'], ), - sa.PrimaryKeyConstraint('id') - ) - op.create_table('shopping_cart', - sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('product_id', sa.Integer(), nullable=False), - sa.Column('count', sa.Integer(), nullable=False), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.Column('updated_at', sa.DateTime(), - server_default=sa.text('now()'), nullable=False), - sa.ForeignKeyConstraint(['product_id'], ['product.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id') - ) + op.create_table( + "product", + sa.Column("name", sa.String(length=256), nullable=False), + sa.Column("image_path", sa.String(length=512), nullable=False), + sa.Column("price", sa.Integer(), nullable=False), + sa.Column("summary", sa.Text(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column( + "created_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.Column( + "updated_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "user", + sa.Column("email", sa.String(length=256), nullable=False), + sa.Column("password", sa.String(length=256), nullable=False), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column( + "created_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.Column( + "updated_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "like_history", + sa.Column("is_like", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("product_id", sa.Integer(), nullable=False), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column( + "created_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.Column( + "updated_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.ForeignKeyConstraint( + ["product_id"], + ["product.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "review", + sa.Column("product_id", sa.Integer(), nullable=False), + sa.Column("comment", sa.Text(), nullable=False), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column( + "created_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.Column( + "updated_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.ForeignKeyConstraint( + ["product_id"], + ["product.id"], + ), + sa.PrimaryKeyConstraint("id"), + ) + op.create_table( + "shopping_cart", + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("product_id", sa.Integer(), nullable=False), + sa.Column("count", sa.Integer(), nullable=False), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column( + "created_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.Column( + "updated_at", + sa.DateTime(), + server_default=sa.text("now()"), + nullable=False, + ), + sa.ForeignKeyConstraint( + ["product_id"], + ["product.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["user.id"], + ), + sa.PrimaryKeyConstraint("id"), + ) # ### end Alembic commands ### def downgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('shopping_cart') - op.drop_table('review') - op.drop_table('like_history') - op.drop_table('user') - op.drop_table('product') + op.drop_table("shopping_cart") + op.drop_table("review") + op.drop_table("like_history") + op.drop_table("user") + op.drop_table("product") # ### end Alembic commands ### diff --git a/orm/base.py b/orm/base.py index 42782e1..eb7a840 100644 --- a/orm/base.py +++ b/orm/base.py @@ -9,11 +9,8 @@ class Base(DeclarativeBase): id: Mapped[int] = mapped_column(primary_key=True) created_at: Mapped[datetime] = mapped_column( - DateTime, - server_default=func.now() + DateTime, server_default=func.now() ) updated_at: Mapped[datetime] = mapped_column( - DateTime, - server_default=func.now(), - onupdate=func.now() + DateTime, server_default=func.now(), onupdate=func.now() ) diff --git a/presentation/cart.py b/presentation/cart.py index d8ae401..a20d03c 100644 --- a/presentation/cart.py +++ b/presentation/cart.py @@ -1,4 +1,3 @@ - from typing import Annotated from fastapi import APIRouter, Depends, status @@ -6,8 +5,11 @@ from command.cart import AddCartCommand, DeleteCartCommand, UpdateCartCommand from depends import get_messagebus, get_session -from depends.cart import (add_cart_command, delete_cart_command, - update_cart_command) +from depends.cart import ( + add_cart_command, + delete_cart_command, + update_cart_command, +) from dto.cart import CartResponseDto, CartResponseModel from messagebus import MessageBus from service import cart as cart_service @@ -17,30 +19,23 @@ @api.get("/{user_id}", status_code=status.HTTP_200_OK) async def list_cart( - user_id: int, - session: Annotated[Session, Depends(get_session)] + user_id: int, session: Annotated[Session, Depends(get_session)] ) -> CartResponseModel: - cart_products = await cart_service.list_cart( - user_id, session - ) + cart_products = await cart_service.list_cart(user_id, session) products = [ CartResponseDto.from_entity(cart_product) for cart_product in cart_products ] - return CartResponseModel( - products=products - ) + return CartResponseModel(products=products) @api.post( - "", - status_code=status.HTTP_201_CREATED, - response_model_exclude_none=True + "", status_code=status.HTTP_201_CREATED, response_model_exclude_none=True ) async def add_cart( command: Annotated[AddCartCommand, Depends(add_cart_command)], - messagebus: Annotated[MessageBus, Depends(get_messagebus)] + messagebus: Annotated[MessageBus, Depends(get_messagebus)], ) -> CartResponseDto: cart = await messagebus.handle(command) return CartResponseDto.from_entity(cart) @@ -49,11 +44,11 @@ async def add_cart( @api.put( "/{cart_id}", status_code=status.HTTP_202_ACCEPTED, - response_model_exclude_none=True + response_model_exclude_none=True, ) async def update_cart( command: Annotated[UpdateCartCommand, Depends(update_cart_command)], - messagebus: Annotated[MessageBus, Depends(get_messagebus)] + messagebus: Annotated[MessageBus, Depends(get_messagebus)], ) -> CartResponseDto: cart = await messagebus.handle(command) return CartResponseDto.from_entity(cart) @@ -62,6 +57,6 @@ async def update_cart( @api.delete("/{cart_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_cart( command: Annotated[DeleteCartCommand, Depends(delete_cart_command)], - messagebus: Annotated[MessageBus, Depends(get_messagebus)] + messagebus: Annotated[MessageBus, Depends(get_messagebus)], ) -> None: await messagebus.handle(command) diff --git a/presentation/like.py b/presentation/like.py index 6f09b44..6c2ce86 100644 --- a/presentation/like.py +++ b/presentation/like.py @@ -14,7 +14,7 @@ @api.post("/like", status_code=status.HTTP_201_CREATED) async def like( command: Annotated[LikeCommand, Depends(like_command)], - messagebus: Annotated[MessageBus, Depends(get_messagebus)] + messagebus: Annotated[MessageBus, Depends(get_messagebus)], ) -> LikeResponseDto: like_obj = await messagebus.handle(command) @@ -24,7 +24,7 @@ async def like( @api.post("/dislike", status_code=status.HTTP_201_CREATED) async def dislike( command: Annotated[DislikeCommand, Depends(dislike_command)], - messagebus: Annotated[MessageBus, Depends(get_messagebus)] + messagebus: Annotated[MessageBus, Depends(get_messagebus)], ) -> LikeResponseDto: like_obj = await messagebus.handle(command) diff --git a/presentation/product.py b/presentation/product.py index ffd2ce9..3289acc 100644 --- a/presentation/product.py +++ b/presentation/product.py @@ -17,11 +17,9 @@ async def show_product( product_id: int, user_id: int, - session: Annotated[Session, Depends(get_session)] + session: Annotated[Session, Depends(get_session)], ) -> ProductResponseDto: - return await product_service.show_product( - product_id, user_id, session - ) + return await product_service.show_product(product_id, user_id, session) @api.get("", status_code=status.HTTP_200_OK) @@ -31,21 +29,18 @@ async def list_product( products = await product_service.list_product(session) product_responses = [ - ProductResponseDto.from_entity(product) - for product in products + ProductResponseDto.from_entity(product) for product in products ] return ProductResponseModel(products=product_responses) @api.post( - "", - status_code=status.HTTP_201_CREATED, - response_model_exclude_none=True + "", status_code=status.HTTP_201_CREATED, response_model_exclude_none=True ) async def add_product( command: Annotated[AddProductCommand, Depends(add_product_command)], - messagebus: Annotated[MessageBus, Depends(get_messagebus)] + messagebus: Annotated[MessageBus, Depends(get_messagebus)], ) -> ProductResponseDto: product = await messagebus.handle(command) diff --git a/repository/base.py b/repository/base.py index 9420a22..868ce17 100644 --- a/repository/base.py +++ b/repository/base.py @@ -3,29 +3,22 @@ from sqlalchemy.orm.session import Session -T = TypeVar('T') +T = TypeVar("T") class Repository(Generic[T], metaclass=ABCMeta): model = None - def __init__( - self, - session: Session - ): + def __init__(self, session: Session): self.session = session def get_by_id(self, id: int) -> T: - return self.session.query( - self.model - ).filter( - self.model.id == id - ).first() + return ( + self.session.query(self.model).filter(self.model.id == id).first() + ) def get_all(self) -> list[T]: - return self.session.query( - self.model - ).all() + return self.session.query(self.model).all() def add(self, obj: T): self.session.add(obj) diff --git a/repository/cart.py b/repository/cart.py index 1e61dfd..4dcd27d 100644 --- a/repository/cart.py +++ b/repository/cart.py @@ -8,22 +8,19 @@ class CartRepository(Repository): model = Cart def get_by_user_id(self, user_id: int): - return self.session.query( - self.model - ).filter( - self.model.user_id == user_id - ).options( - joinedload(Cart.product) - ).all() + return ( + self.session.query(self.model) + .filter(self.model.user_id == user_id) + .options(joinedload(Cart.product)) + .all() + ) - def get_by_user_id_and_product_id( - self, - user_id: int, - product_id: int - ): - return self.session.query( - self.model - ).filter( - self.model.user_id == user_id, - self.model.product_id == product_id - ).first() + def get_by_user_id_and_product_id(self, user_id: int, product_id: int): + return ( + self.session.query(self.model) + .filter( + self.model.user_id == user_id, + self.model.product_id == product_id, + ) + .first() + ) diff --git a/repository/like.py b/repository/like.py index 762d7d3..fdbc659 100644 --- a/repository/like.py +++ b/repository/like.py @@ -6,23 +6,20 @@ class LikeRepository(Repository): model = Like def get_by_user_id_and_product_id( - self, - user_id: int, - product_id: int + self, user_id: int, product_id: int ) -> Like: - return self.session.query( - self.model - ).filter( - self.model.user_id == user_id, - self.model.product_id == product_id - ).first() + return ( + self.session.query(self.model) + .filter( + self.model.user_id == user_id, + self.model.product_id == product_id, + ) + .first() + ) - def get_by_product_id( - self, - product_id: int - ) -> list[Like]: - return self.session.query( - self.model - ).filter( - self.model.product_id == product_id - ).all() + def get_by_product_id(self, product_id: int) -> list[Like]: + return ( + self.session.query(self.model) + .filter(self.model.product_id == product_id) + .all() + ) diff --git a/repository/product.py b/repository/product.py index 576e72d..9bc8244 100644 --- a/repository/product.py +++ b/repository/product.py @@ -6,8 +6,4 @@ class ProductRepository(Repository): model = Product def get_greater_than_id(self, id: int): - return self.session.query( - self.model - ).filter( - self.model.id > id - ).first() + return self.session.query(self.model).filter(self.model.id > id).first() diff --git a/service/cart.py b/service/cart.py index 47385a4..ff2899c 100644 --- a/service/cart.py +++ b/service/cart.py @@ -6,48 +6,30 @@ from repository.cart import CartRepository -async def list_cart( - user_id: int, - session: Session -) -> list[Cart]: +async def list_cart(user_id: int, session: Session) -> list[Cart]: repository = CartRepository(session) cart_products = repository.get_by_user_id(user_id) return cart_products -async def add_cart( - command: AddCartCommand, - session: Session -) -> Cart: +async def add_cart(command: AddCartCommand, session: Session) -> Cart: repository = CartRepository(session) obj = repository.get_by_user_id_and_product_id( - user_id=command.user_id, - product_id=command.product_id + user_id=command.user_id, product_id=command.product_id ) if obj is None: obj = Cart( - user_id=command.user_id, - product_id=command.product_id, - count=1 + user_id=command.user_id, product_id=command.product_id, count=1 ) repository.add(obj) else: - update_command = UpdateCartCommand( - cart_id=obj.id, - count=obj.count + 1 - ) - obj = await update_cart( - update_command, - session - ) + update_command = UpdateCartCommand(cart_id=obj.id, count=obj.count + 1) + obj = await update_cart(update_command, session) return obj -async def update_cart( - command: UpdateCartCommand, - session: Session -) -> Cart: +async def update_cart(command: UpdateCartCommand, session: Session) -> Cart: if command.count <= 0: raise BadRequestException repository = CartRepository(session) diff --git a/service/like.py b/service/like.py index 2712e80..6174531 100644 --- a/service/like.py +++ b/service/like.py @@ -6,20 +6,16 @@ from repository.like import LikeRepository -async def like( - command: LikeCommand, - session: Session -) -> Like: +async def like(command: LikeCommand, session: Session) -> Like: repository = LikeRepository(session) obj = repository.get_by_user_id_and_product_id( - user_id=command.user_id, - product_id=command.product_id + user_id=command.user_id, product_id=command.product_id ) if obj is None: obj = Like( user_id=command.user_id, product_id=command.product_id, - is_like=LikeStatus.LIKE + is_like=LikeStatus.LIKE, ) repository.add(obj) elif obj.is_like == LikeStatus.DISLIKE: @@ -27,20 +23,16 @@ async def like( return obj -async def dislike( - command: DislikeCommand, - session: Session -) -> Like: +async def dislike(command: DislikeCommand, session: Session) -> Like: repository = LikeRepository(session) obj = repository.get_by_user_id_and_product_id( - user_id=command.user_id, - product_id=command.product_id + user_id=command.user_id, product_id=command.product_id ) if obj is None: obj = Like( user_id=command.user_id, product_id=command.product_id, - is_like=LikeStatus.DISLIKE + is_like=LikeStatus.DISLIKE, ) repository.add(obj) elif obj.is_like == LikeStatus.LIKE: diff --git a/service/product.py b/service/product.py index 0bedda9..0eba62e 100644 --- a/service/product.py +++ b/service/product.py @@ -32,7 +32,7 @@ async def show_product( like_count=len(like_user_ids), dislike_count=len(dislike_user_ids), is_like=user_id in like_user_ids, - is_dislike=user_id in dislike_user_ids + is_dislike=user_id in dislike_user_ids, ) @@ -45,16 +45,13 @@ async def list_product( return products -async def add_product( - command: AddProductCommand, - session: Session -) -> Product: +async def add_product(command: AddProductCommand, session: Session) -> Product: repository = ProductRepository(session) product = Product( name=command.name, image_path=command.image_path, price=command.price, - summary=command.summary + summary=command.summary, ) repository.add(product) diff --git a/settings.py b/settings.py index e964acc..491fd8f 100644 --- a/settings.py +++ b/settings.py @@ -6,7 +6,7 @@ class Settings(BaseSettings): model_config = SettingsConfigDict( - env_file='.env', env_file_encoding='utf-8' + env_file=".env", env_file_encoding="utf-8" ) db_name: str = str() @@ -22,12 +22,11 @@ def get_db_url(self): password=self.db_password, host=self.db_host, port=self.db_port, - database=self.db_name + database=self.db_name, ) class TestSettings(Settings): - @override def get_db_url(self): return "sqlite:///pangtok.db" diff --git a/tests/conftest.py b/tests/conftest.py index 3bc82a5..0c63521 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,9 +26,7 @@ async def test_fastapi_app(settings): @pytest_asyncio.fixture(scope="function") async def engine(settings): - eng = create_engine( - url=settings.get_db_url() - ) + eng = create_engine(url=settings.get_db_url()) Base.metadata.create_all(eng) yield eng Base.metadata.drop_all(eng) @@ -46,13 +44,13 @@ async def user(): User( id=1, email=helper.TEST_USER_EMAIL_1, - password=helper.TEST_USER_PASSWORD_1 + password=helper.TEST_USER_PASSWORD_1, ), User( id=2, email=helper.TEST_USER_EMAIL_2, - password=helper.TEST_USER_PASSWORD_2 - ) + password=helper.TEST_USER_PASSWORD_2, + ), ] @@ -64,45 +62,28 @@ async def product(): name=helper.TEST_PRODUCT_NAME_1, image_path=helper.TEST_PRODUCT_IMAGE_PATH_1, price=helper.TEST_PRODUCT_PRICE_1, - summary=helper.TEST_PRODUCT_SUMMARY_1 + summary=helper.TEST_PRODUCT_SUMMARY_1, ), Product( id=2, name=helper.TEST_PRODUCT_NAME_2, image_path=helper.TEST_PRODUCT_IMAGE_PATH_2, price=helper.TEST_PRODUCT_PRICE_2, - summary=helper.TEST_PRODUCT_SUMMARY_2 - ) + summary=helper.TEST_PRODUCT_SUMMARY_2, + ), ] @pytest_asyncio.fixture(scope="function") async def shopping_cart(): - return [ - Cart( - id=1, - user_id=1, - product_id=1, - count=5 - ) - ] + return [Cart(id=1, user_id=1, product_id=1, count=5)] @pytest_asyncio.fixture(scope="function") async def like(): return [ - Like( - id=1, - is_like=LikeStatus.DISLIKE, - user_id=1, - product_id=1 - ), - Like( - id=2, - is_like=LikeStatus.LIKE, - user_id=2, - product_id=2 - ) + Like(id=1, is_like=LikeStatus.DISLIKE, user_id=1, product_id=1), + Like(id=2, is_like=LikeStatus.LIKE, user_id=2, product_id=2), ] diff --git a/tests/e2e/test_cart.py b/tests/e2e/test_cart.py index e101f0e..73f3d6b 100644 --- a/tests/e2e/test_cart.py +++ b/tests/e2e/test_cart.py @@ -21,21 +21,14 @@ async def test_list_cart_returns_200( @pytest.mark.asyncio -async def test_add_cart_returns_201( - test_fastapi_app, bootstrap -): +async def test_add_cart_returns_201(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: response = await client.post( "/cart", - headers={ - "Content-Type": "application/json" - }, - json={ - "user_id": 1, - "product_id": 2 - } + headers={"Content-Type": "application/json"}, + json={"user_id": 1, "product_id": 2}, ) assert response.status_code == status.HTTP_201_CREATED @@ -50,33 +43,22 @@ async def test_add_cart_returns_201_when_increment_count( ) as client: response = await client.post( "/cart", - headers={ - "Content-Type": "application/json" - }, - json={ - "user_id": 1, - "product_id": 1 - } + headers={"Content-Type": "application/json"}, + json={"user_id": 1, "product_id": 1}, ) assert response.status_code == status.HTTP_201_CREATED @pytest.mark.asyncio -async def test_update_cart_returns_202( - test_fastapi_app, bootstrap -): +async def test_update_cart_returns_202(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: response = await client.put( "/cart/1", - headers={ - "Content-Type": "application/json" - }, - json={ - "count": 123 - } + headers={"Content-Type": "application/json"}, + json={"count": 123}, ) assert response.status_code == status.HTTP_202_ACCEPTED @@ -91,41 +73,29 @@ async def test_update_cart_returns_400_when_invalid_count( ) as client: response = await client.put( "/cart/1", - headers={ - "Content-Type": "application/json" - }, - json={ - "count": 0 - } + headers={"Content-Type": "application/json"}, + json={"count": 0}, ) assert response.status_code == status.HTTP_400_BAD_REQUEST @pytest.mark.asyncio -async def test_update_cart_returns_404( - test_fastapi_app, bootstrap -): +async def test_update_cart_returns_404(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: response = await client.put( "/cart/-1", - headers={ - "Content-Type": "application/json" - }, - json={ - "count": 123 - } + headers={"Content-Type": "application/json"}, + json={"count": 123}, ) assert response.status_code == status.HTTP_404_NOT_FOUND @pytest.mark.asyncio -async def test_delete_cart_returns_204( - test_fastapi_app, bootstrap -): +async def test_delete_cart_returns_204(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: @@ -137,9 +107,7 @@ async def test_delete_cart_returns_204( @pytest.mark.asyncio -async def test_delete_cart_returns_404( - test_fastapi_app, bootstrap -): +async def test_delete_cart_returns_404(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: diff --git a/tests/e2e/test_like.py b/tests/e2e/test_like.py index f8ad69e..65c9d6f 100644 --- a/tests/e2e/test_like.py +++ b/tests/e2e/test_like.py @@ -4,80 +4,52 @@ @pytest.mark.asyncio -async def test_like_returns_201( - test_fastapi_app, bootstrap -): +async def test_like_returns_201(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: response = await client.post( "/like", - headers={ - "Content-Type": "application/json" - }, - json={ - "user_id": 2, - "product_id": 1 - } + headers={"Content-Type": "application/json"}, + json={"user_id": 2, "product_id": 1}, ) assert response.status_code == status.HTTP_201_CREATED @pytest.mark.asyncio -async def test_dislike_returns_201( - test_fastapi_app, bootstrap -): +async def test_dislike_returns_201(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: response = await client.post( "/dislike", - headers={ - "Content-Type": "application/json" - }, - json={ - "user_id": 2, - "product_id": 1 - } + headers={"Content-Type": "application/json"}, + json={"user_id": 2, "product_id": 1}, ) assert response.status_code == status.HTTP_201_CREATED @pytest.mark.asyncio -async def test_like_returns_201_when_update( - test_fastapi_app, bootstrap -): +async def test_like_returns_201_when_update(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: response = await client.post( "/like", - headers={ - "Content-Type": "application/json" - }, - json={ - "user_id": 1, - "product_id": 1 - } + headers={"Content-Type": "application/json"}, + json={"user_id": 1, "product_id": 1}, ) assert response.status_code == status.HTTP_201_CREATED @pytest.mark.asyncio -async def test_dislike_returns_201_when_update( - test_fastapi_app, bootstrap -): +async def test_dislike_returns_201_when_update(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: response = await client.post( "/dislike", - headers={ - "Content-Type": "application/json" - }, - json={ - "user_id": 2, - "product_id": 2 - } + headers={"Content-Type": "application/json"}, + json={"user_id": 2, "product_id": 2}, ) assert response.status_code == status.HTTP_201_CREATED diff --git a/tests/e2e/test_ping.py b/tests/e2e/test_ping.py index 184ab1f..868d38c 100644 --- a/tests/e2e/test_ping.py +++ b/tests/e2e/test_ping.py @@ -1,14 +1,10 @@ - - import pytest from fastapi import status from httpx import ASGITransport, AsyncClient @pytest.mark.asyncio -async def test_ping( - test_fastapi_app, bootstrap -): +async def test_ping(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: diff --git a/tests/e2e/test_product.py b/tests/e2e/test_product.py index 2ae757c..f74c6b2 100644 --- a/tests/e2e/test_product.py +++ b/tests/e2e/test_product.py @@ -6,9 +6,7 @@ @pytest.mark.asyncio -async def test_show_product_detail_returns_200( - test_fastapi_app, bootstrap -): +async def test_show_product_detail_returns_200(test_fastapi_app, bootstrap): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: @@ -44,9 +42,7 @@ async def test_show_product_detail_returns_200_when_last_id( @pytest.mark.asyncio -async def test_list_product_returns_200( - test_fastapi_app, bootstrap, product -): +async def test_list_product_returns_200(test_fastapi_app, bootstrap, product): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: @@ -60,22 +56,18 @@ async def test_list_product_returns_200( @pytest.mark.asyncio -async def test_add_product_returns_201( - test_fastapi_app, bootstrap, product -): +async def test_add_product_returns_201(test_fastapi_app, bootstrap, product): async with AsyncClient( transport=ASGITransport(app=test_fastapi_app), base_url="http://test" ) as client: response = await client.post( "/product", - headers={ - "Content-Type": "application/json" - }, + headers={"Content-Type": "application/json"}, json={ "name": "product_name", "image_path": "product_image_path", "price": 50000, - } + }, ) assert response.status_code == status.HTTP_201_CREATED diff --git a/tests/unit/test_exception.py b/tests/unit/test_exception.py index ecb82d4..d5fe18e 100644 --- a/tests/unit/test_exception.py +++ b/tests/unit/test_exception.py @@ -1,4 +1,3 @@ - import pytest from fastapi import status