mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-10-12 10:28:01 +00:00
Split out main cli module into lazily loaded submodules (#1039)
This commit is contained in:
134
kasa/cli/feature.py
Normal file
134
kasa/cli/feature.py
Normal file
@@ -0,0 +1,134 @@
|
||||
"""Module for cli feature commands."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
|
||||
import asyncclick as click
|
||||
|
||||
from kasa import (
|
||||
Device,
|
||||
Feature,
|
||||
)
|
||||
|
||||
from .common import (
|
||||
echo,
|
||||
error,
|
||||
pass_dev_or_child,
|
||||
)
|
||||
|
||||
|
||||
def _echo_features(
|
||||
features: dict[str, Feature],
|
||||
title: str,
|
||||
category: Feature.Category | None = None,
|
||||
verbose: bool = False,
|
||||
indent: str = "\t",
|
||||
):
|
||||
"""Print out a listing of features and their values."""
|
||||
if category is not None:
|
||||
features = {
|
||||
id_: feat for id_, feat in features.items() if feat.category == category
|
||||
}
|
||||
|
||||
echo(f"{indent}[bold]{title}[/bold]")
|
||||
for _, feat in features.items():
|
||||
try:
|
||||
echo(f"{indent}{feat}")
|
||||
if verbose:
|
||||
echo(f"{indent}\tType: {feat.type}")
|
||||
echo(f"{indent}\tCategory: {feat.category}")
|
||||
echo(f"{indent}\tIcon: {feat.icon}")
|
||||
except Exception as ex:
|
||||
echo(f"{indent}{feat.name} ({feat.id}): [red]got exception ({ex})[/red]")
|
||||
|
||||
|
||||
def _echo_all_features(features, *, verbose=False, title_prefix=None, indent=""):
|
||||
"""Print out all features by category."""
|
||||
if title_prefix is not None:
|
||||
echo(f"[bold]\n{indent}== {title_prefix} ==[/bold]")
|
||||
echo()
|
||||
_echo_features(
|
||||
features,
|
||||
title="== Primary features ==",
|
||||
category=Feature.Category.Primary,
|
||||
verbose=verbose,
|
||||
indent=indent,
|
||||
)
|
||||
echo()
|
||||
_echo_features(
|
||||
features,
|
||||
title="== Information ==",
|
||||
category=Feature.Category.Info,
|
||||
verbose=verbose,
|
||||
indent=indent,
|
||||
)
|
||||
echo()
|
||||
_echo_features(
|
||||
features,
|
||||
title="== Configuration ==",
|
||||
category=Feature.Category.Config,
|
||||
verbose=verbose,
|
||||
indent=indent,
|
||||
)
|
||||
echo()
|
||||
_echo_features(
|
||||
features,
|
||||
title="== Debug ==",
|
||||
category=Feature.Category.Debug,
|
||||
verbose=verbose,
|
||||
indent=indent,
|
||||
)
|
||||
|
||||
|
||||
@click.command(name="feature")
|
||||
@click.argument("name", required=False)
|
||||
@click.argument("value", required=False)
|
||||
@pass_dev_or_child
|
||||
@click.pass_context
|
||||
async def feature(
|
||||
ctx: click.Context,
|
||||
dev: Device,
|
||||
name: str,
|
||||
value,
|
||||
):
|
||||
"""Access and modify features.
|
||||
|
||||
If no *name* is given, lists available features and their values.
|
||||
If only *name* is given, the value of named feature is returned.
|
||||
If both *name* and *value* are set, the described setting is changed.
|
||||
"""
|
||||
verbose = ctx.parent.params.get("verbose", False) if ctx.parent else False
|
||||
|
||||
if not name:
|
||||
_echo_all_features(dev.features, verbose=verbose, indent="")
|
||||
|
||||
if dev.children:
|
||||
for child_dev in dev.children:
|
||||
_echo_all_features(
|
||||
child_dev.features,
|
||||
verbose=verbose,
|
||||
title_prefix=f"Child {child_dev.alias}",
|
||||
indent="\t",
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
if name not in dev.features:
|
||||
error(f"No feature by name '{name}'")
|
||||
return
|
||||
|
||||
feat = dev.features[name]
|
||||
|
||||
if value is None:
|
||||
unit = f" {feat.unit}" if feat.unit else ""
|
||||
echo(f"{feat.name} ({name}): {feat.value}{unit}")
|
||||
return feat.value
|
||||
|
||||
value = ast.literal_eval(value)
|
||||
echo(f"Changing {name} from {feat.value} to {value}")
|
||||
response = await dev.features[name].set_value(value)
|
||||
await dev.update()
|
||||
echo(f"New state: {feat.value}")
|
||||
|
||||
return response
|
Reference in New Issue
Block a user