Limit and sort transmission torrents_info attribute (#35411)

This commit is contained in:
Gleb Sinyavskiy 2020-06-28 13:56:54 +02:00 committed by GitHub
parent 15165a3c93
commit 4a374f0378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 114 additions and 27 deletions

View File

@ -24,9 +24,13 @@ from homeassistant.helpers.event import async_track_time_interval
from .const import (
ATTR_DELETE_DATA,
ATTR_TORRENT,
CONF_LIMIT,
CONF_ORDER,
DATA_UPDATED,
DEFAULT_DELETE_DATA,
DEFAULT_LIMIT,
DEFAULT_NAME,
DEFAULT_ORDER,
DEFAULT_PORT,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
@ -238,7 +242,13 @@ class TransmissionClient:
scan_interval = self.config_entry.data.get(
CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
)
options = {CONF_SCAN_INTERVAL: scan_interval}
limit = self.config_entry.data.get(CONF_LIMIT, DEFAULT_LIMIT)
order = self.config_entry.data.get(CONF_ORDER, DEFAULT_ORDER)
options = {
CONF_SCAN_INTERVAL: scan_interval,
CONF_LIMIT: limit,
CONF_ORDER: order,
}
self.hass.config_entries.async_update_entry(
self.config_entry, options=options
@ -260,9 +270,9 @@ class TransmissionClient:
@staticmethod
async def async_options_updated(hass, entry):
"""Triggered by config entry options updates."""
hass.data[DOMAIN][entry.entry_id].set_scan_interval(
entry.options[CONF_SCAN_INTERVAL]
)
tm_client = hass.data[DOMAIN][entry.entry_id]
tm_client.set_scan_interval(entry.options[CONF_SCAN_INTERVAL])
await hass.async_add_executor_job(tm_client.api.update)
class TransmissionData:

View File

@ -13,7 +13,17 @@ from homeassistant.const import (
from homeassistant.core import callback
from . import get_api
from .const import DEFAULT_NAME, DEFAULT_PORT, DEFAULT_SCAN_INTERVAL, DOMAIN
from .const import (
CONF_LIMIT,
CONF_ORDER,
DEFAULT_LIMIT,
DEFAULT_NAME,
DEFAULT_ORDER,
DEFAULT_PORT,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
SUPPORTED_ORDER_MODES,
)
from .errors import AuthenticationError, CannotConnect, UnknownError
DATA_SCHEMA = vol.Schema(
@ -94,7 +104,15 @@ class TransmissionOptionsFlowHandler(config_entries.OptionsFlow):
default=self.config_entry.options.get(
CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
),
): int
): int,
vol.Optional(
CONF_LIMIT,
default=self.config_entry.options.get(CONF_LIMIT, DEFAULT_LIMIT),
): vol.All(vol.Coerce(int), vol.Range(min=1, max=500)),
vol.Optional(
CONF_ORDER,
default=self.config_entry.options.get(CONF_ORDER, DEFAULT_ORDER),
): vol.All(vol.Coerce(str), vol.In(SUPPORTED_ORDER_MODES.keys())),
}
return self.async_show_form(step_id="init", data_schema=vol.Schema(options))

View File

@ -1,10 +1,30 @@
"""Constants for the Transmission Bittorent Client component."""
DOMAIN = "transmission"
SWITCH_TYPES = {"on_off": "Switch", "turtle_mode": "Turtle Mode"}
ORDER_NEWEST_FIRST = "newest_first"
ORDER_OLDEST_FIRST = "oldest_first"
ORDER_BEST_RATIO_FIRST = "best_ratio_first"
ORDER_WORST_RATIO_FIRST = "worst_ratio_first"
SUPPORTED_ORDER_MODES = {
ORDER_NEWEST_FIRST: lambda torrents: sorted(
torrents, key=lambda t: t.addedDate, reverse=True
),
ORDER_OLDEST_FIRST: lambda torrents: sorted(torrents, key=lambda t: t.addedDate),
ORDER_WORST_RATIO_FIRST: lambda torrents: sorted(torrents, key=lambda t: t.ratio),
ORDER_BEST_RATIO_FIRST: lambda torrents: sorted(
torrents, key=lambda t: t.ratio, reverse=True
),
}
CONF_LIMIT = "limit"
CONF_ORDER = "order"
DEFAULT_DELETE_DATA = False
DEFAULT_LIMIT = 10
DEFAULT_ORDER = ORDER_OLDEST_FIRST
DEFAULT_NAME = "Transmission"
DEFAULT_PORT = 9091
DEFAULT_SCAN_INTERVAL = 120

View File

@ -6,7 +6,13 @@ from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity
from .const import DOMAIN, STATE_ATTR_TORRENT_INFO
from .const import (
CONF_LIMIT,
CONF_ORDER,
DOMAIN,
STATE_ATTR_TORRENT_INFO,
SUPPORTED_ORDER_MODES,
)
_LOGGER = logging.getLogger(__name__)
@ -143,28 +149,45 @@ class TransmissionTorrentsSensor(TransmissionSensor):
@property
def device_state_attributes(self):
"""Return the state attributes, if any."""
limit = self._tm_client.config_entry.options[CONF_LIMIT]
order = self._tm_client.config_entry.options[CONF_ORDER]
torrents = self._tm_client.api.torrents[0:limit]
info = _torrents_info(
self._tm_client.api.torrents, self.SUBTYPE_MODES[self._sub_type]
torrents, order=order, statuses=self.SUBTYPE_MODES[self._sub_type],
)
return {STATE_ATTR_TORRENT_INFO: info}
return {
STATE_ATTR_TORRENT_INFO: info,
}
def update(self):
"""Get the latest data from Transmission and updates the state."""
self._state = len(self.device_state_attributes[STATE_ATTR_TORRENT_INFO])
torrents = _filter_torrents(
self._tm_client.api.torrents, statuses=self.SUBTYPE_MODES[self._sub_type]
)
self._state = len(torrents)
def _torrents_info(torrents, statuses=None):
def _filter_torrents(torrents, statuses=None):
return [
torrent
for torrent in torrents
if statuses is None or torrent.status in statuses
]
def _torrents_info(torrents, order, statuses=None):
infos = {}
for torrent in torrents:
if statuses is None or torrent.status in statuses:
info = infos[torrent.name] = {
"added_date": torrent.addedDate,
"percent_done": f"{torrent.percentDone * 100:.2f}",
"status": torrent.status,
"id": torrent.id,
}
try:
info["eta"] = str(torrent.eta)
except ValueError:
pass
torrents = _filter_torrents(torrents, statuses)
torrents = SUPPORTED_ORDER_MODES[order](torrents)
for torrent in _filter_torrents(torrents, statuses):
info = infos[torrent.name] = {
"added_date": torrent.addedDate,
"percent_done": f"{torrent.percentDone * 100:.2f}",
"status": torrent.status,
"id": torrent.id,
}
try:
info["eta"] = str(torrent.eta)
except ValueError:
pass
return infos

View File

@ -8,7 +8,9 @@
"host": "[%key:common::config_flow::data::host%]",
"username": "[%key:common::config_flow::data::username%]",
"password": "[%key:common::config_flow::data::password%]",
"port": "[%key:common::config_flow::data::port%]"
"port": "[%key:common::config_flow::data::port%]",
"limit": "Limit",
"order": "Order"
}
}
},

View File

@ -12,6 +12,8 @@
"user": {
"data": {
"host": "Host",
"limit": "Limit",
"order": "Order",
"name": "Name",
"password": "Password",
"port": "Port",
@ -25,7 +27,9 @@
"step": {
"init": {
"data": {
"scan_interval": "Update frequency"
"scan_interval": "Update frequency",
"limit": "Limit",
"order": "Order"
},
"title": "Configure options for Transmission"
}

View File

@ -8,7 +8,11 @@ from homeassistant import data_entry_flow
from homeassistant.components import transmission
from homeassistant.components.transmission import config_flow
from homeassistant.components.transmission.const import (
CONF_LIMIT,
CONF_ORDER,
DEFAULT_LIMIT,
DEFAULT_NAME,
DEFAULT_ORDER,
DEFAULT_PORT,
DEFAULT_SCAN_INTERVAL,
)
@ -158,6 +162,8 @@ async def test_import(hass, api):
CONF_HOST: HOST,
CONF_PORT: DEFAULT_PORT,
CONF_SCAN_INTERVAL: timedelta(seconds=DEFAULT_SCAN_INTERVAL),
CONF_LIMIT: DEFAULT_LIMIT,
CONF_ORDER: DEFAULT_ORDER,
}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
@ -176,6 +182,8 @@ async def test_import(hass, api):
CONF_PASSWORD: PASSWORD,
CONF_PORT: PORT,
CONF_SCAN_INTERVAL: timedelta(seconds=SCAN_INTERVAL),
CONF_LIMIT: DEFAULT_LIMIT,
CONF_ORDER: DEFAULT_ORDER,
}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY

View File

@ -81,7 +81,9 @@ async def test_successful_config_entry(hass, api):
assert await transmission.async_setup_entry(hass, entry) is True
assert entry.options == {
transmission.CONF_SCAN_INTERVAL: transmission.DEFAULT_SCAN_INTERVAL
transmission.CONF_SCAN_INTERVAL: transmission.DEFAULT_SCAN_INTERVAL,
transmission.CONF_LIMIT: transmission.DEFAULT_LIMIT,
transmission.CONF_ORDER: transmission.DEFAULT_ORDER,
}