분류 전체보기
Router 의존성 주입과 API Func 의존성 주입
오늘 PR 리뷰를 하다가 현재 User에 대한 validate와 user 정보를 받아오는 함수를 정의해서 api args에서 annotate로 선언해서 썼다. 문제가 없는 코드였다. API endpoint에 depends 주입한 코드from typing import Annotated from fastapi import Depends, FastAPI from fastapi.security import OAuth2PasswordBearer from pydantic import BaseModel app = FastAPI() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") def validate_token(token): # 토큰이 유효하지 않다면 raise HT..
상속 안티 패턴
원하는 데이터 객체를 만들기 위해 많은 비용을 들이지 말자. 다음 예를 보자 class TransactionalPolicy(collections.UserDict): """잘못된 상속의 예""" def change_in_policy(self, customer_id, **new_policy_data): self[customer_id].update(**new_policy_data) 이 클래스는 고객의 정책에 접근해 정책을 바꾼다는 목적에는 부합할 수 있으나, 상속의 안티패턴을 보여주고 있다. 계층 구조가 잘못됐다. 기본 클래스에서 새 클래스를 만드는 것은 개념적으로 확장되고 세부적인 것이다라는 것을 뜻한다. 하지만 해당 데이터 객체는 Dict를 상속하면서 Dict의 개념을 확장했다기 보단 필요한 몇몇 부분(고..
FastAPI - Query Parameter에 Custom Validate 적용하기
문제상황 FastAPI에서 Query Parameter에 Validate를 적용하고 싶었다. 기본적인 건 min_length, max_length, pattern, regex 등은 기본적으로 지원해 주지만(공식문서), 조금 복잡한 validate를 적용할 때는 마땅한 게 없었다. View에서 물론 처리해도 되겠지만, 같은 코드 블록이 다른 View에서 계속 쓰이는 것은 보기 불편했다.(validate 함수를 지정하고 view에서 계속 호출하는 그게 너무 싫었다) 해결 과정 처음 생각한 건 BaseModel을 적용해서 @field_validator 를 적용할까 생각했지만, 한 두 개의 query param을 위해 BaseModel을 적용하는 건 필요 이상으로 복잡하게 모델을 구현한다는 생각이 들었다. 생각..
FastApi 사용하면서 기록할 것들
Embed 만약 Body 에서 Request Body 내부에 Key 로 구분지어서 받고 싶다면 Embed=True 로 설정하면 된다. 다음과 같이 나온다 from typing import Annotated from fastapi import Body, FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str description: str | None = None price: float tax: float | None = None @app.put("/items/{item_id}") async def update_item(item_id: int, item: Annotated[Item, Body(embed=Tr..
[ERROR] Pycharm Interpreter package install 시 'cp949' Encode error
pycharm에서 poetry로 가상환경을 세팅했다. 하지만 패키지를 설치하려고 할 때마다 `cp949` 에러가 났다. 사실 큰 문제는 아니었다. terminal에서 poetry 직접 add를 하면 됐다. 하지만 mypy를 plugin 으로 설치하고, 작동을 하려니까 계속 install mypy라는 noti가 뜨고(global 하게 mypy를 설치한 python을 써도 같은 오류를 뱉었다... virtualenv로 가상환경을 구성했을 땐 잘만되던 게... 왜 poetry에서만...ㅠ) 설치하려니 해당 오류를 뱉으니, 더 이상 무시할 수 없게 되었다. Pycharm file encoding 문제인가 싶어 UTF-8로 설정했지만, 에러 로그에는 stream_out.py 에서 `\u2022`를 encode 하..
Annotated
Annotated를 활용해 Type hint에 대한 Metadata를 설정해 보자 정의 typing.Annotated란 해당 타입에 대한 메타데이터를 제공해 준다. 사용법 예를 들어 다음과 같이 사용할 수 있다 T1 = Annotated[int, ValueRange(-10, 5)] T2 = Annotated[T1, ValueRange(-20, 3)] Annotated는 첫 번째 인자는 유효한 자료형이어야 한다. T2와 같이 가변인자도 지원한다. 또한 위와 같이 여러 개의 형 주석이 지원된다. Annotated[int, ValueRange(3, 10), ctype("char")] Annotated는 최소한 두 개의 인자로 호출해야 한다. # error num: Annotated[int] # Good num..
Slack reminder 조회 및 삭제
slack 에서 채널에 계속 공지하다가 삭제할 일이 생겼다. 1. remind 를 조회하자 /remind list 2. 목록에서 삭제를 누르면 된다
QueryParameter
1. kwargs 와 type 힌트를 통해 queryparameter 를 사용할 수 있다. fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] @app.get("/items/") async def read_item(skip: int = 0, limit: int = 10): return fake_items_db[skip : skip + limit] 2. Optional의 경우엔 어떻게? @app.get("/items/{item_id}") async def read_item(item_id: str, q: str | None = None): if q: return {"item_id": item_id, "q": q}..
FastAPI - PathParameter
PathParameter 1. '{}' 를 쓰고 인자로 받으면 된다. @app.get("/items/{item_id}") async def read_item(item_id: int): return {"item_id": item_id} 2. 만약 sub path 가 같고 뒤에 오는게 다르다면? @app.get("/users/me") async def read_user_me(): return {"user_id": "the current user"} @app.get("/users/{user_id}") async def read_user(user_id: str): return {"user_id": user_id} 이럴 경우엔 path param이 me가 오는 경우 read_user_me()가 호출 되고, 다른 ..
FastAPI 시작하기 - 개발환경 세팅
FastAPI로 개발하게 될 거 같아서 공부를 해보자. 일단 개발환경부터 세팅하자 개발환경은 pyenv와 poetry로 가상환경을 설정했다. pyenv 특징 pyenv 는 Python의 버전을 관리할 수 있다. 여러 개의 프로젝트에서 다양한 python 버전으로 개발환경을 세팅할 수 있다. 시스템 전체에 영향을 주지 않고 버전을 바꿀 수 있다. 주요 기능 여러 버전의 Python 설치 가상 환경 관리 pyenv를 사용하여 가상 환경을 생성하고 관리할 수 있다. 각각의 프로젝트에 맞게 가상 환경을 생성하여 의존성을 격리할 수 있다. 사용 예시 python 설치하기 # Python 3.9.6 버전 설치 pyenv install 3.9.6 # Python 3.8.12 버전 설치 pyenv install 3.8..