Skip to content

Conversation

@houllette
Copy link

Migrate from subprocess upsc to PyNUTClient library

Overview

This PR refactors the UPS monitoring system to use the native Python PyNUTClient library instead of subprocess calls to the upsc command. This provides more reliable communication with NUT servers, better error handling, and eliminates the external upsc dependency.

Additionally addresses #4

Changes

Core Functionality

  • wolnut/monitor.py: Refactored get_ups_status() to use PyNUTClient.GetUPSVars() instead of subprocess

    • Added graceful handling of PyNUTClient import failures
    • Implemented proper byte string decoding for Python 3 compatibility
    • Enhanced error handling with PyNUTError exceptions
    • Retained subprocess import for is_client_online() ping functionality
  • wolnut/config.py: Enhanced UPS identifier parsing

    • Added parse_ups_identifier() function supporting multiple formats:
      • Simple: "myups" → connects to localhost:3493
      • With host: "myups@nut-server" → connects to nut-server:3493
      • Full: "myups@nut-server:9999" → custom port
    • Added host field to NutConfig dataclass (default: "localhost")
    • Explicit host/port config fields override parsed values
  • wolnut/cli.py: Updated get_ups_status() calls to pass full NutConfig object

Dependencies

  • pyproject.toml: Added PyNUTClient>=2.8.4 dependency

Tests

  • tests/test_monitor.py: New comprehensive test suite (16+ tests)

    • UPS status retrieval with various configurations
    • Authentication handling
    • Byte string and mixed type handling
    • Connection errors and exception handling
    • Custom ports, timeouts, and edge cases
  • tests/test_config.py: Added 17 new tests

    • TestParseUpsIdentifier: 10 tests for UPS identifier parsing
    • TestLoadConfigWithParsing: 7 tests for config loading with parsing
    • Updated existing tests to match new parsing behavior

Documentation

  • README.md: Updated to reflect PyNUTClient usage
  • config.example.yaml: Added comprehensive comments explaining UPS format options and optional fields
  • Fixed typo in config example

Backward Compatibility

Fully backward compatible - all existing configurations continue to work:

  • ups: "myups@localhost" → parsed to ups="myups", host="localhost"
  • ups: "myups@server:3493" → parsed with custom port
  • New explicit field format also supported

Testing

  • ✅ All 79 tests passing
  • ✅ 40+ new/updated test cases
  • ✅ Comprehensive coverage of new functionality
  • ✅ Error handling and edge cases covered

Benefits

  • Native Python communication: No external upsc process required
  • Better error handling: Proper exception handling with PyNUTError
  • Enhanced authentication: Native username/password support
  • Flexible configuration: Multiple ways to specify UPS connection details
  • Type safety: Improved type hints and structured data
  • Python 3 compatible: Proper byte string handling

Migration Notes

No action required for existing users - all current configurations work as-is. Optional: Users can now specify host and port as separate fields for clarity.

Files Changed

File Lines Type
pyproject.toml +1 Dependency
wolnut/config.py +43 Enhancement
wolnut/monitor.py ~60 Refactor
wolnut/cli.py 2 Update
tests/test_monitor.py +238 New file
tests/test_config.py +191 Enhancement
README.md 1 Documentation
config.example.yaml +9 Documentation

Total: ~545 lines added/modified

@houllette
Copy link
Author

This PR addresses #4 - @hardwarehaven would you be willing to take a look at this and consider merging? Happy to make any changes necessary!

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.

1 participant