"""TOML config loading: namespaced sections per device class.""" import textwrap import pytest from tuya_re.config import ( GatewayFingerbot, SwitchCredentials, load_fingerbots, load_gateway, load_ir_blasters, load_switches, select_devices, ) FULL = textwrap.dedent(""" [fingerbots] default = "robot2" [fingerbots.devices.robot1] device_id = "testdevice000000000001" uuid = "uuidTESTtest0000" local_key = "abcdef0123456789" product_id = "mknd4lci" [fingerbots.devices.robot2] device_id = "testdevice000000000002" uuid = "uuidTESTtest0002" local_key = "abcdef0123456789" product_id = "mknd4lci" [switches] default = "plug" [switches.devices.plug] device_id = "testdevice000000000003" local_key = "abcdef0123456789" product_id = "o7ve1lp3gfjvsvyo" version = "3.4" ip = "192.0.2.10" [ir_blasters] default = "blaster" [ir_blasters.devices.blaster] device_id = "testdevice000000000004" uuid = "uuidTESTtest0004" local_key = "abcdef0123456789" product_id = "xgahj3gjk3ftaejt" [gateway] device_id = "testdevice000000000005" ip = "192.0.2.20" local_key = "abcdef0123456789" version = "3.4" [gateway.fingerbots] default = "robot1" [gateway.fingerbots.devices.robot1] device_id = "testdevice000000000001" node_id = "uuidTESTtest0000" """) @pytest.fixture def cfg_path(tmp_path): p = tmp_path / "config.toml" p.write_text(FULL) return p def test_load_fingerbots_default_selection(cfg_path): cfg = load_fingerbots(cfg_path) [creds] = select_devices(cfg, None) assert creds.name == "robot2" assert creds.device_id == "testdevice000000000002" def test_select_by_name_and_all(cfg_path): cfg = load_fingerbots(cfg_path) assert select_devices(cfg, "robot1")[0].uuid == "uuidTESTtest0000" assert {c.name for c in select_devices(cfg, "all")} == {"robot1", "robot2"} def test_unknown_device_raises(cfg_path): with pytest.raises(ValueError, match="unknown device"): select_devices(load_fingerbots(cfg_path), "nope") def test_load_switches(cfg_path): [sw] = select_devices(load_switches(cfg_path), None) assert sw == SwitchCredentials( device_id="testdevice000000000003", local_key="abcdef0123456789", product_id="o7ve1lp3gfjvsvyo", name="plug", version="3.4", ip="192.0.2.10", ) def test_switch_optional_fields_default_none(tmp_path): p = tmp_path / "config.toml" p.write_text( textwrap.dedent(""" [switches.devices.plug] device_id = "testdevice000000000003" local_key = "abcdef0123456789" product_id = "o7ve1lp3gfjvsvyo" """) ) [sw] = select_devices(load_switches(p), None) assert sw.version is None and sw.ip is None def test_switch_numeric_version_coerced_to_str(tmp_path): p = tmp_path / "config.toml" p.write_text( textwrap.dedent(""" [switches.devices.plug] device_id = "testdevice000000000003" local_key = "abcdef0123456789" product_id = "o7ve1lp3gfjvsvyo" version = 3.4 """) ) [sw] = select_devices(load_switches(p), None) assert sw.version == "3.4" def test_load_ir_blasters(cfg_path): [blaster] = select_devices(load_ir_blasters(cfg_path), None) assert blaster.product_id == "xgahj3gjk3ftaejt" def test_missing_section_gives_empty_config(tmp_path): p = tmp_path / "config.toml" p.write_text( '[fingerbots.devices.r]\ndevice_id = "x"\nuuid = "u"\n' 'local_key = "k"\nproduct_id = "p"\n' ) with pytest.raises(ValueError, match="no .* devices configured"): select_devices(load_ir_blasters(p), None) def test_multiple_devices_without_default_raises(tmp_path): p = tmp_path / "config.toml" p.write_text( textwrap.dedent(""" [fingerbots.devices.a] device_id = "x" uuid = "u" local_key = "k" product_id = "p" [fingerbots.devices.b] device_id = "y" uuid = "u2" local_key = "k" product_id = "p" """) ) with pytest.raises(ValueError, match="multiple devices"): select_devices(load_fingerbots(p), None) def test_load_gateway(cfg_path): gw = load_gateway(cfg_path) assert gw.ip == "192.0.2.20" assert gw.version == "3.4" [fb] = select_devices(gw.fingerbots, None) assert fb == GatewayFingerbot( device_id="testdevice000000000001", node_id="uuidTESTtest0000", name="robot1" ) def test_load_gateway_absent_returns_none(tmp_path): p = tmp_path / "config.toml" p.write_text("[fingerbots]\n") assert load_gateway(p) is None