- install.py / uninstall.py: full Python installer for Linux, macOS, Windows
- detect_platform.py: shared Inkscape config path detection
- Windows config path: %APPDATA%\inkscape (native/winget/scoop) or
%LOCALAPPDATA%\Packages\org.inkscape.Inkscape* (MS Store)
- Windows desktop: Start Menu .lnk via PowerShell WScript.Shell COM object
- macOS: XDG / ~/Library/Application Support detection, no desktop step
- install.sh / uninstall.sh: reduced to one-line exec python3 wrappers
- eliminates SC1091 (source not followed) and SC2155 (declare+assign)
- scripts/detect_platform.sh: export INKSCAPE_CONFIG / INKSCAPE_INSTALL_METHOD
- fixes SC2034 (variables appear unused to shellcheck)
- assets/illuscape.ico: pre-rendered 16/32/48/64/128/256px ICO (ImageMagick)
- tests/test_install.py: pytest integration tests replacing test_install.bats
- cross-platform fake inkscape injected via PATH
- 12 tests covering backup, palettes, templates, prefs, uninstall restore
- ci.yml: add windows-latest matrix leg; shellcheck/inkscape Linux-only;
bats removed in favour of pytest integration tests; 27 tests total
82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
"""
|
|
detect_platform.py — Inkscape config-path detection, cross-platform.
|
|
|
|
Shared by install.py and uninstall.py.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
def _cmd_contains(cmd: list[str], pattern: str) -> bool:
|
|
"""Run *cmd*; return True if stdout contains *pattern*."""
|
|
try:
|
|
result = subprocess.run(
|
|
cmd, capture_output=True, text=True, timeout=5
|
|
)
|
|
return pattern in result.stdout
|
|
except (FileNotFoundError, subprocess.TimeoutExpired):
|
|
return False
|
|
|
|
|
|
def detect_config() -> tuple[Path, str]:
|
|
"""
|
|
Return (inkscape_config_path, install_method).
|
|
|
|
install_method is one of: "flatpak", "snap", "native", "store"
|
|
"""
|
|
system = platform.system()
|
|
if system == "Windows":
|
|
return _detect_windows()
|
|
if system == "Darwin":
|
|
return _detect_macos()
|
|
return _detect_linux()
|
|
|
|
|
|
def _detect_linux() -> tuple[Path, str]:
|
|
# Flatpak takes priority — most common modern Linux install
|
|
flatpak_config = Path.home() / ".var/app/org.inkscape.Inkscape/config/inkscape"
|
|
if flatpak_config.is_dir() or _cmd_contains(
|
|
["flatpak", "list"], "org.inkscape.Inkscape"
|
|
):
|
|
return flatpak_config, "flatpak"
|
|
|
|
# Snap
|
|
snap_config = Path.home() / "snap/inkscape/current/.config/inkscape"
|
|
if snap_config.is_dir() or _cmd_contains(["snap", "list"], "inkscape"):
|
|
return snap_config, "snap"
|
|
|
|
# Native / XDG
|
|
xdg = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")) / "inkscape"
|
|
return xdg, "native"
|
|
|
|
|
|
def _detect_macos() -> tuple[Path, str]:
|
|
# App Bundle (DMG install) stores config under ~/Library/Application Support
|
|
app_support = (
|
|
Path.home()
|
|
/ "Library/Application Support/org.inkscape.Inkscape/config/inkscape"
|
|
)
|
|
if app_support.is_dir():
|
|
return app_support, "native"
|
|
# Homebrew / XDG fallback
|
|
xdg = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")) / "inkscape"
|
|
return xdg, "native"
|
|
|
|
|
|
def _detect_windows() -> tuple[Path, str]:
|
|
# MS Store — glob for the Packages directory
|
|
local_appdata = os.environ.get("LOCALAPPDATA", "")
|
|
if local_appdata:
|
|
packages = Path(local_appdata) / "Packages"
|
|
if packages.is_dir():
|
|
matches = list(packages.glob("org.inkscape.Inkscape*"))
|
|
if matches:
|
|
return matches[0] / "LocalCache/Roaming/inkscape", "store"
|
|
|
|
# Native (winget / Scoop / chocolatey / official installer)
|
|
appdata = Path(os.environ.get("APPDATA", Path.home() / "AppData/Roaming"))
|
|
return appdata / "inkscape", "native"
|