All skills
github avatar

/python-pypi-package-builder

@49fd3f3 official
by githubgithub/awesome-copilot40k stars
5,040

End-to-end skill for building, testing, linting, versioning, and publishing a production-grade Python library to PyPI. Covers all four build backends (setuptools+setuptools_scm, hatchling, flit, poetry), PEP 440 versioning, semantic versioning, dynamic git-tag versioning, OOP/SOLID design, type hints (PEP 484/526/544/561), Trusted Publishing (OIDC), and the full PyPA packaging flow. Use for: creating Python packages, pip-installable SDKs, CLI tools, framework plugins, pyproject.toml setup, py.typed, setuptools_scm, semver, mypy, pre-commit, GitHub Actions CI/CD, or PyPI publishing.

Use this Skill: https://skilld.dev/gh/github/awesome-copilot/python-pypi-package-builder

This session only. Nothing lands on disk.

referencestooling-ruff.md

≈2.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Tooling — Ruff-Only Setup and Code Quality

Table of Contents

  1. Use Only Ruff (Replaces black, isort, flake8)
  2. Ruff Configuration in pyproject.toml
  3. mypy Configuration
  4. pre-commit Configuration
  5. pytest and Coverage Configuration
  6. Dev Dependencies in pyproject.toml
  7. CI Lint Job — Ruff Only
  8. Migration Guide — Removing black and isort

1. Use Only Ruff (Replaces black, isort, flake8)

Decision: Use ruff as the single linting and formatting tool. Remove black and isort.

Old (avoid) New (use) What it does
black ruff format Code formatting
isort ruff check --select I Import sorting
flake8 ruff check Style and error linting
pyupgrade ruff check --select UP Upgrade syntax to modern Python
bandit ruff check --select S Security linting
All of the above ruff One tool, one config section

Why ruff?

  • 10–100× faster than the tools it replaces (written in Rust).
  • Single config section in pyproject.toml — no .flake8, .isort.cfg, pyproject.toml[tool.black] sprawl.
  • Actively maintained by Astral; follows the same rules as the tools it replaces.
  • ruff format is black-compatible — existing black-formatted code passes without changes.

2. Ruff Configuration in pyproject.toml

[tool.ruff]
target-version = "py310"        # Minimum supported Python version
line-length    = 88             # black-compatible default
src            = ["src", "tests"]

[tool.ruff.lint]
select = [
    "E",   # pycodestyle errors
    "W",   # pycodestyle warnings
    "F",   # pyflakes
    "I",   # isort
    "B",   # flake8-bugbear (opinionated but very useful)
    "C4",  # flake8-comprehensions
    "UP",  # pyupgrade (modernise syntax)
    "SIM", # flake8-simplify
    "TCH", # flake8-type-checking (move imports to TYPE_CHECKING block)
    "ANN", # flake8-annotations (enforce type hints — remove if too strict)
    "S",   # flake8-bandit (security)
    "N",   # pep8-naming
]
ignore = [
    "ANN101",  # Missing type annotation for `self`
    "ANN102",  # Missing type annotation for `cls`
    "S101",    # Use of `assert` — necessary in tests
    "S603",    # subprocess without shell=True — often intentional
    "B008",    # Do not perform function calls in default arguments (false positives in FastAPI/Typer)
]

[tool.ruff.lint.isort]
known-first-party = ["your_package"]

[tool.ruff.lint.per-file-ignores]
"tests/**" = ["S101", "ANN", "D"]   # Allow assert and skip annotations/docstrings in tests

[tool.ruff.format]
quote-style              = "double"   # black-compatible
indent-style             = "space"
skip-magic-trailing-comma = false
line-ending              = "auto"

Useful ruff commands

# Check for lint issues (no changes)
ruff check .

# Auto-fix fixable issues
ruff check --fix .

# Format code (replaces black)
ruff format .

# Check formatting without changing files (CI mode)
ruff format --check .

# Run both lint and format check in one command (for CI)
ruff check . && ruff format --check .

3. mypy Configuration

[tool.mypy]
python_version          = "3.10"
strict                  = true
warn_return_any         = true
warn_unused_ignores     = true
warn_redundant_casts    = true
disallow_untyped_defs   = true
disallow_incomplete_defs = true
check_untyped_defs      = true
no_implicit_optional    = true
show_error_codes        = true

# Ignore missing stubs for third-party packages that don't ship types
[[tool.mypy.overrides]]
module = ["redis.*", "pydantic_settings.*"]
ignore_missing_imports = true

Running mypy — handle both src and flat layouts

# src layout:
mypy src/your_package/

# flat layout:
mypy your_package/

In CI, detect layout dynamically:

- name: Run mypy
  run: |
    if [ -d "src" ]; then
        mypy src/
    else
        mypy your_package/
    fi

4. pre-commit Configuration

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.4.4    # Pin to a specific release; update periodically with `pre-commit autoupdate`
    hooks:
      - id: ruff
        args: [--fix]       # Auto-fix what can be fixed
      - id: ruff-format     # Format (replaces black hook)

  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.10.0
    hooks:
      - id: mypy
        additional_dependencies:
          - types-requests
          - types-redis
          # Add stubs for any typed dependency used in your package

  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-toml
      - id: check-yaml
      - id: check-merge-conflict
      - id: check-added-large-files
        args: ["--maxkb=500"]

❌ Remove these hooks (replaced by ruff)

# DELETE or never add:
- repo: https://github.com/psf/black           # replaced by ruff-format
- repo: https://github.com/PyCQA/isort          # replaced by ruff lint I rules
- repo: https://github.com/PyCQA/flake8         # replaced by ruff check
- repo: https://github.com/PyCQA/autoflake      # replaced by ruff check F401

Setup

pip install pre-commit
pre-commit install     # Installs git hook — runs on every commit
pre-commit run --all-files  # Run manually on all files
pre-commit autoupdate  # Update all hooks to latest pinned versions

5. pytest and Coverage Configuration

[tool.pytest.ini_options]
testpaths    = ["tests"]
addopts      = "-ra -q --strict-markers --cov=your_package --cov-report=term-missing"
asyncio_mode = "auto"    # Enables async tests without @pytest.mark.asyncio decorator

[tool.coverage.run]
source   = ["your_package"]
branch   = true
omit     = ["**/__main__.py", "**/cli.py"]  # omit entry points from coverage

[tool.coverage.report]
show_missing   = true
skip_covered   = false
fail_under     = 85        # Fail CI if coverage drops below 85%
exclude_lines  = [
    "pragma: no cover",
    "if TYPE_CHECKING:",
    "raise NotImplementedError",
    "@abstractmethod",
]

asyncio_mode = "auto" — remove @pytest.mark.asyncio

With asyncio_mode = "auto" set in pyproject.toml, do not add @pytest.mark.asyncio to test functions. The decorator is redundant and will raise a warning in modern pytest-asyncio.

# WRONG — the decorator is deprecated when asyncio_mode = "auto":
@pytest.mark.asyncio
async def test_async_operation():
    result = await my_async_func()
    assert result == expected

# CORRECT — just use async def:
async def test_async_operation():
    result = await my_async_func()
    assert result == expected

6. Dev Dependencies in pyproject.toml

Declare all dev/test tools in an [extras] group named dev.

[project.optional-dependencies]
dev = [
    "pytest>=8",
    "pytest-asyncio>=0.23",
    "pytest-cov>=5",
    "ruff>=0.4",
    "mypy>=1.10",
    "pre-commit>=3.7",
    "httpx>=0.27",       # If testing HTTP transport
    "respx>=0.21",       # If mocking httpx in tests
]
redis = [
    "redis>=5",
]
docs = [
    "mkdocs-material>=9",
    "mkdocstrings[python]>=0.25",
]

Install dev dependencies:

pip install -e ".[dev]"
pip install -e ".[dev,redis]"   # Include optional extras

7. CI Lint Job — Ruff Only

Replace the separate black, isort, and flake8 steps with a single ruff step.

# .github/workflows/ci.yml  — lint job
lint:
  name: Lint & Type Check
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - uses: actions/setup-python@v5
      with:
        python-version: "3.11"

    - name: Install dev dependencies
      run: pip install -e ".[dev]"

    # Single step: ruff replaces black + isort + flake8
    - name: ruff lint
      run: ruff check .

    - name: ruff format check
      run: ruff format --check .

    - name: mypy
      run: |
        if [ -d "src" ]; then
            mypy src/
        else
            mypy $(basename $(ls -d */))/ 2>/dev/null || mypy .
        fi

8. Migration Guide — Removing black and isort

If you are converting an existing project that used black and isort:

# 1. Remove black and isort from dev dependencies
pip uninstall black isort

# 2. Remove black and isort config sections from pyproject.toml
# [tool.black]  ← delete this section
# [tool.isort]  ← delete this section

# 3. Add ruff to dev dependencies (see Section 2 for config)

# 4. Run ruff format to confirm existing code is already compatible
ruff format --check .
# ruff format is black-compatible; output should be identical

# 5. Update .pre-commit-config.yaml (see Section 4)
# Remove black and isort hooks; add ruff and ruff-format hooks

# 6. Update CI (see Section 7)
# Remove black, isort, flake8 steps; add ruff check + ruff format --check

# 7. Reinstall pre-commit hooks
pre-commit uninstall
pre-commit install
pre-commit run --all-files   # Verify clean

Source: SKILL.md on GitHub

No alerts10d4 checks · Risk SAFE
  • Gen Agent Trust Hub10d

    This skill provides a comprehensive and secure framework for building, testing, and publishing Python packages following industry best practices. It incorporates secure publishing via OpenID Connect (OIDC), uses modern and efficient tooling like Ruff, and provides a local scaffolding script that follows standard templating procedures. All external references and dependencies target well-known and trusted organizations within the Python and GitHub ecosystems.

  • Socket10d

    No alerts

  • Snyk10d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 49fd3f3. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 6 months ago
  • Python
  • pypi
  • packaging
  • setuptools
  • hatchling
  • flit
  • poetry
  • versioning
  • ci-cd
  • github-actions

README badge

README badge for github/awesome-copilot/python-pypi-package-builder

Covers the full PyPI publishing pipeline for Python packages: build backend selection (setuptools+setuptools_scm, hatchling, flit, poetry), project structure (src/ vs flat), type hints, testing, versioning (PEP 440 / semver / git-tag), and GitHub Actions CI/CD with Trusted Publishing. Targets teams building pip-installable libraries, SDKs, CLI tools, or framework plugins.

Generated from the current SKILL.md.

Which build backend should I use?
Use setuptools + setuptools_scm if you want version derived from git tags. Use hatchling or flit for pure-Python projects without git-tag versioning. Use poetry v2+ if you want an all-in-one tool. Use setuptools only if you have C/Cython extensions.
Does this skill support publishing with Trusted Publishing (OIDC)?
Yes. The skill covers Trusted Publishing setup in the CI/publishing workflow references and includes GitHub Actions templates for OIDC-based PyPI publishing.
What folder structure should I use for a new package?
Use src/ layout as the default for new projects — it prevents accidental imports of uninstalled code and is PyPA-recommended. Use flat layout only for single-purpose packages with 1–4 modules.
Does this cover type hints and mypy configuration?
Yes. The skill includes PEP 484/526/544/561 type hint patterns, py.typed marker file setup, and complete mypy configuration in the testing and quality reference.
Can I use this skill for CLI tools, SDKs, and plugins?
Yes. The skill covers all package types including utility libraries, API clients/SDKs, CLI tools, framework plugins, and data processing libraries, with patterns and entry-point configuration for each.

Generated from the current SKILL.md. These answers refresh after source changes.