Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@
"workbench": {
"iconTheme": "vscode-icons"
},
"editor": {
"formatOnSave": true,
"defaultFormatter": "ms-python.black-formatter",
"codeActionsOnSave": {
"source.organizeImports": true
}
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff"
}
},
"extensions": [
Expand All @@ -52,9 +53,7 @@
"tamasfe.even-better-toml",
"redhat.vscode-yaml",
"ms-python.mypy-type-checker",
"ms-python.flake8",
"ms-python.black-formatter",
"ms-python.isort"
"charliermarsh.ruff"
]
}
}
Expand Down
77 changes: 0 additions & 77 deletions .flake8

This file was deleted.

10 changes: 3 additions & 7 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,10 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
linter: [black, isort, flake8, mypy]
linter: [ruff, mypy]
include:
- linter: black
command: black --check --diff .
- linter: isort
command: isort --check-only --diff .
- linter: flake8
command: flake8 --count .
- linter: ruff
command: ruff check --diff .
- linter: mypy
command: mypy .
steps:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
__pycache__/
*.py[cod]
*$py.class

.idea
# C extensions
*.so

Expand Down
39 changes: 12 additions & 27 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,28 @@ repos:
- id: trailing-whitespace
types: [python]

- repo: https://github.com/asottile/pyupgrade
rev: v3.16.0
hooks:
- id: pyupgrade
args: [--py312-plus]
- repo: https://github.com/asottile/pyupgrade
rev: v3.16.0
hooks:
- id: pyupgrade
args: [--py312-plus]

- repo: local
hooks:
- id: black
name: Format Python code with Black
entry: uv run black
language: system
types: [python]

- id: isort
name: Sort Python imports with isort
entry: uv run isort
- id: ruff-lint
name: Python code linting with Ruff
entry: uv run ruff check --fix
language: system
types: [python]

- id: autoflake
name: autoflake
entry: uv run autoflake
- id: ruff-format
name: Python code formatting with Ruff
entry: uv run ruff format
language: system
types: [python]
args: [--in-place, --remove-all-unused-imports, --remove-duplicate-keys, --ignore-init-module-imports]

- id: flake8
name: Check with Flake8
entry: uv run flake8
language: system
pass_filenames: false
types: [python]
args: [--count, .]

- id: mypy
name: Validate types with MyPy
name: Python type checking with MyPy
entry: uv run mypy
language: system
types: [python]
Expand Down
8 changes: 4 additions & 4 deletions app/v1/routers/users/users_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ async def create_user(user: User, user_manager: UserManager = Depends(get_user_m
try:
return user_manager.create_user(user)
except ValueError as ex:
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(ex))
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(ex)) from ex


@router.get("/{username}")
async def get_user(username: str, user_manager: UserManager = Depends(get_user_manager)) -> User:
try:
return user_manager.get_user(username)
except ValueError as ex:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(ex))
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)) from ex


@router.get("/")
Expand All @@ -34,12 +34,12 @@ async def update_user(username: str, user: User, user_manager: UserManager = Dep
try:
return user_manager.update_user(username, user)
except ValueError as ex:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(ex))
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)) from ex


@router.delete("/{username}")
async def delete_user(username: str, user_manager: UserManager = Depends(get_user_manager)) -> User:
try:
return user_manager.delete_user(username)
except ValueError as ex:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(ex))
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)) from ex
28 changes: 7 additions & 21 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,24 @@
name = "python-fastapi-template"
version = "0.1.0"
description = "A template for a Python FastAPI service with uv & Devcontainer"
authors = ["Ibraheem Tuffaha <ibraheem.z.tuffaha@gmail.com>"]
authors = [{ name = "Ibraheem Tuffaha", email = "ibraheem.z.tuffaha@gmail.com" }]
license = "MIT"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"fastapi[standard]>=0.115.8",
"fastapi[standard]>=0.115.8",
]


[dependency-groups]
dev = [
"autoflake>=2.3.1",
"black>=25.1.0",
"flake8>=7.1.2",
"isort>=6.0.0",
"mypy>=1.15.0",
"pre-commit>=4.1.0",
"pytest>=8.3.4",
"pytest-cov>=6.0.0",
"wemake-python-styleguide>=1.0.0",
"mypy>=1.15.0",
"pre-commit>=4.1.0",
"pytest>=8.3.4",
"pytest-cov>=6.0.0",
"ruff>=0.9.9",
]

[tool.black]
line-length = 120

[tool.isort]
profile = "black"
line_length = 120
src_paths = ["app", "tests"]
lines_between_types = 1
lines_after_imports = 2

[tool.mypy]
strict = true
pretty = true
Expand Down
51 changes: 51 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
line-length = 120
[format]
quote-style = "double"
docstring-code-format = true

exclude = [
"./.cache",
"./.git",
"./.idea",
"./.mypy_cache",
"./.pytest_cache",
"./.venv",
"./venv",
"./env",
"./cached_venv",
"./docs",
"./var",
"./.vscode",
]

[lint.isort]
lines-after-imports = 2
lines-between-types = 1
no-lines-before = ["future", "standard-library"]
no-sections = false
order-by-type = true

[lint]
extend-select = ["E", "F", "I", "UP", "B", "W", "C90", "N", "D", "PYI", "PT", "RET", "SIM", "ARG", "ERA"]
ignore = [
"B008",
"D100",
"D101",
"D102",
"D103",
"D104",
"D105",
"D106",
"D107",
"D203",
"D213",
"COM812"
]

[lint.per-file-ignores]
"test_*.py" = ["S101"]
"tests.py" = ["S101"]
"tests_*.py" = ["S101"]
"*/tests/*" = ["S101"]
"conftest.py" = ["S101"]
"__init__.py" = ["F401", "F403"]
Loading