mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-10-13 02:48:07 +00:00
Update dump_devinfo for raw discovery json and common redactors (#1358)
Some checks failed
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Has been cancelled
Some checks failed
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Has been cancelled
This PR does a few related things to dump_devinfo: - Store the raw discovery result in the fixture. - Consolidate redaction logic so it's not duplicated in dump_devinfo. - Update existing fixtures to: - Store raw discovery result under `result` - Use `SCRUBBED_CHILD_DEVICE_ID` everywhere - Have correct values as per the consolidated redactors.
This commit is contained in:
128
devtools/update_fixtures.py
Normal file
128
devtools/update_fixtures.py
Normal file
@@ -0,0 +1,128 @@
|
||||
"""Module to mass update fixture files."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
import asyncclick as click
|
||||
|
||||
from devtools.dump_devinfo import _wrap_redactors
|
||||
from kasa.discover import NEW_DISCOVERY_REDACTORS, redact_data
|
||||
from kasa.protocols.iotprotocol import REDACTORS as IOT_REDACTORS
|
||||
from kasa.protocols.smartprotocol import REDACTORS as SMART_REDACTORS
|
||||
|
||||
FIXTURE_FOLDER = "tests/fixtures/"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def update_fixtures(update_func: Callable[[dict], bool], *, dry_run: bool) -> None:
|
||||
"""Run the update function against the fixtures."""
|
||||
for file in Path(FIXTURE_FOLDER).glob("**/*.json"):
|
||||
with file.open("r") as f:
|
||||
fixture_data = json.load(f)
|
||||
|
||||
if file.parent.name == "serialization":
|
||||
continue
|
||||
changed = update_func(fixture_data)
|
||||
if changed:
|
||||
click.echo(f"Will update {file.name}\n")
|
||||
if changed and not dry_run:
|
||||
with file.open("w") as f:
|
||||
json.dump(fixture_data, f, sort_keys=True, indent=4)
|
||||
f.write("\n")
|
||||
|
||||
|
||||
def _discovery_result_update(info) -> bool:
|
||||
"""Update discovery_result to be the raw result and error_code."""
|
||||
if (disco_result := info.get("discovery_result")) and "result" not in disco_result:
|
||||
info["discovery_result"] = {
|
||||
"result": disco_result,
|
||||
"error_code": 0,
|
||||
}
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _child_device_id_update(info) -> bool:
|
||||
"""Update child device ids to be the scrubbed ids from dump_devinfo."""
|
||||
changed = False
|
||||
if get_child_device_list := info.get("get_child_device_list"):
|
||||
child_device_list = get_child_device_list["child_device_list"]
|
||||
child_component_list = info["get_child_device_component_list"][
|
||||
"child_component_list"
|
||||
]
|
||||
for index, child_device in enumerate(child_device_list):
|
||||
child_component = child_component_list[index]
|
||||
if "SCRUBBED" not in child_device["device_id"]:
|
||||
dev_id = f"SCRUBBED_CHILD_DEVICE_ID_{index + 1}"
|
||||
click.echo(
|
||||
f"child_device_id{index}: {child_device['device_id']} -> {dev_id}"
|
||||
)
|
||||
child_device["device_id"] = dev_id
|
||||
child_component["device_id"] = dev_id
|
||||
changed = True
|
||||
|
||||
if children := info.get("system", {}).get("get_sysinfo", {}).get("children"):
|
||||
for index, child_device in enumerate(children):
|
||||
if "SCRUBBED" not in child_device["id"]:
|
||||
dev_id = f"SCRUBBED_CHILD_DEVICE_ID_{index + 1}"
|
||||
click.echo(f"child_device_id{index}: {child_device['id']} -> {dev_id}")
|
||||
child_device["id"] = dev_id
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
def _diff_data(fullkey, data1, data2, diffs):
|
||||
if isinstance(data1, dict):
|
||||
for k, v in data1.items():
|
||||
_diff_data(fullkey + "/" + k, v, data2[k], diffs)
|
||||
elif isinstance(data1, list):
|
||||
for index, item in enumerate(data1):
|
||||
_diff_data(fullkey + "/" + str(index), item, data2[index], diffs)
|
||||
elif data1 != data2:
|
||||
diffs[fullkey] = (data1, data2)
|
||||
|
||||
|
||||
def _redactor_result_update(info) -> bool:
|
||||
"""Update fixtures with the output using the common redactors."""
|
||||
changed = False
|
||||
|
||||
redactors = IOT_REDACTORS if "system" in info else SMART_REDACTORS
|
||||
|
||||
for key, val in info.items():
|
||||
if not isinstance(val, dict):
|
||||
continue
|
||||
if key == "discovery_result":
|
||||
info[key] = redact_data(val, _wrap_redactors(NEW_DISCOVERY_REDACTORS))
|
||||
else:
|
||||
info[key] = redact_data(val, _wrap_redactors(redactors))
|
||||
diffs: dict[str, tuple[str, str]] = {}
|
||||
_diff_data(key, val, info[key], diffs)
|
||||
if diffs:
|
||||
for k, v in diffs.items():
|
||||
click.echo(f"{k}: {v[0]} -> {v[1]}")
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
@click.option(
|
||||
"--dry-run/--no-dry-run",
|
||||
default=False,
|
||||
is_flag=True,
|
||||
type=bool,
|
||||
help="Perform a dry run without saving.",
|
||||
)
|
||||
@click.command()
|
||||
async def cli(dry_run: bool) -> None:
|
||||
"""Cli method fo rupdating fixtures."""
|
||||
update_fixtures(_discovery_result_update, dry_run=dry_run)
|
||||
update_fixtures(_child_device_id_update, dry_run=dry_run)
|
||||
update_fixtures(_redactor_result_update, dry_run=dry_run)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
Reference in New Issue
Block a user