elytra_client/BUILD.md

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

# 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 name
  • 0.1.0 - Version
  • py3 - 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

  1. Visit your Forgejo instance: https://your-forgejo-instance.com
  2. Go to: User SettingsApplications
  3. Click Create New Token
  4. Name it: PyPI Upload
  5. Grant scope: write:packages
  6. Copy the generated token
  7. Paste into .pypirc as password

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)

# 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

  1. Load credentials - Reads .pypirc configuration
  2. Setup environment - Copies .pypirc to user home directory temporarily
  3. Activate venv - Sets up Python virtual environment
  4. Build wheel - Builds wheel if not present (or with --build flag)
  5. Upload - Uploads wheel to Forgejo PyPI repository using twine
  6. Cleanup - Removes temporary credentials from home directory
  7. 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:packages scope
  • 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:

  1. Install twine: pip install twine
  2. Create account at https://pypi.org/
  3. Generate token at https://pypi.org/manage/account/tokens/
  4. Create .pypirc:
    [distutils]
    index-servers =
        pypi
    
    [pypi]
    repository = https://upload.pypi.org/legacy/
    username = __token__
    password = pypi_your_token_here
    
  5. 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:

  1. Remove old build artifacts
  2. Clean dist/, build/, and .egg-info directories
  3. Verify build dependencies
  4. Validate Python version compatibility
  5. 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

  1. Setup Forgejo PyPI (first time only)

    cp .pypirc.example .pypirc
    # Edit .pypirc with your Forgejo credentials
    echo ".pypirc" >> .gitignore
    
  2. 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
    
  3. Increment version for each release

    • Patch: Bug fixes (0.1.1)
    • Minor: New features (0.2.0)
    • Major: Breaking changes (1.0.0)
  4. Clean before rebuilding

    python build_wheel.py  # Automatically cleans
    # Or manually
    rm -rf dist/ build/ *.egg-info/
    
  5. Keep dependencies minimal

    • Only required packages in dependencies
    • Development tools in [project.optional-dependencies]
  6. Use .pypirc template

    • Never commit .pypirc with real credentials
    • Always keep .pypirc in .gitignore
    • Share .pypirc.example with template values
  7. Secure credential handling

    • Use Forgejo personal access tokens with limited scope
    • Rotate tokens regularly
    • Never share tokens or .pypirc files

Resources