Compare commits
No commits in common. "03991fdea542f063314841515ed5e53d8d229a65" and "14dac17024a13e6441449f651c50a31ee76a7e47" have entirely different histories.
03991fdea5
...
14dac17024
8 changed files with 2982 additions and 2994 deletions
53
README.md
53
README.md
|
|
@ -19,7 +19,7 @@ WebDrop Bridge embeds a web application in a Qt container with full filesystem a
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- ✅ **Qt-based Architecture** - Professional Windows support via PySide6 (macOS support planned)
|
- ✅ **Qt-based Architecture** - Native Windows & macOS support via PySide6
|
||||||
- ✅ **Embedded Web App** - QtWebEngine provides Chromium without browser limitations
|
- ✅ **Embedded Web App** - QtWebEngine provides Chromium without browser limitations
|
||||||
- ✅ **Drag Interception** - Converts text paths to native file operations
|
- ✅ **Drag Interception** - Converts text paths to native file operations
|
||||||
- ✅ **Path Whitelist** - Security-conscious file system access control
|
- ✅ **Path Whitelist** - Security-conscious file system access control
|
||||||
|
|
@ -35,7 +35,7 @@ WebDrop Bridge embeds a web application in a Qt container with full filesystem a
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
- Python 3.10+
|
- Python 3.10+
|
||||||
- Windows 10/11
|
- Windows 10/11 or macOS 12+
|
||||||
- 200 MB disk space (includes Chromium from PyInstaller)
|
- 200 MB disk space (includes Chromium from PyInstaller)
|
||||||
|
|
||||||
### Installation from Source
|
### Installation from Source
|
||||||
|
|
@ -47,6 +47,7 @@ cd webdrop-bridge
|
||||||
|
|
||||||
# Create and activate virtual environment
|
# Create and activate virtual environment
|
||||||
python -m venv venv
|
python -m venv venv
|
||||||
|
source venv/bin/activate # macOS/Linux
|
||||||
# venv\Scripts\activate.ps1 # Windows (PowerShell)
|
# venv\Scripts\activate.ps1 # Windows (PowerShell)
|
||||||
# venv\Scripts\activate.bat # Windows (cmd.exe)
|
# venv\Scripts\activate.bat # Windows (cmd.exe)
|
||||||
|
|
||||||
|
|
@ -70,7 +71,8 @@ pytest tests -v
|
||||||
tox
|
tox
|
||||||
|
|
||||||
# Build installers
|
# Build installers
|
||||||
python build/scripts/build_windows.py --msi # Windows MSI
|
python build/scripts/build_windows.py # Windows MSI
|
||||||
|
bash build/scripts/build_macos.sh # macOS DMG
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
@ -90,6 +92,7 @@ webdrop-bridge/
|
||||||
│ └── conftest.py # Pytest configuration
|
│ └── conftest.py # Pytest configuration
|
||||||
├── build/
|
├── build/
|
||||||
│ ├── windows/ # Windows-specific build configs
|
│ ├── windows/ # Windows-specific build configs
|
||||||
|
│ ├── macos/ # macOS-specific build configs
|
||||||
│ └── scripts/ # Build automation scripts
|
│ └── scripts/ # Build automation scripts
|
||||||
├── webapp/ # Embedded web application
|
├── webapp/ # Embedded web application
|
||||||
├── resources/
|
├── resources/
|
||||||
|
|
@ -222,27 +225,48 @@ See [CHANGELOG.md](CHANGELOG.md) for release notes.
|
||||||
### Windows MSI Installer
|
### Windows MSI Installer
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Build with MSI installer (recommended)
|
# Simple build (creates standalone .exe)
|
||||||
|
python build/scripts/build_windows.py
|
||||||
|
|
||||||
|
# Build with MSI installer
|
||||||
python build/scripts/build_windows.py --msi
|
python build/scripts/build_windows.py --msi
|
||||||
|
|
||||||
# Build with code signing (requires certificate)
|
# Build and sign executable
|
||||||
python build/scripts/build_windows.py --msi --code-sign
|
python build/scripts/build_windows.py --sign
|
||||||
```
|
```
|
||||||
|
|
||||||
Output:
|
Output:
|
||||||
- Portable executable: `build/dist/windows/WebDropBridge/WebDropBridge.exe` (~195 MB)
|
- Standalone executable: `build/dist/windows/WebDropBridge.exe` (~195 MB)
|
||||||
- Professional MSI installer: `build/dist/windows/WebDropBridge-{version}-Setup.msi`
|
- Optional MSI installer: `build/dist/windows/WebDropBridge.msi`
|
||||||
- SHA256 checksum: `build/dist/windows/WebDropBridge/WebDropBridge.exe.sha256`
|
- SHA256 checksum: `build/dist/windows/WebDropBridge.exe.sha256`
|
||||||
|
|
||||||
**Note on macOS**: Build scripts exist for macOS (DMG generation), but have never been built or tested. macOS support is theoretical at this point. The Qt/PySide6 architecture should support macOS, but platform-specific testing and validation would be required.
|
### macOS DMG Installer
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build DMG (requires macOS)
|
||||||
|
bash build/scripts/build_macos.sh
|
||||||
|
|
||||||
|
# Build with code signing
|
||||||
|
SIGN_APP=true bash build/scripts/build_macos.sh
|
||||||
|
|
||||||
|
# Build with notarization
|
||||||
|
NOTARIZE_APP=true bash build/scripts/build_macos.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
- DMG installer: `build/dist/macos/WebDropBridge.dmg`
|
||||||
|
- App bundle: `build/dist/macos/WebDropBridge.app`
|
||||||
|
|
||||||
### Creating Releases
|
### Creating Releases
|
||||||
|
|
||||||
For Forgejo/GitHub releases:
|
For Forgejo/GitHub releases:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Windows - Create release with MSI installer
|
# Windows - Create release with executable
|
||||||
powershell -ExecutionPolicy Bypass -File build/scripts/create_release.ps1
|
powershell -ExecutionPolicy Bypass -File build/scripts/create_release.ps1
|
||||||
|
|
||||||
|
# macOS - Create release with DMG
|
||||||
|
bash build/scripts/create_release.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development Workflow
|
## Development Workflow
|
||||||
|
|
@ -290,10 +314,9 @@ powershell -ExecutionPolicy Bypass -File build/scripts/create_release.ps1
|
||||||
|
|
||||||
| Platform | Version | Status | Notes |
|
| Platform | Version | Status | Notes |
|
||||||
|----------|---------|--------|-------|
|
|----------|---------|--------|-------|
|
||||||
| Windows | 10, 11 | ✅ Full | Tested on x64, MSI installer support |
|
| Windows | 10, 11 | ✅ Full | Tested on x64 |
|
||||||
| macOS | 12+ | ⚠️ **Untested** | Possible via Qt/PySide6, but never built or tested. Theoretical support only. |
|
| macOS | 12, 13, 14 | ✅ Full | Intel & Apple Silicon |
|
||||||
|
| Linux | Ubuntu 22.04+ | ⚠️ Partial | Limited testing |
|
||||||
**Note**: WebDrop Bridge is currently developed and tested exclusively on Windows. While the Qt/PySide6 framework supports macOS, we cannot guarantee functionality without actual macOS testing and validation. Contributions for macOS support validation are welcome.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||||
xmlns:ui="http://schemas.microsoft.com/wix/2010/ui">
|
xmlns:ui="http://schemas.microsoft.com/wix/2010/ui">
|
||||||
<Product Id="*" Name="WebDrop Bridge" Language="1033" Version="0.6.0"
|
<Product Id="*" Name="WebDrop Bridge" Language="1033" Version="0.5.0"
|
||||||
Manufacturer="HIM-Tools"
|
Manufacturer="HIM-Tools"
|
||||||
UpgradeCode="12345678-1234-1234-1234-123456789012">
|
UpgradeCode="12345678-1234-1234-1234-123456789012">
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
|
@ -16,12 +16,11 @@ param(
|
||||||
|
|
||||||
[switch]$ClearCredentials,
|
[switch]$ClearCredentials,
|
||||||
|
|
||||||
[switch]$SkipExe,
|
|
||||||
|
|
||||||
[string]$ForgejoUrl = "https://git.him-tools.de",
|
[string]$ForgejoUrl = "https://git.him-tools.de",
|
||||||
[string]$Repo = "HIM-public/webdrop-bridge",
|
[string]$Repo = "HIM-public/webdrop-bridge",
|
||||||
[string]$ExePath = "build\dist\windows\WebDropBridge\WebDropBridge.exe",
|
[string]$ExePath = "build\dist\windows\WebDropBridge.exe",
|
||||||
[string]$ChecksumPath = "build\dist\windows\WebDropBridge\WebDropBridge.exe.sha256"
|
[string]$ChecksumPath = "build\dist\windows\WebDropBridge.exe.sha256",
|
||||||
|
[string]$MsiPath = "build\dist\windows\WebDropBridge-1.0.0-Setup.msi"
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
@ -108,44 +107,32 @@ if (-not $Version) {
|
||||||
Write-Host "Using version: $Version" -ForegroundColor Green
|
Write-Host "Using version: $Version" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
|
|
||||||
# Define MSI path with resolved version
|
# Verify files exist
|
||||||
$MsiPath = Join-Path $projectRoot "build\dist\windows\WebDropBridge-$Version-Setup.msi"
|
if (-not (Test-Path $ExePath)) {
|
||||||
|
Write-Host "ERROR: Executable not found at $ExePath" -ForegroundColor Red
|
||||||
# Verify files exist (exe/checksum optional, MSI required)
|
|
||||||
if (-not $SkipExe) {
|
|
||||||
if (-not (Test-Path $ExePath)) {
|
|
||||||
Write-Host "WARNING: Executable not found at $ExePath" -ForegroundColor Yellow
|
|
||||||
Write-Host " Use -SkipExe flag to skip exe upload" -ForegroundColor Gray
|
|
||||||
$SkipExe = $true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-not $SkipExe -and -not (Test-Path $ChecksumPath)) {
|
|
||||||
Write-Host "WARNING: Checksum file not found at $ChecksumPath" -ForegroundColor Yellow
|
|
||||||
Write-Host " Exe will not be uploaded" -ForegroundColor Gray
|
|
||||||
$SkipExe = $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# MSI is the primary release artifact
|
|
||||||
if (-not (Test-Path $MsiPath)) {
|
|
||||||
Write-Host "ERROR: MSI installer not found at $MsiPath" -ForegroundColor Red
|
|
||||||
Write-Host "Please build with MSI support:" -ForegroundColor Yellow
|
|
||||||
Write-Host " python build\scripts\build_windows.py --msi" -ForegroundColor Cyan
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path $ChecksumPath)) {
|
||||||
|
Write-Host "ERROR: Checksum file not found at $ChecksumPath" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# MSI is optional (only available on Windows after build)
|
||||||
|
$hasMsi = Test-Path $MsiPath
|
||||||
|
|
||||||
Write-Host "Creating WebDropBridge $Version release on Forgejo..." -ForegroundColor Cyan
|
Write-Host "Creating WebDropBridge $Version release on Forgejo..." -ForegroundColor Cyan
|
||||||
|
|
||||||
# Get file info
|
# Get file info
|
||||||
$msiSize = (Get-Item $MsiPath).Length / 1MB
|
$exeSize = (Get-Item $ExePath).Length / 1MB
|
||||||
Write-Host "Primary Artifact: WebDropBridge-$Version-Setup.msi ($([math]::Round($msiSize, 2)) MB)"
|
$checksum = Get-Content $ChecksumPath -Raw
|
||||||
|
|
||||||
if (-not $SkipExe) {
|
Write-Host "File: WebDropBridge.exe ($([math]::Round($exeSize, 2)) MB)"
|
||||||
$exeSize = (Get-Item $ExePath).Length / 1MB
|
if ($hasMsi) {
|
||||||
$checksum = Get-Content $ChecksumPath -Raw
|
$msiSize = (Get-Item $MsiPath).Length / 1MB
|
||||||
Write-Host "Optional Artifact: WebDropBridge.exe ($([math]::Round($exeSize, 2)) MB)"
|
Write-Host "File: WebDropBridge-1.0.0-Setup.msi ($([math]::Round($msiSize, 2)) MB)"
|
||||||
Write-Host " Checksum: $($checksum.Substring(0, 16))..."
|
|
||||||
}
|
}
|
||||||
|
Write-Host "Checksum: $($checksum.Substring(0, 16))..."
|
||||||
|
|
||||||
# Create basic auth header
|
# Create basic auth header
|
||||||
$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${ForgejoUser}:${ForgejoPW}"))
|
$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${ForgejoUser}:${ForgejoPW}"))
|
||||||
|
|
@ -159,17 +146,10 @@ $headers = @{
|
||||||
Write-Host "`nCreating release v$Version..." -ForegroundColor Yellow
|
Write-Host "`nCreating release v$Version..." -ForegroundColor Yellow
|
||||||
$releaseUrl = "$ForgejoUrl/api/v1/repos/$Repo/releases"
|
$releaseUrl = "$ForgejoUrl/api/v1/repos/$Repo/releases"
|
||||||
|
|
||||||
# Build release body with checksum info if exe is being uploaded
|
|
||||||
$releaseBody = "WebDropBridge v$Version`n`n**Release Artifacts:**`n- MSI Installer (Windows Setup)`n"
|
|
||||||
if (-not $SkipExe) {
|
|
||||||
$checksum = Get-Content $ChecksumPath -Raw
|
|
||||||
$releaseBody += "- Portable Executable`n`n**Checksum:**`n$checksum`n"
|
|
||||||
}
|
|
||||||
|
|
||||||
$releaseData = @{
|
$releaseData = @{
|
||||||
tag_name = "v$Version"
|
tag_name = "v$Version"
|
||||||
name = "WebDropBridge v$Version"
|
name = "WebDropBridge v$Version"
|
||||||
body = $releaseBody
|
body = "WebDropBridge v$Version`n`nChecksum: $checksum"
|
||||||
draft = $false
|
draft = $false
|
||||||
prerelease = $false
|
prerelease = $false
|
||||||
} | ConvertTo-Json
|
} | ConvertTo-Json
|
||||||
|
|
@ -192,70 +172,71 @@ catch {
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Setup curl authentication
|
# Step 2: Upload executable as asset using curl
|
||||||
$curlAuth = "$ForgejoUser`:$ForgejoPW"
|
Write-Host "Uploading executable asset..." -ForegroundColor Yellow
|
||||||
$uploadUrl = "$ForgejoUrl/api/v1/repos/$Repo/releases/$releaseId/assets"
|
|
||||||
|
|
||||||
# Step 2: Upload MSI installer as primary artifact
|
try {
|
||||||
Write-Host "`nUploading MSI installer (primary artifact)..." -ForegroundColor Yellow
|
$curlAuth = "$ForgejoUser`:$ForgejoPW"
|
||||||
|
$uploadUrl = "$ForgejoUrl/api/v1/repos/$Repo/releases/$releaseId/assets"
|
||||||
|
|
||||||
|
$response = curl.exe -s -X POST `
|
||||||
|
-u $curlAuth `
|
||||||
|
-F "attachment=@$ExePath" `
|
||||||
|
$uploadUrl
|
||||||
|
|
||||||
|
if ($response -like "*error*" -or $response -like "*404*") {
|
||||||
|
Write-Host "ERROR uploading executable: $response" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "[OK] Executable uploaded" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "ERROR uploading executable: $_" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Step 3: Upload checksum as asset using curl
|
||||||
|
Write-Host "Uploading checksum asset..." -ForegroundColor Yellow
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = curl.exe -s -X POST `
|
$response = curl.exe -s -X POST `
|
||||||
-u $curlAuth `
|
-u $curlAuth `
|
||||||
-F "attachment=@$MsiPath" `
|
-F "attachment=@$ChecksumPath" `
|
||||||
$uploadUrl
|
$uploadUrl
|
||||||
|
|
||||||
if ($response -like "*error*" -or $response -like "*404*") {
|
if ($response -like "*error*" -or $response -like "*404*") {
|
||||||
Write-Host "ERROR uploading MSI: $response" -ForegroundColor Red
|
Write-Host "ERROR uploading checksum: $response" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "[OK] MSI installer uploaded" -ForegroundColor Green
|
Write-Host "[OK] Checksum uploaded" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Host "ERROR uploading MSI: $_" -ForegroundColor Red
|
Write-Host "ERROR uploading checksum: $_" -ForegroundColor Red
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Step 3: Upload executable as optional artifact (if available)
|
# Step 4: Upload MSI as asset (if available)
|
||||||
if (-not $SkipExe) {
|
if ($hasMsi) {
|
||||||
Write-Host "`nUploading executable (optional portable version)..." -ForegroundColor Yellow
|
Write-Host "Uploading MSI installer asset..." -ForegroundColor Yellow
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = curl.exe -s -X POST `
|
$response = curl.exe -s -X POST `
|
||||||
-u $curlAuth `
|
-u $curlAuth `
|
||||||
-F "attachment=@$ExePath" `
|
-F "attachment=@$MsiPath" `
|
||||||
$uploadUrl
|
$uploadUrl
|
||||||
|
|
||||||
if ($response -like "*error*" -or $response -like "*404*") {
|
if ($response -like "*error*" -or $response -like "*404*") {
|
||||||
Write-Host "WARNING: Could not upload executable: $response" -ForegroundColor Yellow
|
Write-Host "ERROR uploading MSI: $response" -ForegroundColor Red
|
||||||
}
|
exit 1
|
||||||
else {
|
|
||||||
Write-Host "[OK] Executable uploaded" -ForegroundColor Green
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host "[OK] MSI uploaded" -ForegroundColor Green
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Host "WARNING: Could not upload executable: $_" -ForegroundColor Yellow
|
Write-Host "ERROR uploading MSI: $_" -ForegroundColor Red
|
||||||
}
|
exit 1
|
||||||
|
|
||||||
# Step 4: Upload checksum as asset
|
|
||||||
Write-Host "Uploading checksum..." -ForegroundColor Yellow
|
|
||||||
|
|
||||||
try {
|
|
||||||
$response = curl.exe -s -X POST `
|
|
||||||
-u $curlAuth `
|
|
||||||
-F "attachment=@$ChecksumPath" `
|
|
||||||
$uploadUrl
|
|
||||||
|
|
||||||
if ($response -like "*error*" -or $response -like "*404*") {
|
|
||||||
Write-Host "WARNING: Could not upload checksum: $response" -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Host "[OK] Checksum uploaded" -ForegroundColor Green
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Host "WARNING: Could not upload checksum: $_" -ForegroundColor Yellow
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,22 +137,7 @@ class Config:
|
||||||
log_file = Config.get_default_log_path()
|
log_file = Config.get_default_log_path()
|
||||||
|
|
||||||
app_name = data.get("app_name", "WebDrop Bridge")
|
app_name = data.get("app_name", "WebDrop Bridge")
|
||||||
stored_window_title = data.get("window_title", "")
|
window_title = data.get("window_title", f"{app_name} v{__version__}")
|
||||||
|
|
||||||
# Regenerate default window titles on version upgrade
|
|
||||||
# If the stored title matches the pattern "{app_name} v{version}", regenerate it
|
|
||||||
# with the current version. This ensures the title updates automatically on upgrades.
|
|
||||||
import re
|
|
||||||
version_pattern = re.compile(rf"^{re.escape(app_name)}\s+v[\d.]+$")
|
|
||||||
if stored_window_title and version_pattern.match(stored_window_title):
|
|
||||||
# Detected a default-pattern title with old version, regenerate
|
|
||||||
window_title = f"{app_name} v{__version__}"
|
|
||||||
elif stored_window_title:
|
|
||||||
# Custom window title, keep it as-is
|
|
||||||
window_title = stored_window_title
|
|
||||||
else:
|
|
||||||
# No window title specified, use default
|
|
||||||
window_title = f"{app_name} v{__version__}"
|
|
||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
app_name=app_name,
|
app_name=app_name,
|
||||||
|
|
@ -193,10 +178,12 @@ class Config:
|
||||||
|
|
||||||
# Extract and validate configuration values
|
# Extract and validate configuration values
|
||||||
app_name = os.getenv("APP_NAME", "WebDrop Bridge")
|
app_name = os.getenv("APP_NAME", "WebDrop Bridge")
|
||||||
# Version always comes from __init__.py for consistency
|
# Version comes from __init__.py (lazy import to avoid circular imports)
|
||||||
from webdrop_bridge import __version__
|
if not os.getenv("APP_VERSION"):
|
||||||
app_version = __version__
|
from webdrop_bridge import __version__
|
||||||
|
app_version = __version__
|
||||||
|
else:
|
||||||
|
app_version = os.getenv("APP_VERSION")
|
||||||
log_level = os.getenv("LOG_LEVEL", "INFO").upper()
|
log_level = os.getenv("LOG_LEVEL", "INFO").upper()
|
||||||
log_file_str = os.getenv("LOG_FILE", None)
|
log_file_str = os.getenv("LOG_FILE", None)
|
||||||
allowed_roots_str = os.getenv("ALLOWED_ROOTS", "Z:/,C:/Users/Public")
|
allowed_roots_str = os.getenv("ALLOWED_ROOTS", "Z:/,C:/Users/Public")
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,8 @@ class TestConfigFromEnv:
|
||||||
# Load config (env vars from file, not system)
|
# Load config (env vars from file, not system)
|
||||||
config = Config.from_env(str(env_file))
|
config = Config.from_env(str(env_file))
|
||||||
|
|
||||||
# Version always comes from package __init__.py, not from APP_VERSION env var
|
|
||||||
from webdrop_bridge import __version__
|
|
||||||
|
|
||||||
assert config.app_name == "TestApp"
|
assert config.app_name == "TestApp"
|
||||||
assert config.app_version == __version__ # Uses package version, not env var
|
assert config.app_version == "2.0.0"
|
||||||
assert config.log_level == "DEBUG"
|
assert config.log_level == "DEBUG"
|
||||||
assert config.allowed_roots == [root1.resolve(), root2.resolve()]
|
assert config.allowed_roots == [root1.resolve(), root2.resolve()]
|
||||||
assert config.allowed_urls == ["example.com", "*.test.org"]
|
assert config.allowed_urls == ["example.com", "*.test.org"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue