plugins/python-engineering/skills/python3-packaging/SKILL.md
Configures pyproject.toml and Python packaging using PEP 517/518/621/660/723 standards. Use when creating or updating pyproject.toml, selecting a build backend (hatchling/setuptools/flit), configuring ruff, ty, mypy, pytest, or coverage tool sections, setting up dependency constraints or optional extras, defining CLI entry points, configuring pre-commit hooks, establishing src-layout directory structure, or preparing a package for PyPI publishing.
npx skillsauth add jamie-bitflight/claude_skills python3-packagingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
<project_path>$ARGUMENTS</project_path>
The model configures modern Python packaging using pyproject.toml and PEP standards.
<project_path/>
Consult ../python3-core/references/python3-standards.md when applying shared architecture, typing, testing, or CLI rules; full standards, graphs, and amendment process are documented there.
python3-standards.md, pytest, hatch/setuptools)| PEP | Standard | Description | | -------------------------------------------- | ------------------ | ------------------------------------ | | PEP 517 | Build system | Specifies build-backend interface | | PEP 518 | Build requirements | Specifies [build-system] table | | PEP 621 | Project metadata | Specifies [project] table | | PEP 660 | Editable installs | Specifies editable install mechanism | | PEP 723 | Inline metadata | For standalone scripts |
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-package"
version = "0.1.0"
description = "A brief description of the package"
readme = "README.md"
license = "MIT"
requires-python = ">=3.11"
authors = [
{ name = "Author Name", email = "[email protected]" }
]
keywords = ["keyword1", "keyword2"]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Typing :: Typed",
]
dependencies = [
"typer>=0.21.2",
"rich>=13.0.0",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0.0",
"pytest-cov>=4.0.0",
"pytest-mock>=3.12.0",
"pytest-asyncio>=0.23.0",
"ty>=0.0.0a1",
"ruff>=0.9.0",
]
# Type checker: ty is the default for new work. If the project uses mypy, replace ty with
# mypy>=1.8.0 here. See python3-standards.md for type checker selection guidance.
[project.scripts]
my-cli = "my_package.cli:app"
[project.urls]
Documentation = "https://github.com/user/my-package#readme"
Issues = "https://github.com/user/my-package/issues"
Source = "https://github.com/user/my-package"
# ============================================================================
# Tool Configuration
# ============================================================================
[tool.hatch.build.targets.wheel]
packages = ["src/my_package"]
[tool.ruff]
target-version = "py311"
line-length = 100
src = ["src", "tests"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # Pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
"ARG", # flake8-unused-arguments
"SIM", # flake8-simplify
"TCH", # flake8-type-checking
"PTH", # flake8-use-pathlib
"ERA", # eradicate (commented code)
"PL", # pylint
"RUF", # Ruff-specific rules
"ANN", # flake8-annotations
"D", # pydocstyle
"S", # flake8-bandit (security)
"T20", # flake8-print
]
ignore = [
"D100", # Missing docstring in public module
"D104", # Missing docstring in public package
"D107", # Missing docstring in __init__
"ANN101", # Missing type annotation for self
"ANN102", # Missing type annotation for cls
]
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["S101", "D", "ANN", "PLR2004"]
"scripts/**" = ["T201", "S"]
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_ignores = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_any_generics = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_configs = true
[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = [
"--strict-markers",
"--strict-config",
"-ra",
"-v",
]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
[tool.coverage.run]
source = ["src"]
branch = true
omit = ["tests/*"]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
"if __name__ == .__main__.:",
"raise NotImplementedError",
]
fail_under = 80
my-package/
├── pyproject.toml
├── README.md
├── LICENSE
├── .gitignore
├── .pre-commit-config.yaml
├── src/
│ └── my_package/
│ ├── __init__.py
│ ├── py.typed # PEP 561 marker
│ ├── cli.py
│ └── core.py
└── tests/
├── __init__.py
├── conftest.py
└── test_core.py
src/my_package/init.py:
"""My package description."""
from .core import main_function
__all__ = ["main_function"]
__version__ = "0.1.0"
src/my_package/py.typed:
# PEP 561 marker file - indicates this package has type hints
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/my_package"]
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
where = ["src"]
[build-system]
requires = ["flit_core>=3.4"]
build-backend = "flit_core.buildapi"
[tool.flit.module]
name = "my_package"
dependencies = [
# Minimum version
"requests>=2.28.0",
# Compatible release (2.28.x)
"requests~=2.28.0",
# Exact version (avoid in libraries)
"requests==2.28.0",
# Version range
"requests>=2.28.0,<3.0.0",
# With extras
"requests[security]>=2.28.0",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0.0",
"ruff>=0.9.0",
"ty>=0.0.0a1",
# Type checker: ty is the default. Replace with mypy>=1.8.0 if the project uses mypy.
# See python3-standards.md for type checker selection guidance.
]
docs = [
"mkdocs>=1.5.0",
"mkdocs-material>=9.0.0",
]
all = [
"my-package[dev,docs]",
]
[project.scripts]
my-cli = "my_package.cli:app"
my-other-cli = "my_package.other:main"
[project.gui-scripts]
my-gui = "my_package.gui:main"
[project.entry-points."my_package.plugins"]
plugin1 = "my_package.plugins.plugin1:Plugin1"
plugin2 = "my_package.plugins.plugin2:Plugin2"
.pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
# Type checker hook: ty is the default for new work.
# If the project uses mypy, replace this block with:
# - repo: https://github.com/pre-commit/mirrors-mypy
# rev: v1.8.0
# hooks:
# - id: mypy
# args: [--strict]
# See python3-standards.md for type checker selection guidance.
- repo: https://github.com/astral-sh/ty
rev: 0.0.0-alpha.11
hooks:
- id: ty
After configuration, verify the setup:
# Install in development mode
uv pip install -e ".[dev]"
# Run linters
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
# Type check — ty is default; use uv run mypy src/ if project hooks/CI run mypy
# Type checker selection: see python3-standards.md
uv run ty check src/
# Run tests
uv run pytest tests/ -v --cov=src
# Build package
uv build
# Check package metadata
uv run python -c "import my_package; print(my_package.__version__)"
Fix: Verify packages in hatch config or setuptools config:
[tool.hatch.build.targets.wheel]
packages = ["src/my_package"]
Fix: Add py.typed marker file:
touch src/my_package/py.typed
Fix: Verify entry point matches actual module path:
[project.scripts]
# Format: "command-name = module.path:function"
my-cli = "my_package.cli:app"
development
When an application needs to store config, data, cache, or state files. When designing where user-specific files should live. When code writes to ~/.appname or hardcoded home paths. When implementing cross-platform file storage with platformdirs.
testing
Enforce mandatory pre-action verification checkpoints to prevent pattern-matching from overriding explicit reasoning. Use this skill when about to execute implementation actions (Bash, Write, Edit) to verify hypothesis-action alignment. Blocks execution when hypothesis unverified or action targets different system than hypothesis identified. Critical for preventing cognitive dissonance where correct diagnosis leads to wrong implementation.
tools
Reference guide for the Twelve-Factor App methodology — 15 principles (12 original + 3 modern extensions) for building portable, resilient, cloud-native applications. Use when evaluating application architecture, designing cloud-native services, reviewing codebases for methodology compliance, advising on configuration, scaling, observability, security, and deployment patterns. Incorporates the 2025 open-source community evolution and cloud-native reinterpretations of each factor.
tools
Converts user-facing documentation (how-to guides, tutorials, API references, examples) in any format — Markdown, PDF, DOCX, PPTX, XLSX, AsciiDoc, RST, HTML, Jupyter notebooks, man pages, TOML/YAML/JSON configs, and plain text — into Claude Code skill directories with SKILL.md plus thematically grouped references/*.md files. Use when given a docs directory or mixed-format documentation to transform into an AI skill. Uses MCP file-reader server for binary formats.