feat(@configs/python): add shared Python tooling configurations
Provides standardized configs for ruff, mypy, and pytest. - ruff.toml: linting + formatting (100 char, E/F/I/N/W/UP/B/C4/SIM/RUF/PTH/ERA) - mypy.ini: strict type checking - pytest.ini: auto async, strict markers Usage: extend = ".venv/.../tqftw_python_configs/ruff.toml" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
commit
56af66b24e
7 changed files with 492 additions and 0 deletions
51
.gitignore
vendored
Normal file
51
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Virtual environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Testing
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
htmlcov/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
|
||||
# Distribution
|
||||
*.manifest
|
||||
*.spec
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
161
README.md
Normal file
161
README.md
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
# tqftw-python-configs
|
||||
|
||||
Shared Python tooling configurations for all TQFTW projects. Provides standardized, opinionated configurations for:
|
||||
|
||||
- **ruff** - Linting and formatting (replaces black, isort, flake8)
|
||||
- **mypy** - Type checking
|
||||
- **pytest** - Testing
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install tqftw-python-configs
|
||||
```
|
||||
|
||||
Or with uv:
|
||||
|
||||
```bash
|
||||
uv add tqftw-python-configs --dev
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Ruff Configuration
|
||||
|
||||
Ruff supports extending external configurations. Add to your `pyproject.toml`:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
extend = ".venv/lib/python3.11/site-packages/tqftw_python_configs/ruff.toml"
|
||||
```
|
||||
|
||||
Or use the helper to get the path programmatically:
|
||||
|
||||
```python
|
||||
from tqftw_python_configs import get_ruff_config_path
|
||||
|
||||
print(get_ruff_config_path())
|
||||
# /path/to/.venv/lib/python3.11/site-packages/tqftw_python_configs/ruff.toml
|
||||
```
|
||||
|
||||
**Override specific settings** while inheriting the base:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
extend = ".venv/lib/python3.11/site-packages/tqftw_python_configs/ruff.toml"
|
||||
line-length = 120 # Override: use 120 instead of 100
|
||||
|
||||
[tool.ruff.lint]
|
||||
extend-select = ["ANN"] # Add: type annotation checks
|
||||
```
|
||||
|
||||
### MyPy Configuration
|
||||
|
||||
MyPy doesn't support extending external configs. Copy the settings to your `pyproject.toml`:
|
||||
|
||||
```toml
|
||||
[tool.mypy]
|
||||
python_version = "3.10"
|
||||
strict = true
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
warn_unreachable = true
|
||||
show_error_codes = true
|
||||
show_column_numbers = true
|
||||
incremental = true
|
||||
|
||||
[tool.mypy.overrides]
|
||||
module = "tests.*"
|
||||
disallow_untyped_defs = false
|
||||
```
|
||||
|
||||
Or copy `mypy.ini` to your project root:
|
||||
|
||||
```python
|
||||
from tqftw_python_configs import get_mypy_config_path
|
||||
import shutil
|
||||
|
||||
shutil.copy(get_mypy_config_path(), "mypy.ini")
|
||||
```
|
||||
|
||||
### Pytest Configuration
|
||||
|
||||
Copy the pytest settings to your `pyproject.toml`:
|
||||
|
||||
```toml
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py"]
|
||||
python_classes = ["Test*"]
|
||||
python_functions = ["test_*"]
|
||||
asyncio_mode = "auto"
|
||||
addopts = "-v --tb=short --strict-markers --strict-config"
|
||||
filterwarnings = [
|
||||
"error",
|
||||
"ignore::DeprecationWarning",
|
||||
]
|
||||
markers = [
|
||||
"slow: marks tests as slow",
|
||||
"integration: marks tests as integration tests",
|
||||
]
|
||||
```
|
||||
|
||||
## What's Included
|
||||
|
||||
### Ruff Rules
|
||||
|
||||
The ruff configuration enables:
|
||||
|
||||
| Category | Rules | Purpose |
|
||||
|----------|-------|---------|
|
||||
| Core | E, F, W | pycodestyle errors/warnings, pyflakes |
|
||||
| Imports | I | isort-style import sorting |
|
||||
| Quality | N, UP, B, C4, SIM | naming, upgrades, bugs, comprehensions |
|
||||
| Hygiene | RUF, PTH, ERA | ruff-specific, pathlib, dead code |
|
||||
|
||||
### Formatting
|
||||
|
||||
- Line length: 100 characters
|
||||
- Double quotes
|
||||
- Space indentation
|
||||
- Docstring code formatting enabled
|
||||
|
||||
### Type Checking (MyPy)
|
||||
|
||||
- Strict mode enabled
|
||||
- All strict flags explicitly listed for transparency
|
||||
- Test files have relaxed typing requirements
|
||||
|
||||
### Testing (Pytest)
|
||||
|
||||
- Auto async mode (pytest-asyncio)
|
||||
- Verbose output with short tracebacks
|
||||
- Strict markers and config
|
||||
- Common markers pre-registered (slow, integration, unit)
|
||||
|
||||
## API Reference
|
||||
|
||||
```python
|
||||
from tqftw_python_configs import (
|
||||
__version__,
|
||||
get_config_dir,
|
||||
get_ruff_config_path,
|
||||
get_mypy_config_path,
|
||||
get_pytest_config_path,
|
||||
)
|
||||
|
||||
# Get package version
|
||||
print(__version__) # "1.0.0"
|
||||
|
||||
# Get config directory
|
||||
print(get_config_dir()) # Path to package directory
|
||||
|
||||
# Get individual config paths
|
||||
print(get_ruff_config_path()) # Path to ruff.toml
|
||||
print(get_mypy_config_path()) # Path to mypy.ini
|
||||
print(get_pytest_config_path()) # Path to pytest.ini
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
38
pyproject.toml
Normal file
38
pyproject.toml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "tqftw-python-configs"
|
||||
version = "1.0.0"
|
||||
description = "Shared Python tooling configurations for ruff, mypy, and pytest"
|
||||
requires-python = ">=3.10"
|
||||
license = "MIT"
|
||||
authors = [{ name = "transquinnftw", email = "dev@transquinnftw.com" }]
|
||||
keywords = ["ruff", "mypy", "pytest", "linting", "config", "formatting"]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
"Topic :: Software Development :: Testing",
|
||||
"Typing :: Typed",
|
||||
]
|
||||
readme = "README.md"
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = ["build>=1.0.0", "twine>=5.0.0"]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/tqftw_python_configs"]
|
||||
|
||||
[tool.hatch.build.targets.sdist]
|
||||
include = ["/src", "/README.md"]
|
||||
|
||||
[tool.tqftw]
|
||||
registry = "forgejo"
|
||||
78
src/tqftw_python_configs/__init__.py
Normal file
78
src/tqftw_python_configs/__init__.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
tqftw-python-configs: Shared Python tooling configurations.
|
||||
|
||||
Provides standardized configurations for:
|
||||
- ruff (linting + formatting)
|
||||
- mypy (type checking)
|
||||
- pytest (testing)
|
||||
|
||||
Usage:
|
||||
from tqftw_python_configs import get_ruff_config_path, get_mypy_config_path
|
||||
|
||||
# Get path to bundled ruff.toml
|
||||
ruff_path = get_ruff_config_path()
|
||||
|
||||
# Use in pyproject.toml:
|
||||
# [tool.ruff]
|
||||
# extend = ".venv/lib/python3.11/site-packages/tqftw_python_configs/ruff.toml"
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
__version__: Final[str] = "1.0.0"
|
||||
__all__ = [
|
||||
"__version__",
|
||||
"get_ruff_config_path",
|
||||
"get_mypy_config_path",
|
||||
"get_pytest_config_path",
|
||||
"get_config_dir",
|
||||
]
|
||||
|
||||
|
||||
def get_config_dir() -> Path:
|
||||
"""Get the directory containing all config files."""
|
||||
return Path(__file__).parent
|
||||
|
||||
|
||||
def get_ruff_config_path() -> Path:
|
||||
"""
|
||||
Get the path to the bundled ruff.toml configuration.
|
||||
|
||||
Returns:
|
||||
Path to ruff.toml that can be used with ruff's extend feature.
|
||||
|
||||
Example:
|
||||
>>> from tqftw_python_configs import get_ruff_config_path
|
||||
>>> config_path = get_ruff_config_path()
|
||||
>>> print(f"extend = '{config_path}'")
|
||||
"""
|
||||
return get_config_dir() / "ruff.toml"
|
||||
|
||||
|
||||
def get_mypy_config_path() -> Path:
|
||||
"""
|
||||
Get the path to the bundled mypy.ini configuration.
|
||||
|
||||
Returns:
|
||||
Path to mypy.ini for reference or copying.
|
||||
|
||||
Note:
|
||||
MyPy doesn't support extending external configs directly.
|
||||
Copy the contents or symlink the file to your project.
|
||||
"""
|
||||
return get_config_dir() / "mypy.ini"
|
||||
|
||||
|
||||
def get_pytest_config_path() -> Path:
|
||||
"""
|
||||
Get the path to the bundled pytest.ini configuration.
|
||||
|
||||
Returns:
|
||||
Path to pytest.ini for reference or copying.
|
||||
|
||||
Note:
|
||||
Pytest doesn't support extending external configs directly.
|
||||
Copy the contents to your pyproject.toml [tool.pytest.ini_options].
|
||||
"""
|
||||
return get_config_dir() / "pytest.ini"
|
||||
50
src/tqftw_python_configs/mypy.ini
Normal file
50
src/tqftw_python_configs/mypy.ini
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# tqftw-python-configs: MyPy Configuration
|
||||
# Type checking for all TQFTW Python projects
|
||||
#
|
||||
# Usage in pyproject.toml:
|
||||
# [tool.mypy]
|
||||
# # Copy these settings or reference via extends (if supported)
|
||||
#
|
||||
# Or copy this file to your project root as mypy.ini
|
||||
|
||||
[mypy]
|
||||
python_version = 3.10
|
||||
strict = true
|
||||
|
||||
# Strict mode enables these (documented for reference):
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
disallow_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
check_untyped_defs = true
|
||||
no_implicit_optional = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
disallow_any_generics = true
|
||||
disallow_subclassing_any = true
|
||||
disallow_untyped_calls = true
|
||||
disallow_untyped_decorators = true
|
||||
no_implicit_reexport = true
|
||||
strict_equality = true
|
||||
strict_concatenate = true
|
||||
|
||||
# Additional strictness
|
||||
warn_unreachable = true
|
||||
show_error_codes = true
|
||||
show_column_numbers = true
|
||||
|
||||
# Performance
|
||||
incremental = true
|
||||
cache_dir = .mypy_cache
|
||||
|
||||
# Third-party library handling
|
||||
ignore_missing_imports = false
|
||||
follow_imports = normal
|
||||
|
||||
# Per-module overrides for common patterns
|
||||
[mypy-tests.*]
|
||||
disallow_untyped_defs = false
|
||||
disallow_untyped_decorators = false
|
||||
|
||||
[mypy-conftest]
|
||||
disallow_untyped_defs = false
|
||||
45
src/tqftw_python_configs/pytest.ini
Normal file
45
src/tqftw_python_configs/pytest.ini
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# tqftw-python-configs: Pytest Configuration
|
||||
# Testing configuration for all TQFTW Python projects
|
||||
#
|
||||
# Usage: Copy to your project root as pytest.ini
|
||||
# Or reference in pyproject.toml:
|
||||
# [tool.pytest.ini_options]
|
||||
# # Copy these settings
|
||||
|
||||
[pytest]
|
||||
testpaths = tests
|
||||
python_files = test_*.py
|
||||
python_classes = Test*
|
||||
python_functions = test_*
|
||||
|
||||
# Async support (pytest-asyncio)
|
||||
asyncio_mode = auto
|
||||
asyncio_default_fixture_loop_scope = function
|
||||
|
||||
# Output configuration
|
||||
addopts =
|
||||
-v
|
||||
--tb=short
|
||||
--strict-markers
|
||||
--strict-config
|
||||
|
||||
# Warnings configuration
|
||||
filterwarnings =
|
||||
error
|
||||
ignore::DeprecationWarning
|
||||
ignore::PendingDeprecationWarning
|
||||
|
||||
# Markers (register custom markers here)
|
||||
markers =
|
||||
slow: marks tests as slow (deselect with '-m "not slow"')
|
||||
integration: marks tests as integration tests
|
||||
unit: marks tests as unit tests
|
||||
|
||||
# Minimum pytest version
|
||||
minversion = 7.0
|
||||
|
||||
# Logging
|
||||
log_cli = false
|
||||
log_cli_level = INFO
|
||||
log_cli_format = %(asctime)s [%(levelname)8s] %(name)s: %(message)s
|
||||
log_cli_date_format = %Y-%m-%d %H:%M:%S
|
||||
69
src/tqftw_python_configs/ruff.toml
Normal file
69
src/tqftw_python_configs/ruff.toml
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# tqftw-python-configs: Ruff Configuration
|
||||
# Linting and formatting for all TQFTW Python projects
|
||||
#
|
||||
# Usage in pyproject.toml:
|
||||
# [tool.ruff]
|
||||
# extend = ".venv/lib/python3.11/site-packages/tqftw_python_configs/ruff.toml"
|
||||
#
|
||||
# Or use the helper:
|
||||
# from tqftw_python_configs import get_ruff_config_path
|
||||
# print(get_ruff_config_path())
|
||||
|
||||
line-length = 100
|
||||
target-version = "py310"
|
||||
|
||||
[lint]
|
||||
select = [
|
||||
# Core rules (always enabled)
|
||||
"E", # pycodestyle errors
|
||||
"F", # pyflakes
|
||||
"W", # pycodestyle warnings
|
||||
|
||||
# Import organization
|
||||
"I", # isort
|
||||
|
||||
# Code quality
|
||||
"N", # pep8-naming
|
||||
"UP", # pyupgrade (Python version upgrades)
|
||||
"B", # flake8-bugbear (common bugs)
|
||||
"C4", # flake8-comprehensions
|
||||
"SIM", # flake8-simplify
|
||||
|
||||
# Ruff-specific
|
||||
"RUF", # ruff-specific rules
|
||||
|
||||
# Path handling
|
||||
"PTH", # flake8-use-pathlib
|
||||
|
||||
# Code hygiene
|
||||
"ERA", # eradicate (commented-out code)
|
||||
]
|
||||
|
||||
ignore = [
|
||||
"E501", # Line too long (handled by formatter)
|
||||
]
|
||||
|
||||
[lint.per-file-ignores]
|
||||
"tests/**/*.py" = [
|
||||
"S101", # Allow assert in tests
|
||||
]
|
||||
"__init__.py" = [
|
||||
"F401", # Allow unused imports in __init__.py (re-exports)
|
||||
]
|
||||
|
||||
[lint.isort]
|
||||
known-first-party = ["tqftw_*"]
|
||||
combine-as-imports = true
|
||||
force-wrap-aliases = true
|
||||
force-single-line = false
|
||||
lines-after-imports = 2
|
||||
|
||||
[lint.pep8-naming]
|
||||
classmethod-decorators = ["classmethod", "pydantic.validator", "pydantic.field_validator"]
|
||||
|
||||
[format]
|
||||
quote-style = "double"
|
||||
indent-style = "space"
|
||||
skip-magic-trailing-comma = false
|
||||
line-ending = "auto"
|
||||
docstring-code-format = true
|
||||
Loading…
Add table
Reference in a new issue