This guide explains how to publish hyper2kvm to PyPI so users can install it with pip install hyper2kvm.
# Install/upgrade build tools
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade build twine
Verify all required files exist:
ls -1 pyproject.toml MANIFEST.in README.md LICENSE requirements.txt setup.py
All files should be present.
Create accounts on both Test PyPI and production PyPI:
Highly recommended for security:
API tokens are more secure than passwords.
pypi-)Create ~/.pypirc:
cat >~/.pypirc <<'EOF'
[distutils]
index-servers =
pypi
testpypi
[pypi]
username = __token__
password = pypi-YOUR-PRODUCTION-TOKEN-HERE
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-YOUR-TEST-TOKEN-HERE
EOF
chmod 600 ~/.pypirc
Important: Replace pypi-YOUR-*-TOKEN-HERE with your actual API tokens.
# Remove old build artifacts
rm -rf build/ dist/ *.egg-info
Edit version in 3 places:
# 1. pyproject.toml
vim pyproject.toml # Update version = "0.0.1" to "0.0.2" etc.
# 2. hyper2kvm/__init__.py
vim hyper2kvm/__init__.py # Update __version__ = "0.0.1"
# 3. setup.py (if still used)
vim setup.py # Update version="0.0.1"
Pro tip: Use a script to update all versions:
NEW_VERSION="0.0.2"
sed -i "s/^version = \".*\"/version = \"$NEW_VERSION\"/" pyproject.toml
sed -i "s/__version__ = \".*\"/__version__ = \"$NEW_VERSION\"/" hyper2kvm/__init__.py
sed -i "s/version=\".*\"/version=\"$NEW_VERSION\"/" setup.py
git diff # Review changes
python3 -m build
This creates:
dist/hyper2kvm-0.0.1.tar.gz (source distribution)dist/hyper2kvm-0.0.1-py3-none-any.whl (wheel)# Check built files
ls -lh dist/
# Inspect wheel contents
unzip -l dist/hyper2kvm-*.whl
# Inspect tarball contents
tar tzf dist/hyper2kvm-*.tar.gz | head -20
# Check with twine
twine check dist/*
Should output: Checking dist/... PASSED
Always test with TestPyPI first before publishing to production.
twine upload --repository testpypi dist/*
# Create test virtual environment
python3 -m venv /tmp/test-hyper2kvm
source /tmp/test-hyper2kvm/bin/activate
# Install from TestPyPI
pip install --index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
hyper2kvm
# Test the package
hyper2kvm --version
hyper2kvm --help
# Test library import
python3 -c "import hyper2kvm; print(hyper2kvm.__version__)"
# Test library API
python3 <<'EOF'
from hyper2kvm import GuestDetector, DiskProcessor
print("✓ Library imports work!")
EOF
# Cleanup
deactivate
rm -rf /tmp/test-hyper2kvm
Visit: https://test.pypi.org/project/hyper2kvm/
Verify:
Once testing passes, publish to production PyPI.
# Ensure you're on main branch
git branch
# Ensure working tree is clean
git status
# Verify version is correct
grep version pyproject.toml
grep __version__ hyper2kvm/__init__.py
# Re-check package
twine check dist/*
VERSION="0.0.1"
git tag -a "v${VERSION}" -m "Release v${VERSION}"
git push origin "v${VERSION}"
twine upload dist/*
Visit: https://pypi.org/project/hyper2kvm/
# Fresh environment
python3 -m venv /tmp/test-pypi-hyper2kvm
source /tmp/test-pypi-hyper2kvm/bin/activate
# Install from production PyPI
pip install hyper2kvm
# Test
hyper2kvm --version
python3 -c "import hyper2kvm; print(hyper2kvm.__version__)"
# Cleanup
deactivate
rm -rf /tmp/test-pypi-hyper2kvm
Go to: https://github.com/ssahani/hyper2kvm/releases/new
v0.0.1v0.0.1 - Initial Release## What's New
- Initial public release
- Full library API support
- VMware, Azure, Hyper-V support
- Comprehensive documentation
## Installation
```bash
pip install hyper2kvm
dist/ filesAutomate releases with GitHub Actions.
.github/workflows/publish-pypi.ymlname: Publish to PyPI
on:
release:
types: [published]
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install build tools
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build package
run: python -m build
- name: Check package
run: twine check dist/*
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: $
run: twine upload dist/*
PYPI_API_TOKEN# Create and push a tag
git tag -a v0.0.2 -m "Release v0.0.2"
git push origin v0.0.2
# Create GitHub release (via UI or gh CLI)
gh release create v0.0.2 \
--title "v0.0.2" \
--notes "Bug fixes and improvements"
# GitHub Actions will automatically:
# - Build the package
# - Run checks
# - Publish to PyPI
Follow SemVer:
For testing:
# Alpha release
version = "0.1.0a1"
# Beta release
version = "0.1.0b1"
# Release candidate
version = "0.1.0rc1"
Before each release:
pyproject.tomlhyper2kvm/__init__.pysetup.pyhyper2kvm.spec (for RPM)CHANGELOG.md (if exists)PyPI doesn’t allow re-uploading the same version. Solutions:
# Change 0.0.1 to 0.0.2
version = "0.0.1.post1"
# Check ~/.pypirc exists and has correct format
cat ~/.pypirc
# Verify token is correct (starts with pypi-)
# Regenerate token if needed
Wait a few minutes - PyPI indexing takes time. Check:
# Check PyPI project page
curl -s https://pypi.org/pypi/hyper2kvm/json | jq -r '.info.version'
Verify package structure:
# Check wheel contents
unzip -l dist/hyper2kvm-*.whl | grep -E "\.py$"
# Should include all hyper2kvm/* files
# Ensure pyproject.toml is valid
python3 <<EOF
import tomllib
with open('pyproject.toml', 'rb') as f:
print(tomllib.load(f))
EOF
Ensure README.md uses standard markdown (not GitHub-specific features).
Test locally:
pip install readme-renderer
python3 -m readme_renderer README.md
# 1. Update version
VERSION="0.0.2"
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
sed -i "s/__version__ = \".*\"/__version__ = \"$VERSION\"/" hyper2kvm/__init__.py
# 2. Clean and build
rm -rf build/ dist/ *.egg-info
python3 -m build
# 3. Check
twine check dist/*
# 4. Test with TestPyPI
twine upload --repository testpypi dist/*
pip install --index-url https://test.pypi.org/simple/ hyper2kvm
# 5. Tag and publish
git tag -a "v${VERSION}" -m "Release v${VERSION}"
git push origin "v${VERSION}"
twine upload dist/*
# 6. Verify
pip install --upgrade hyper2kvm
hyper2kvm --version
Status: Ready for PyPI publication