Skip to content

Conversation

@X9X0
Copy link
Owner

@X9X0 X9X0 commented Nov 16, 2025

Summary

Major improvements to the LabLink GUI launcher (lablink.py) to handle Ubuntu 24.04's PEP 668 restrictions, fix dependency detection/installation, improve UX, and add all missing dependencies discovered during testing.

Launcher Improvements

UX Enhancements

  • Auto-closing launch messages: Server/client launch confirmations now auto-dismiss after 3 seconds for smoother workflow
  • Background fix worker: Fixes now run in a separate QThread, preventing GUI freezes and "Python not responding" dialogs during package installation
  • Improved status indicators: Changed venv and PEP668 checks from WARNING to OK when properly handled by launcher

Dependency Management

  • Priority-based fix ordering: Ensures correct installation sequence (apt packages → ensurepip → venv creation → pip installs)
  • Broken venv detection: Automatically detects and removes corrupted virtual environments before recreation
  • Correct environment checking: Package verification now uses venv Python instead of system Python
  • Package-to-import mapping: Added mappings for packages with non-standard import names:
    • python-dotenvdotenv
    • python-dateutildateutil
    • pydantic-settingspydantic_settings
    • pyserialserial
    • pyusbusb
    • PyJWTjwt
    • email-validatoremail_validator
    • pyvisa-pypyvisa_py

Platform Compatibility

  • Ubuntu 24.04 support: Changed libgl1-mesa-glx to libgl1 for Qt dependencies
  • PEP 668 handling: Proper detection and automatic venv usage on externally-managed systems

Launch Fixes

  • Client launch: Uses python -m client.main with correct working directory for proper import resolution
  • Server launch: Uses absolute venv paths and sets PYTHONPATH for mixed import patterns

Missing Dependencies Added

Server Requirements (server/requirements.txt)

Added 10 missing packages discovered during runtime testing:

Data Processing:

  • scipy==1.11.4 - Signal processing in acquisition/statistics.py

System Utilities:

  • psutil==5.9.8 - System monitoring for diagnostics
  • apscheduler==3.10.4 - Task scheduling
  • zeroconf==0.132.2 - mDNS network discovery

Security & Authentication:

  • bcrypt==4.1.3 - Password hashing
  • httpx==0.27.0 - Async HTTP client for OAuth2
  • PyJWT==2.10.1 - JWT token handling
  • pyotp==2.9.0 - TOTP multi-factor authentication
  • qrcode[pil]==8.2 - QR code generation for MFA

Configuration:

  • email-validator==2.1.0 - Pydantic email validation

Client Requirements (client/requirements.txt)

  • zeroconf==0.132.2 - mDNS service discovery for server detection

Code Fixes

Performance Module Export

  • Fixed ImportError in server/main.py by exporting initialize_performance_monitor from server/performance/__init__.py

Testing

Tested on Ubuntu 24.04:

  • ✅ All dependencies detected and installed correctly
  • ✅ Server launches successfully with all subsystems initialized
  • ✅ Client launches and connects to server
  • ✅ Background fix worker prevents GUI freezing
  • ✅ Auto-close messages work as expected
  • ✅ No import errors in server or client startup

Breaking Changes

None - all changes are backwards compatible.

Related Issues

Fixes launcher issues on Ubuntu 24.04 with PEP 668 externally-managed Python environments.

…ecking

This commit applies critical fixes to the launcher to properly handle virtual
environments and dependency checking on Ubuntu 24.04 systems.

**Issues Fixed:**

1. **Fix Application Order** - Fixes were applied in the wrong order, causing
   venv creation to fail before python3-venv was installed
   - Now sorts fixes by priority: apt_install → ensurepip → create_venv → pip_install
   - Prevents broken venv creation

2. **Broken Venv Detection** - Existing venvs without pip weren't detected
   - Added detection for broken venvs (missing venv/bin/pip)
   - Automatically removes and recreates broken venvs
   - Validates pip exists after venv creation

3. **Wrong pip Used** - Package installation used system pip instead of venv pip
   - Modified pip_install to detect and use venv/bin/pip when available
   - Falls back to system pip if no venv exists

4. **Dependency Checks Failed** - After successful installation to venv,
   dependency checks still showed RED (errors)
   - Modified _check_packages() to use subprocess with venv/bin/python
   - Now correctly checks packages installed in venv
   - Falls back to __import__() for system environment

5. **Launch Commands Used Wrong Python** - Server/client launched with system
   Python, couldn't import venv packages
   - Updated launch_server() to use venv/bin/python when available
   - Updated launch_client() to use venv/bin/python when available
   - Both fall back to system Python if no venv

**Result:**
The launcher now correctly:
- Installs system packages before creating venv
- Creates functional venvs with pip
- Installs dependencies to venv
- Shows correct LED status (GREEN/YELLOW not RED)
- Launches server/client with venv Python and dependencies
This commit adds detailed logging to help diagnose launcher issues and track
the fix application process.

**Changes:**

1. **Logging Configuration** (lines 23-43)
   - Set up logging with DEBUG level
   - Logs to both lablink_debug.log file and console
   - Format: timestamp - level - function:line - message
   - Log startup banner on launch

2. **System Check Logging**
   - check_all(): Logs "Starting comprehensive system check"
   - on_env_checked(): Logs completion with result count and details
   - update_led_status(): Logs LED updates with status and color

3. **Fix Application Logging** (apply_fixes method)
   - Logs all fixes to be applied
   - Logs environment status (externally managed, venv exists)
   - Logs each fix step with progress (1/5, 2/5, etc.)
   - Logs ensurepip execution
   - Logs venv creation/recreation with detailed steps
   - Logs pip package installation with pip path used
   - Logs apt package installation
   - Logs errors with full traceback
   - Logs completion and re-check trigger

**Result:**
Debug log file (lablink_debug.log) now captures:
- All system checks and their results
- LED status updates
- Every fix attempted and its outcome
- Errors with full stack traces
- Environment and venv status throughout the process

This makes it much easier to diagnose issues when the launcher encounters
problems on different systems.
This commit fixes an AttributeError that occurred when apply_fixes() tried
to call self._check_externally_managed() which didn't exist in the
LabLinkLauncher class.

**Error Fixed:**
AttributeError: 'LabLinkLauncher' object has no attribute '_check_externally_managed'

**Changes:**
- Added _check_externally_managed() method to LabLinkLauncher class
  - Checks if Python installation is externally managed (PEP 668)
  - Used for logging environment status during fix application

- Added _check_command_exists() method to LabLinkLauncher class
  - Checks if a command exists in PATH
  - Used by _install_apt_packages() to detect pkexec availability

Both methods were already present in CheckWorker but are now also available
in LabLinkLauncher where they are needed by apply_fixes() and
_install_apt_packages().
This commit fixes two issues:

1. **Wrong package name for Ubuntu 24.04**
   - Changed libgl1-mesa-glx to libgl1
   - libgl1-mesa-glx doesn't exist in Ubuntu 24.04 repositories
   - Error: "E: Package 'libgl1-mesa-glx' has no installation candidate"
   - Ubuntu 24.04 uses libgl1 instead

2. **Missing apt error logging**
   - Added logger.error() calls for apt update failures
   - Added logger.error() calls for apt install failures
   - Logs return code, stderr, and stdout for debugging
   - Added logging in exception handler with full traceback
   - Added logging for successful installations and user cancellations

**Result:**
- Launcher can now successfully install Qt dependencies on Ubuntu 24.04
- All apt errors are captured in lablink_debug.log for debugging
- Error messages from apt (like "no installation candidate") are now logged
This commit fixes the issue where dependency checks failed after successful
installation due to incorrect import name mapping.

**Problem:**
After successfully installing packages to venv, the dependency check still
showed RED (errors) because some packages have different import names than
their package names.

Examples:
- python-dotenv → imports as "dotenv" (not "python_dotenv")
- python-dateutil → imports as "dateutil" (not "python_dateutil")
- PyQt6-Qt6 → no importable module (just Qt binaries, check PyQt6)

**Solution:**

1. **Package Name Mapping** (lines 621-629)
   Added package_to_import dictionary to map special package names:
   - python-dotenv → dotenv
   - python-dateutil → dateutil
   - pydantic-settings → pydantic_settings
   - pyvisa-py → pyvisa_py
   - PyQt6-Qt6 → PyQt6

2. **Debug Logging for Package Checks**
   - Logs venv detection and which Python is used
   - Logs each package check result (INSTALLED/MISSING)
   - Logs import errors with stderr output
   - Logs final summary (X installed, Y missing)

**Result:**
- Dependency checks now use correct import names
- After successful pip install, LEDs show GREEN/YELLOW (not RED)
- Debug log shows exactly which packages pass/fail import checks
- Much easier to diagnose package check issues
This commit fixes the last two package import name mismatches that were
causing server dependencies to show RED even after successful installation.

**Problem:**
Server dependencies LED still showed RED because two packages couldn't be
imported correctly:
- pyserial package imports as 'serial' (not 'pyserial')
- pyusb package imports as 'usb' (not 'pyusb')

**Debug log showed:**
- pyserial: MISSING (import pyserial failed: ModuleNotFoundError)
- pyusb: MISSING (import pyusb failed: ModuleNotFoundError)

**Solution:**
Added two entries to package_to_import mapping:
- 'pyserial': 'serial'
- 'pyusb': 'usb'

**Result:**
- All 18 server dependencies now check correctly
- Server Dependencies LED shows GREEN after successful installation
- Both server and client dependencies now work correctly
This commit fixes confusing WARNING messages that appeared even when the
launcher was correctly handling virtual environments and PEP 668.

**Problem:**
Users saw two YELLOW warnings that looked like problems:
1. "Virtual Environment - Exists but not active"
2. "Package Installation - Externally managed"

But these aren't actually problems! The launcher automatically uses the venv
via absolute paths (venv/bin/pip, venv/bin/python) and doesn't need the venv
to be "activated" in the traditional sense.

**Changes:**

1. **Virtual Environment Status** (lines 297-309)
   - Changed from WARNING to OK when venv exists
   - New message: "✓ Virtual environment found"
   - Explains: "The launcher automatically uses this venv"
   - Note: "Manual activation not required for the launcher"

2. **PEP 668 Status** (lines 341-353)
   - Changed from WARNING to OK when venv exists
   - New status: "Handled via venv"
   - Explains this is normal for Ubuntu 24.04
   - Notes: "The launcher uses the virtual environment to handle this"
   - Clarifies: "All package installations go to the venv"

**Result:**
- Environment LED shows GREEN instead of YELLOW when venv exists
- Users see reassuring "✓" messages instead of "⚠" warnings
- Clearer explanation that the launcher handles everything automatically
- Only shows WARNING when venv truly doesn't exist
This commit fixes ModuleNotFoundError when launching client and server
from the GUI launcher.

**Problem:**
When launching the client, it failed with:
  ModuleNotFoundError: No module named 'client'

This occurred because the code was running `python client/main.py` directly,
but client/main.py uses `from client.ui.main_window import MainWindow`,
which requires the parent directory to be in Python's import path.

**Root Cause:**
Running a script directly (python path/to/script.py) doesn't add the parent
directory to sys.path, so package-relative imports fail.

**Solution:**

1. **Client Launch** (lines 1334-1339)
   - Changed from: python client/main.py
   - Changed to: python -m client.main (with cwd set to LabLink root)
   - The -m flag runs as a module, properly handling package imports
   - Set cwd parameter to ensure we're in the correct directory

2. **Server Launch** (lines 1292-1300)
   - Changed from: cd server && python main.py
   - Changed to: cd <LabLink-root> && python -m server.main
   - Keeps terminal open with "exec bash" so errors are visible
   - Uses absolute path to LabLink root directory

**Result:**
- Client launches successfully without import errors
- Server launches successfully with proper module path
- Both use venv Python when available
- Terminal stays open for server to show output/errors
This commit fixes the server import error by changing the working directory
to server/ before launching, which is what the server code expects.

**Problem:**
Server failed to launch with:
  ModuleNotFoundError: No module named 'api'

This occurred because the previous fix tried to run the server as:
  python -m server.main (from LabLink root)

But server/main.py uses relative imports like:
  from api import acquisition_router, ...
  from config.settings import settings

These imports expect the current directory to be server/, not LabLink root.

**Solution:**
Changed server launch command from:
  cd /path/to/LabLink && python -m server.main

To:
  cd /path/to/LabLink/server && python main.py

**Why This Works:**
- The server code is designed to run from the server/ directory
- Running main.py directly from server/ makes relative imports work
- The client still uses -m client.main because its imports are structured
  differently (uses absolute imports like "from client.ui...")

**Note:**
This is the correct approach - the server and client have different import
structures and need different launch strategies.
This commit fixes "No such file or directory" error when launching server
because the venv Python path was relative.

**Problem:**
Server launch failed with:
  bash: line 1: venv/bin/python: No such file or directory

This occurred because:
1. The code checked Path("venv/bin/python") from LabLink root (exists ✓)
2. Then stored it as the relative string "venv/bin/python"
3. But the launch command changed directory to server/
4. From server/, the relative path "venv/bin/python" doesn't exist

**Solution:**
Changed both server and client launch to use absolute paths:

**Before:**
  venv_python = Path("venv/bin/python")  # relative
  python_exe = str(venv_python)  # "venv/bin/python"

**After:**
  lablink_root = Path.cwd().absolute()
  venv_python = lablink_root / "venv" / "bin" / "python"  # absolute
  python_exe = str(venv_python)  # "/full/path/to/venv/bin/python"

**Result:**
- Server launches correctly even though we cd to server/
- Client also updated for consistency
- Absolute paths work from any working directory
This commit fixes the ModuleNotFoundError for 'server' module by adding
the LabLink root directory to PYTHONPATH when launching the server.

**Problem:**
Server failed with:
  ModuleNotFoundError: No module named 'server'
  at: from server.acquisition import ...

This occurred because the server code has mixed import styles:
1. server/main.py uses: from api import ... (relative, needs cwd=server/)
2. server/api/acquisition.py uses: from server.acquisition import ...
   (absolute, needs 'server' in Python path)

**Root Cause:**
When running from server/ directory, Python can't find the 'server' module
because the parent directory (LabLink root) isn't in sys.path.

**Solution:**
Set PYTHONPATH to include LabLink root when launching server:

**Linux/macOS:**
  PYTHONPATH=/path/to/LabLink:$PYTHONPATH python main.py

**Windows:**
  set PYTHONPATH=/path/to/LabLink;%PYTHONPATH% && python main.py

This allows both import styles to work:
- Relative imports work because cwd is server/
- Absolute imports work because LabLink root is in PYTHONPATH

**Result:**
Server launches successfully with all imports working correctly.
This commit adds scipy as a required dependency for the server.

**Problem:**
Server failed to start with:
  ModuleNotFoundError: No module named 'scipy'
  at: from scipy import fft, signal

The server code uses scipy for signal processing and FFT analysis in
server/acquisition/statistics.py, but scipy was not listed in the
requirements.txt file.

**Solution:**
Added scipy==1.11.4 to server/requirements.txt under Data Handling section.

**Version Choice:**
- scipy 1.11.4 is compatible with numpy 1.26.3 (already in requirements)
- This is a stable version from late 2023
- Compatible with Python 3.12.3

**Result:**
After running "Fix Issues" in the launcher to install the updated
requirements, the server will have scipy available and start successfully.
Updated launch_client method to use the auto-close message helper,
matching the behavior of launch_server. Launch messages now
automatically dismiss after 3 seconds for a smoother UX.
Added psutil==5.9.8 to server requirements. This package is required
by the diagnostics manager for system monitoring functionality.
Added:
- apscheduler==3.10.4 for task scheduling functionality
- zeroconf==0.132.2 for mDNS network discovery

Both are required by the server but were missing from requirements.txt
Server additions (for security/authentication modules):
- bcrypt==4.1.3 - Password hashing
- httpx==0.27.0 - Async HTTP client for OAuth2
- PyJWT==2.10.1 - JWT token handling
- pyotp==2.9.0 - TOTP multi-factor authentication
- qrcode[pil]==8.2 - QR code generation with PIL support

Client additions:
- zeroconf==0.132.2 - mDNS service discovery

These packages were actively imported in the codebase but missing
from requirements.txt, causing runtime import errors.
PyJWT is the package name but it imports as 'jwt'. Added to the
mapping so dependency checks use the correct import name.
Added email-validator==2.1.0 to server requirements and added the
package-to-import mapping (email-validator -> email_validator).

This is required by pydantic when using EmailStr type in models,
specifically in the User model in security/models.py.
Added initialize_performance_monitor to the exports in performance/__init__.py
to fix ImportError in server startup. The function exists in monitor.py but
was not being exported from the module.
@X9X0 X9X0 merged commit 5b5791e into main Nov 16, 2025
25 checks passed
X9X0 added a commit that referenced this pull request Dec 7, 2025
…ecture

## Summary
Unified version management across all components (server, client, launcher, Docker)
using a single VERSION file as the source of truth. Updated to v1.2.0 to accurately
reflect work completed since v1.0.0 (30+ PRs merged).

## Version System Changes

### Unified to v1.2.0
- Analyzed git history from v1.0.0 through current main
- Determined v1.2.0 accurately represents features and fixes delivered
- All components now read from single VERSION file

### Components Updated
- VERSION file: 0.28.0 → 1.2.0
- README badge: 1.0.1 → 1.2.0
- Server: Now reads VERSION (already implemented)
- Client: Added dynamic VERSION reading at startup
- Launcher: Added __version__ variable from VERSION
- Docker images: Labels updated to 1.2.0
- Copyright: Updated to © 2025 (project start year)

## CHANGELOG Updates

Added comprehensive release notes for missing versions:

### v1.2.0 (2025-12-06)
- Server update system with stable/development modes (#114, #118, #119)
- Smart branch filtering and UI consolidation (#120)
- Enhanced dropdown visibility
- Multiple bug fixes (#105, #106, #108, #121)

### v1.0.1 (2025-11-28)
- Equipment control panel (#104)
- GUI system launcher with diagnostics (#70-74)
- Raspberry Pi image builder (#75-76)
- Waveform analysis tools (#79)
- Automated test sequence builder (#80)
- Remote firmware update (#81)
- Equipment diagnostics system (#84-87)
- WebSocket integration completion (#77)

## Automation & Documentation

### Created scripts/bump_version.py
Automated version bumping tool with:
- Support for major/minor/patch increments
- Automatic VERSION file updates
- CHANGELOG.md section generation
- Git commit and tag creation
- Dry-run mode for testing

Usage:
  python scripts/bump_version.py patch   # 1.2.0 → 1.2.1
  python scripts/bump_version.py minor   # 1.2.0 → 1.3.0
  python scripts/bump_version.py major   # 1.2.0 → 2.0.0

### Created docs/VERSIONING.md
Complete versioning system documentation covering:
- Single-source architecture
- Semantic versioning guidelines
- Automated bumping procedures
- Manual update processes
- Troubleshooting guide
- Best practices

## Files Modified

Core Version Files:
  - VERSION (0.28.0 → 1.2.0)
  - CHANGELOG.md (added v1.0.1 and v1.2.0 entries)
  - README.md (badge updated to 1.2.0)

Component Updates:
  - client/main.py (dynamic VERSION reading)
  - lablink.py (added __version__ from VERSION)
  - docker/Dockerfile.server (label 1.2.0)
  - docker/Dockerfile.web (label 1.2.0)

Copyright Updates (© 2025):
  - docs/USER_GUIDE.md
  - client/ui/main_window.py

New Files:
  + scripts/bump_version.py (version management tool)
  + docs/VERSIONING.md (complete documentation)

## Benefits

✅ Single source of truth for version (VERSION file)
✅ Consistent versioning across all components
✅ Accurate version history in CHANGELOG
✅ Automated version bumping workflow
✅ Complete documentation for future updates
✅ Git-tagged releases (v1.2.0)

## Testing

Verified:
- VERSION file: 1.2.0 ✓
- Server reads VERSION correctly ✓
- Client would read VERSION at startup ✓
- Launcher reads VERSION correctly ✓
- bump_version.py dry-run works ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants