9.3 KiB
name, description
| name | description |
|---|---|
| python-pypi-setup | Set up Python project for PyPI publishing with pyproject.toml, src layout, and build scripts |
Python PyPI Project Setup Pattern
This skill helps you set up a Python project for PyPI publishing following modern best practices with pyproject.toml, src layout, and standardized build/publish scripts.
When to Use This Skill
Use this skill when:
- Starting a new Python package for PyPI distribution
- You want to use modern pyproject.toml-based configuration
- You need a standardized src/ layout with explicit package discovery
- You want automated build and publish scripts
What This Skill Creates
pyproject.toml- Modern Python project configurationsrc/{package_name}/- Source layout with package structure.gitignore- Comprehensive Python gitignoredev-requirements.txt- Development dependencies (build, twine, testing tools)build-publish.sh- Automated build and publish scriptREADME.md- Basic project documentation
Step 1: Gather Project Information
IMPORTANT: Before creating files, ask the user these questions:
-
"What is your project name?" (e.g., "pg-podcast-toolkit", "mypackage")
- Use this to derive:
- PyPI package name:
{project-name}(with hyphens, e.g.,pg-podcast-toolkit) - Python package name:
{package_name}(with underscores, e.g.,pg_podcast_toolkit) - Module directory:
src/{package_name}/
- PyPI package name:
- Use this to derive:
-
"What is the project description?" (brief one-line description for PyPI)
-
"What is your name?" (for author field)
-
"What is your email?" (for author field)
-
"What is your GitHub username?" (for project URLs)
-
"What license do you want to use?" (options: MIT, Apache-2.0, GPL-3.0, BSD-3-Clause)
-
"What Python version should be the minimum requirement?" (default: 3.8)
-
"What are your initial dependencies?" (optional - comma-separated list, can be empty)
-
"What keywords describe your project?" (optional - for PyPI searchability)
Step 2: Create Directory Structure
Create these directories if they don't exist:
{project_root}/
├── src/
│ └── {package_name}/
└── (other files at root)
Step 3: Create pyproject.toml
Create pyproject.toml with the following structure, substituting project-specific values:
[project]
name = "{project-name}"
version = "0.0.1"
authors = [
{ name="{author_name}", email="{author_email}" },
]
description = "{project_description}"
keywords = [{keywords_list}]
readme = "README.md"
requires-python = ">={python_version}"
license = {text = "{license_name} License"}
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: {license_classifier}",
"Operating System :: OS Independent",
]
dependencies = [
{dependencies_list}
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/{package_name}"]
[project.urls]
Homepage = "https://github.com/{github_username}/{project-name}"
Issues = "https://github.com/{github_username}/{project-name}/issues"
CRITICAL Substitutions:
{project-name}→ project name with hyphens (e.g.,pg-podcast-toolkit){package_name}→ package name with underscores (e.g.,pg_podcast_toolkit){author_name}→ author's name{author_email}→ author's email{project_description}→ one-line description{keywords_list}→ comma-separated quoted keywords (e.g.,"podcasting", "rss", "parser") or empty{python_version}→ minimum Python version (e.g.,3.8){license_name}→ license name (e.g.,MIT,Apache-2.0){license_classifier}→ OSI classifier (e.g.,MIT License,Apache Software License){dependencies_list}→ comma-separated quoted dependencies (e.g.,'requests', 'beautifulsoup4') or empty{github_username}→ GitHub username
License Classifiers Mapping:
- MIT →
MIT License - Apache-2.0 →
Apache Software License - GPL-3.0 →
GNU General Public License v3 (GPLv3) - BSD-3-Clause →
BSD License
Step 4: Create Comprehensive .gitignore
Create .gitignore with comprehensive Python patterns:
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
*.manifest
*.spec
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
Pipfile.lock
# PEP 582
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
bin/
include/
pyvenv.cfg
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# IDEs
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
Step 5: Create dev-requirements.txt
Create dev-requirements.txt with development dependencies:
build
twine
pytest
black
mypy
These are the tools needed to build, publish, and develop the package. Add other dev tools as needed (isort, pytest-cov, etc.).
Step 6: Create build-publish.sh
Create build-publish.sh with venv activation and build/publish commands:
#!/bin/bash
# Build and publish package to PyPI
# Activates virtual environment before running
# Activate virtual environment
source bin/activate
# Clean previous builds
rm -rf dist/*
# Build package
python -m build
# Upload to PyPI
python -m twine upload dist/*
Note: This script follows the convention that the virtual environment is in bin/ at the project root.
Step 7: Create Package Structure
Create the basic package structure:
-
src/{package_name}/__init__.py- Package initialization file:""" {project_description} """ __version__ = "0.0.1" -
If this is a library package, you can add:
# Export main classes/functions here for easier imports # from .module import ClassName, function_name # __all__ = ['ClassName', 'function_name']
Step 8: Create README.md
Create README.md with basic project documentation:
# {project-name}
{project_description}
## Installation
```bash
pip install {project-name}
Usage
import {package_name}
# Add usage examples here
Development
Setup
# Create virtual environment
python -m venv .
# Activate virtual environment
source bin/activate # On Windows: bin\Scripts\activate
# Install dependencies
pip install -r dev-requirements.txt
pip install -e .
Building and Publishing
# Make sure you have PyPI credentials configured
# Build and publish to PyPI
./build-publish.sh
License
{license_name}
Author
{author_name} ({author_email})
## Step 9: Make Script Executable
Run:
```bash
chmod +x build-publish.sh
Step 10: Create Initial Git Repository (if needed)
If not already a git repository:
git init
git add .
git commit -m "Initial project structure for PyPI package"
Step 11: Document Next Steps
Inform the user of the next steps:
-
Install development dependencies:
source bin/activate pip install -r dev-requirements.txt -
Install package in development mode:
pip install -e . -
Write your code in
src/{package_name}/ -
Update version in
pyproject.tomlbefore publishing -
Configure PyPI credentials (one-time setup):
# Create ~/.pypirc with your PyPI token -
Build and publish:
./build-publish.sh
Design Principles
This pattern follows these principles:
- Modern pyproject.toml - No setup.py needed, all config in pyproject.toml
- Src Layout - Source code in
src/directory for better separation - Explicit Package Discovery - Using hatchling with explicit package paths
- Comprehensive .gitignore - Covers all common Python artifacts
- Virtual Environment Convention - Uses
bin/at project root - Automated Publishing - Simple script for build and publish
- Best Practices - Follows PEP 517/518 and modern Python packaging standards
Example Usage in Claude Code
User: "Set up a Python package for PyPI" Claude: "What is your project name?" User: "awesome-lib" Claude: [Asks remaining questions] Claude:
- Creates src/awesome_lib/ directory structure
- Creates pyproject.toml with project metadata
- Creates comprehensive .gitignore
- Creates dev-requirements.txt with build tools and dev dependencies
- Creates build-publish.sh script
- Creates src/awesome_lib/init.py
- Creates README.md with instructions
- Makes script executable
- Documents next steps for the user