Allow enabling experimental devices from environment variable (#1194)

This commit is contained in:
Steven B. 2024-10-29 09:30:30 +00:00 committed by GitHub
parent d30d116f37
commit 4aec9d302f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 75 additions and 22 deletions

View File

@ -309,9 +309,9 @@ async def cli(
if debug: if debug:
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
from kasa.experimental.enabled import Enabled from kasa.experimental import Experimental
Enabled.set(True) Experimental.set_enabled(True)
credentials = Credentials(username=username, password=password) credentials = Credentials(username=username, password=password)
if host is not None: if host is not None:

View File

@ -16,6 +16,7 @@ if TYPE_CHECKING:
from kasa import Device from kasa import Device
from kasa.deviceconfig import DeviceEncryptionType from kasa.deviceconfig import DeviceEncryptionType
from kasa.experimental import Experimental
from .common import ( from .common import (
SKIP_UPDATE_COMMANDS, SKIP_UPDATE_COMMANDS,
@ -220,11 +221,11 @@ def _legacy_type_to_class(_type):
help="Hashed credentials used to authenticate to the device.", help="Hashed credentials used to authenticate to the device.",
) )
@click.option( @click.option(
"--experimental", "--experimental/--no-experimental",
default=False, default=None,
is_flag=True, is_flag=True,
type=bool, type=bool,
envvar="KASA_EXPERIMENTAL", envvar=Experimental.ENV_VAR,
help="Enable experimental mode for devices not yet fully supported.", help="Enable experimental mode for devices not yet fully supported.",
) )
@click.version_option(package_name="python-kasa") @click.version_option(package_name="python-kasa")
@ -260,10 +261,11 @@ async def cli(
if target != DEFAULT_TARGET and host: if target != DEFAULT_TARGET and host:
error("--target is not a valid option for single host discovery") error("--target is not a valid option for single host discovery")
if experimental: if experimental is not None:
from kasa.experimental.enabled import Enabled Experimental.set_enabled(experimental)
Enabled.set(True) if Experimental.enabled():
echo("Experimental support is enabled")
logging_config: dict[str, Any] = { logging_config: dict[str, Any] = {
"level": logging.DEBUG if debug > 0 else logging.INFO "level": logging.DEBUG if debug > 0 else logging.INFO

View File

@ -214,9 +214,9 @@ def get_protocol(
"SMART.KLAP": (SmartProtocol, KlapTransportV2), "SMART.KLAP": (SmartProtocol, KlapTransportV2),
} }
if not (prot_tran_cls := supported_device_protocols.get(protocol_transport_key)): if not (prot_tran_cls := supported_device_protocols.get(protocol_transport_key)):
from .experimental.enabled import Enabled from .experimental import Experimental
if Enabled.value and protocol_transport_key == "SMART.AES.HTTPS": if Experimental.enabled() and protocol_transport_key == "SMART.AES.HTTPS":
prot_tran_cls = (SmartCameraProtocol, SslAesTransport) prot_tran_cls = (SmartCameraProtocol, SslAesTransport)
else: else:
return None return None

View File

@ -1 +1,28 @@
"""Package for experimental.""" """Package for experimental."""
from __future__ import annotations
import os
class Experimental:
"""Class for enabling experimental functionality."""
_enabled: bool | None = None
ENV_VAR = "KASA_EXPERIMENTAL"
@classmethod
def set_enabled(cls, enabled):
"""Set the enabled value."""
cls._enabled = enabled
@classmethod
def enabled(cls):
"""Get the enabled value."""
if cls._enabled is not None:
return cls._enabled
if env_var := os.getenv(cls.ENV_VAR):
return env_var.lower() in {"true", "1", "t", "on"}
return False

View File

@ -1,12 +0,0 @@
"""Package for experimental enabled."""
class Enabled:
"""Class for enabling experimental functionality."""
value = False
@classmethod
def set(cls, value):
"""Set the enabled value."""
cls.value = value

View File

@ -1232,3 +1232,39 @@ async def test_discover_config_invalid(mocker, runner):
) )
assert res.exit_code == 1 assert res.exit_code == 1
assert "--target is not a valid option for single host discovery" in res.output assert "--target is not a valid option for single host discovery" in res.output
@pytest.mark.parametrize(
("option", "env_var_value", "expectation"),
[
pytest.param("--experimental", None, True),
pytest.param("--experimental", "false", True),
pytest.param(None, None, False),
pytest.param(None, "true", True),
pytest.param(None, "false", False),
pytest.param("--no-experimental", "true", False),
],
)
async def test_experimental_flags(mocker, option, env_var_value, expectation):
"""Test the experimental flag is set correctly."""
mocker.patch("kasa.discover.Discover.try_connect_all", return_value=None)
# reset the class internal variable
from kasa.experimental import Experimental
Experimental._enabled = None
KASA_VARS = {k: None for k, v in os.environ.items() if k.startswith("KASA_")}
if env_var_value:
KASA_VARS["KASA_EXPERIMENTAL"] = env_var_value
args = [
"--host",
"127.0.0.2",
"discover",
"config",
]
if option:
args.insert(0, option)
runner = CliRunner(env=KASA_VARS)
res = await runner.invoke(cli, args)
assert ("Experimental support is enabled" in res.output) is expectation