550 lines
12 KiB
Markdown
550 lines
12 KiB
Markdown
# 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 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:
|
|
|
|
```bash
|
|
cp .pypirc.example .pypirc
|
|
```
|
|
|
|
Edit `.pypirc` with your Forgejo details:
|
|
|
|
```ini
|
|
[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 Settings** → **Applications**
|
|
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!
|
|
|
|
```bash
|
|
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)
|
|
|
|
```powershell
|
|
# 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)
|
|
|
|
```batch
|
|
upload_wheel_to_forgejo_pypi.bat
|
|
|
|
REM Rebuild and upload
|
|
upload_wheel_to_forgejo_pypi.bat --build
|
|
```
|
|
|
|
#### Option 3: Using Shell Script (Unix/Linux)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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
|
|
```ini
|
|
[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
|
|
```bash
|
|
curl https://your-forgejo-instance.com/api/v1/user
|
|
```
|
|
|
|
#### ".pypirc not found" Error
|
|
|
|
Create it from template:
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
### Example Workflow
|
|
|
|
```bash
|
|
# 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`:
|
|
```ini
|
|
[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`:
|
|
|
|
```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)
|
|
├── 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)**
|
|
```bash
|
|
cp .pypirc.example .pypirc
|
|
# Edit .pypirc with your Forgejo credentials
|
|
echo ".pypirc" >> .gitignore
|
|
```
|
|
|
|
2. **Complete release workflow**
|
|
```bash
|
|
# 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**
|
|
```bash
|
|
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
|
|
|
|
- [Forgejo Documentation](https://docs.forgejo.org/)
|
|
- [Forgejo PyPI Package Registry](https://docs.forgejo.org/en/latest/usage/packages/pypi/)
|
|
- [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/)
|