docs: modernize docstrings across the repository (#1682)

Comprehensive docstring cleanup across the repository — fix Sphinx
cross-references, Python REPL continuation syntax, stale class names,
and modernize the IotBulb docstring to use the
`Module.Light`/`Module.LightPreset` interface.
This commit is contained in:
ZeliardM
2026-07-05 12:30:01 -04:00
committed by GitHub
parent 7f10a39655
commit bb27a43027
18 changed files with 136 additions and 120 deletions

View File

@@ -6,8 +6,8 @@
>>> devices = await Discover.discover(username="user@example.com", password="great_password") >>> devices = await Discover.discover(username="user@example.com", password="great_password")
>>> for dev in devices.values(): >>> for dev in devices.values():
>>> await dev.update() ... await dev.update()
>>> print(dev.host) ... print(dev.host)
127.0.0.1 127.0.0.1
127.0.0.2 127.0.0.2
127.0.0.3 127.0.0.3
@@ -56,20 +56,23 @@ True
>>> light.has_feature("hsv") >>> light.has_feature("hsv")
True True
>>> if light.has_feature("hsv"): >>> if light.has_feature("hsv"):
>>> print(light.hsv) ... print(light.hsv)
HSV(hue=0, saturation=100, value=50) HSV(hue=0, saturation=100, value=50)
You can test if a module is supported by using `get` to access it. You can test if a module is supported by using `get` to access it.
>>> if effect := dev.modules.get(Module.LightEffect): >>> if effect := dev.modules.get(Module.LightEffect):
>>> print(effect.effect) ... print(effect.effect)
>>> print(effect.effect_list) ... print(effect.effect_list)
>>> if effect := dev.modules.get(Module.LightEffect):
>>> await effect.set_effect("Party")
>>> await dev.update()
>>> print(effect.effect)
Off Off
['Off', 'Party', 'Relax'] ['Off', 'Party', 'Relax']
You can then interact with the module:
>>> if effect := dev.modules.get(Module.LightEffect):
... _ = await effect.set_effect("Party")
... await dev.update()
... print(effect.effect)
Party Party
Individual pieces of functionality are also exposed via features which you can access via :attr:`~kasa.Device.features` and will only be present if they are supported. Individual pieces of functionality are also exposed via features which you can access via :attr:`~kasa.Device.features` and will only be present if they are supported.
@@ -83,14 +86,14 @@ The advantage of features is that they have a simple common interface of `id`, `
They are useful if you want write code that dynamically adapts as new features are added to the API. They are useful if you want write code that dynamically adapts as new features are added to the API.
>>> if auto_update := dev.features.get("auto_update_enabled"): >>> if auto_update := dev.features.get("auto_update_enabled"):
>>> print(auto_update.value) ... print(auto_update.value)
False False
>>> if auto_update: >>> if auto_update:
>>> await auto_update.set_value(True) ... _ = await auto_update.set_value(True)
>>> await dev.update() ... await dev.update()
>>> print(auto_update.value) ... print(auto_update.value)
True True
>>> for feat in dev.features.values(): >>> for feat in dev.features.values():
>>> print(f"{feat.name}: {feat.value}") ... print(f"{feat.name}: {feat.value}")
Device ID: 0000000000000000000000000000000000000000\nState: True\nSignal Level: 2\nRSSI: -52\nSSID: #MASKED_SSID#\nReboot: <Action>\nDevice time: 2024-02-23 02:40:15+01:00\nBrightness: 50\nCloud connection: True\nHSV: HSV(hue=0, saturation=100, value=50)\nColor temperature: 2700\nAuto update enabled: True\nUpdate available: None\nCurrent firmware version: 1.1.6 Build 240130 Rel.173828\nAvailable firmware version: None\nCheck latest firmware: <Action>\nLight effect: Party\nLight preset: Light preset 1\nSmooth transition on: 2\nSmooth transition off: 2\nOverheated: False Device ID: 0000000000000000000000000000000000000000\nState: True\nSignal Level: 2\nRSSI: -52\nSSID: #MASKED_SSID#\nReboot: <Action>\nDevice time: 2024-02-23 02:40:15+01:00\nBrightness: 50\nCloud connection: True\nHSV: HSV(hue=0, saturation=100, value=50)\nColor temperature: 2700\nAuto update enabled: True\nUpdate available: None\nCurrent firmware version: 1.1.6 Build 240130 Rel.173828\nAvailable firmware version: None\nCheck latest firmware: <Action>\nLight effect: Party\nLight preset: Light preset 1\nSmooth transition on: 2\nSmooth transition off: 2\nOverheated: False
""" """

View File

@@ -6,10 +6,10 @@ Once you have a device via :ref:`Discovery <discover_target>` or
>>> from kasa import Discover >>> from kasa import Discover
>>> >>>
>>> dev = await Discover.discover_single( >>> dev = await Discover.discover_single(
>>> "127.0.0.2", ... "127.0.0.2",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password" ... password="great_password"
>>> ) ... )
>>> >>>
Most devices can be turned on and off Most devices can be turned on and off
@@ -46,7 +46,7 @@ Devices support different functionality that are exposed via
:ref:`modules <module_target>` that you can access via :attr:`~kasa.Device.modules`: :ref:`modules <module_target>` that you can access via :attr:`~kasa.Device.modules`:
>>> for module_name in dev.modules: >>> for module_name in dev.modules:
>>> print(module_name) ... print(module_name)
homekit homekit
Energy Energy
schedule schedule
@@ -81,7 +81,7 @@ They are useful if you want write code that dynamically adapts as new features a
added to the API. added to the API.
>>> for feature_name in dev.features: >>> for feature_name in dev.features:
>>> print(feature_name) ... print(feature_name)
state state
rssi rssi
on_since on_since

View File

@@ -7,10 +7,10 @@ Discovery returns a list of discovered devices:
>>> from kasa import Discover, Device >>> from kasa import Discover, Device
>>> device = await Discover.discover_single( >>> device = await Discover.discover_single(
>>> "127.0.0.3", ... "127.0.0.3",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password", ... password="great_password",
>>> ) ... )
>>> print(device.alias) # Alias is None because update() has not been called >>> print(device.alias) # Alias is None because update() has not been called
None None

View File

@@ -1,11 +1,11 @@
"""Discover TPLink Smart Home devices. """Discover TPLink Smart Home devices.
The main entry point for this library is :func:`Discover.discover()`, The main entry point for this library is :meth:`Discover.discover()`,
which returns a dictionary of the found devices. The key is the IP address which returns a dictionary of the found devices. The key is the IP address
of the device and the value contains ready-to-use, SmartDevice-derived of the device and the value contains ready-to-use, SmartDevice-derived
device object. device object.
:func:`discover_single()` can be used to initialize a single device given its :meth:`discover_single()` can be used to initialize a single device given its
IP address. If the :class:`DeviceConfig` of the device is already known, IP address. If the :class:`DeviceConfig` of the device is already known,
you can initialize the corresponding device class directly without discovery. you can initialize the corresponding device class directly without discovery.
@@ -27,9 +27,9 @@ Discovery returns a dict of {ip: discovered devices}:
You can pass username and password for devices requiring authentication You can pass username and password for devices requiring authentication
>>> devices = await Discover.discover( >>> devices = await Discover.discover(
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password", ... password="great_password",
>>> ) ... )
>>> print(len(devices)) >>> print(len(devices))
6 6
@@ -61,8 +61,8 @@ None
It is also possible to pass a coroutine to be executed for each found device: It is also possible to pass a coroutine to be executed for each found device:
>>> async def print_dev_info(dev): >>> async def print_dev_info(dev):
>>> await dev.update() ... await dev.update()
>>> print(f"Discovered {dev.alias} (model: {dev.model})") ... print(f"Discovered {dev.alias} (model: {dev.model})")
>>> >>>
>>> devices = await Discover.discover(on_discovered=print_dev_info, credentials=creds) >>> devices = await Discover.discover(on_discovered=print_dev_info, credentials=creds)
Discovered Bedroom Power Strip (model: KP303) Discovered Bedroom Power Strip (model: KP303)

View File

@@ -6,10 +6,10 @@ state, time, firmware.
>>> from kasa import Discover, Module >>> from kasa import Discover, Module
>>> >>>
>>> dev = await Discover.discover_single( >>> dev = await Discover.discover_single(
>>> "127.0.0.3", ... "127.0.0.3",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password" ... password="great_password"
>>> ) ... )
>>> await dev.update() >>> await dev.update()
>>> print(dev.alias) >>> print(dev.alias)
Living Room Bulb Living Room Bulb
@@ -18,7 +18,7 @@ Features allow for instrospection and can be interacted with as new features are
to the API: to the API:
>>> for feature_id, feature in dev.features.items(): >>> for feature_id, feature in dev.features.items():
>>> print(f"{feature.name} ({feature_id}): {feature.value}") ... print(f"{feature.name} ({feature_id}): {feature.value}")
Device ID (device_id): 0000000000000000000000000000000000000000 Device ID (device_id): 0000000000000000000000000000000000000000
State (state): True State (state): True
Signal Level (signal_level): 2 Signal Level (signal_level): 2
@@ -44,7 +44,7 @@ Overheated (overheated): False
To see whether a device supports a feature, check for the existence of it: To see whether a device supports a feature, check for the existence of it:
>>> if feature := dev.features.get("brightness"): >>> if feature := dev.features.get("brightness"):
>>> print(feature.value) ... print(feature.value)
100 100
You can update the value of a feature You can update the value of a feature

View File

@@ -6,10 +6,10 @@ hubs.
>>> from kasa import Discover, Module, LightState >>> from kasa import Discover, Module, LightState
>>> >>>
>>> dev = await Discover.discover_single( >>> dev = await Discover.discover_single(
>>> "127.0.0.6", ... "127.0.0.6",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password" ... password="great_password"
>>> ) ... )
>>> await dev.update() >>> await dev.update()
>>> print(dev.alias) >>> print(dev.alias)
Tapo Hub Tapo Hub
@@ -27,7 +27,7 @@ The hub will pair with all supported devices in pairing mode:
'device_model': 'S200B', 'name': 'I01BU0tFRF9OQU1FIw===='}] 'device_model': 'S200B', 'name': 'I01BU0tFRF9OQU1FIw===='}]
>>> for child in dev.children: >>> for child in dev.children:
>>> print(f"{child.device_id} - {child.model}") ... print(f"{child.device_id} - {child.model}")
SCRUBBED_CHILD_DEVICE_ID_1 - T310 SCRUBBED_CHILD_DEVICE_ID_1 - T310
SCRUBBED_CHILD_DEVICE_ID_2 - T315 SCRUBBED_CHILD_DEVICE_ID_2 - T315
SCRUBBED_CHILD_DEVICE_ID_3 - T110 SCRUBBED_CHILD_DEVICE_ID_3 - T110
@@ -38,7 +38,7 @@ Unpair with the child `device_id`:
>>> await childsetup.unpair("SCRUBBED_CHILD_DEVICE_ID_4") >>> await childsetup.unpair("SCRUBBED_CHILD_DEVICE_ID_4")
>>> for child in dev.children: >>> for child in dev.children:
>>> print(f"{child.device_id} - {child.model}") ... print(f"{child.device_id} - {child.model}")
SCRUBBED_CHILD_DEVICE_ID_1 - T310 SCRUBBED_CHILD_DEVICE_ID_1 - T310
SCRUBBED_CHILD_DEVICE_ID_2 - T315 SCRUBBED_CHILD_DEVICE_ID_2 - T315
SCRUBBED_CHILD_DEVICE_ID_3 - T110 SCRUBBED_CHILD_DEVICE_ID_3 - T110

View File

@@ -3,10 +3,10 @@
>>> from kasa import Discover, Module >>> from kasa import Discover, Module
>>> >>>
>>> dev = await Discover.discover_single( >>> dev = await Discover.discover_single(
>>> "127.0.0.3", ... "127.0.0.3",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password" ... password="great_password"
>>> ) ... )
>>> await dev.update() >>> await dev.update()
>>> print(dev.alias) >>> print(dev.alias)
Living Room Bulb Living Room Bulb
@@ -44,7 +44,7 @@ All known bulbs support changing the brightness:
Bulbs supporting color temperature can be queried for the supported range: Bulbs supporting color temperature can be queried for the supported range:
>>> if color_temp_feature := light.get_feature("color_temp"): >>> if color_temp_feature := light.get_feature("color_temp"):
>>> print(f"{color_temp_feature.minimum_value}, {color_temp_feature.maximum_value}") ... print(f"{color_temp_feature.minimum_value}, {color_temp_feature.maximum_value}")
2500, 6500 2500, 6500
>>> await light.set_color_temp(3000) >>> await light.set_color_temp(3000)
>>> await dev.update() >>> await dev.update()

View File

@@ -3,10 +3,10 @@
>>> from kasa import Discover, Module, LightState >>> from kasa import Discover, Module, LightState
>>> >>>
>>> dev = await Discover.discover_single( >>> dev = await Discover.discover_single(
>>> "127.0.0.3", ... "127.0.0.3",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password" ... password="great_password"
>>> ) ... )
>>> await dev.update() >>> await dev.update()
>>> print(dev.alias) >>> print(dev.alias)
Living Room Bulb Living Room Bulb
@@ -32,8 +32,8 @@ Party
If the device supports it you can set custom effects: If the device supports it you can set custom effects:
>>> if light_effect.has_custom_effects: >>> if light_effect.has_custom_effects:
>>> effect_list = { "brightness", 50 } ... effect_list = {"brightness": 50}
>>> await light_effect.set_custom_effect(effect_list) ... await light_effect.set_custom_effect(effect_list)
>>> light_effect.has_custom_effects # The device in this examples does not support \ >>> light_effect.has_custom_effects # The device in this examples does not support \
custom effects custom effects
False False

View File

@@ -3,10 +3,10 @@
>>> from kasa import Discover, Module, LightState >>> from kasa import Discover, Module, LightState
>>> >>>
>>> dev = await Discover.discover_single( >>> dev = await Discover.discover_single(
>>> "127.0.0.3", ... "127.0.0.3",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password" ... password="great_password"
>>> ) ... )
>>> await dev.update() >>> await dev.update()
>>> print(dev.alias) >>> print(dev.alias)
Living Room Bulb Living Room Bulb
@@ -48,9 +48,9 @@ LightState(light_on=True, brightness=50, hue=0,\
You can save a new preset state if the device supports it: You can save a new preset state if the device supports it:
>>> if light_preset.has_save_preset: >>> if light_preset.has_save_preset:
>>> new_preset_state = LightState(light_on=True, brightness=75, hue=0,\ ... new_preset_state = LightState(light_on=True, brightness=75, hue=0,\
saturation=100, color_temp=2700, transition=None) saturation=100, color_temp=2700, transition=None)
>>> await light_preset.save_preset("Light preset 1", new_preset_state) ... await light_preset.save_preset("Light preset 1", new_preset_state)
>>> await dev.update() >>> await dev.update()
>>> light_preset.preset # Saving updates the preset state for the preset, it does not \ >>> light_preset.preset # Saving updates the preset state for the preset, it does not \
set the preset set the preset

View File

@@ -102,12 +102,12 @@ _LOGGER = logging.getLogger(__name__)
class IotBulb(IotDevice): class IotBulb(IotDevice):
r"""Representation of a TP-Link Smart Bulb. r"""Representation of a TP-Link Smart Bulb.
To initialize, you have to await :func:`update()` at least once. To initialize, you have to await :meth:`update()` at least once.
This will allow accessing the properties using the exposed properties. This will allow accessing the properties using the exposed properties.
All changes to the device are done using awaitable methods, All changes to the device are done using awaitable methods,
which will not change the cached values, which will not change the cached values,
so you must await :func:`update()` to fetch updates values from the device. so you must await :meth:`update()` to fetch updated values from the device.
Errors reported by the device are raised as Errors reported by the device are raised as
:class:`KasaException <kasa.exceptions.KasaException>`, :class:`KasaException <kasa.exceptions.KasaException>`,
@@ -118,7 +118,7 @@ class IotBulb(IotDevice):
>>> bulb = IotBulb("127.0.0.1") >>> bulb = IotBulb("127.0.0.1")
>>> asyncio.run(bulb.update()) >>> asyncio.run(bulb.update())
>>> print(bulb.alias) >>> print(bulb.alias)
Bulb2 Bedroom Bulb
Bulbs, like any other supported devices, can be turned on and off: Bulbs, like any other supported devices, can be turned on and off:
@@ -128,72 +128,82 @@ class IotBulb(IotDevice):
>>> print(bulb.is_on) >>> print(bulb.is_on)
True True
You can use the ``is_``-prefixed properties to check for supported features: Get the light module to interact with light-specific features:
>>> bulb.is_dimmable >>> light = bulb.modules[Module.Light]
You can use the :meth:`~kasa.module.Module.has_feature` method to check for supported light features:
>>> light.has_feature("brightness")
True True
>>> bulb.is_color >>> light.has_feature("hsv")
True True
>>> bulb.is_variable_color_temp >>> light.has_feature("color_temp")
True True
All known bulbs support changing the brightness: All known bulbs support changing the brightness:
>>> bulb.brightness >>> light.brightness
30 30
>>> asyncio.run(bulb.set_brightness(50)) >>> asyncio.run(light.set_brightness(50))
>>> asyncio.run(bulb.update()) >>> asyncio.run(bulb.update())
>>> bulb.brightness >>> light.brightness
50 50
Bulbs supporting color temperature can be queried for the supported range: Bulbs supporting color temperature can be queried for the supported range:
>>> bulb.valid_temperature_range >>> if color_temp_feature := light.get_feature("color_temp"):
ColorTempRange(min=2500, max=9000) ... print(
>>> asyncio.run(bulb.set_color_temp(3000)) ... f"{color_temp_feature.minimum_value}, "
... f"{color_temp_feature.maximum_value}"
... )
2500, 9000
>>> asyncio.run(light.set_color_temp(3000))
>>> asyncio.run(bulb.update()) >>> asyncio.run(bulb.update())
>>> bulb.color_temp >>> light.color_temp
3000 3000
Color bulbs can be adjusted by passing hue, saturation and value: Color bulbs can be adjusted by passing hue, saturation and value:
>>> asyncio.run(bulb.set_hsv(180, 100, 80)) >>> asyncio.run(light.set_hsv(180, 100, 80))
>>> asyncio.run(bulb.update()) >>> asyncio.run(bulb.update())
>>> bulb.hsv >>> light.hsv
HSV(hue=180, saturation=100, value=80) HSV(hue=180, saturation=100, value=80)
If you don't want to use the default transitions, If you don't want to use the default transitions,
you can pass `transition` in milliseconds. you can pass `transition` in milliseconds.
All methods changing the state of the device support this parameter: All methods changing the light state support this parameter:
* :func:`turn_on` * :meth:`turn_on`
* :func:`turn_off` * :meth:`turn_off`
* :func:`set_hsv` * :meth:`set_hsv`
* :func:`set_color_temp` * :meth:`set_color_temp`
* :func:`set_brightness` * :meth:`set_brightness`
Light strips (e.g., KL420L5) do not support this feature, Light strips (e.g., KL420L5) do not support this feature,
but silently ignore the parameter. but silently ignore the parameter.
The following changes the brightness over a period of 10 seconds: The following changes the brightness over a period of 10 seconds:
>>> asyncio.run(bulb.set_brightness(100, transition=10_000)) >>> asyncio.run(light.set_brightness(100, transition=10_000))
Bulb configuration presets can be accessed using the :func:`presets` property: Bulb configuration presets can be accessed using the light preset module:
>>> [ preset.to_dict() for preset in bulb.presets } >>> light_preset = bulb.modules[Module.LightPreset]
[{'brightness': 50, 'hue': 0, 'saturation': 0, 'color_temp': 2700, 'index': 0}, {'brightness': 100, 'hue': 0, 'saturation': 75, 'color_temp': 0, 'index': 1}, {'brightness': 100, 'hue': 120, 'saturation': 75, 'color_temp': 0, 'index': 2}, {'brightness': 100, 'hue': 240, 'saturation': 75, 'color_temp': 0, 'index': 3}] >>> light_preset.preset_states_list[0]
IotLightPreset(light_on=None, brightness=50, hue=0, saturation=0, color_temp=2700, transition=None)
To modify an existing preset, pass :class:`~kasa.interfaces.light.LightPreset` To modify an existing preset, update one of the entries in
instance to :func:`save_preset` method: ``preset_states_list`` and pass it to
:meth:`~kasa.interfaces.lightpreset.LightPreset.save_preset`:
>>> preset = bulb.presets[0] >>> preset = light_preset.preset_states_list[0]
>>> preset.brightness >>> preset.brightness
50 50
>>> preset.brightness = 100 >>> preset.brightness = 100
>>> asyncio.run(bulb.save_preset(preset)) >>> asyncio.run(light_preset.save_preset("Light preset 1", preset))
>>> asyncio.run(bulb.update()) >>> asyncio.run(bulb.update())
>>> bulb.presets[0].brightness >>> light_preset.preset_states_list[0]
100 IotLightPreset(light_on=None, brightness=100, hue=0, saturation=0, color_temp=2700, transition=None)
""" # noqa: E501 """ # noqa: E501

View File

@@ -92,7 +92,7 @@ class IotDevice(Device):
* :class:`IotDimmer` * :class:`IotDimmer`
* :class:`IotLightStrip` * :class:`IotLightStrip`
To initialize, you have to await :func:`update()` at least once. To initialize, you have to await :meth:`update()` at least once.
This will allow accessing the properties using the exposed properties. This will allow accessing the properties using the exposed properties.
All changes to the device are done using awaitable methods, All changes to the device are done using awaitable methods,

View File

@@ -41,14 +41,14 @@ class IotDimmer(IotPlug):
r"""Representation of a TP-Link Smart Dimmer. r"""Representation of a TP-Link Smart Dimmer.
Dimmers work similarly to plugs, but provide also support for Dimmers work similarly to plugs, but provide also support for
adjusting the brightness. This class extends :class:`SmartPlug` interface. adjusting the brightness. This class extends :class:`IotPlug` interface.
To initialize, you have to await :func:`update()` at least once. To initialize, you have to await :meth:`update()` at least once.
This will allow accessing the properties using the exposed properties. This will allow accessing the properties using the exposed properties.
All changes to the device are done using awaitable methods, All changes to the device are done using awaitable methods,
which will not change the cached values, which will not change the cached values,
but you must await :func:`update()` separately. but you must await :meth:`update()` separately.
Errors reported by the device are raised as :class:`KasaException`\s, Errors reported by the device are raised as :class:`KasaException`\s,
and should be handled by the user of the library. and should be handled by the user of the library.
@@ -65,7 +65,7 @@ class IotDimmer(IotPlug):
>>> dimmer.brightness >>> dimmer.brightness
50 50
Refer to :class:`SmartPlug` for the full API. Refer to :class:`IotPlug` for the full API.
""" """
DIMMER_SERVICE = "smartlife.iot.dimmer" DIMMER_SERVICE = "smartlife.iot.dimmer"

View File

@@ -16,7 +16,7 @@ class IotLightStrip(IotBulb):
Light strips work similarly to bulbs, but use a different service for controlling, Light strips work similarly to bulbs, but use a different service for controlling,
and expose some extra information (such as length and active effect). and expose some extra information (such as length and active effect).
This class extends :class:`SmartBulb` interface. This class extends :class:`IotBulb` interface.
Examples: Examples:
>>> import asyncio >>> import asyncio
@@ -41,7 +41,7 @@ class IotLightStrip(IotBulb):
feel free to find out how to control them and create a PR! feel free to find out how to control them and create a PR!
See :class:`SmartBulb` for more examples. See :class:`IotBulb` for more examples.
""" """
LIGHT_SERVICE = "smartlife.iot.lightStrip" LIGHT_SERVICE = "smartlife.iot.lightStrip"

View File

@@ -18,12 +18,12 @@ _LOGGER = logging.getLogger(__name__)
class IotPlug(IotDevice): class IotPlug(IotDevice):
r"""Representation of a TP-Link Smart Plug. r"""Representation of a TP-Link Smart Plug.
To initialize, you have to await :func:`update()` at least once. To initialize, you have to await :meth:`update()` at least once.
This will allow accessing the properties using the exposed properties. This will allow accessing the properties using the exposed properties.
All changes to the device are done using awaitable methods, All changes to the device are done using awaitable methods,
which will not change the cached values, which will not change the cached values,
but you must await :func:`update()` separately. but you must await :meth:`update()` separately.
Errors reported by the device are raised as :class:`KasaException`\s, Errors reported by the device are raised as :class:`KasaException`\s,
and should be handled by the user of the library. and should be handled by the user of the library.

View File

@@ -53,14 +53,14 @@ class IotStrip(IotDevice):
A strip consists of the parent device and its children. A strip consists of the parent device and its children.
All methods of the parent act on all children, while the child devices All methods of the parent act on all children, while the child devices
share the common API with the :class:`SmartPlug` class. share the common API with the :class:`IotPlug` class.
To initialize, you have to await :func:`update()` at least once. To initialize, you have to await :meth:`update()` at least once.
This will allow accessing the properties using the exposed properties. This will allow accessing the properties using the exposed properties.
All changes to the device are done using awaitable methods, All changes to the device are done using awaitable methods,
which will not change the cached values, which will not change the cached values,
but you must await :func:`update()` separately. but you must await :meth:`update()` separately.
Errors reported by the device are raised as :class:`KasaException`\s, Errors reported by the device are raised as :class:`KasaException`\s,
and should be handled by the user of the library. and should be handled by the user of the library.
@@ -75,7 +75,7 @@ class IotStrip(IotDevice):
All methods act on the whole strip: All methods act on the whole strip:
>>> for plug in strip.children: >>> for plug in strip.children:
>>> print(f"{plug.alias}: {plug.is_on}") ... print(f"{plug.alias}: {plug.is_on}")
Plug 1: True Plug 1: True
Plug 2: False Plug 2: False
Plug 3: False Plug 3: False
@@ -89,7 +89,7 @@ class IotStrip(IotDevice):
>>> len(strip.children) >>> len(strip.children)
3 3
>>> for plug in strip.children: >>> for plug in strip.children:
>>> print(f"{plug.alias}: {plug.is_on}") ... print(f"{plug.alias}: {plug.is_on}")
Plug 1: False Plug 1: False
Plug 2: False Plug 2: False
Plug 3: False Plug 3: False

View File

@@ -6,10 +6,10 @@ Light, AutoOff, Firmware etc.
>>> from kasa import Discover, Module >>> from kasa import Discover, Module
>>> >>>
>>> dev = await Discover.discover_single( >>> dev = await Discover.discover_single(
>>> "127.0.0.3", ... "127.0.0.3",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password" ... password="great_password"
>>> ) ... )
>>> await dev.update() >>> await dev.update()
>>> print(dev.alias) >>> print(dev.alias)
Living Room Bulb Living Room Bulb
@@ -18,7 +18,7 @@ To see whether a device supports a group of functionality
check for the existence of the module: check for the existence of the module:
>>> if light := dev.modules.get("Light"): >>> if light := dev.modules.get("Light"):
>>> print(light.brightness) ... print(light.brightness)
100 100
.. include:: ../featureattributes.md .. include:: ../featureattributes.md
@@ -28,7 +28,7 @@ To see whether a device supports specific functionality, you can check whether t
module has that feature: module has that feature:
>>> if light.has_feature("hsv"): >>> if light.has_feature("hsv"):
>>> print(light.hsv) ... print(light.hsv)
HSV(hue=0, saturation=100, value=100) HSV(hue=0, saturation=100, value=100)
If you know or expect the module to exist you can access by index: If you know or expect the module to exist you can access by index:
@@ -44,8 +44,8 @@ Modules support typing via the Module names in Module:
>>> light_effect = dev.modules.get("LightEffect") >>> light_effect = dev.modules.get("LightEffect")
>>> light_effect_typed = dev.modules.get(Module.LightEffect) >>> light_effect_typed = dev.modules.get(Module.LightEffect)
>>> if TYPE_CHECKING: >>> if TYPE_CHECKING:
>>> reveal_type(light_effect) # Static checker will reveal: str ... reveal_type(light_effect) # Static checker will reveal: str
>>> reveal_type(light_effect_typed) # Static checker will reveal: LightEffect ... reveal_type(light_effect_typed) # Static checker will reveal: LightEffect
""" """

View File

@@ -3,10 +3,10 @@
>>> from kasa import Discover >>> from kasa import Discover
>>> >>>
>>> dev = await Discover.discover_single( >>> dev = await Discover.discover_single(
>>> "127.0.0.1", ... "127.0.0.1",
>>> username="user@example.com", ... username="user@example.com",
>>> password="great_password" ... password="great_password"
>>> ) ... )
>>> await dev.update() >>> await dev.update()
>>> print(dev.alias) >>> print(dev.alias)
Bedroom Power Strip Bedroom Power Strip
@@ -14,7 +14,7 @@ Bedroom Power Strip
All methods act on the whole strip: All methods act on the whole strip:
>>> for plug in dev.children: >>> for plug in dev.children:
>>> print(f"{plug.alias}: {plug.is_on}") ... print(f"{plug.alias}: {plug.is_on}")
Plug 1: True Plug 1: True
Plug 2: False Plug 2: False
Plug 3: False Plug 3: False
@@ -28,7 +28,7 @@ Accessing individual plugs can be done using the `children` property:
>>> len(dev.children) >>> len(dev.children)
3 3
>>> for plug in dev.children: >>> for plug in dev.children:
>>> print(f"{plug.alias}: {plug.is_on}") ... print(f"{plug.alias}: {plug.is_on}")
Plug 1: False Plug 1: False
Plug 2: False Plug 2: False
Plug 3: False Plug 3: False

View File

@@ -13,6 +13,9 @@ from .conftest import (
def test_bulb_examples(mocker): def test_bulb_examples(mocker):
"""Use KL130 (bulb with all features) to test the doctests.""" """Use KL130 (bulb with all features) to test the doctests."""
p = asyncio.run(get_device_for_fixture_protocol("KL130(US)_1.0_1.8.11.json", "IOT")) p = asyncio.run(get_device_for_fixture_protocol("KL130(US)_1.0_1.8.11.json", "IOT"))
asyncio.run(p.set_alias("Bedroom Bulb"))
asyncio.run(p.update())
mocker.patch("kasa.iot.iotbulb.IotBulb", return_value=p) mocker.patch("kasa.iot.iotbulb.IotBulb", return_value=p)
mocker.patch("kasa.iot.iotbulb.IotBulb.update") mocker.patch("kasa.iot.iotbulb.IotBulb.update")
res = xdoctest.doctest_module("kasa.iot.iotbulb", "all") res = xdoctest.doctest_module("kasa.iot.iotbulb", "all")