Skip to content

Commit b05ac04

Browse files
authored
Merge pull request #372 from nanotaboada/feature/black
chore: configure Black as the default Python code formatter
2 parents 26e3e7d + cc61d5a commit b05ac04

File tree

17 files changed

+313
-173
lines changed

17 files changed

+313
-173
lines changed

.flake8

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,11 @@
11
[flake8]
2-
# Maximum line length allowed
3-
max-line-length = 127
4-
5-
# Maximum allowed code complexity (10 is a reasonable threshold)
2+
max-line-length = 88
63
max-complexity = 10
7-
8-
# Only check for specific error codes:
9-
# - E9 -> Syntax errors
10-
# - F63 -> Issues related to improper usage of `+=`, `-=`, etc.
11-
# - F7 -> Issues related to improper `break`, `continue`, etc.
12-
# - F82 -> Undefined names
13-
select = E9,F63,F7,F82
14-
15-
# Exclude `.venv` from linting (prevents checking dependencies)
4+
select = E,F,W
5+
extend-ignore = E203, W503
166
exclude = .venv
17-
18-
# Print the count of linting errors
7+
per-file-ignores = tests/test_main.py: E501
198
count = True
20-
21-
# Show the exact source of the error
229
show-source = True
23-
24-
# Display statistics of errors at the end of the report
2510
statistics = True
26-
27-
# Enable verbose mode for more detailed output
2811
verbose = True

.github/workflows/python-app.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
python-version: ${{ env.PYTHON_VERSION }}
3232
cache: 'pip'
3333

34-
- name: Install dependencies
34+
- name: Install lint dependencies
3535
run: |
3636
python -m pip install --upgrade pip
3737
pip install -r requirements-lint.txt
@@ -40,6 +40,10 @@ jobs:
4040
run: |
4141
flake8 .
4242
43+
- name: Check code formatting with Black
44+
run: |
45+
black --check .
46+
4347
test:
4448
needs: lint
4549
runs-on: ubuntu-latest
@@ -53,7 +57,7 @@ jobs:
5357
python-version: ${{ env.PYTHON_VERSION }}
5458
cache: 'pip'
5559

56-
- name: Install dependencies
60+
- name: Install test dependencies
5761
run: |
5862
python -m pip install --upgrade pip
5963
pip install -r requirements-test.txt

.vscode/extensions.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"recommendations": [
33
"ms-python.python",
4-
"ms-python.vscode-pylance",
4+
"ms-python.flake8",
5+
"ms-python.black-formatter",
56
"github.vscode-pull-request-github",
67
"github.vscode-github-actions",
78
"ms-azuretools.vscode-containers",

.vscode/settings.json

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,53 @@
11
{
2-
"python.testing.unittestEnabled": false,
3-
"python.testing.pytestEnabled": true,
4-
"python.testing.pytestArgs": ["tests"],
52
"files.exclude": {
63
"**/__pycache__": true,
74
"**/.git": true,
85
"**/.DS_Store": true
96
},
7+
"editor.wordWrapColumn": 88,
8+
"editor.rulers": [88],
109
"[python]": {
11-
"editor.defaultFormatter": "ms-python.autopep8",
10+
"editor.defaultFormatter": "ms-python.black-formatter",
1211
"editor.formatOnSave": true
1312
},
13+
"python.testing.unittestEnabled": false,
14+
"python.testing.pytestEnabled": true,
15+
"python.testing.pytestArgs": ["tests"],
16+
"flake8.enabled": true,
17+
"flake8.importStrategy": "fromEnvironment",
18+
"flake8.path": ["${interpreter}", "-m", "flake8"],
19+
// Point flake8 to use your existing config file automatically
20+
"flake8.args": [
21+
"--max-line-length=88",
22+
"--max-complexity=10",
23+
"--select=E,F,W",
24+
"--extend-ignore=E203,W503",
25+
"--exclude=.venv",
26+
"--per-file-ignores=tests/test_main.py:E501"
27+
],
28+
// Exclude files/folders you don’t want to lint (matching Black’s exclude)
29+
"flake8.ignorePatterns": [
30+
"**/.git/**",
31+
"**/.github/**",
32+
"**/.pytest_cache/**",
33+
"**/.venv/**",
34+
"**/.vscode/**",
35+
"**/assets/**",
36+
"**/htmlcov/**",
37+
"**/postman_collections/**",
38+
"**/scripts/**",
39+
"**/storage/**",
40+
"**/__pycache__/**",
41+
"**/tests/test_main.py"
42+
],
43+
"flake8.severity": {
44+
"convention": "Information",
45+
"error": "Error",
46+
"fatal": "Error",
47+
"refactor": "Hint",
48+
"warning": "Warning",
49+
"info": "Information"
50+
},
1451
"sonarlint.connectedMode.project": {
1552
"connectionId": "nanotaboada",
1653
"projectKey": "nanotaboada_python-samples-fastapi-restful"

CONTRIBUTING.md

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,58 @@ We value **incremental, detail‑first contributions** over big rewrites or abst
1010
## 2. Code & Commit Conventions
1111

1212
- **Conventional Commits**
13-
Follow <https://www.conventionalcommits.org/en/v1.0.0/>:
14-
- `feat: ` for new features
15-
- `fix: ` for bug fixes
16-
- `chore: ` for maintenance
13+
Follow <https://www.conventionalcommits.org/en/v1.0.0/>:
14+
- `feat: ` for new features
15+
- `fix: ` for bug fixes
16+
- `chore: ` for maintenance or tooling
1717

1818
- **Logical Commits**
19-
Group changes by purpose. It’s okay to have multiple commits in a PR, but if they’re mere checkpoints, squash them into a single logical commit.
20-
21-
- **Lint & Tests**
22-
Run existing linters/formatters and ensure all tests pass.
19+
Group changes by purpose. Multiple commits are fine, but avoid noise. Squash when appropriate.
20+
21+
- **Python Formatting & Style**
22+
- Use **[Black](https://black.readthedocs.io/)** for consistent code formatting.
23+
- Black is opinionated: don't argue with it, just run it.
24+
- Line length is set to **88**, matching the default.
25+
- Use **[flake8](https://flake8.pycqa.org/en/latest/)** for static checks.
26+
- Line length also set to 88.
27+
- Some flake8 warnings are disabled (e.g. `E203`, `W503`) to avoid conflicts with Black.
28+
- Run `black .` and `flake8` before submitting.
29+
- Use Python **3.13.x** for local testing and formatting.
30+
31+
- **Testing**
32+
- Run `pytest` before pushing.
33+
- Ensure coverage isn’t regressing.
2334

2435
## 3. Pull Request Workflow
2536

2637
- **One logical change per PR.**
27-
- **Rebase or squash** before opening to keep history concise.
38+
- **Rebase or squash** before opening to keep history clean.
2839
- **Title & Description**
29-
- Title uses Conventional Commits style.
30-
- Description explains _what_ and _why_—keep context minimal.
40+
- Use Conventional Commit format.
41+
- Explain _what_ and _why_ concisely in the PR body.
3142

3243
## 4. Issue Reporting
3344

34-
- Search existing issues first.
35-
- Provide a minimal reproducible example and clear steps.
45+
- Search open issues before creating a new one.
46+
- Include clear steps to reproduce and environment details.
47+
- Prefer **focused** issues—don’t bundle multiple topics.
3648

3749
## 5. Automation & Checks
3850

39-
We enforce quality via CI on every push and PR:
51+
All PRs and pushes go through CI:
4052

41-
- **Commitlint** for commit‑message style
42-
- **Linters/Formatters**
43-
- **Unit tests**
53+
- **Commitlint** for commit style
54+
- **Black** for formatting
55+
- **flake8** for static checks
56+
- **pytest** with coverage
4457

45-
Failures must be fixed before review.
58+
PRs must pass all checks to be reviewed.
4659

4760
## 6. Code of Conduct & Support
4861

49-
- Please see `CODE_OF_CONDUCT.md` for behavioral expectations and reporting.
50-
- For quick questions or discussions, open an issue with the `discussion` label or mention a maintainer.
62+
- See `CODE_OF_CONDUCT.md` for guidelines and reporting.
63+
- For questions or planning, open an issue and use the `discussion` label, or mention a maintainer.
64+
65+
---
5166

52-
Thanks again for helping keep this project small, simple, and impactful!
67+
Thanks again for helping keep this project small, sharp, and focused.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
[![codecov](https://codecov.io/gh/nanotaboada/python-samples-fastapi-restful/branch/master/graph/badge.svg?token=A1WNZPRQEJ)](https://codecov.io/gh/nanotaboada/python-samples-fastapi-restful)
99
[![CodeFactor](https://www.codefactor.io/repository/github/nanotaboada/python-samples-fastapi-restful/badge)](https://www.codefactor.io/repository/github/nanotaboada/python-samples-fastapi-restful)
1010
[![codebeat badge](https://codebeat.co/badges/4c4f7c08-3b35-4b57-a875-bf2043efe515)](https://codebeat.co/projects/github-com-nanotaboada-python-samples-fastapi-restful-master)
11+
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
1112

1213
## About
1314

databases/player_database.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
The `STORAGE_PATH` environment variable controls the SQLite file location.
1010
"""
11+
1112
import logging
1213
import os
1314
from typing import AsyncGenerator
@@ -21,16 +22,11 @@
2122
logging.getLogger("sqlalchemy.engine.Engine").handlers = logger.handlers
2223

2324
async_engine = create_async_engine(
24-
DATABASE_URL,
25-
connect_args={"check_same_thread": False},
26-
echo=True
25+
DATABASE_URL, connect_args={"check_same_thread": False}, echo=True
2726
)
2827

2928
async_sessionmaker = sessionmaker(
30-
bind=async_engine,
31-
class_=AsyncSession,
32-
autocommit=False,
33-
autoflush=False
29+
bind=async_engine, class_=AsyncSession, autocommit=False, autoflush=False
3430
)
3531

3632
Base = declarative_base()

main.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
88
This serves as the entry point for running the API server.
99
"""
10+
1011
from contextlib import asynccontextmanager
1112
import logging
1213
from typing import AsyncIterator
@@ -17,6 +18,7 @@
1718
UVICORN_LOGGER = "uvicorn.error"
1819
logger = logging.getLogger(UVICORN_LOGGER)
1920

21+
2022
@asynccontextmanager
2123
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
2224
"""
@@ -25,10 +27,13 @@ async def lifespan(_: FastAPI) -> AsyncIterator[None]:
2527
logger.info("Lifespan event handler execution complete.")
2628
yield
2729

28-
app = FastAPI(lifespan=lifespan,
29-
title="python-samples-fastapi-restful",
30-
description="🧪 Proof of Concept for a RESTful API made with Python 3 and FastAPI",
31-
version="1.0.0",)
30+
31+
app = FastAPI(
32+
lifespan=lifespan,
33+
title="python-samples-fastapi-restful",
34+
description="🧪 Proof of Concept for a RESTful API made with Python 3 and FastAPI",
35+
version="1.0.0",
36+
)
3237

3338
app.include_router(player_route.api_router)
3439
app.include_router(health_route.api_router)

models/player_model.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
These models are used for data validation and serialization in the API.
88
"""
9+
910
from typing import Optional
1011
from pydantic import BaseModel, ConfigDict
1112
from pydantic.alias_generators import to_camel
@@ -22,8 +23,10 @@ class MainModel(BaseModel):
2223
model_config (ConfigDict): Configuration for Pydantic models, including:
2324
alias_generator (function): A function to generate field aliases.
2425
Here, it uses `to_camel` to convert field names to camelCase.
25-
populate_by_name (bool): Allows population of fields by name when using Pydantic models.
26+
populate_by_name (bool): Allows population of fields by name when using
27+
Pydantic models.
2628
"""
29+
2730
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
2831

2932

@@ -39,11 +42,14 @@ class PlayerModel(MainModel):
3942
date_of_birth (Optional[str]): The date of birth of the Player, if provided.
4043
squad_number (int): The unique squad number assigned to the Player.
4144
position (str): The playing position of the Player.
42-
abbr_position (Optional[str]): The abbreviated form of the Player's position, if any.
45+
abbr_position (Optional[str]): The abbreviated form of the Player's position,
46+
if any.
4347
team (Optional[str]): The team to which the Player belongs, if any.
4448
league (Optional[str]): The league where the team plays, if any.
45-
starting11 (Optional[bool]): Indicates if the Player is in the starting 11, if provided.
49+
starting11 (Optional[bool]): Indicates if the Player is in the starting 11,
50+
if provided.
4651
"""
52+
4753
id: int
4854
first_name: str
4955
middle_name: Optional[str]

pyproject.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[tool.black]
2+
line-length = 88
3+
target-version = ['py313']
4+
include = '\.pyi?$'
5+
exclude = '''
6+
/(
7+
\.git
8+
| \.github
9+
| \.pytest_cache
10+
| \.venv
11+
| \.vscode
12+
| assets
13+
| htmlcov
14+
| postman_collections
15+
| scripts
16+
| storage
17+
| __pycache__
18+
| tests/test_main\.py
19+
)/
20+
'''

0 commit comments

Comments
 (0)