Coverage for src / server_list / spec / webapi / ups.py: 97%
31 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-31 11:45 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-31 11:45 +0000
1#!/usr/bin/env python3
2"""
3UPS API.
4Provides UPS information and topology via REST API from SQLite cache.
5"""
7import dataclasses
9import flask
11import server_list.spec.data_collector as data_collector
12import server_list.spec.webapi as webapi
14ups_api = flask.Blueprint("ups_api", __name__)
17@ups_api.route("/ups", methods=["GET"])
18def get_all_ups():
19 """Get all UPS information with topology (clients)."""
20 ups_info_list = data_collector.get_all_ups_info()
21 all_clients = data_collector.get_all_ups_clients()
23 # Group clients by UPS
24 clients_by_ups: dict[tuple[str, str], list[dict]] = {}
25 for client in all_clients:
26 key = (client.ups_name, client.host)
27 if key not in clients_by_ups: 27 ↛ 29line 27 didn't jump to line 29 because the condition on line 27 was always true
28 clients_by_ups[key] = []
29 clients_by_ups[key].append(dataclasses.asdict(client))
31 # Build response with topology
32 result = []
33 for ups in ups_info_list:
34 ups_data = dataclasses.asdict(ups)
35 key = (ups.ups_name, ups.host)
36 ups_data["clients"] = clients_by_ups.get(key, [])
37 result.append(ups_data)
39 return webapi.success_response(result)
42@ups_api.route("/ups/<host>/<ups_name>", methods=["GET"])
43def get_ups_detail(host: str, ups_name: str):
44 """Get specific UPS information with clients."""
45 ups_info = data_collector.get_ups_info(ups_name, host)
47 if not ups_info:
48 return webapi.error_response(f"UPS not found: {ups_name}@{host}", 404)
50 clients = data_collector.get_ups_clients(ups_name, host)
52 result = dataclasses.asdict(ups_info)
53 result["clients"] = [dataclasses.asdict(c) for c in clients]
55 return webapi.success_response(result)