-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: application 초기 작업 (health check, function test)
- Loading branch information
Mincheol Kim
committed
Jul 5, 2020
1 parent
d437063
commit 68d158b
Showing
22 changed files
with
2,425 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ source = src | |
omit = | ||
.venv/* | ||
tests/* | ||
src/asgi.py | ||
|
||
[pytest] | ||
junit_family=xunit1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# pipenv .venv path | ||
PIPENV_VENV_IN_PROJECT=true | ||
|
||
APP_NAME=landlords-server | ||
|
||
HOST=0.0.0.0 | ||
PORT=5001 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "Python: FastAPI", | ||
"type": "python", | ||
"request": "launch", | ||
"module": "uvicorn", | ||
"args": [ | ||
"src.asgi:app", | ||
"--host", | ||
"0.0.0.0", | ||
"--port", | ||
"5000" | ||
], | ||
"console": "integratedTerminal", | ||
"subProcess": true, | ||
"envFile": "${workspaceFolder}/.env" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
{ | ||
"files.exclude": { | ||
"**/.git": true, | ||
"**/.svn": true, | ||
"**/.hg": true, | ||
"**/CVS": true, | ||
"**/.DS_Store": true, | ||
"**/.mypy_cache": true, | ||
"**/.benchmarks": true, | ||
"**/.venv": true, | ||
"**/node_modules": true, | ||
"**/public": true, | ||
"**/.pytest_cache": true, | ||
"**/__pycache__": true | ||
}, | ||
"editor.detectIndentation": false, | ||
"editor.insertSpaces": true, | ||
"editor.tabSize": 4, | ||
"editor.formatOnSave": true, | ||
"python.envFile": "${workspaceFolder}/.env", | ||
"python.testing.pytestEnabled": true, | ||
"python.linting.enabled": true, | ||
"python.linting.lintOnSave": true, | ||
"python.linting.mypyEnabled": true, | ||
"python.linting.pycodestyleArgs": [ | ||
"--max-line-length=80" | ||
], | ||
"python.linting.pycodestyleEnabled": true, | ||
"python.linting.pylintEnabled": false, | ||
"python.linting.pylintArgs": [ | ||
"--errors-only", // mypy, pycodestyle | ||
"--disable=no-member", // mypy | ||
"--enable=unused-import" // 이것 때문에 씀.. | ||
], | ||
"python.formatting.provider": "black", | ||
"python.formatting.blackArgs": [ | ||
"-l", | ||
"80" | ||
], | ||
"explorer.sortOrder": "modified", | ||
"editor.formatOnSaveTimeout": 3000, | ||
"editor.codeActionsOnSaveTimeout": 3000, | ||
"editor.fontFamily": "D2Coding" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
include .env | ||
GREEN=\n\033[1;32;40m | ||
RED=\n\033[1;31;40m | ||
NC=\033[0m # No Color | ||
|
||
|
||
PYCODESTYLE = pycodestyle | ||
MYPY = mypy | ||
# no-member: mypy | ||
PYLINTFLAGS = --verbose --reports=no --output-format=colorized --errors-only --disable=no-member --enable=unused-import | ||
|
||
PYTHONFILES := $(shell find . -name '*.py' | grep -v .venv) | ||
PYTHON_VERSION = py38 | ||
PYTHON_LINE_LENGTH = 80 | ||
targets: | ||
@echo $(PYTHONFILES) | ||
.PHONY: targets | ||
|
||
PIP := $(shell command -v pip 2> /dev/null) | ||
PIPENV := $(shell command -v pipenv 2> /dev/null) | ||
|
||
ref: | ||
ifndef PIP | ||
# https://pip.pypa.io/en/stable/installing/ | ||
$(error "pip이 설치되어 있지 않습니다.") | ||
endif | ||
@/bin/sh -c "echo \"${GREEN}pip 설치되어 있음${NC}\"" | ||
|
||
ifndef PIPENV | ||
pip install pipenv | ||
endif | ||
@/bin/sh -c "echo \"${GREEN}pipenv 설치되어 있음${NC}\"" | ||
|
||
.PHONY: ref | ||
|
||
# 의존성 모듈 관리 | ||
venv_dir=.venv | ||
venv-dev: | ||
ifneq "$(wildcard $(venv_dir) )" "" | ||
@/bin/sh -c "echo \"${GREEN}Already installation${NC}\"" | ||
else | ||
@/bin/sh -c "echo \"${GREEN}pipenv install${NC}\"" | ||
export PIPENV_VENV_IN_PROJECT=${PWD} && pipenv install --dev | ||
pipenv graph | ||
endif | ||
.PHONY: venv-dev | ||
|
||
pycodestyle: ref venv-dev | ||
@/bin/sh -c "echo \"${GREEN}[pycodestyle 시작]${NC}\"" | ||
pipenv run $(PYCODESTYLE) --first $(PYTHONFILES) | ||
.PHONY: pycodestyle | ||
|
||
# vscode의 formatting 도구로 black을 사용 | ||
black: ref venv-dev | ||
@/bin/sh -c "echo \"${GREEN}[black 시작]${NC}\"" | ||
pipenv run black -t $(PYTHON_VERSION) -l $(PYTHON_LINE_LENGTH) $(PYTHONFILES) | ||
.PHONY: black | ||
|
||
pylint: ref venv-dev | ||
@/bin/sh -c "echo \"${GREEN}[pylint 시작]${NC}\"" | ||
pipenv run pylint $(PYLINTFLAGS) $(PYTHONFILES) | ||
.PHONY: fast-pylint | ||
|
||
mypy: ref venv-dev | ||
@/bin/sh -c "echo \"${GREEN}[정적분석 시작]${NC}\"" | ||
pipenv run $(MYPY) --config-file mypy.ini $(PYTHONFILES) | ||
.PHONY: mypy | ||
|
||
lint: pycodestyle mypy pylint | ||
.PHONY: lint | ||
|
||
test: ref venv-dev | ||
pipenv run pytest \ | ||
--pdb \ | ||
--cov=src tests \ | ||
--cov-report=html \ | ||
--cov-report=term \ | ||
--cov-report=xml \ | ||
--disable-warnings | ||
.PHONY: test-coverage | ||
|
||
docker: requirements | ||
@/bin/sh -c "echo \"${GREEN}[docker image 빌드를 시작합니다]${NC}\"" | ||
@set -ex && docker build --rm -t ${APP_NAME}:latest "." | ||
.PHONY: docker | ||
|
||
requirements: ref venv-dev | ||
@/bin/sh -c "echo \"${GREEN}[requirements.txt를 추출합니다]${NC}\"" | ||
@pipenv lock -r > requirements.txt | ||
.PHONY: requirements | ||
|
||
# yaml에서 colon 버그 존재 이외에도 특문 버그도 존재하므로 script로 처리 | ||
# https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30097 | ||
__ci_commit: | ||
@git add app/__init__.py | ||
@git commit -m "chore(version): changed version ${AGENT_VERSION}" | ||
.PHONY: __ci_commit | ||
|
||
# 마지막 tag로부터 현재까지의 changelog 및 버전 확인 용 | ||
current_changelog: | ||
@/bin/sh -c "echo \"${GREEN}[release version] $(shell yarn run standard-version --dry-run | grep tagging | cut -d ' ' -f4)${NC}\"" | ||
@/bin/sh -c "echo \"${GREEN}[description] ${NC}\"" | ||
@yarn run standard-version --dry-run --silent | grep -v yarn | grep -v Done | grep -v "\-\-\-" | grep -v standard-version | ||
.PHONY: current_changelog |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"name": "todo-list-fastapi", | ||
"version": "1.8.5", | ||
"description": "practice project", | ||
"main": "src/main.py", | ||
"license": "MIT", | ||
"scripts": { | ||
"start": "pipenv run uvicorn src.main:app --host 0.0.0.0 --port 5000", | ||
"build": "make docker", | ||
"lint": "make lint", | ||
"test": "make test", | ||
"release": "standard-version", | ||
"version": "echo v$npm_package_version", | ||
"next-version": "node ./get-next-version.js" | ||
}, | ||
"devDependencies": { | ||
"@commitlint/cli": "^8.3.5", | ||
"@commitlint/config-conventional": "^8.3.4", | ||
"husky": "^4.2.5", | ||
"standard-version": "^7.1.0" | ||
}, | ||
"commitlint": { | ||
"extends": [ | ||
"@commitlint/config-conventional" | ||
] | ||
}, | ||
"husky": { | ||
"skipCI": false, | ||
"hooks": { | ||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS", | ||
"pre-commit": "npm run lint && npm run test && npm run build", | ||
"pre-push": "npm run lint" | ||
} | ||
}, | ||
"dependencies": { | ||
"yarn": "^1.22.4" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# 소스코드 패키지 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
""" | ||
""" | ||
from .core.config import settings | ||
from .main import create_app | ||
from .routes import api_v1 | ||
|
||
app = create_app() | ||
app.include_router(api_v1, prefix=f"{settings.API_VERSION_PREFIX}") |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# pylint: disable=no-self-argument | ||
from pydantic import BaseSettings | ||
|
||
|
||
class Settings(BaseSettings): | ||
""" | ||
application 설정 (환경변수 최우선) | ||
""" | ||
|
||
API_VERSION_PREFIX: str = "/api/v1" | ||
|
||
class Config: | ||
""" setting의 부가 설정 """ | ||
|
||
case_sensitive = True | ||
|
||
|
||
settings = Settings() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
""" | ||
에러 | ||
""" | ||
from typing import Union | ||
|
||
from fastapi import status | ||
from fastapi.exceptions import HTTPException, RequestValidationError | ||
from fastapi.openapi.constants import REF_PREFIX | ||
from fastapi.openapi.utils import validation_error_response_definition | ||
from pydantic import ValidationError | ||
from starlette.requests import Request | ||
from starlette.responses import JSONResponse | ||
|
||
|
||
async def http_exception_handler( | ||
_: Request, exc: HTTPException | ||
) -> JSONResponse: | ||
""" http exception handling """ | ||
return JSONResponse({"errors": [exc.detail]}, status_code=exc.status_code) | ||
|
||
|
||
async def validation_exception_handler( | ||
_: Request, exc: Union[RequestValidationError, ValidationError] | ||
) -> JSONResponse: | ||
""" client request exception handling """ | ||
return JSONResponse( | ||
{"errors": exc.errors()}, status_code=status.HTTP_400_BAD_REQUEST | ||
) | ||
|
||
|
||
validation_error_response_definition["properties"] = { | ||
"errors": { | ||
"title": "Errors", | ||
"type": "array", | ||
"items": {"$ref": "{0}ValidationError".format(REF_PREFIX)}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
""" | ||
main.py | ||
""" | ||
from fastapi.applications import FastAPI | ||
from fastapi.exceptions import RequestValidationError | ||
from starlette.exceptions import HTTPException | ||
from .core.handlers import http_exception_handler, validation_exception_handler | ||
|
||
|
||
def create_app() -> FastAPI: | ||
""" app factory method """ | ||
app = FastAPI() | ||
|
||
app.add_exception_handler( | ||
RequestValidationError, handler=validation_exception_handler | ||
) | ||
app.add_exception_handler(HTTPException, handler=http_exception_handler) | ||
|
||
return app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
""" | ||
routes | ||
""" | ||
from fastapi.routing import APIRouter | ||
|
||
from .health import health as health_router | ||
|
||
api_v1 = APIRouter() | ||
|
||
api_v1.include_router(health_router, prefix="/health", tags=["manage"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
""" | ||
router | ||
""" | ||
from typing import Dict | ||
from fastapi.routing import APIRouter | ||
|
||
health = APIRouter() | ||
|
||
|
||
@health.get("") | ||
async def health_check() -> Dict[str, str]: | ||
""" health check """ | ||
return {"status": "up"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# 테스트 패키지 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import pytest | ||
from starlette.testclient import TestClient | ||
from fastapi.applications import FastAPI | ||
|
||
from src.main import create_app | ||
from src.routes import api_v1 | ||
from src.core.config import settings | ||
|
||
|
||
@pytest.fixture | ||
def app() -> FastAPI: | ||
""" test app """ | ||
app = create_app() | ||
app.include_router(api_v1, prefix=f"{settings.API_VERSION_PREFIX}") | ||
return app | ||
|
||
|
||
@pytest.fixture | ||
def client(app: FastAPI) -> TestClient: | ||
""" test client """ | ||
return TestClient(app) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# 기능 테스트 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
""" | ||
routes/health.py 테스트 | ||
""" | ||
from http import HTTPStatus | ||
from starlette.testclient import TestClient | ||
from src.core.config import settings | ||
|
||
|
||
def test_health(client: TestClient) -> None: | ||
""" test health """ | ||
response = client.get(f"{settings.API_VERSION_PREFIX}/health") | ||
assert response.status_code == HTTPStatus.OK |
Oops, something went wrong.