[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EJVVTXDB34DTV8PEX4P8HC":3,"skill-same:01M6EJVVTXDB34DTV8PEX4P8HC":70},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":36,"linkOnly":37,"markdownContent":38,"markdownBody":39,"frontMatter":40,"refName":41,"commitSha":42,"skillDirectory":43,"forksCount":44,"repositoryHtmlUrl":45,"repositoryHomepageUrl":46,"ownerHtmlUrl":47,"ownerBlogUrl":6,"ownerDescription":48,"updatedAt":49,"install":50,"resources":63},"01M6EJVVTXDB34DTV8PEX4P8HC","python-packaging",null,"Create distributable Python packages with proper project structure, setup.py\u002Fpyproject.toml, and publishing to PyPI. Use when packaging Python libraries, creating CLI tools, or distributing Python code.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Factiveinferenceinstitute\u002Fpython-packaging\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35],"python","python packaging","packaging","toml","cli","project","structure","publishing","use","Tools","pypi","code","create","packages","libraries","setup","project structure","2026-11-10 10:12:30",false,"---\nname: python-packaging\ndescription: Create distributable Python packages with proper project structure, setup.py\u002Fpyproject.toml, and publishing to PyPI. Use when packaging Python libraries, creating CLI tools, or distributing Python code.\n---\n\n# Python Packaging\n\nComprehensive guide to creating, structuring, and distributing Python packages using modern packaging tools, pyproject.toml, and publishing to PyPI.\n\n## When to Use This Skill\n\n- Creating Python libraries for distribution\n- Building command-line tools with entry points\n- Publishing packages to PyPI or private repositories\n- Setting up Python project structure\n- Creating installable packages with dependencies\n- Building wheels and source distributions\n- Versioning and releasing Python packages\n- Creating namespace packages\n- Implementing package metadata and classifiers\n\n## Core Concepts\n\n### 1. Package Structure\n- **Source layout**: `src\u002Fpackage_name\u002F` (recommended)\n- **Flat layout**: `package_name\u002F` (simpler but less flexible)\n- **Package metadata**: pyproject.toml, setup.py, or setup.cfg\n- **Distribution formats**: wheel (.whl) and source distribution (.tar.gz)\n\n### 2. Modern Packaging Standards\n- **PEP 517\u002F518**: Build system requirements\n- **PEP 621**: Metadata in pyproject.toml\n- **PEP 660**: Editable installs\n- **pyproject.toml**: Single source of configuration\n\n### 3. Build Backends\n- **setuptools**: Traditional, widely used\n- **hatchling**: Modern, opinionated\n- **flit**: Lightweight, for pure Python\n- **poetry**: Dependency management + packaging\n\n### 4. Distribution\n- **PyPI**: Python Package Index (public)\n- **TestPyPI**: Testing before production\n- **Private repositories**: JFrog, AWS CodeArtifact, etc.\n\n## Quick Start\n\n### Minimal Package Structure\n\n```\nmy-package\u002F\n├── pyproject.toml\n├── README.md\n├── LICENSE\n├── src\u002F\n│   └── my_package\u002F\n│       ├── __init__.py\n│       └── module.py\n└── tests\u002F\n    └── test_module.py\n```\n\n### Minimal pyproject.toml\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"my-package\"\nversion = \"0.1.0\"\ndescription = \"A short description\"\nauthors = [{name = \"Your Name\", email = \"you@example.com\"}]\nreadme = \"README.md\"\nrequires-python = \">=3.8\"\ndependencies = [\n    \"requests>=2.28.0\",\n]\n\n[project.optional-dependencies]\ndev = [\n    \"pytest>=7.0\",\n    \"black>=22.0\",\n]\n```\n\n## Package Structure Patterns\n\n### Pattern 1: Source Layout (Recommended)\n\n```\nmy-package\u002F\n├── pyproject.toml\n├── README.md\n├── LICENSE\n├── .gitignore\n├── src\u002F\n│   └── my_package\u002F\n│       ├── __init__.py\n│       ├── core.py\n│       ├── utils.py\n│       └── py.typed          # For type hints\n├── tests\u002F\n│   ├── __init__.py\n│   ├── test_core.py\n│   └── test_utils.py\n└── docs\u002F\n    └── index.md\n```\n\n**Advantages:**\n- Prevents accidentally importing from source\n- Cleaner test imports\n- Better isolation\n\n**pyproject.toml for source layout:**\n```toml\n[tool.setuptools.packages.find]\nwhere = [\"src\"]\n```\n\n### Pattern 2: Flat Layout\n\n```\nmy-package\u002F\n├── pyproject.toml\n├── README.md\n├── my_package\u002F\n│   ├── __init__.py\n│   └── module.py\n└── tests\u002F\n    └── test_module.py\n```\n\n**Simpler but:**\n- Can import package without installing\n- Less professional for libraries\n\n### Pattern 3: Multi-Package Project\n\n```\nproject\u002F\n├── pyproject.toml\n├── packages\u002F\n│   ├── package-a\u002F\n│   │   └── src\u002F\n│   │       └── package_a\u002F\n│   └── package-b\u002F\n│       └── src\u002F\n│           └── package_b\u002F\n└── tests\u002F\n```\n\n## Complete pyproject.toml Examples\n\n### Pattern 4: Full-Featured pyproject.toml\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"my-awesome-package\"\nversion = \"1.0.0\"\ndescription = \"An awesome Python package\"\nreadme = \"README.md\"\nrequires-python = \">=3.8\"\nlicense = {text = \"MIT\"}\nauthors = [\n    {name = \"Your Name\", email = \"you@example.com\"},\n]\nmaintainers = [\n    {name = \"Maintainer Name\", email = \"maintainer@example.com\"},\n]\nkeywords = [\"example\", \"package\", \"awesome\"]\nclassifiers = [\n    \"Development Status :: 4 - Beta\",\n    \"Intended Audience :: Developers\",\n    \"License :: OSI Approved :: MIT License\",\n    \"Programming Language :: Python :: 3\",\n    \"Programming Language :: Python :: 3.8\",\n    \"Programming Language :: Python :: 3.9\",\n    \"Programming Language :: Python :: 3.10\",\n    \"Programming Language :: Python :: 3.11\",\n    \"Programming Language :: Python :: 3.12\",\n]\n\ndependencies = [\n    \"requests>=2.28.0,\u003C3.0.0\",\n    \"click>=8.0.0\",\n    \"pydantic>=2.0.0\",\n]\n\n[project.optional-dependencies]\ndev = [\n    \"pytest>=7.0.0\",\n    \"pytest-cov>=4.0.0\",\n    \"black>=23.0.0\",\n    \"ruff>=0.1.0\",\n    \"mypy>=1.0.0\",\n]\ndocs = [\n    \"sphinx>=5.0.0\",\n    \"sphinx-rtd-theme>=1.0.0\",\n]\nall = [\n    \"my-awesome-package[dev,docs]\",\n]\n\n[project.urls]\nHomepage = \"https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-awesome-package\"\nDocumentation = \"https:\u002F\u002Fmy-awesome-package.readthedocs.io\"\nRepository = \"https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-awesome-package\"\n\"Bug Tracker\" = \"https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-awesome-package\u002Fissues\"\nChangelog = \"https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-awesome-package\u002Fblob\u002Fmain\u002FCHANGELOG.md\"\n\n[project.scripts]\nmy-cli = \"my_package.cli:main\"\nawesome-tool = \"my_package.tools:run\"\n\n[project.entry-points.\"my_package.plugins\"]\nplugin1 = \"my_package.plugins:plugin1\"\n\n[tool.setuptools]\npackage-dir = {\"\" = \"src\"}\nzip-safe = false\n\n[tool.setuptools.packages.find]\nwhere = [\"src\"]\ninclude = [\"my_package*\"]\nexclude = [\"tests*\"]\n\n[tool.setuptools.package-data]\nmy_package = [\"py.typed\", \"*.pyi\", \"data\u002F*.json\"]\n\n# Black configuration\n[tool.black]\nline-length = 100\ntarget-version = [\"py38\", \"py39\", \"py310\", \"py311\"]\ninclude = '\\.pyi?$'\n\n# Ruff configuration\n[tool.ruff]\nline-length = 100\ntarget-version = \"py38\"\n\n[tool.ruff.lint]\nselect = [\"E\", \"F\", \"I\", \"N\", \"W\", \"UP\"]\n\n# MyPy configuration\n[tool.mypy]\npython_version = \"3.8\"\nwarn_return_any = true\nwarn_unused_configs = true\ndisallow_untyped_defs = true\n\n# Pytest configuration\n[tool.pytest.ini_options]\ntestpaths = [\"tests\"]\npython_files = [\"test_*.py\"]\naddopts = \"-v --cov=my_package --cov-report=term-missing\"\n\n# Coverage configuration\n[tool.coverage.run]\nsource = [\"src\"]\nomit = [\"*\u002Ftests\u002F*\"]\n\n[tool.coverage.report]\nexclude_lines = [\n    \"pragma: no cover\",\n    \"def __repr__\",\n    \"raise AssertionError\",\n    \"raise NotImplementedError\",\n]\n```\n\n### Pattern 5: Dynamic Versioning\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"setuptools-scm>=8.0\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"my-package\"\ndynamic = [\"version\"]\ndescription = \"Package with dynamic version\"\n\n[tool.setuptools.dynamic]\nversion = {attr = \"my_package.__version__\"}\n\n# Or use setuptools-scm for git-based versioning\n[tool.setuptools_scm]\nwrite_to = \"src\u002Fmy_package\u002F_version.py\"\n```\n\n**In __init__.py:**\n```python\n# src\u002Fmy_package\u002F__init__.py\n__version__ = \"1.0.0\"\n\n# Or with setuptools-scm\nfrom importlib.metadata import version\n__version__ = version(\"my-package\")\n```\n\n## Command-Line Interface (CLI) Patterns\n\n### Pattern 6: CLI with Click\n\n```python\n# src\u002Fmy_package\u002Fcli.py\nimport click\n\n@click.group()\n@click.version_option()\ndef cli():\n    \"\"\"My awesome CLI tool.\"\"\"\n    pass\n\n@cli.command()\n@click.argument(\"name\")\n@click.option(\"--greeting\", default=\"Hello\", help=\"Greeting to use\")\ndef greet(name: str, greeting: str):\n    \"\"\"Greet someone.\"\"\"\n    click.echo(f\"{greeting}, {name}!\")\n\n@cli.command()\n@click.option(\"--count\", default=1, help=\"Number of times to repeat\")\ndef repeat(count: int):\n    \"\"\"Repeat a message.\"\"\"\n    for i in range(count):\n        click.echo(f\"Message {i + 1}\")\n\ndef main():\n    \"\"\"Entry point for CLI.\"\"\"\n    cli()\n\nif __name__ == \"__main__\":\n    main()\n```\n\n**Register in pyproject.toml:**\n```toml\n[project.scripts]\nmy-tool = \"my_package.cli:main\"\n```\n\n**Usage:**\n```bash\npip install -e .\nmy-tool greet World\nmy-tool greet Alice --greeting=\"Hi\"\nmy-tool repeat --count=3\n```\n\n### Pattern 7: CLI with argparse\n\n```python\n# src\u002Fmy_package\u002Fcli.py\nimport argparse\nimport sys\n\ndef main():\n    \"\"\"Main CLI entry point.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"My awesome tool\",\n        prog=\"my-tool\"\n    )\n\n    parser.add_argument(\n        \"--version\",\n        action=\"version\",\n        version=\"%(prog)s 1.0.0\"\n    )\n\n    subparsers = parser.add_subparsers(dest=\"command\", help=\"Commands\")\n\n    # Add subcommand\n    process_parser = subparsers.add_parser(\"process\", help=\"Process data\")\n    process_parser.add_argument(\"input_file\", help=\"Input file path\")\n    process_parser.add_argument(\n        \"--output\", \"-o\",\n        default=\"output.txt\",\n        help=\"Output file path\"\n    )\n\n    args = parser.parse_args()\n\n    if args.command == \"process\":\n        process_data(args.input_file, args.output)\n    else:\n        parser.print_help()\n        sys.exit(1)\n\ndef process_data(input_file: str, output_file: str):\n    \"\"\"Process data from input to output.\"\"\"\n    print(f\"Processing {input_file} -> {output_file}\")\n\nif __name__ == \"__main__\":\n    main()\n```\n\n## Building and Publishing\n\n### Pattern 8: Build Package Locally\n\n```bash\n# Install build tools\npip install build twine\n\n# Build distribution\npython -m build\n\n# This creates:\n# dist\u002F\n#   my-package-1.0.0.tar.gz (source distribution)\n#   my_package-1.0.0-py3-none-any.whl (wheel)\n\n# Check the distribution\ntwine check dist\u002F*\n```\n\n### Pattern 9: Publishing to PyPI\n\n```bash\n# Install publishing tools\npip install twine\n\n# Test on TestPyPI first\ntwine upload --repository testpypi dist\u002F*\n\n# Install from TestPyPI to test\npip install --index-url https:\u002F\u002Ftest.pypi.org\u002Fsimple\u002F my-package\n\n# If all good, publish to PyPI\ntwine upload dist\u002F*\n```\n\n**Using API tokens (recommended):**\n```bash\n# Create ~\u002F.pypirc\n[distutils]\nindex-servers =\n    pypi\n    testpypi\n\n[pypi]\nusername = __token__\npassword = pypi-...your-token...\n\n[testpypi]\nusername = __token__\npassword = pypi-...your-test-token...\n```\n\n### Pattern 10: Automated Publishing with GitHub Actions\n\n```yaml\n# .github\u002Fworkflows\u002Fpublish.yml\nname: Publish to PyPI\n\non:\n  release:\n    types: [created]\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions\u002Fcheckout@v3\n\n      - name: Set up Python\n        uses: actions\u002Fsetup-python@v4\n        with:\n          python-version: \"3.11\"\n\n      - name: Install dependencies\n        run: |\n          pip install build twine\n\n      - name: Build package\n        run: python -m build\n\n      - name: Check package\n        run: twine check dist\u002F*\n\n      - name: Publish to PyPI\n        env:\n          TWINE_USERNAME: __token__\n          TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}\n        run: twine upload dist\u002F*\n```\n\n## Advanced Patterns\n\n### Pattern 11: Including Data Files\n\n```toml\n[tool.setuptools.package-data]\nmy_package = [\n    \"data\u002F*.json\",\n    \"templates\u002F*.html\",\n    \"static\u002Fcss\u002F*.css\",\n    \"py.typed\",\n]\n```\n\n**Accessing data files:**\n```python\n# src\u002Fmy_package\u002Floader.py\nfrom importlib.resources import files\nimport json\n\ndef load_config():\n    \"\"\"Load configuration from package data.\"\"\"\n    config_file = files(\"my_package\").joinpath(\"data\u002Fconfig.json\")\n    with config_file.open() as f:\n        return json.load(f)\n\n# Python 3.9+\nfrom importlib.resources import files\n\ndata = files(\"my_package\").joinpath(\"data\u002Ffile.txt\").read_text()\n```\n\n### Pattern 12: Namespace Packages\n\n**For large projects split across multiple repositories:**\n\n```\n# Package 1: company-core\ncompany\u002F\n└── core\u002F\n    ├── __init__.py\n    └── models.py\n\n# Package 2: company-api\ncompany\u002F\n└── api\u002F\n    ├── __init__.py\n    └── routes.py\n```\n\n**Do NOT include __init__.py in the namespace directory (company\u002F):**\n\n```toml\n# company-core\u002Fpyproject.toml\n[project]\nname = \"company-core\"\n\n[tool.setuptools.packages.find]\nwhere = [\".\"]\ninclude = [\"company.core*\"]\n\n# company-api\u002Fpyproject.toml\n[project]\nname = \"company-api\"\n\n[tool.setuptools.packages.find]\nwhere = [\".\"]\ninclude = [\"company.api*\"]\n```\n\n**Usage:**\n```python\n# Both packages can be imported under same namespace\nfrom company.core import models\nfrom company.api import routes\n```\n\n### Pattern 13: C Extensions\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"wheel\", \"Cython>=0.29\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[tool.setuptools]\next-modules = [\n    {name = \"my_package.fast_module\", sources = [\"src\u002Ffast_module.c\"]},\n]\n```\n\n**Or with setup.py:**\n```python\n# setup.py\nfrom setuptools import setup, Extension\n\nsetup(\n    ext_modules=[\n        Extension(\n            \"my_package.fast_module\",\n            sources=[\"src\u002Ffast_module.c\"],\n            include_dirs=[\"src\u002Finclude\"],\n        )\n    ]\n)\n```\n\n## Version Management\n\n### Pattern 14: Semantic Versioning\n\n```python\n# src\u002Fmy_package\u002F__init__.py\n__version__ = \"1.2.3\"\n\n# Semantic versioning: MAJOR.MINOR.PATCH\n# MAJOR: Breaking changes\n# MINOR: New features (backward compatible)\n# PATCH: Bug fixes\n```\n\n**Version constraints in dependencies:**\n```toml\ndependencies = [\n    \"requests>=2.28.0,\u003C3.0.0\",  # Compatible range\n    \"click~=8.1.0\",              # Compatible release (~= 8.1.0 means >=8.1.0,\u003C8.2.0)\n    \"pydantic>=2.0\",             # Minimum version\n    \"numpy==1.24.3\",             # Exact version (avoid if possible)\n]\n```\n\n### Pattern 15: Git-Based Versioning\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"setuptools-scm>=8.0\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"my-package\"\ndynamic = [\"version\"]\n\n[tool.setuptools_scm]\nwrite_to = \"src\u002Fmy_package\u002F_version.py\"\nversion_scheme = \"post-release\"\nlocal_scheme = \"dirty-tag\"\n```\n\n**Creates versions like:**\n- `1.0.0` (from git tag)\n- `1.0.1.dev3+g1234567` (3 commits after tag)\n\n## Testing Installation\n\n### Pattern 16: Editable Install\n\n```bash\n# Install in development mode\npip install -e .\n\n# With optional dependencies\npip install -e \".[dev]\"\npip install -e \".[dev,docs]\"\n\n# Now changes to source code are immediately reflected\n```\n\n### Pattern 17: Testing in Isolated Environment\n\n```bash\n# Create virtual environment\npython -m venv test-env\nsource test-env\u002Fbin\u002Factivate  # Linux\u002FMac\n# test-env\\Scripts\\activate  # Windows\n\n# Install package\npip install dist\u002Fmy_package-1.0.0-py3-none-any.whl\n\n# Test it works\npython -c \"import my_package; print(my_package.__version__)\"\n\n# Test CLI\nmy-tool --help\n\n# Cleanup\ndeactivate\nrm -rf test-env\n```\n\n## Documentation\n\n### Pattern 18: README.md Template\n\n```markdown\n# My Package\n\n[![PyPI version](https:\u002F\u002Fbadge.fury.io\u002Fpy\u002Fmy-package.svg)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fmy-package\u002F)\n[![Python versions](https:\u002F\u002Fimg.shields.io\u002Fpypi\u002Fpyversions\u002Fmy-package.svg)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fmy-package\u002F)\n[![Tests](https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-package\u002Fworkflows\u002FTests\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-package\u002Factions)\n\nBrief description of your package.\n\n## Installation\n\n```bash\npip install my-package\n```\n\n## Quick Start\n\n```python\nfrom my_package import something\n\nresult = something.do_stuff()\n```\n\n## Features\n\n- Feature 1\n- Feature 2\n- Feature 3\n\n## Documentation\n\nFull documentation: https:\u002F\u002Fmy-package.readthedocs.io\n\n## Development\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-package.git\ncd my-package\npip install -e \".[dev]\"\npytest\n```\n\n## License\n\nMIT\n```\n\n## Common Patterns\n\n### Pattern 19: Multi-Architecture Wheels\n\n```yaml\n# .github\u002Fworkflows\u002Fwheels.yml\nname: Build wheels\n\non: [push, pull_request]\n\njobs:\n  build_wheels:\n    name: Build wheels on ${{ matrix.os }}\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n\n    steps:\n      - uses: actions\u002Fcheckout@v3\n\n      - name: Build wheels\n        uses: pypa\u002Fcibuildwheel@v2.16.2\n\n      - uses: actions\u002Fupload-artifact@v3\n        with:\n          path: .\u002Fwheelhouse\u002F*.whl\n```\n\n### Pattern 20: Private Package Index\n\n```bash\n# Install from private index\npip install my-package --index-url https:\u002F\u002Fprivate.pypi.org\u002Fsimple\u002F\n\n# Or add to pip.conf\n[global]\nindex-url = https:\u002F\u002Fprivate.pypi.org\u002Fsimple\u002F\nextra-index-url = https:\u002F\u002Fpypi.org\u002Fsimple\u002F\n\n# Upload to private index\ntwine upload --repository-url https:\u002F\u002Fprivate.pypi.org\u002F dist\u002F*\n```\n\n## File Templates\n\n### .gitignore for Python Packages\n\n```gitignore\n# Build artifacts\nbuild\u002F\ndist\u002F\n*.egg-info\u002F\n*.egg\n.eggs\u002F\n\n# Python\n__pycache__\u002F\n*.py[cod]\n*$py.class\n*.so\n\n# Virtual environments\nvenv\u002F\nenv\u002F\nENV\u002F\n\n# IDE\n.vscode\u002F\n.idea\u002F\n*.swp\n\n# Testing\n.pytest_cache\u002F\n.coverage\nhtmlcov\u002F\n\n# Distribution\n*.whl\n*.tar.gz\n```\n\n### MANIFEST.in\n\n```\n# MANIFEST.in\ninclude README.md\ninclude LICENSE\ninclude pyproject.toml\n\nrecursive-include src\u002Fmy_package\u002Fdata *.json\nrecursive-include src\u002Fmy_package\u002Ftemplates *.html\nrecursive-exclude * __pycache__\nrecursive-exclude * *.py[co]\n```\n\n## Checklist for Publishing\n\n- [ ] Code is tested (pytest passing)\n- [ ] Documentation is complete (README, docstrings)\n- [ ] Version number updated\n- [ ] CHANGELOG.md updated\n- [ ] License file included\n- [ ] pyproject.toml is complete\n- [ ] Package builds without errors\n- [ ] Installation tested in clean environment\n- [ ] CLI tools work (if applicable)\n- [ ] PyPI metadata is correct (classifiers, keywords)\n- [ ] GitHub repository linked\n- [ ] Tested on TestPyPI first\n- [ ] Git tag created for release\n\n## Resources\n\n- **Python Packaging Guide**: https:\u002F\u002Fpackaging.python.org\u002F\n- **PyPI**: https:\u002F\u002Fpypi.org\u002F\n- **TestPyPI**: https:\u002F\u002Ftest.pypi.org\u002F\n- **setuptools documentation**: https:\u002F\u002Fsetuptools.pypa.io\u002F\n- **build**: https:\u002F\u002Fpypa-build.readthedocs.io\u002F\n- **twine**: https:\u002F\u002Ftwine.readthedocs.io\u002F\n\n## Best Practices Summary\n\n1. **Use src\u002F layout** for cleaner package structure\n2. **Use pyproject.toml** for modern packaging\n3. **Pin build dependencies** in build-system.requires\n4. **Version appropriately** with semantic versioning\n5. **Include all metadata** (classifiers, URLs, etc.)\n6. **Test installation** in clean environments\n7. **Use TestPyPI** before publishing to PyPI\n8. **Document thoroughly** with README and docstrings\n9. **Include LICENSE** file\n10. **Automate publishing** with CI\u002FCD\n","# Python Packaging\n\nComprehensive guide to creating, structuring, and distributing Python packages using modern packaging tools, pyproject.toml, and publishing to PyPI.\n\n## When to Use This Skill\n\n- Creating Python libraries for distribution\n- Building command-line tools with entry points\n- Publishing packages to PyPI or private repositories\n- Setting up Python project structure\n- Creating installable packages with dependencies\n- Building wheels and source distributions\n- Versioning and releasing Python packages\n- Creating namespace packages\n- Implementing package metadata and classifiers\n\n## Core Concepts\n\n### 1. Package Structure\n- **Source layout**: `src\u002Fpackage_name\u002F` (recommended)\n- **Flat layout**: `package_name\u002F` (simpler but less flexible)\n- **Package metadata**: pyproject.toml, setup.py, or setup.cfg\n- **Distribution formats**: wheel (.whl) and source distribution (.tar.gz)\n\n### 2. Modern Packaging Standards\n- **PEP 517\u002F518**: Build system requirements\n- **PEP 621**: Metadata in pyproject.toml\n- **PEP 660**: Editable installs\n- **pyproject.toml**: Single source of configuration\n\n### 3. Build Backends\n- **setuptools**: Traditional, widely used\n- **hatchling**: Modern, opinionated\n- **flit**: Lightweight, for pure Python\n- **poetry**: Dependency management + packaging\n\n### 4. Distribution\n- **PyPI**: Python Package Index (public)\n- **TestPyPI**: Testing before production\n- **Private repositories**: JFrog, AWS CodeArtifact, etc.\n\n## Quick Start\n\n### Minimal Package Structure\n\n```\nmy-package\u002F\n├── pyproject.toml\n├── README.md\n├── LICENSE\n├── src\u002F\n│   └── my_package\u002F\n│       ├── __init__.py\n│       └── module.py\n└── tests\u002F\n    └── test_module.py\n```\n\n### Minimal pyproject.toml\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"my-package\"\nversion = \"0.1.0\"\ndescription = \"A short description\"\nauthors = [{name = \"Your Name\", email = \"you@example.com\"}]\nreadme = \"README.md\"\nrequires-python = \">=3.8\"\ndependencies = [\n    \"requests>=2.28.0\",\n]\n\n[project.optional-dependencies]\ndev = [\n    \"pytest>=7.0\",\n    \"black>=22.0\",\n]\n```\n\n## Package Structure Patterns\n\n### Pattern 1: Source Layout (Recommended)\n\n```\nmy-package\u002F\n├── pyproject.toml\n├── README.md\n├── LICENSE\n├── .gitignore\n├── src\u002F\n│   └── my_package\u002F\n│       ├── __init__.py\n│       ├── core.py\n│       ├── utils.py\n│       └── py.typed          # For type hints\n├── tests\u002F\n│   ├── __init__.py\n│   ├── test_core.py\n│   └── test_utils.py\n└── docs\u002F\n    └── index.md\n```\n\n**Advantages:**\n- Prevents accidentally importing from source\n- Cleaner test imports\n- Better isolation\n\n**pyproject.toml for source layout:**\n```toml\n[tool.setuptools.packages.find]\nwhere = [\"src\"]\n```\n\n### Pattern 2: Flat Layout\n\n```\nmy-package\u002F\n├── pyproject.toml\n├── README.md\n├── my_package\u002F\n│   ├── __init__.py\n│   └── module.py\n└── tests\u002F\n    └── test_module.py\n```\n\n**Simpler but:**\n- Can import package without installing\n- Less professional for libraries\n\n### Pattern 3: Multi-Package Project\n\n```\nproject\u002F\n├── pyproject.toml\n├── packages\u002F\n│   ├── package-a\u002F\n│   │   └── src\u002F\n│   │       └── package_a\u002F\n│   └── package-b\u002F\n│       └── src\u002F\n│           └── package_b\u002F\n└── tests\u002F\n```\n\n## Complete pyproject.toml Examples\n\n### Pattern 4: Full-Featured pyproject.toml\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"my-awesome-package\"\nversion = \"1.0.0\"\ndescription = \"An awesome Python package\"\nreadme = \"README.md\"\nrequires-python = \">=3.8\"\nlicense = {text = \"MIT\"}\nauthors = [\n    {name = \"Your Name\", email = \"you@example.com\"},\n]\nmaintainers = [\n    {name = \"Maintainer Name\", email = \"maintainer@example.com\"},\n]\nkeywords = [\"example\", \"package\", \"awesome\"]\nclassifiers = [\n    \"Development Status :: 4 - Beta\",\n    \"Intended Audience :: Developers\",\n    \"License :: OSI Approved :: MIT License\",\n    \"Programming Language :: Python :: 3\",\n    \"Programming Language :: Python :: 3.8\",\n    \"Programming Language :: Python :: 3.9\",\n    \"Programming Language :: Python :: 3.10\",\n    \"Programming Language :: Python :: 3.11\",\n    \"Programming Language :: Python :: 3.12\",\n]\n\ndependencies = [\n    \"requests>=2.28.0,\u003C3.0.0\",\n    \"click>=8.0.0\",\n    \"pydantic>=2.0.0\",\n]\n\n[project.optional-dependencies]\ndev = [\n    \"pytest>=7.0.0\",\n    \"pytest-cov>=4.0.0\",\n    \"black>=23.0.0\",\n    \"ruff>=0.1.0\",\n    \"mypy>=1.0.0\",\n]\ndocs = [\n    \"sphinx>=5.0.0\",\n    \"sphinx-rtd-theme>=1.0.0\",\n]\nall = [\n    \"my-awesome-package[dev,docs]\",\n]\n\n[project.urls]\nHomepage = \"https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-awesome-package\"\nDocumentation = \"https:\u002F\u002Fmy-awesome-package.readthedocs.io\"\nRepository = \"https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-awesome-package\"\n\"Bug Tracker\" = \"https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-awesome-package\u002Fissues\"\nChangelog = \"https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-awesome-package\u002Fblob\u002Fmain\u002FCHANGELOG.md\"\n\n[project.scripts]\nmy-cli = \"my_package.cli:main\"\nawesome-tool = \"my_package.tools:run\"\n\n[project.entry-points.\"my_package.plugins\"]\nplugin1 = \"my_package.plugins:plugin1\"\n\n[tool.setuptools]\npackage-dir = {\"\" = \"src\"}\nzip-safe = false\n\n[tool.setuptools.packages.find]\nwhere = [\"src\"]\ninclude = [\"my_package*\"]\nexclude = [\"tests*\"]\n\n[tool.setuptools.package-data]\nmy_package = [\"py.typed\", \"*.pyi\", \"data\u002F*.json\"]\n\n# Black configuration\n[tool.black]\nline-length = 100\ntarget-version = [\"py38\", \"py39\", \"py310\", \"py311\"]\ninclude = '\\.pyi?$'\n\n# Ruff configuration\n[tool.ruff]\nline-length = 100\ntarget-version = \"py38\"\n\n[tool.ruff.lint]\nselect = [\"E\", \"F\", \"I\", \"N\", \"W\", \"UP\"]\n\n# MyPy configuration\n[tool.mypy]\npython_version = \"3.8\"\nwarn_return_any = true\nwarn_unused_configs = true\ndisallow_untyped_defs = true\n\n# Pytest configuration\n[tool.pytest.ini_options]\ntestpaths = [\"tests\"]\npython_files = [\"test_*.py\"]\naddopts = \"-v --cov=my_package --cov-report=term-missing\"\n\n# Coverage configuration\n[tool.coverage.run]\nsource = [\"src\"]\nomit = [\"*\u002Ftests\u002F*\"]\n\n[tool.coverage.report]\nexclude_lines = [\n    \"pragma: no cover\",\n    \"def __repr__\",\n    \"raise AssertionError\",\n    \"raise NotImplementedError\",\n]\n```\n\n### Pattern 5: Dynamic Versioning\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"setuptools-scm>=8.0\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"my-package\"\ndynamic = [\"version\"]\ndescription = \"Package with dynamic version\"\n\n[tool.setuptools.dynamic]\nversion = {attr = \"my_package.__version__\"}\n\n# Or use setuptools-scm for git-based versioning\n[tool.setuptools_scm]\nwrite_to = \"src\u002Fmy_package\u002F_version.py\"\n```\n\n**In __init__.py:**\n```python\n# src\u002Fmy_package\u002F__init__.py\n__version__ = \"1.0.0\"\n\n# Or with setuptools-scm\nfrom importlib.metadata import version\n__version__ = version(\"my-package\")\n```\n\n## Command-Line Interface (CLI) Patterns\n\n### Pattern 6: CLI with Click\n\n```python\n# src\u002Fmy_package\u002Fcli.py\nimport click\n\n@click.group()\n@click.version_option()\ndef cli():\n    \"\"\"My awesome CLI tool.\"\"\"\n    pass\n\n@cli.command()\n@click.argument(\"name\")\n@click.option(\"--greeting\", default=\"Hello\", help=\"Greeting to use\")\ndef greet(name: str, greeting: str):\n    \"\"\"Greet someone.\"\"\"\n    click.echo(f\"{greeting}, {name}!\")\n\n@cli.command()\n@click.option(\"--count\", default=1, help=\"Number of times to repeat\")\ndef repeat(count: int):\n    \"\"\"Repeat a message.\"\"\"\n    for i in range(count):\n        click.echo(f\"Message {i + 1}\")\n\ndef main():\n    \"\"\"Entry point for CLI.\"\"\"\n    cli()\n\nif __name__ == \"__main__\":\n    main()\n```\n\n**Register in pyproject.toml:**\n```toml\n[project.scripts]\nmy-tool = \"my_package.cli:main\"\n```\n\n**Usage:**\n```bash\npip install -e .\nmy-tool greet World\nmy-tool greet Alice --greeting=\"Hi\"\nmy-tool repeat --count=3\n```\n\n### Pattern 7: CLI with argparse\n\n```python\n# src\u002Fmy_package\u002Fcli.py\nimport argparse\nimport sys\n\ndef main():\n    \"\"\"Main CLI entry point.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"My awesome tool\",\n        prog=\"my-tool\"\n    )\n\n    parser.add_argument(\n        \"--version\",\n        action=\"version\",\n        version=\"%(prog)s 1.0.0\"\n    )\n\n    subparsers = parser.add_subparsers(dest=\"command\", help=\"Commands\")\n\n    # Add subcommand\n    process_parser = subparsers.add_parser(\"process\", help=\"Process data\")\n    process_parser.add_argument(\"input_file\", help=\"Input file path\")\n    process_parser.add_argument(\n        \"--output\", \"-o\",\n        default=\"output.txt\",\n        help=\"Output file path\"\n    )\n\n    args = parser.parse_args()\n\n    if args.command == \"process\":\n        process_data(args.input_file, args.output)\n    else:\n        parser.print_help()\n        sys.exit(1)\n\ndef process_data(input_file: str, output_file: str):\n    \"\"\"Process data from input to output.\"\"\"\n    print(f\"Processing {input_file} -> {output_file}\")\n\nif __name__ == \"__main__\":\n    main()\n```\n\n## Building and Publishing\n\n### Pattern 8: Build Package Locally\n\n```bash\n# Install build tools\npip install build twine\n\n# Build distribution\npython -m build\n\n# This creates:\n# dist\u002F\n#   my-package-1.0.0.tar.gz (source distribution)\n#   my_package-1.0.0-py3-none-any.whl (wheel)\n\n# Check the distribution\ntwine check dist\u002F*\n```\n\n### Pattern 9: Publishing to PyPI\n\n```bash\n# Install publishing tools\npip install twine\n\n# Test on TestPyPI first\ntwine upload --repository testpypi dist\u002F*\n\n# Install from TestPyPI to test\npip install --index-url https:\u002F\u002Ftest.pypi.org\u002Fsimple\u002F my-package\n\n# If all good, publish to PyPI\ntwine upload dist\u002F*\n```\n\n**Using API tokens (recommended):**\n```bash\n# Create ~\u002F.pypirc\n[distutils]\nindex-servers =\n    pypi\n    testpypi\n\n[pypi]\nusername = __token__\npassword = pypi-...your-token...\n\n[testpypi]\nusername = __token__\npassword = pypi-...your-test-token...\n```\n\n### Pattern 10: Automated Publishing with GitHub Actions\n\n```yaml\n# .github\u002Fworkflows\u002Fpublish.yml\nname: Publish to PyPI\n\non:\n  release:\n    types: [created]\n\njobs:\n  publish:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions\u002Fcheckout@v3\n\n      - name: Set up Python\n        uses: actions\u002Fsetup-python@v4\n        with:\n          python-version: \"3.11\"\n\n      - name: Install dependencies\n        run: |\n          pip install build twine\n\n      - name: Build package\n        run: python -m build\n\n      - name: Check package\n        run: twine check dist\u002F*\n\n      - name: Publish to PyPI\n        env:\n          TWINE_USERNAME: __token__\n          TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}\n        run: twine upload dist\u002F*\n```\n\n## Advanced Patterns\n\n### Pattern 11: Including Data Files\n\n```toml\n[tool.setuptools.package-data]\nmy_package = [\n    \"data\u002F*.json\",\n    \"templates\u002F*.html\",\n    \"static\u002Fcss\u002F*.css\",\n    \"py.typed\",\n]\n```\n\n**Accessing data files:**\n```python\n# src\u002Fmy_package\u002Floader.py\nfrom importlib.resources import files\nimport json\n\ndef load_config():\n    \"\"\"Load configuration from package data.\"\"\"\n    config_file = files(\"my_package\").joinpath(\"data\u002Fconfig.json\")\n    with config_file.open() as f:\n        return json.load(f)\n\n# Python 3.9+\nfrom importlib.resources import files\n\ndata = files(\"my_package\").joinpath(\"data\u002Ffile.txt\").read_text()\n```\n\n### Pattern 12: Namespace Packages\n\n**For large projects split across multiple repositories:**\n\n```\n# Package 1: company-core\ncompany\u002F\n└── core\u002F\n    ├── __init__.py\n    └── models.py\n\n# Package 2: company-api\ncompany\u002F\n└── api\u002F\n    ├── __init__.py\n    └── routes.py\n```\n\n**Do NOT include __init__.py in the namespace directory (company\u002F):**\n\n```toml\n# company-core\u002Fpyproject.toml\n[project]\nname = \"company-core\"\n\n[tool.setuptools.packages.find]\nwhere = [\".\"]\ninclude = [\"company.core*\"]\n\n# company-api\u002Fpyproject.toml\n[project]\nname = \"company-api\"\n\n[tool.setuptools.packages.find]\nwhere = [\".\"]\ninclude = [\"company.api*\"]\n```\n\n**Usage:**\n```python\n# Both packages can be imported under same namespace\nfrom company.core import models\nfrom company.api import routes\n```\n\n### Pattern 13: C Extensions\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"wheel\", \"Cython>=0.29\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[tool.setuptools]\next-modules = [\n    {name = \"my_package.fast_module\", sources = [\"src\u002Ffast_module.c\"]},\n]\n```\n\n**Or with setup.py:**\n```python\n# setup.py\nfrom setuptools import setup, Extension\n\nsetup(\n    ext_modules=[\n        Extension(\n            \"my_package.fast_module\",\n            sources=[\"src\u002Ffast_module.c\"],\n            include_dirs=[\"src\u002Finclude\"],\n        )\n    ]\n)\n```\n\n## Version Management\n\n### Pattern 14: Semantic Versioning\n\n```python\n# src\u002Fmy_package\u002F__init__.py\n__version__ = \"1.2.3\"\n\n# Semantic versioning: MAJOR.MINOR.PATCH\n# MAJOR: Breaking changes\n# MINOR: New features (backward compatible)\n# PATCH: Bug fixes\n```\n\n**Version constraints in dependencies:**\n```toml\ndependencies = [\n    \"requests>=2.28.0,\u003C3.0.0\",  # Compatible range\n    \"click~=8.1.0\",              # Compatible release (~= 8.1.0 means >=8.1.0,\u003C8.2.0)\n    \"pydantic>=2.0\",             # Minimum version\n    \"numpy==1.24.3\",             # Exact version (avoid if possible)\n]\n```\n\n### Pattern 15: Git-Based Versioning\n\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"setuptools-scm>=8.0\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"my-package\"\ndynamic = [\"version\"]\n\n[tool.setuptools_scm]\nwrite_to = \"src\u002Fmy_package\u002F_version.py\"\nversion_scheme = \"post-release\"\nlocal_scheme = \"dirty-tag\"\n```\n\n**Creates versions like:**\n- `1.0.0` (from git tag)\n- `1.0.1.dev3+g1234567` (3 commits after tag)\n\n## Testing Installation\n\n### Pattern 16: Editable Install\n\n```bash\n# Install in development mode\npip install -e .\n\n# With optional dependencies\npip install -e \".[dev]\"\npip install -e \".[dev,docs]\"\n\n# Now changes to source code are immediately reflected\n```\n\n### Pattern 17: Testing in Isolated Environment\n\n```bash\n# Create virtual environment\npython -m venv test-env\nsource test-env\u002Fbin\u002Factivate  # Linux\u002FMac\n# test-env\\Scripts\\activate  # Windows\n\n# Install package\npip install dist\u002Fmy_package-1.0.0-py3-none-any.whl\n\n# Test it works\npython -c \"import my_package; print(my_package.__version__)\"\n\n# Test CLI\nmy-tool --help\n\n# Cleanup\ndeactivate\nrm -rf test-env\n```\n\n## Documentation\n\n### Pattern 18: README.md Template\n\n```markdown\n# My Package\n\n[![PyPI version](https:\u002F\u002Fbadge.fury.io\u002Fpy\u002Fmy-package.svg)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fmy-package\u002F)\n[![Python versions](https:\u002F\u002Fimg.shields.io\u002Fpypi\u002Fpyversions\u002Fmy-package.svg)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fmy-package\u002F)\n[![Tests](https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-package\u002Fworkflows\u002FTests\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-package\u002Factions)\n\nBrief description of your package.\n\n## Installation\n\n```bash\npip install my-package\n```\n\n## Quick Start\n\n```python\nfrom my_package import something\n\nresult = something.do_stuff()\n```\n\n## Features\n\n- Feature 1\n- Feature 2\n- Feature 3\n\n## Documentation\n\nFull documentation: https:\u002F\u002Fmy-package.readthedocs.io\n\n## Development\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fusername\u002Fmy-package.git\ncd my-package\npip install -e \".[dev]\"\npytest\n```\n\n## License\n\nMIT\n```\n\n## Common Patterns\n\n### Pattern 19: Multi-Architecture Wheels\n\n```yaml\n# .github\u002Fworkflows\u002Fwheels.yml\nname: Build wheels\n\non: [push, pull_request]\n\njobs:\n  build_wheels:\n    name: Build wheels on ${{ matrix.os }}\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n\n    steps:\n      - uses: actions\u002Fcheckout@v3\n\n      - name: Build wheels\n        uses: pypa\u002Fcibuildwheel@v2.16.2\n\n      - uses: actions\u002Fupload-artifact@v3\n        with:\n          path: .\u002Fwheelhouse\u002F*.whl\n```\n\n### Pattern 20: Private Package Index\n\n```bash\n# Install from private index\npip install my-package --index-url https:\u002F\u002Fprivate.pypi.org\u002Fsimple\u002F\n\n# Or add to pip.conf\n[global]\nindex-url = https:\u002F\u002Fprivate.pypi.org\u002Fsimple\u002F\nextra-index-url = https:\u002F\u002Fpypi.org\u002Fsimple\u002F\n\n# Upload to private index\ntwine upload --repository-url https:\u002F\u002Fprivate.pypi.org\u002F dist\u002F*\n```\n\n## File Templates\n\n### .gitignore for Python Packages\n\n```gitignore\n# Build artifacts\nbuild\u002F\ndist\u002F\n*.egg-info\u002F\n*.egg\n.eggs\u002F\n\n# Python\n__pycache__\u002F\n*.py[cod]\n*$py.class\n*.so\n\n# Virtual environments\nvenv\u002F\nenv\u002F\nENV\u002F\n\n# IDE\n.vscode\u002F\n.idea\u002F\n*.swp\n\n# Testing\n.pytest_cache\u002F\n.coverage\nhtmlcov\u002F\n\n# Distribution\n*.whl\n*.tar.gz\n```\n\n### MANIFEST.in\n\n```\n# MANIFEST.in\ninclude README.md\ninclude LICENSE\ninclude pyproject.toml\n\nrecursive-include src\u002Fmy_package\u002Fdata *.json\nrecursive-include src\u002Fmy_package\u002Ftemplates *.html\nrecursive-exclude * __pycache__\nrecursive-exclude * *.py[co]\n```\n\n## Checklist for Publishing\n\n- [ ] Code is tested (pytest passing)\n- [ ] Documentation is complete (README, docstrings)\n- [ ] Version number updated\n- [ ] CHANGELOG.md updated\n- [ ] License file included\n- [ ] pyproject.toml is complete\n- [ ] Package builds without errors\n- [ ] Installation tested in clean environment\n- [ ] CLI tools work (if applicable)\n- [ ] PyPI metadata is correct (classifiers, keywords)\n- [ ] GitHub repository linked\n- [ ] Tested on TestPyPI first\n- [ ] Git tag created for release\n\n## Resources\n\n- **Python Packaging Guide**: https:\u002F\u002Fpackaging.python.org\u002F\n- **PyPI**: https:\u002F\u002Fpypi.org\u002F\n- **TestPyPI**: https:\u002F\u002Ftest.pypi.org\u002F\n- **setuptools documentation**: https:\u002F\u002Fsetuptools.pypa.io\u002F\n- **build**: https:\u002F\u002Fpypa-build.readthedocs.io\u002F\n- **twine**: https:\u002F\u002Ftwine.readthedocs.io\u002F\n\n## Best Practices Summary\n\n1. **Use src\u002F layout** for cleaner package structure\n2. **Use pyproject.toml** for modern packaging\n3. **Pin build dependencies** in build-system.requires\n4. **Version appropriately** with semantic versioning\n5. **Include all metadata** (classifiers, URLs, etc.)\n6. **Test installation** in clean environments\n7. **Use TestPyPI** before publishing to PyPI\n8. **Document thoroughly** with README and docstrings\n9. **Include LICENSE** file\n10. **Automate publishing** with CI\u002FCD\n",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Factiveinferenceinstitute\u002Fpython-packaging",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":51,"prompt":61,"zipAvailable":62},[52,55,58],{"tool":53,"command":54},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill python-packaging",{"tool":56,"command":57},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill python-packaging",{"tool":59,"command":60},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill python-packaging","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Factiveinferenceinstitute\u002Fpython-packaging\u002FSKILL.md",true,[64],{"path":65,"resourceType":66,"resourceTypeDesc":67,"sizeBytes":68,"sourceHtmlUrl":69},"skill-report.json","REFERENCE","参考文档",20647,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Factiveinferenceinstitute\u002Fpython-packaging\u002Fskill-report.json",[71,85,95,104,110,117],{"skillNo":72,"name":73,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":81,"publishedAt":36},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[76],{"categoryNo":77,"categoryName":78,"taxonomyType":79,"taxonomyTypeDesc":80},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[82,83,84],"model","model hierarchy","model hierarchy skill",{"skillNo":86,"name":87,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":91,"publishedAt":36},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[90],{"categoryNo":77,"categoryName":78,"taxonomyType":79,"taxonomyTypeDesc":80},[92,93,94],"MCP","zoom","zoom mcp",{"skillNo":96,"name":97,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":100,"publishedAt":36},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[101,102,103,93],"sdk","zoom apps sdk","apps",{"skillNo":105,"name":106,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":36},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[106],{"skillNo":111,"name":112,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":116,"publishedAt":36},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[115],{"categoryNo":77,"categoryName":78,"taxonomyType":79,"taxonomyTypeDesc":80},[112],{"skillNo":118,"name":119,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":120,"categories":121,"keywords":122,"publishedAt":36},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[119]]