# 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: ```bash pip install -r build_requirements.txt ``` Or manually: ```bash pip install "setuptools>=65.0" "wheel>=0.38.0" "build>=0.10.0" ``` ## Building Wheels ### Option 1: Using Python Script (Recommended for All Platforms) ```bash # 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) ```powershell # 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) ```bash # 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 ```bash # 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 ```bash # 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: ```bash 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: ```bash pip install -e . ``` Or with dev dependencies: ```bash pip install -e ".[dev]" ``` ## Uploading to PyPI ### Prerequisites 1. Create PyPI account at https://pypi.org/ 2. Create PyPI token: https://pypi.org/manage/account/tokens/ 3. Configure credentials ### Using twine ```bash # Install twine pip install twine # Upload to PyPI (after building) twine upload dist/* # Or to TestPyPI for testing first twine upload -r testpypi dist/* ``` ### Authentication **Option 1: Using .pypirc file** Create `~/.pypirc`: ```ini [distutils] index-servers = pypi testpypi [pypi] repository = https://upload.pypi.org/legacy/ username = __token__ password = pypi_your_token_here [testpypi] repository = https://test.pypi.org/legacy/ username = __token__ password = pypi_your_test_token_here ``` **Option 2: Interactive prompt** twine will prompt for username and password when uploading. ### Upload to Test PyPI First Before uploading to production, test with TestPyPI: ```bash twine upload -r testpypi dist/* ``` Then test installation: ```bash pip install -i https://test.pypi.org/simple/ elytra-pim-client==0.1.0 ``` ## 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`: ```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 ```yaml 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'" ```bash pip install build python build_wheel.py ``` ### "setuptools not found" ```bash pip install setuptools>=65.0 ``` ### Permission Denied (Unix/Linux) Make build script executable: ```bash chmod +x build_wheel.sh ``` ### "twine: command not found" ```bash pip install twine python -m twine upload dist/* ``` ### Wheel not in dist/ Check that `pyproject.toml` exists and is valid: ```bash 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) ├── build_requirements.txt # Build dependencies ├── setup.py # Setup configuration (legacy compatibility) ├── pyproject.toml # Modern build configuration (PEP 517/518) ├── MANIFEST.in # (Optional) File inclusion rules └── 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. **Always test before releasing** ```bash twine upload -r testpypi dist/* pip install -i https://test.pypi.org/simple/ elytra-pim-client==0.1.0 ``` 2. **Increment version for each release** - Patch: Bug fixes (0.1.1) - Minor: New features (0.2.0) - Major: Breaking changes (1.0.0) 3. **Clean before rebuilding** ```bash python build_wheel.py # Automatically cleans # Or manually rm -rf dist/ build/ *.egg-info/ ``` 4. **Keep dependencies minimal** - Only required packages in `dependencies` - Development tools in `[project.optional-dependencies]` 5. **Document changes** - Update CHANGELOG.md (if present) - Update version in pyproject.toml - Create git tag for release ## Resources - [Python Packaging Guide](https://packaging.python.org/) - [PEP 517 - Build System Interface](https://www.python.org/dev/peps/pep-0517/) - [PEP 518 - pyproject.toml](https://www.python.org/dev/peps/pep-0518/) - [PEP 440 - Version Identification](https://www.python.org/dev/peps/pep-0440/) - [setuptools Documentation](https://setuptools.pypa.io/) - [twine Documentation](https://twine.readthedocs.io/) - [PyPI Help](https://pypi.org/help/)