fix(install): correct openSUSE Tumbleweed dependencies (#420)
* fix(install): correct openSUSE Tumbleweed dependencies * style: format openSUSE installer changes --------- Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>
This commit is contained in:
co-authored by
Jatin K Malik
parent
c39f9ce431
commit
a47747d6a4
@@ -104,11 +104,25 @@ sudo pacman -S --needed python-gobject gtk3 gobject-introspection \
|
||||
|
||||
### openSUSE
|
||||
```bash
|
||||
sudo zypper install -y python3-gobject python3-gobject-cairo gtk3 \
|
||||
gobject-introspection-devel portaudio-devel python3-devel \
|
||||
python3-virtualenv pkg-config
|
||||
PYVER=$(python3 -c 'import sys; print(f"python{sys.version_info.major}{sys.version_info.minor}")')
|
||||
|
||||
sudo zypper install -y \
|
||||
"${PYVER}-pip" "${PYVER}-gobject" "${PYVER}-gobject-cairo" \
|
||||
"${PYVER}-devel" "${PYVER}-virtualenv" \
|
||||
gtk3 typelib-1_0-AyatanaAppIndicator3-0_1 libayatana-appindicator3-1 \
|
||||
typelib-1_0-Notify-0_7 libnotify4 \
|
||||
gobject-introspection-devel portaudio-devel pkg-config cmake wget curl unzip \
|
||||
xdotool wtype
|
||||
|
||||
# Optional: only needed for whisper.cpp Vulkan GPU builds
|
||||
sudo zypper install -y vulkan-tools vulkan-devel shaderc
|
||||
```
|
||||
|
||||
**Note:** openSUSE Tumbleweed often uses versioned Python package names such as
|
||||
`python313-devel`. The `-devel` suffix means development headers for compiling
|
||||
native dependencies; it does **not** mean beta or unstable packages. If
|
||||
`${PYVER}-virtualenv` is unavailable on your snapshot, try `${PYVER}-venv`.
|
||||
|
||||
### Gentoo
|
||||
```bash
|
||||
sudo emerge dev-python/pygobject:3 x11-libs/gtk+:3 dev-libs/libappindicator:3 \
|
||||
@@ -190,9 +204,12 @@ sudo pacman -S python-gobject gtk3 libappindicator gobject-introspection \
|
||||
|
||||
#### openSUSE
|
||||
```bash
|
||||
sudo zypper install python3-gobject python3-gobject-cairo gtk3 libappindicator \
|
||||
gobject-introspection-devel portaudio-devel python3-devel \
|
||||
python3-virtualenv pkg-config xdotool wtype
|
||||
PYVER=$(python3 -c 'import sys; print(f"python{sys.version_info.major}{sys.version_info.minor}")')
|
||||
|
||||
sudo zypper install "${PYVER}-gobject" "${PYVER}-gobject-cairo" gtk3 \
|
||||
typelib-1_0-AyatanaAppIndicator3-0_1 libayatana-appindicator3-1 \
|
||||
typelib-1_0-Notify-0_7 libnotify4 \
|
||||
portaudio-devel "${PYVER}-devel" "${PYVER}-virtualenv" pkg-config xdotool wtype
|
||||
```
|
||||
|
||||
### pip Installation Steps
|
||||
|
||||
@@ -78,6 +78,25 @@ pip install vocalinux
|
||||
vocalinux
|
||||
```
|
||||
|
||||
**openSUSE Tumbleweed:**
|
||||
|
||||
```bash
|
||||
PYVER=$(python3 -c 'import sys; print(f"python{sys.version_info.major}{sys.version_info.minor}")')
|
||||
|
||||
sudo zypper install -y \
|
||||
"${PYVER}-gobject" "${PYVER}-gobject-cairo" gtk3 \
|
||||
typelib-1_0-AyatanaAppIndicator3-0_1 libayatana-appindicator3-1 \
|
||||
typelib-1_0-Notify-0_7 libnotify4 \
|
||||
gobject-introspection-devel portaudio-devel "${PYVER}-devel" \
|
||||
"${PYVER}-virtualenv" pkg-config xdotool wtype
|
||||
|
||||
python3 -m venv ~/.local/share/vocalinux-pypi/venv --system-site-packages
|
||||
source ~/.local/share/vocalinux-pypi/venv/bin/activate
|
||||
pip install --upgrade pip setuptools wheel
|
||||
pip install vocalinux
|
||||
vocalinux
|
||||
```
|
||||
|
||||
If `vocalinux` starts but reports a missing speech model, open Settings and
|
||||
download a model, or use the recommended installer which downloads the default
|
||||
model during setup.
|
||||
@@ -340,6 +359,26 @@ sudo pacman -S --noconfirm \
|
||||
wget curl unzip xdotool
|
||||
```
|
||||
|
||||
**openSUSE Tumbleweed:**
|
||||
```bash
|
||||
PYVER=$(python3 -c 'import sys; print(f"python{sys.version_info.major}{sys.version_info.minor}")')
|
||||
|
||||
sudo zypper install -y \
|
||||
"${PYVER}-pip" "${PYVER}-gobject" "${PYVER}-gobject-cairo" \
|
||||
"${PYVER}-devel" "${PYVER}-virtualenv" \
|
||||
gtk3 typelib-1_0-AyatanaAppIndicator3-0_1 libayatana-appindicator3-1 \
|
||||
typelib-1_0-Notify-0_7 libnotify4 \
|
||||
gobject-introspection-devel portaudio-devel pkg-config cmake \
|
||||
wget curl unzip xdotool wtype
|
||||
|
||||
# Optional: only needed for whisper.cpp Vulkan GPU builds
|
||||
sudo zypper install -y vulkan-tools vulkan-devel shaderc
|
||||
```
|
||||
|
||||
On openSUSE, `-devel` packages are development headers for native Python
|
||||
dependencies. They are not beta or unstable packages. If `${PYVER}-virtualenv`
|
||||
is unavailable on your snapshot, try `${PYVER}-venv`.
|
||||
|
||||
### 2. Create Virtual Environment
|
||||
|
||||
```bash
|
||||
|
||||
+200
-48
@@ -100,6 +100,7 @@ RUN_TESTS="no"
|
||||
DEV_MODE="no"
|
||||
VENV_DIR="venv"
|
||||
SKIP_MODELS="no"
|
||||
SKIP_SYSTEM_DEPS="no"
|
||||
WITH_WHISPER="no"
|
||||
WHISPER_CPU="no"
|
||||
NO_WHISPER_EXPLICIT="no"
|
||||
@@ -151,6 +152,10 @@ while [[ $# -gt 0 ]]; do
|
||||
SKIP_MODELS="yes"
|
||||
shift
|
||||
;;
|
||||
--skip-system-deps)
|
||||
SKIP_SYSTEM_DEPS="yes"
|
||||
shift
|
||||
;;
|
||||
--rebuild-whispercpp)
|
||||
REBUILD_WHISPERCPP="yes"
|
||||
shift
|
||||
@@ -195,6 +200,8 @@ while [[ $# -gt 0 ]]; do
|
||||
echo " --test Run tests after installation"
|
||||
echo " --venv-dir=PATH Specify custom virtual environment directory"
|
||||
echo " --skip-models Skip downloading speech models during installation"
|
||||
echo " --skip-system-deps"
|
||||
echo " Skip package-manager dependency installation (advanced)"
|
||||
echo " --rebuild-whispercpp Rebuild/reinstall pywhispercpp even if already installed"
|
||||
echo " --no-rebuild-whispercpp Reuse existing pywhispercpp when present (auto-mode default)"
|
||||
echo " --tag=TAG Install specific release tag (default: latest release)"
|
||||
@@ -1159,6 +1166,106 @@ pacman_package_installed() {
|
||||
pacman -Q "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
suse_python_package_prefix() {
|
||||
python3 -c 'import sys; print(f"python{sys.version_info.major}{sys.version_info.minor}")' 2>/dev/null || echo "python3"
|
||||
}
|
||||
|
||||
suse_python_package_candidates() {
|
||||
local suffix="$1"
|
||||
local PY_PREFIX
|
||||
PY_PREFIX=$(suse_python_package_prefix)
|
||||
|
||||
if [[ "$PY_PREFIX" != "python3" ]]; then
|
||||
echo "${PY_PREFIX}-${suffix} python3-${suffix}"
|
||||
else
|
||||
echo "python3-${suffix}"
|
||||
fi
|
||||
}
|
||||
|
||||
suse_package_installed() {
|
||||
rpm -q "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
suse_install_first_available() {
|
||||
local DESCRIPTION="$1"
|
||||
shift
|
||||
|
||||
local PKG
|
||||
for PKG in "$@"; do
|
||||
[ -z "$PKG" ] && continue
|
||||
|
||||
if suse_package_installed "$PKG"; then
|
||||
print_info "$DESCRIPTION is already installed ($PKG)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if sudo zypper install -y "$PKG" 2>/dev/null; then
|
||||
print_success "Installed $DESCRIPTION ($PKG)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_info "$DESCRIPTION package '$PKG' not available, trying next option..."
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
suse_appindicator_gi_available() {
|
||||
python3 - <<'PY' >/dev/null 2>&1
|
||||
import importlib
|
||||
import gi
|
||||
|
||||
for namespace in ("AppIndicator3", "AyatanaAppIndicator3", "AyatanaAppindicator3"):
|
||||
try:
|
||||
gi.require_version(namespace, "0.1")
|
||||
importlib.import_module(f"gi.repository.{namespace}")
|
||||
raise SystemExit(0)
|
||||
except (ImportError, ValueError):
|
||||
pass
|
||||
|
||||
raise SystemExit(1)
|
||||
PY
|
||||
}
|
||||
|
||||
suse_install_appindicator_runtime() {
|
||||
local APPINDICATOR_PACKAGES=(
|
||||
"typelib-1_0-AyatanaAppIndicator3-0_1"
|
||||
"typelib-1_0-AppIndicator3-0_1"
|
||||
"typelib-1_0-AyatanaAppIndicator-0_1"
|
||||
"libayatana-appindicator3-1"
|
||||
"libappindicator3-1"
|
||||
"libappindicator-gtk3"
|
||||
)
|
||||
|
||||
if suse_appindicator_gi_available; then
|
||||
print_info "AppIndicator/Ayatana GI namespace is already available."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local PKG
|
||||
for PKG in "${APPINDICATOR_PACKAGES[@]}"; do
|
||||
if suse_package_installed "$PKG"; then
|
||||
print_info "AppIndicator/Ayatana package is already installed ($PKG); verifying GI namespace..."
|
||||
elif sudo zypper install -y "$PKG" 2>/dev/null; then
|
||||
print_success "Installed AppIndicator/Ayatana package ($PKG)."
|
||||
else
|
||||
print_info "AppIndicator/Ayatana package '$PKG' not available, trying next option..."
|
||||
continue
|
||||
fi
|
||||
|
||||
if suse_appindicator_gi_available; then
|
||||
print_success "AppIndicator/Ayatana GI namespace is available."
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
suse_shader_compiler_available() {
|
||||
command_exists glslc || command_exists glslangValidator
|
||||
}
|
||||
|
||||
# Function to install system dependencies based on the detected distribution
|
||||
install_system_dependencies() {
|
||||
print_info "Installing system dependencies..."
|
||||
@@ -1185,7 +1292,7 @@ install_system_dependencies() {
|
||||
local APT_PACKAGES_DEBIAN_13_PLUS="$APT_PACKAGES_DEBIAN_BASE libgirepository-2.0-dev gir1.2-ayatanaappindicator3-0.1"
|
||||
local DNF_PACKAGES="python3-pip python3-gobject gtk3 libappindicator-gtk3 ibus-devel gobject-introspection-devel python3-devel portaudio-devel python3-virtualenv pkg-config cmake wget curl unzip vulkan-tools vulkan-loader-devel glslang xclip wl-clipboard"
|
||||
local PACMAN_PACKAGES="python-pip python-gobject gtk3 libappindicator-gtk3 ibus gobject-introspection python-cairo portaudio python-virtualenv pkg-config cmake wget curl unzip base-devel vulkan-tools vulkan-headers glslang xclip wl-clipboard"
|
||||
local ZYPPER_PACKAGES="python3-pip python3-gobject python3-gobject-cairo gtk3 libappindicator-gtk3 ibus-devel gobject-introspection-devel python3-devel portaudio-devel python3-virtualenv pkg-config cmake wget curl unzip vulkan-tools vulkan-devel glslang xclip wl-clipboard"
|
||||
local ZYPPER_PACKAGES="gtk3 ibus-devel gobject-introspection-devel portaudio-devel pkg-config cmake wget curl unzip xclip wl-clipboard typelib-1_0-Notify-0_7 libnotify4"
|
||||
# Gentoo uses Portage and different package naming convention
|
||||
local EMERGE_PACKAGES="dev-python/pygobject:3 x11-libs/gtk+:3 dev-libs/libayatana-appindicator media-libs/portaudio dev-lang/python:3.9 pkgconf cmake dev-util/glslang x11-misc/xclip gui-apps/wl-clipboard"
|
||||
# Alpine Linux uses apk and has musl libc
|
||||
@@ -1305,56 +1412,87 @@ install_system_dependencies() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
zypper_package_installed() {
|
||||
rpm -q "$1" >/dev/null 2>&1
|
||||
}
|
||||
sudo zypper refresh || true
|
||||
|
||||
if [[ "${SELECTED_ENGINE:-whisper_cpp}" == "whisper_cpp" && "${WHISPERCPP_BACKEND:-}" != "cpu" ]]; then
|
||||
ZYPPER_PACKAGES="$ZYPPER_PACKAGES vulkan-tools vulkan-devel"
|
||||
fi
|
||||
|
||||
local MISSING_ZYPPER_PACKAGES=()
|
||||
for pkg in $ZYPPER_PACKAGES; do
|
||||
if ! zypper_package_installed "$pkg"; then
|
||||
MISSING_PACKAGES="$MISSING_PACKAGES $pkg"
|
||||
if ! suse_package_installed "$pkg"; then
|
||||
MISSING_ZYPPER_PACKAGES+=("$pkg")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$MISSING_PACKAGES" ]; then
|
||||
print_info "Installing missing packages:$MISSING_PACKAGES"
|
||||
sudo zypper refresh || true
|
||||
|
||||
if echo "$MISSING_PACKAGES" | grep -qw "glslang"; then
|
||||
if ! sudo zypper install -y glslang 2>/dev/null; then
|
||||
print_info "glslang not found, trying glslang-devel..."
|
||||
if ! sudo zypper install -y glslang-devel 2>/dev/null; then
|
||||
print_warning "glslang not available - Vulkan shader compilation may not work"
|
||||
print_warning "Install glslang manually for whisper.cpp GPU support"
|
||||
fi
|
||||
fi
|
||||
FILTERED_PACKAGES=$(echo "$MISSING_PACKAGES" | sed 's/glslang//' | xargs)
|
||||
else
|
||||
FILTERED_PACKAGES="$MISSING_PACKAGES"
|
||||
fi
|
||||
|
||||
if echo "$FILTERED_PACKAGES" | grep -qw "libappindicator-gtk3"; then
|
||||
if ! sudo zypper install -y libappindicator-gtk3 2>/dev/null; then
|
||||
print_info "libappindicator-gtk3 not available, trying typelib-1_0-AppIndicator3-0_1..."
|
||||
if ! sudo zypper install -y typelib-1_0-AppIndicator3-0_1 2>/dev/null; then
|
||||
print_info "Trying libayatana-appindicator3-1..."
|
||||
if sudo zypper install -y libayatana-appindicator3-1 2>/dev/null; then
|
||||
print_success "Installed libayatana-appindicator3-1"
|
||||
else
|
||||
print_warning "No appindicator package found - system tray may not work"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
FILTERED_PACKAGES=$(echo "$FILTERED_PACKAGES" | sed 's/libappindicator-gtk3//' | xargs)
|
||||
fi
|
||||
|
||||
if [ -n "$FILTERED_PACKAGES" ]; then
|
||||
sudo zypper install -y $FILTERED_PACKAGES || {
|
||||
print_error "Failed to install dependencies"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
if [ "${#MISSING_ZYPPER_PACKAGES[@]}" -gt 0 ]; then
|
||||
print_info "Installing missing packages: ${MISSING_ZYPPER_PACKAGES[*]}"
|
||||
sudo zypper install -y "${MISSING_ZYPPER_PACKAGES[@]}" || {
|
||||
print_error "Failed to install openSUSE base dependencies"
|
||||
exit 1
|
||||
}
|
||||
else
|
||||
print_info "All required packages are already installed."
|
||||
print_info "All base openSUSE packages are already installed."
|
||||
fi
|
||||
|
||||
local PY_PIP_CANDIDATES=()
|
||||
local PY_GOBJECT_CANDIDATES=()
|
||||
local PY_GOBJECT_CAIRO_CANDIDATES=()
|
||||
local PY_DEVEL_CANDIDATES=()
|
||||
local PY_VIRTUALENV_CANDIDATES=()
|
||||
local PY_VENV_CANDIDATES=()
|
||||
|
||||
read -r -a PY_PIP_CANDIDATES <<< "$(suse_python_package_candidates "pip")"
|
||||
read -r -a PY_GOBJECT_CANDIDATES <<< "$(suse_python_package_candidates "gobject")"
|
||||
read -r -a PY_GOBJECT_CAIRO_CANDIDATES <<< "$(suse_python_package_candidates "gobject-cairo")"
|
||||
read -r -a PY_DEVEL_CANDIDATES <<< "$(suse_python_package_candidates "devel")"
|
||||
read -r -a PY_VIRTUALENV_CANDIDATES <<< "$(suse_python_package_candidates "virtualenv")"
|
||||
read -r -a PY_VENV_CANDIDATES <<< "$(suse_python_package_candidates "venv")"
|
||||
|
||||
print_info "Resolving openSUSE Python packages for $(suse_python_package_prefix)..."
|
||||
|
||||
if ! suse_install_first_available "Python pip" "${PY_PIP_CANDIDATES[@]}"; then
|
||||
print_error "Failed to install Python pip package (tried: ${PY_PIP_CANDIDATES[*]})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! suse_install_first_available "PyGObject bindings" "${PY_GOBJECT_CANDIDATES[@]}"; then
|
||||
print_error "Failed to install PyGObject package (tried: ${PY_GOBJECT_CANDIDATES[*]})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! suse_install_first_available "PyGObject Cairo bindings" "${PY_GOBJECT_CAIRO_CANDIDATES[@]}"; then
|
||||
print_error "Failed to install PyGObject Cairo package (tried: ${PY_GOBJECT_CAIRO_CANDIDATES[*]})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! suse_install_first_available "Python development headers" "${PY_DEVEL_CANDIDATES[@]}"; then
|
||||
print_error "Failed to install Python development headers (tried: ${PY_DEVEL_CANDIDATES[*]})"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! suse_install_first_available "Python virtualenv/venv" "${PY_VIRTUALENV_CANDIDATES[@]}" "${PY_VENV_CANDIDATES[@]}"; then
|
||||
print_warning "Python virtualenv/venv package was not found (tried: ${PY_VIRTUALENV_CANDIDATES[*]} ${PY_VENV_CANDIDATES[*]})"
|
||||
print_warning "Continuing because python3 -m venv may still be available."
|
||||
fi
|
||||
|
||||
if ! suse_install_appindicator_runtime; then
|
||||
print_error "Failed to install a working AppIndicator/Ayatana GI runtime on openSUSE."
|
||||
print_error "Try manually: sudo zypper install typelib-1_0-AyatanaAppIndicator3-0_1 libayatana-appindicator3-1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${SELECTED_ENGINE:-whisper_cpp}" == "whisper_cpp" && "${WHISPERCPP_BACKEND:-}" != "cpu" ]]; then
|
||||
if ! suse_shader_compiler_available; then
|
||||
if ! suse_install_first_available "Vulkan shader compiler" shaderc glslang-devel glslang; then
|
||||
print_warning "No Vulkan shader compiler found - whisper.cpp Vulkan build may fail"
|
||||
print_warning "Install shaderc manually for glslc support if you want GPU acceleration."
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! suse_shader_compiler_available; then
|
||||
print_warning "glslc/glslangValidator is still unavailable; CPU fallback will be used if Vulkan build fails."
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
@@ -1531,7 +1669,12 @@ install_system_dependencies() {
|
||||
}
|
||||
|
||||
# Install system dependencies
|
||||
install_system_dependencies
|
||||
if [[ "$SKIP_SYSTEM_DEPS" == "yes" ]]; then
|
||||
print_warning "Skipping system dependency installation (--skip-system-deps specified)."
|
||||
print_warning "Make sure GTK, PyGObject, AppIndicator/Ayatana, PortAudio, and text input tools are installed."
|
||||
else
|
||||
install_system_dependencies
|
||||
fi
|
||||
|
||||
# Define XDG directories
|
||||
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/vocalinux"
|
||||
@@ -1541,6 +1684,11 @@ ICON_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor/scalable/apps"
|
||||
|
||||
# Function to detect and install text input tools
|
||||
install_text_input_tools() {
|
||||
if [[ "$SKIP_SYSTEM_DEPS" == "yes" ]]; then
|
||||
print_warning "Skipping text input tool installation (--skip-system-deps specified)."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Detect session type more robustly
|
||||
local SESSION_TYPE="unknown"
|
||||
|
||||
@@ -1856,8 +2004,11 @@ setup_virtual_environment() {
|
||||
# Use --system-site-packages to access pre-compiled system packages like PyGObject
|
||||
# This avoids build failures with Python 3.13+ where PyGObject may not build from source
|
||||
python3 -m venv --system-site-packages "$VENV_DIR" || {
|
||||
print_error "Failed to create virtual environment. Please check your Python installation."
|
||||
exit 1
|
||||
print_warning "python3 -m venv failed, trying python3 -m virtualenv..."
|
||||
python3 -m virtualenv --system-site-packages "$VENV_DIR" || {
|
||||
print_error "Failed to create virtual environment. Please check your Python installation."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Activate virtual environment
|
||||
@@ -2163,6 +2314,7 @@ install_python_package() {
|
||||
print_info " Ubuntu/Debian: sudo apt install libvulkan-dev vulkan-tools glslc || glslang-tools"
|
||||
print_info " Fedora: sudo dnf install vulkan-loader-devel vulkan-tools glslang"
|
||||
print_info " Arch: sudo pacman -S vulkan-headers vulkan-tools glslang"
|
||||
print_info " openSUSE: sudo zypper install vulkan-devel vulkan-tools shaderc"
|
||||
elif [[ "$GPU_BACKEND" == "CUDA" ]]; then
|
||||
print_info " To use CUDA GPU acceleration, please install CUDA toolkit:"
|
||||
print_info " Visit: https://developer.nvidia.com/cuda-downloads"
|
||||
|
||||
@@ -59,6 +59,28 @@ check_deps() {
|
||||
MISSING=1
|
||||
fi
|
||||
|
||||
# Check for AppIndicator/Ayatana AppIndicator GI runtime
|
||||
if python3 - <<'PY' >/dev/null 2>&1
|
||||
import importlib
|
||||
import gi
|
||||
|
||||
for namespace in ("AppIndicator3", "AyatanaAppIndicator3", "AyatanaAppindicator3"):
|
||||
try:
|
||||
gi.require_version(namespace, "0.1")
|
||||
importlib.import_module(f"gi.repository.{namespace}")
|
||||
raise SystemExit(0)
|
||||
except (ImportError, ValueError):
|
||||
pass
|
||||
|
||||
raise SystemExit(1)
|
||||
PY
|
||||
then
|
||||
echo "✓ AppIndicator/Ayatana GI runtime"
|
||||
else
|
||||
echo "✗ AppIndicator/Ayatana GI runtime not found"
|
||||
MISSING=1
|
||||
fi
|
||||
|
||||
# Check for PortAudio
|
||||
if command -v pkg-config >/dev/null 2>&1 && pkg-config --exists portaudio-2.0 2>/dev/null; then
|
||||
PA_VERSION=$(pkg-config --modversion portaudio-2.0 2>/dev/null)
|
||||
@@ -124,7 +146,9 @@ check_deps() {
|
||||
echo " sudo pacman -S --needed python-gobject gtk3 gobject-introspection portaudio python pkg-config xdotool wtype"
|
||||
elif [[ "$DETECTED_DISTRO" == "opensuse" || "$DETECTED_DISTRO_LIKE" == *"suse"* ]]; then
|
||||
echo "openSUSE:"
|
||||
echo " sudo zypper install -y python3-gobject python3-gobject-cairo gtk3 gobject-introspection-devel portaudio-devel python3-devel python3-virtualenv pkg-config xdotool wtype"
|
||||
echo " PYVER=\$(python3 -c 'import sys; print(f\"python{sys.version_info.major}{sys.version_info.minor}\")')"
|
||||
echo " sudo zypper install -y \"\${PYVER}-gobject\" \"\${PYVER}-gobject-cairo\" gtk3 typelib-1_0-AyatanaAppIndicator3-0_1 libayatana-appindicator3-1 typelib-1_0-Notify-0_7 libnotify4 gobject-introspection-devel portaudio-devel \"\${PYVER}-devel\" \"\${PYVER}-virtualenv\" pkg-config xdotool wtype"
|
||||
echo " If \"\${PYVER}-virtualenv\" is unavailable, try \"\${PYVER}-venv\"."
|
||||
elif [[ "$DETECTED_DISTRO" == "gentoo" ]]; then
|
||||
echo "Gentoo:"
|
||||
echo " sudo emerge dev-python/pygobject:3 x11-libs/gtk+:3 dev-libs/libappindicator:3 media-libs/portaudio dev-lang/python:3.9 xdotool wtype"
|
||||
|
||||
@@ -10,7 +10,8 @@ system_packages:
|
||||
debian: ["python3-gi", "python3-gi-cairo", "gir1.2-gtk-3.0", "gir1.2-gdkpixbuf-2.0", "libcairo2-dev"]
|
||||
fedora: ["python3-gobject", "gtk3", "gobject-introspection-devel"]
|
||||
arch: ["python-gobject", "gtk3", "gobject-introspection", "python-cairo"]
|
||||
opensuse: ["python3-gobject", "python3-gobject-cairo", "gtk3", "gobject-introspection-devel"]
|
||||
# Tumbleweed often uses versioned Python package names such as python313-gobject.
|
||||
opensuse: ["python3XY-gobject", "python3XY-gobject-cairo", "gtk3", "gobject-introspection-devel"]
|
||||
gentoo: ["dev-python/pygobject:3", "x11-libs/gtk+:3"]
|
||||
alpine: ["py3-gobject3", "py3-cairo", "gtk+3.0"]
|
||||
void: ["python3-gobject", "gtk+3"]
|
||||
@@ -23,7 +24,7 @@ system_packages:
|
||||
debian_12_plus: ["gir1.2-ayatanaappindicator3-0.1"]
|
||||
fedora: ["libappindicator-gtk3"]
|
||||
arch: ["libappindicator-gtk3"]
|
||||
opensuse: ["libappindicator-gtk3"]
|
||||
opensuse: ["typelib-1_0-AyatanaAppIndicator3-0_1", "libayatana-appindicator3-1", "typelib-1_0-AppIndicator3-0_1"]
|
||||
gentoo: ["dev-libs/libappindicator:3"]
|
||||
alpine: ["libayatana-appindicator"]
|
||||
void: ["libappindicator"]
|
||||
@@ -47,7 +48,8 @@ system_packages:
|
||||
debian: ["python3-dev", "python3-venv"]
|
||||
fedora: ["python3-devel", "python3-virtualenv"]
|
||||
arch: ["python"] # Arch includes venv by default
|
||||
opensuse: ["python3-devel", "python3-virtualenv"]
|
||||
# Tumbleweed package names follow the active Python minor version, e.g. python313-devel.
|
||||
opensuse: ["python3XY-devel", "python3XY-virtualenv", "python3XY-venv", "python3XY-pip"]
|
||||
gentoo: ["dev-lang/python:3.9"]
|
||||
alpine: ["py3-virtualenv"]
|
||||
void: ["python3-devel"]
|
||||
|
||||
@@ -139,6 +139,17 @@ def check_dependencies():
|
||||
logger.error(" Arch Linux:")
|
||||
logger.error(" sudo pacman -S python-gobject gtk3 libappindicator")
|
||||
logger.error("")
|
||||
logger.error(" openSUSE Tumbleweed:")
|
||||
logger.error(
|
||||
" PYVER=$(python3 -c 'import sys; "
|
||||
'print(f"python{sys.version_info.major}{sys.version_info.minor}")\')'
|
||||
)
|
||||
logger.error(
|
||||
' sudo zypper install "${PYVER}-gobject" gtk3 '
|
||||
"typelib-1_0-AyatanaAppIndicator3-0_1 "
|
||||
"typelib-1_0-Notify-0_7 libnotify4"
|
||||
)
|
||||
logger.error("")
|
||||
logger.error(
|
||||
"For pipx users: Install system packages BEFORE running 'pipx install vocalinux'"
|
||||
)
|
||||
|
||||
@@ -129,6 +129,36 @@ class TestCrossDistroCompatibility:
|
||||
for path in expected_paths:
|
||||
assert path in install_sh_content, f"Should have fallback path: {path}"
|
||||
|
||||
def test_opensuse_dependency_mapping_uses_tumbleweed_package_names(self, install_sh_content):
|
||||
"""Test that openSUSE uses Tumbleweed-compatible dependency resolution."""
|
||||
assert "suse_python_package_prefix()" in install_sh_content
|
||||
assert "suse_python_package_candidates()" in install_sh_content
|
||||
assert "typelib-1_0-AyatanaAppIndicator3-0_1" in install_sh_content
|
||||
assert "typelib-1_0-Notify-0_7" in install_sh_content
|
||||
assert "libnotify4" in install_sh_content
|
||||
assert "suse_install_appindicator_runtime" in install_sh_content
|
||||
assert "shaderc glslang-devel glslang" in install_sh_content
|
||||
|
||||
zypper_line = next(
|
||||
line for line in install_sh_content.splitlines() if "local ZYPPER_PACKAGES=" in line
|
||||
)
|
||||
assert "python3-devel" not in zypper_line
|
||||
assert "python3-virtualenv" not in zypper_line
|
||||
assert "libappindicator-gtk3" not in zypper_line
|
||||
assert "glslang" not in zypper_line
|
||||
|
||||
def test_skip_system_deps_option_is_implemented(self, install_sh_content):
|
||||
"""Test that the documented --skip-system-deps option is parsed and honored."""
|
||||
assert "SKIP_SYSTEM_DEPS" in install_sh_content
|
||||
assert "--skip-system-deps" in install_sh_content
|
||||
assert "Skipping system dependency installation" in install_sh_content
|
||||
|
||||
def test_noninteractive_tty_fallback_does_not_abort(self, install_sh_content):
|
||||
"""Test that missing controlling TTY falls back to non-interactive mode."""
|
||||
assert "{ true < /dev/tty; } 2>/dev/null" in install_sh_content
|
||||
assert "exec < /dev/tty" in install_sh_content
|
||||
assert 'NON_INTERACTIVE="yes"' in install_sh_content
|
||||
|
||||
def test_ci_workflow_uses_dynamic_detection(self, workflow_content):
|
||||
"""Test that CI workflow uses dynamic GI_TYPELIB_PATH detection."""
|
||||
# Should use pkg-config or dynamic detection
|
||||
|
||||
Reference in New Issue
Block a user