Compare commits
No commits in common. "9c8ddfdc8a7e4b345d3c3eed70cc7e519f27b6f0" and "904f4e487e6c0c4bfdc89d6008ab3fb6c1fe088b" have entirely different histories.
9c8ddfdc8a
...
904f4e487e
8 changed files with 0 additions and 417 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -15,7 +15,6 @@ dist/
|
|||
*.egg-info/
|
||||
.eggs/
|
||||
pip-wheel-metadata/
|
||||
.pypirc
|
||||
|
||||
# Test and coverage output
|
||||
.pytest_cache/
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
[distutils]
|
||||
index-servers = forgejo
|
||||
|
||||
[forgejo]
|
||||
repository = https://git.him-tools.de/api/packages/HIM-public/pypi
|
||||
username = __token__
|
||||
password = YOUR_FORGEJO_ACCESS_TOKEN
|
||||
46
README.md
46
README.md
|
|
@ -43,52 +43,6 @@ Install development dependencies when you want tests and code generation tooling
|
|||
& .\.venv\Scripts\python.exe -m pip install -e .[dev]
|
||||
```
|
||||
|
||||
## Packaging
|
||||
|
||||
Print the current package version:
|
||||
|
||||
```powershell
|
||||
& .\.venv\Scripts\python.exe .\scripts\set_version.py --print-current
|
||||
```
|
||||
|
||||
Update the package version in `pyproject.toml`:
|
||||
|
||||
```powershell
|
||||
& .\.venv\Scripts\python.exe .\scripts\set_version.py 0.1.1
|
||||
```
|
||||
|
||||
Build a wheel into `dist\`:
|
||||
|
||||
```powershell
|
||||
& .\.venv\Scripts\python.exe .\scripts\build_wheel.py
|
||||
```
|
||||
|
||||
Set the version and build the wheel in one step:
|
||||
|
||||
```powershell
|
||||
& .\.venv\Scripts\python.exe .\scripts\build_wheel.py --version 0.1.1
|
||||
```
|
||||
|
||||
Upload the wheel to the Forgejo package registry:
|
||||
|
||||
```powershell
|
||||
.\upload_wheel_to_forgejo_pypi.ps1
|
||||
```
|
||||
|
||||
Force a rebuild before upload:
|
||||
|
||||
```powershell
|
||||
.\upload_wheel_to_forgejo_pypi.ps1 -Build
|
||||
```
|
||||
|
||||
Build a specific version and upload it:
|
||||
|
||||
```powershell
|
||||
.\upload_wheel_to_forgejo_pypi.ps1 -Build -Version 0.1.1
|
||||
```
|
||||
|
||||
Create `.pypirc` in the project root from `.pypirc.example` and fill in your Forgejo token before uploading.
|
||||
|
||||
Create a client with your eBay credentials:
|
||||
|
||||
```python
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@ dependencies = [
|
|||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"build>=1.2,<2",
|
||||
"datamodel-code-generator>=0.28,<0.31",
|
||||
"pytest>=8,<9",
|
||||
"pytest-httpx>=0.35,<0.36",
|
||||
"twine>=6,<7",
|
||||
]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import importlib.util
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from set_version import PYPROJECT_PATH, extract_project_version, write_project_version
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Build a wheel for the project.")
|
||||
parser.add_argument("--version", help="Optionally set the project version before building.")
|
||||
parser.add_argument("--outdir", default="dist", help="Directory where the wheel will be written.")
|
||||
parser.add_argument("--no-clean", action="store_true", help="Keep existing build and output directories.")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def resolve_output_dir(outdir: str) -> Path:
|
||||
output_dir = Path(outdir)
|
||||
if not output_dir.is_absolute():
|
||||
output_dir = ROOT / output_dir
|
||||
return output_dir
|
||||
|
||||
|
||||
def ensure_build_dependency() -> None:
|
||||
if importlib.util.find_spec("build") is None:
|
||||
raise RuntimeError(
|
||||
'Missing dependency "build". Install development dependencies with '\
|
||||
'"python -m pip install -e .[dev]" or install "build" directly.'
|
||||
)
|
||||
|
||||
|
||||
def clean_build_artifacts(output_dir: Path) -> None:
|
||||
for path in (ROOT / "build", output_dir):
|
||||
if path.exists():
|
||||
shutil.rmtree(path)
|
||||
|
||||
|
||||
def build_wheel(output_dir: Path) -> None:
|
||||
command = [
|
||||
sys.executable,
|
||||
"-m",
|
||||
"build",
|
||||
"--wheel",
|
||||
"--outdir",
|
||||
str(output_dir),
|
||||
]
|
||||
subprocess.run(command, check=True, cwd=ROOT)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
output_dir = resolve_output_dir(args.outdir)
|
||||
|
||||
if args.version:
|
||||
previous_version, updated_version = write_project_version(PYPROJECT_PATH, args.version)
|
||||
if previous_version == updated_version:
|
||||
print(f"Version already set to {updated_version}")
|
||||
else:
|
||||
print(f"Updated version: {previous_version} -> {updated_version}")
|
||||
|
||||
ensure_build_dependency()
|
||||
|
||||
if not args.no_clean:
|
||||
clean_build_artifacts(output_dir)
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
version = extract_project_version(PYPROJECT_PATH.read_text(encoding="utf-8"))
|
||||
print(f"Building wheel for version {version} into {output_dir}")
|
||||
build_wheel(output_dir)
|
||||
|
||||
wheels = sorted(output_dir.glob("*.whl"))
|
||||
if not wheels:
|
||||
raise RuntimeError("Build completed without producing a wheel file.")
|
||||
for wheel in wheels:
|
||||
print(f"Built wheel: {wheel}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
PYPROJECT_PATH = ROOT / "pyproject.toml"
|
||||
PROJECT_VERSION_PATTERN = re.compile(
|
||||
r'(?ms)(^\[project\]\s*$.*?^version\s*=\s*")([^"\r\n]+)(")'
|
||||
)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Update the project version in pyproject.toml.")
|
||||
parser.add_argument("version", nargs="?", help="New project version.")
|
||||
parser.add_argument("--print-current", action="store_true", help="Print the current project version.")
|
||||
args = parser.parse_args()
|
||||
if not args.print_current and not args.version:
|
||||
parser.error("Provide a version or use --print-current.")
|
||||
return args
|
||||
|
||||
|
||||
def validate_version(version: str) -> str:
|
||||
normalized = version.strip()
|
||||
if not normalized:
|
||||
raise ValueError("Version cannot be empty.")
|
||||
if normalized != version:
|
||||
raise ValueError("Version cannot start or end with whitespace.")
|
||||
if any(character.isspace() for character in version):
|
||||
raise ValueError("Version cannot contain whitespace.")
|
||||
if '"' in version or "'" in version:
|
||||
raise ValueError("Version cannot contain quote characters.")
|
||||
return version
|
||||
|
||||
|
||||
def extract_project_version(pyproject_text: str) -> str:
|
||||
match = PROJECT_VERSION_PATTERN.search(pyproject_text)
|
||||
if match is None:
|
||||
raise ValueError("Could not find [project].version in pyproject.toml.")
|
||||
return match.group(2)
|
||||
|
||||
|
||||
def set_project_version_in_text(pyproject_text: str, new_version: str) -> str:
|
||||
validate_version(new_version)
|
||||
|
||||
def replace(match: re.Match[str]) -> str:
|
||||
return f"{match.group(1)}{new_version}{match.group(3)}"
|
||||
|
||||
updated_text, replacements = PROJECT_VERSION_PATTERN.subn(replace, pyproject_text, count=1)
|
||||
if replacements != 1:
|
||||
raise ValueError("Could not update [project].version in pyproject.toml.")
|
||||
|
||||
tomllib.loads(updated_text)
|
||||
return updated_text
|
||||
|
||||
|
||||
def write_project_version(pyproject_path: Path, new_version: str) -> tuple[str, str]:
|
||||
original_text = pyproject_path.read_text(encoding="utf-8")
|
||||
current_version = extract_project_version(original_text)
|
||||
updated_text = set_project_version_in_text(original_text, new_version)
|
||||
|
||||
if updated_text != original_text:
|
||||
pyproject_path.write_text(updated_text, encoding="utf-8")
|
||||
|
||||
return current_version, new_version
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
pyproject_text = PYPROJECT_PATH.read_text(encoding="utf-8")
|
||||
|
||||
if args.print_current:
|
||||
print(extract_project_version(pyproject_text))
|
||||
return 0
|
||||
|
||||
previous_version, updated_version = write_project_version(PYPROJECT_PATH, args.version)
|
||||
if previous_version == updated_version:
|
||||
print(f"Version already set to {updated_version}")
|
||||
else:
|
||||
print(f"Updated version: {previous_version} -> {updated_version}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(ROOT / "scripts"))
|
||||
|
||||
from set_version import extract_project_version, set_project_version_in_text, write_project_version
|
||||
|
||||
|
||||
def test_extract_project_version_reads_project_version() -> None:
|
||||
pyproject_text = (
|
||||
"[build-system]\n"
|
||||
'requires = ["setuptools>=69", "wheel"]\n\n'
|
||||
"[project]\n"
|
||||
'name = "ebay-rest-client"\n'
|
||||
'version = "0.1.0"\n'
|
||||
)
|
||||
|
||||
assert extract_project_version(pyproject_text) == "0.1.0"
|
||||
|
||||
|
||||
def test_set_project_version_in_text_updates_project_version_only() -> None:
|
||||
pyproject_text = (
|
||||
"[build-system]\n"
|
||||
'requires = ["setuptools>=69", "wheel"]\n\n'
|
||||
"[project]\n"
|
||||
'name = "ebay-rest-client"\n'
|
||||
'version = "0.1.0"\n'
|
||||
'description = "test package"\n'
|
||||
)
|
||||
|
||||
updated_text = set_project_version_in_text(pyproject_text, "1.2.3")
|
||||
|
||||
assert extract_project_version(updated_text) == "1.2.3"
|
||||
assert tomllib.loads(updated_text)["project"]["version"] == "1.2.3"
|
||||
|
||||
|
||||
def test_write_project_version_updates_file(tmp_path: Path) -> None:
|
||||
pyproject_path = tmp_path / "pyproject.toml"
|
||||
pyproject_path.write_text(
|
||||
"[project]\n"
|
||||
'name = "ebay-rest-client"\n'
|
||||
'version = "0.1.0"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
previous_version, updated_version = write_project_version(pyproject_path, "2.0.0")
|
||||
|
||||
assert previous_version == "0.1.0"
|
||||
assert updated_version == "2.0.0"
|
||||
assert tomllib.loads(pyproject_path.read_text(encoding="utf-8"))["project"]["version"] == "2.0.0"
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
param(
|
||||
[switch]$Build = $false,
|
||||
[string]$Version,
|
||||
[switch]$Help = $false
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Show-Help {
|
||||
Write-Host @"
|
||||
Upload wheel to the Forgejo PyPI registry for ebay-rest-client
|
||||
|
||||
USAGE:
|
||||
.\upload_wheel_to_forgejo_pypi.ps1 [-Build] [-Version <version>]
|
||||
|
||||
OPTIONS:
|
||||
-Build Force a rebuild before uploading
|
||||
-Version <version> Set the package version before building
|
||||
-Help Display this help message
|
||||
|
||||
SETUP:
|
||||
1. Copy .pypirc.example to .pypirc in the project root
|
||||
2. Add your Forgejo access token to .pypirc
|
||||
3. Run this script again
|
||||
|
||||
EXAMPLES:
|
||||
.\upload_wheel_to_forgejo_pypi.ps1
|
||||
.\upload_wheel_to_forgejo_pypi.ps1 -Build
|
||||
.\upload_wheel_to_forgejo_pypi.ps1 -Build -Version 0.1.1
|
||||
"@
|
||||
}
|
||||
|
||||
if ($Help) {
|
||||
Show-Help
|
||||
exit 0
|
||||
}
|
||||
|
||||
$projectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$python = Join-Path $projectRoot ".venv\Scripts\python.exe"
|
||||
$pypiRcPath = Join-Path $projectRoot ".pypirc"
|
||||
$buildScript = Join-Path $projectRoot "scripts\build_wheel.py"
|
||||
$distPath = Join-Path $projectRoot "dist"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "========================================================================"
|
||||
Write-Host "eBay REST Client - Upload to Forgejo PyPI"
|
||||
Write-Host "========================================================================"
|
||||
Write-Host ""
|
||||
|
||||
if (!(Test-Path $python)) {
|
||||
Write-Host "[!] Virtual environment Python not found at .venv\\Scripts\\python.exe" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (!(Test-Path $pypiRcPath)) {
|
||||
Write-Host "[!] .pypirc not found in project root." -ForegroundColor Red
|
||||
Write-Host ""
|
||||
Write-Host "Setup instructions:"
|
||||
Write-Host " 1. Copy .pypirc.example to .pypirc"
|
||||
Write-Host " 2. Edit .pypirc and add your Forgejo access token"
|
||||
Write-Host " 3. Run this script again"
|
||||
Write-Host ""
|
||||
Write-Host "For help: .\upload_wheel_to_forgejo_pypi.ps1 -Help"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (!(Test-Path $buildScript)) {
|
||||
Write-Host "[!] Build script not found at scripts\\build_wheel.py" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$null = & $python -c "import importlib.util, sys; sys.exit(0 if importlib.util.find_spec('twine') else 1)"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "Installing twine..."
|
||||
& $python -m pip install twine
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[!] Failed to install twine." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
$wheelFiles = @(Get-ChildItem -Path $distPath -Filter "*.whl" -ErrorAction SilentlyContinue)
|
||||
|
||||
if ($Build -or $wheelFiles.Count -eq 0) {
|
||||
if ($Build) {
|
||||
Write-Host "Building wheel (forced)..."
|
||||
} else {
|
||||
Write-Host "Building wheel..."
|
||||
}
|
||||
|
||||
$buildArgs = @($buildScript)
|
||||
if ($Version) {
|
||||
$buildArgs += "--version"
|
||||
$buildArgs += $Version
|
||||
}
|
||||
|
||||
& $python @buildArgs
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[!] Wheel build failed." -ForegroundColor Red
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
$wheelFiles = @(Get-ChildItem -Path $distPath -Filter "*.whl" -ErrorAction Stop)
|
||||
}
|
||||
|
||||
if ($wheelFiles.Count -eq 0) {
|
||||
Write-Host "[!] No wheel files found in dist." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "========================================================================"
|
||||
Write-Host "Uploading to Forgejo PyPI..."
|
||||
Write-Host "========================================================================"
|
||||
Write-Host ""
|
||||
|
||||
& $python -m twine upload --config-file $pypiRcPath -r forgejo $wheelFiles.FullName
|
||||
$uploadResult = $LASTEXITCODE
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "========================================================================"
|
||||
if ($uploadResult -eq 0) {
|
||||
Write-Host "Upload successful!" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "Upload failed" -ForegroundColor Red
|
||||
}
|
||||
Write-Host "========================================================================"
|
||||
Write-Host ""
|
||||
|
||||
exit $uploadResult
|
||||
Loading…
Add table
Add a link
Reference in a new issue