feat: Add packaging and publishing scripts, update dependencies, and enhance .gitignore

This commit is contained in:
claudi 2026-04-16 15:40:05 +02:00
parent f2e5774204
commit 6ba7b0773a
6 changed files with 218 additions and 1 deletions

1
.gitignore vendored
View file

@ -7,3 +7,4 @@ __pycache__/
dist/
build/
*.egg-info/
.pypirc

22
.pypirc.example Normal file
View file

@ -0,0 +1,22 @@
[distutils]
index-servers =
forgejo
[forgejo]
# Forgejo PyPI Repository Configuration
# Repository: https://your-forgejo-instance.com/api/packages/{username}/pypi
# Documentation: https://docs.forgejo.org/en/latest/usage/packages/pypi/
#
# To use this file:
# 1. Replace YOUR_FORGEJO_INSTANCE with your Forgejo URL
# 2. Replace YOUR_USERNAME with your Forgejo username
# 3. Replace YOUR_ACCESS_TOKEN with your Forgejo personal access token
# (Generate at: https://your-forgejo-instance.com/user/settings/applications)
# 4. Keep this file secure (credentials inside!)
#
# WARNING: This file contains sensitive credentials.
# Add to .gitignore to prevent accidental commits!
repository = https://git.him-tools.de/api/packages/HIM-public/pypi/
username = __token__
password = YOUR_ACCESS_TOKEN

View file

@ -17,6 +17,20 @@ A Python client for the Booklooker REST API designed for middleware and connecto
pip install -e .[dev,webhooks]
```
## Packaging and publishing
Build a source distribution and wheel:
```bash
python build_dist.py
```
Upload the artifacts to Forgejo PyPI after creating your local `.pypirc` from `.pypirc.example`:
```powershell
.\upload_dist_to_forgejo_pypi.ps1 -Build
```
## Quick start
```python

60
build_dist.py Normal file
View file

@ -0,0 +1,60 @@
"""Build wheel and source distribution for publishing."""
from __future__ import annotations
import shutil
import subprocess
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent
DIST_DIR = PROJECT_ROOT / "dist"
BUILD_DIR = PROJECT_ROOT / "build"
def run(cmd: list[str]) -> None:
print(f"[+] Running: {' '.join(cmd)}")
result = subprocess.run(cmd, cwd=PROJECT_ROOT)
if result.returncode != 0:
raise SystemExit(result.returncode)
def ensure_package(package: str) -> None:
result = subprocess.run(
[sys.executable, "-m", "pip", "show", package],
cwd=PROJECT_ROOT,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
if result.returncode != 0:
print(f"[+] Installing missing dependency: {package}")
run([sys.executable, "-m", "pip", "install", package])
def main() -> None:
print()
print("=" * 72)
print("Booklooker Client - Build Python Distribution")
print("=" * 72)
print()
ensure_package("build")
if DIST_DIR.exists():
shutil.rmtree(DIST_DIR)
if BUILD_DIR.exists():
shutil.rmtree(BUILD_DIR)
run([sys.executable, "-m", "build"])
files = sorted(path.name for path in DIST_DIR.glob("*"))
print()
print("Built artifacts:")
for name in files:
print(f" - {name}")
print()
print("Build completed successfully.")
if __name__ == "__main__":
main()

View file

@ -24,7 +24,9 @@ webhooks = [
]
dev = [
"pytest>=8.3.3",
"pytest-asyncio>=0.24.0"
"pytest-asyncio>=0.24.0",
"build>=1.2.2",
"twine>=5.1.1"
]
[tool.setuptools.package-dir]

View file

@ -0,0 +1,118 @@
# Upload Python distribution artifacts to Forgejo PyPI
#
# Prerequisites:
# 1. Create .pypirc in the project root
# 2. Copy from .pypirc.example and add your Forgejo credentials
#
# Usage:
# .\upload_dist_to_forgejo_pypi.ps1
# .\upload_dist_to_forgejo_pypi.ps1 -Build
param(
[switch]$Build = $false,
[switch]$Help = $false
)
if ($Help) {
Write-Host @"
Upload distribution artifacts to Forgejo PyPI for Booklooker Client
USAGE:
.\upload_dist_to_forgejo_pypi.ps1 [-Build]
OPTIONS:
-Build Force rebuild the package before uploading
-Help Display this help message
SETUP:
1. Create .pypirc in the project root
2. Copy from .pypirc.example as template
3. Add your Forgejo repository URL and credentials:
[distutils]
index-servers = forgejo
[forgejo]
repository = https://your-forgejo-instance.com/api/packages/YOUR_USERNAME/pypi
username = __token__
password = YOUR_ACCESS_TOKEN
EXAMPLES:
.\upload_dist_to_forgejo_pypi.ps1 # Upload existing dist artifacts
.\upload_dist_to_forgejo_pypi.ps1 -Build # Rebuild and upload
"@
exit 0
}
$projectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$pypiRcSrc = Join-Path $projectRoot ".pypirc"
$pypiRcDest = Join-Path $env:USERPROFILE ".pypirc"
$activateScript = Join-Path $projectRoot ".venv\Scripts\Activate.ps1"
Write-Host ""
Write-Host "========================================================================"
Write-Host "Booklooker Client - Upload to Forgejo PyPI"
Write-Host "========================================================================"
Write-Host ""
if (!(Test-Path $pypiRcSrc)) {
Write-Host "[!] .pypirc not found in the project root." -ForegroundColor Red
Write-Host ""
Write-Host "Setup instructions:"
Write-Host " 1. Copy .pypirc.example to .pypirc"
Write-Host " 2. Edit .pypirc with your Forgejo credentials"
Write-Host " 3. Run this script again"
Write-Host ""
exit 1
}
if (!(Test-Path $activateScript)) {
Write-Host "[!] Virtual environment activation script not found: $activateScript" -ForegroundColor Red
exit 1
}
Write-Host "Configuring credentials..."
Copy-Item -Path $pypiRcSrc -Destination $pypiRcDest -Force
try {
& $activateScript
python -m pip show twine *> $null
if ($LASTEXITCODE -ne 0) {
Write-Host "Installing twine..."
python -m pip install twine
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}
Push-Location $projectRoot
$distArtifacts = Get-ChildItem -Path "dist" -File -ErrorAction SilentlyContinue
if ($Build -or !$distArtifacts) {
if ($Build) {
Write-Host "Rebuilding distribution artifacts..."
} else {
Write-Host "No distribution artifacts found. Building package..."
}
python .\build_dist.py
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}
Write-Host ""
Write-Host "========================================================================"
Write-Host "Uploading distribution artifacts to Forgejo PyPI..."
Write-Host "========================================================================"
Write-Host ""
twine upload -r forgejo dist/*
exit $LASTEXITCODE
}
finally {
Pop-Location -ErrorAction SilentlyContinue
if (Test-Path $pypiRcDest) {
Remove-Item $pypiRcDest -Force -ErrorAction SilentlyContinue
}
}