FootyCollect maintains high code quality standards using modern Python tooling. All code is automatically checked for formatting, linting, and type errors.
Quick Reference
Format code
Lint code
Fix linting issues
Type checking
Run all checks
Ruff
Ruff is an extremely fast Python linter and formatter, replacing Black, isort, flake8, and more.
Ruff checks for code quality issues: # Check all files
ruff check .
# Fix auto-fixable issues
ruff check . --fix
# Show fixes without applying
ruff check . --diff
Enabled rule sets:
F - Pyflakes
E, W - pycodestyle
I - isort (import sorting)
N - pep8-naming
UP - pyupgrade
S - flake8-bandit (security)
B - flake8-bugbear
DJ - flake8-django
PT - flake8-pytest-style
PL - Pylint
RUF - Ruff-specific rules
And many more! See pyproject.toml for the full list.
Some rules are disabled for specific files: [ tool . ruff . lint . per-file-ignores ]
# Ignore in test files
" **/tests/**/*.py " = [ "SLF001" , "S105" , "S106" ]
" **/test_*.py " = [ "SLF001" , "S105" , "S106" ]
# Ignore in settings
" config/settings/*.py " = [ "F403" ]
# Ignore in complex E2E tests
" footycollect/collection/tests/test_e2e_*.py " = [
"PT009" ,
"FBT003" ,
"BLE001" ,
"PLR0915" ,
]
mypy
Static type checker for Python:
# Type check the entire project
mypy footycollect
# Type check specific app
mypy footycollect/collection
# Type check with verbose output
mypy footycollect --verbose
Configuration
[ tool . mypy ]
python_version = "3.12"
check_untyped_defs = true
ignore_missing_imports = true
warn_unused_ignores = true
warn_redundant_casts = true
warn_unused_configs = true
plugins = [
"mypy_django_plugin.main" ,
"mypy_drf_plugin.main" ,
]
[[ tool . mypy . overrides ]]
# Django migrations should not produce errors
module = "*.migrations.*"
ignore_errors = true
[ tool . django-stubs ]
django_settings_module = "config.settings.test"
mypy uses Django-specific plugins (mypy_django_plugin and mypy_drf_plugin) to understand Django models and DRF serializers.
Pre-commit Hooks
Pre-commit hooks automatically run checks before each commit:
Setup
Run manually (optional)
# Run on all files
pre-commit run --all-files
# Run on staged files only
pre-commit run
From .pre-commit-config.yaml:
- trailing-whitespace # Remove trailing whitespace
- end-of-file-fixer # Ensure files end with newline
- check-json # Validate JSON files
- check-toml # Validate TOML files
- check-yaml # Validate YAML files
- debug-statements # Detect debug statements
- check-builtin-literals # Check builtin type constructor use
- check-case-conflict # Check for case conflicts
- check-docstring-first # Check docstring position
- detect-private-key # Detect private keys
Automatically upgrade Django code to target version: - repo : https://github.com/adamchainz/django-upgrade
rev : '1.20.0'
hooks :
- id : django-upgrade
args : [ '--target-version' , '5.0' ]
- repo : https://github.com/astral-sh/ruff-pre-commit
rev : v0.6.2
hooks :
# Linter
- id : ruff
args : [ --fix , --exit-non-zero-on-fix ]
# Formatter
- id : ruff-format
Formats and lints Django templates: - repo : https://github.com/Riverside-Healthcare/djLint
rev : v1.34.1
hooks :
- id : djlint-reformat-django
files : ^footycollect/.*\.html$
- id : djlint-django
files : ^footycollect/.*\.html$
Code Quality Standards
Line Length
Maximum line length is 119 characters for code and comments.
Import Sorting
Ruff automatically sorts imports (replaces isort):
# Standard library
import os
import sys
# Third-party
import requests
from django.conf import settings
# Local
from footycollect.collection.models import Jersey
from footycollect.core.models import Club
Naming Conventions
Classes: PascalCase
Functions/methods: snake_case
Constants: UPPER_SNAKE_CASE
Private methods: _leading_underscore
Django Best Practices
Ruff includes Django-specific rules (DJ rules):
DJ001 - Avoid using null=True on string-based fields
DJ006 - Do not use exclude in ModelForm
DJ008 - Model does not define __str__ method
And more!
Security
Ruff includes security checks from Bandit (S rules):
S105 - Hardcoded password string
S106 - Hardcoded password function argument
S108 - Hardcoded /tmp directory
S301 - Pickle usage
Security warnings should be carefully reviewed, not blindly ignored.
CI/CD Integration
Code quality checks run automatically on GitHub Actions:
.github/workflows/ci.yml (example)
- name : Lint with Ruff
run : ruff check .
- name : Check formatting
run : ruff format . --check
- name : Type check with mypy
run : mypy footycollect
All checks must pass before code can be merged.
IDE Integration
VS Code
Install the Ruff extension:
{
"[python]" : {
"editor.defaultFormatter" : "charliermarsh.ruff" ,
"editor.formatOnSave" : true ,
"editor.codeActionsOnSave" : {
"source.fixAll" : true ,
"source.organizeImports" : true
}
},
"ruff.lint.args" : [ "--config=pyproject.toml" ],
"mypy-type-checker.args" : [ "--config-file=pyproject.toml" ]
}
PyCharm
Configure external tools for Ruff and mypy:
Add Ruff as External Tool
Settings → Tools → External Tools → Add
Program: ruff
Arguments: check . --fix
Configure mypy
Settings → Tools → Python Integrated Tools
Running All Quality Checks
Before committing, run all checks:
# Activate virtual environment
source venv/bin/activate # or: venv\Scripts\activate on Windows
# Format code
ruff format .
# Lint and fix
ruff check . --fix
# Type check
mypy footycollect
# Run tests
pytest
Or use pre-commit:
pre-commit run --all-files
Next Steps