feat: Add packaging and publishing scripts, update dependencies, and enhance .gitignore
This commit is contained in:
parent
f2e5774204
commit
6ba7b0773a
6 changed files with 218 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,3 +7,4 @@ __pycache__/
|
||||||
dist/
|
dist/
|
||||||
build/
|
build/
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
|
.pypirc
|
||||||
|
|
|
||||||
22
.pypirc.example
Normal file
22
.pypirc.example
Normal 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
|
||||||
14
README.md
14
README.md
|
|
@ -17,6 +17,20 @@ A Python client for the Booklooker REST API designed for middleware and connecto
|
||||||
pip install -e .[dev,webhooks]
|
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
|
## Quick start
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
|
||||||
60
build_dist.py
Normal file
60
build_dist.py
Normal 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()
|
||||||
|
|
@ -24,7 +24,9 @@ webhooks = [
|
||||||
]
|
]
|
||||||
dev = [
|
dev = [
|
||||||
"pytest>=8.3.3",
|
"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]
|
[tool.setuptools.package-dir]
|
||||||
|
|
|
||||||
118
upload_dist_to_forgejo_pypi.ps1
Normal file
118
upload_dist_to_forgejo_pypi.ps1
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue