12 KiB
Building and Distributing Elytra PIM Client
This guide explains how to build wheel distributions and upload them to PyPI or other package repositories.
Project Version
Current version: 0.1.0 (Development Release)
The version is defined in pyproject.toml under [project] section.
Build Tools
Requirements
- Python 3.9 or higher
- pip with setuptools and wheel
Build Dependencies
Install build requirements:
pip install -r build_requirements.txt
Or manually:
pip install "setuptools>=65.0" "wheel>=0.38.0" "build>=0.10.0"
Building Wheels
Option 1: Using Python Script (Recommended for All Platforms)
# Activate virtual environment first
.venv\Scripts\activate # Windows
source .venv/bin/activate # macOS/Linux
# Run the build script
python build_wheel.py
This script will:
- Clean previous build artifacts
- Build wheel (
.whl) and source (.tar.gz) distributions - Display the build results with file sizes
- Show installation instructions
Option 2: Using PowerShell Script (Windows)
# Activate virtual environment
.\.venv\Scripts\Activate.ps1
# Run the build script
.\build_wheel.ps1
# Clean and rebuild
.\build_wheel.ps1 -Clean
# Build and upload to PyPI
.\build_wheel.ps1 -Upload
Option 3: Using Shell Script (macOS/Linux)
# Activate virtual environment
source .venv/bin/activate
# Run the build script
chmod +x build_wheel.sh # Make executable (first time only)
./build_wheel.sh
# Clean and rebuild
./build_wheel.sh --clean
# Build and upload to PyPI
./build_wheel.sh --upload
Option 4: Using Modern Build Tool Directly
# Install build tool
pip install build
# Build wheel and sdist in one command
python -m build
# Build only wheel
python -m build --wheel
# Build only source distribution
python -m build --sdist
Option 5: Using setuptools Directly
# Create wheel only
python setup.py bdist_wheel
# Create both wheel and source distribution
python setup.py sdist bdist_wheel
Build Output
Distributions are created in the dist/ directory:
dist/
├── elytra_pim_client-0.1.0-py3-none-any.whl # Wheel distribution
└── elytra_pim_client-0.1.0.tar.gz # Source distribution
Understanding the Wheel Filename
elytra_pim_client-0.1.0-py3-none-any.whl
elytra_pim_client- Package name0.1.0- Versionpy3- Python version (3.x only)none- No C extensions (pure Python)any- Platform independent
Installation from Built Wheel
From Local File
After building, install the wheel locally:
pip install dist/elytra_pim_client-0.1.0-py3-none-any.whl
Editable Install During Development
During development, use editable install so changes are reflected immediately:
pip install -e .
Or with dev dependencies:
pip install -e ".[dev]"
Uploading to Forgejo PyPI
This project uses Forgejo PyPI for package distribution, not the public PyPI. Forgejo is a self-hosted Git service with integrated package registry support.
Setup Forgejo PyPI
Step 1: Create .pypirc Configuration
Copy the example configuration:
cp .pypirc.example .pypirc
Edit .pypirc with your Forgejo details:
[distutils]
index-servers =
forgejo
[forgejo]
repository = https://your-forgejo-instance.com/api/packages/YOUR_USERNAME/pypi
username = __token__
password = YOUR_ACCESS_TOKEN
Step 2: Generate Forgejo Personal Access Token
- Visit your Forgejo instance:
https://your-forgejo-instance.com - Go to: User Settings → Applications
- Click Create New Token
- Name it:
PyPI Upload - Grant scope: write:packages
- Copy the generated token
- Paste into
.pypircaspassword
Step 3: Secure .pypirc
IMPORTANT: Add .pypirc to .gitignore to prevent committing credentials!
echo ".pypirc" >> .gitignore
git add .gitignore
git commit -m "chore: add .pypirc to gitignore"
Uploading to Forgejo PyPI
Requirement: twine must be installed (see Prerequisites section above)
Option 1: Using PowerShell Script (Windows - Recommended)
# Activate virtual environment first
.\.venv\Scripts\Activate.ps1
# Upload existing wheel
.\upload_wheel_to_forgejo_pypi.ps1
# Rebuild and upload
.\upload_wheel_to_forgejo_pypi.ps1 -Build
# Show help
.\upload_wheel_to_forgejo_pypi.ps1 -Help
Option 2: Using Batch Script (Windows)
upload_wheel_to_forgejo_pypi.bat
REM Rebuild and upload
upload_wheel_to_forgejo_pypi.bat --build
Option 3: Using Shell Script (Unix/Linux)
# Make script executable (first time only)
chmod +x upload_wheel_to_forgejo_pypi.sh
# Upload existing wheel
./upload_wheel_to_forgejo_pypi.sh
# Rebuild and upload
./upload_wheel_to_forgejo_pypi.sh --build
# Show help
./upload_wheel_to_forgejo_pypi.sh --help
Option 4: Using twine Directly
# Activate virtual environment
.venv\Scripts\activate # Windows
source .venv/bin/activate # macOS/Linux
# Upload wheel to Forgejo (twine is already in requirements.txt)
twine upload -r forgejo dist/*.whl
What the Upload Scripts Do
- Load credentials - Reads .pypirc configuration
- Setup environment - Copies .pypirc to user home directory temporarily
- Activate venv - Sets up Python virtual environment
- Build wheel - Builds wheel if not present (or with --build flag)
- Upload - Uploads wheel to Forgejo PyPI repository using twine
- Cleanup - Removes temporary credentials from home directory
- Deactivate - Deactivates virtual environment
Accessing Your Package
After upload, your package is available in the Forgejo PyPI repository:
# Install from Forgejo PyPI
pip install --index-url https://your-forgejo-instance.com/api/packages/YOUR_USERNAME/pypi/simple/ elytra-pim-client
# Or add to requirements.txt
-i https://your-forgejo-instance.com/api/packages/YOUR_USERNAME/pypi/simple/
elytra-pim-client
Troubleshooting Upload Issues
"Upload failed" Error
Check: Verify .pypirc configuration
[forgejo]
repository = https://correct-url.com/api/packages/USERNAME/pypi
username = __token__
password = VALID_TOKEN
Verify: Token has correct permissions
- Token must have
write:packagesscope - Visit:
https://your-forgejo-instance.com/user/settings/applications
Network: Ensure Forgejo instance is reachable
curl https://your-forgejo-instance.com/api/v1/user
".pypirc not found" Error
Create it from template:
cp .pypirc.example .pypirc
# Then edit with your credentials
"twine: command not found" Error
Solution: twine is included in requirements.txt as a development dependency. Install all dependencies:
pip install -r requirements.txt
Example Workflow
# 1. Setup Forgejo PyPI (first time only)
cp .pypirc.example .pypirc
# Edit .pypirc with your Forgejo repository URL and credentials
echo ".pypirc" >> .gitignore
git add .gitignore
git commit -m "chore: add .pypirc to gitignore"
# 2. Make code changes
git commit -am "feat: add new feature"
# 3. Update version in pyproject.toml
# version = "0.2.0"
# 4. Build and upload to Forgejo PyPI
.\upload_wheel_to_forgejo_pypi.ps1 # PowerShell
# or
./upload_wheel_to_forgejo_pypi.sh # Bash/Shell
# or
./upload_wheel_to_forgejo_pypi.bat # Batch
# 5. Tag and push release
git tag v0.2.0
git push origin v0.2.0
Uploading to Public PyPI (Future)
To upload to public PyPI instead of Forgejo:
- Install twine:
pip install twine - Create account at https://pypi.org/
- Generate token at https://pypi.org/manage/account/tokens/
- Create
.pypirc:[distutils] index-servers = pypi [pypi] repository = https://upload.pypi.org/legacy/ username = __token__ password = pypi_your_token_here - Upload:
twine upload -r pypi dist/*.whl
Versioning
Version Format
Follow PEP 440 versioning:
Major.Minor.Patch (e.g., 0.1.0)
Major.Minor.Patch.preN (e.g., 0.1.0.pre1)
Major.Minor.Patch.postN (e.g., 0.1.0.post1)
Major.Minor.Patch.devN (e.g., 0.1.0.dev1)
Updating Version
Edit pyproject.toml:
[project]
name = "elytra-pim-client"
version = "0.2.0" # Update version here
Automatic Build Validation
Before building, scripts automatically:
- Remove old build artifacts
- Clean
dist/,build/, and.egg-infodirectories - Verify build dependencies
- Validate Python version compatibility
- Check that distributions were created
Continuous Integration
GitHub Actions Example
name: Build Distribution
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: pip install -r build_requirements.txt
- run: python build_wheel.py
- uses: actions/upload-artifact@v3
with:
name: dist
path: dist/
upload:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v3
with:
name: dist
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1
Troubleshooting
Build Fails with "No module named 'build'"
pip install build
python build_wheel.py
"setuptools not found"
pip install setuptools>=65.0
Permission Denied (Unix/Linux)
Make build script executable:
chmod +x build_wheel.sh
"twine: command not found"
pip install twine
python -m twine upload dist/*
Wheel not in dist/
Check that pyproject.toml exists and is valid:
python -m build --verbose
File Structure
elytra_client/
├── build_wheel.py # Python build script (all platforms)
├── build_wheel.ps1 # PowerShell build script (Windows)
├── build_wheel.sh # Shell build script (Unix/Linux)
├── upload_wheel_to_forgejo_pypi.bat # Batch upload script (Windows)
├── upload_wheel_to_forgejo_pypi.ps1 # PowerShell upload script (Windows)
├── upload_wheel_to_forgejo_pypi.sh # Shell upload script (Unix/Linux)
├── .pypirc.example # Forgejo PyPI configuration template
├── .pypirc # Forgejo PyPI credentials (in .gitignore!)
├── build_requirements.txt # Build dependencies
├── setup.py # Setup configuration (legacy compatibility)
├── pyproject.toml # Modern build configuration (PEP 517/518)
└── dist/ # Output directory for distributions
├── elytra_pim_client-0.1.0-py3-none-any.whl
└── elytra_pim_client-0.1.0.tar.gz
Best Practices
-
Setup Forgejo PyPI (first time only)
cp .pypirc.example .pypirc # Edit .pypirc with your Forgejo credentials echo ".pypirc" >> .gitignore -
Complete release workflow
# Update version in pyproject.toml # version = "0.2.0" # Build and upload .\upload_wheel_to_forgejo_pypi.ps1 # Tag and push git tag v0.2.0 git push origin v0.2.0 -
Increment version for each release
- Patch: Bug fixes (0.1.1)
- Minor: New features (0.2.0)
- Major: Breaking changes (1.0.0)
-
Clean before rebuilding
python build_wheel.py # Automatically cleans # Or manually rm -rf dist/ build/ *.egg-info/ -
Keep dependencies minimal
- Only required packages in
dependencies - Development tools in
[project.optional-dependencies]
- Only required packages in
-
Use .pypirc template
- Never commit
.pypircwith real credentials - Always keep
.pypircin.gitignore - Share
.pypirc.examplewith template values
- Never commit
-
Secure credential handling
- Use Forgejo personal access tokens with limited scope
- Rotate tokens regularly
- Never share tokens or .pypirc files