mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
a01247d48f
Python 3.11 ships with latest Debian Bookworm. pypy is not that widely used with this library based on statistics. It could be added back when pypy supports python 3.11.
95 lines
3.7 KiB
Python
95 lines
3.7 KiB
Python
"""Typing stub file for ModuleMapping."""
|
|
|
|
from abc import ABCMeta
|
|
from collections.abc import Mapping
|
|
from typing import Generic, TypeVar, overload
|
|
|
|
from .module import Module
|
|
|
|
__all__ = [
|
|
"ModuleMapping",
|
|
"ModuleName",
|
|
]
|
|
|
|
_ModuleT = TypeVar("_ModuleT", bound=Module, covariant=True)
|
|
_ModuleBaseT = TypeVar("_ModuleBaseT", bound=Module, covariant=True)
|
|
|
|
class ModuleName(Generic[_ModuleT]):
|
|
"""Class for typed Module names. At runtime delegated to str."""
|
|
|
|
def __init__(self, value: str, /) -> None: ...
|
|
def __len__(self) -> int: ...
|
|
def __hash__(self) -> int: ...
|
|
def __eq__(self, other: object) -> bool: ...
|
|
def __getitem__(self, index: int) -> str: ...
|
|
|
|
class ModuleMapping(
|
|
Mapping[ModuleName[_ModuleBaseT] | str, _ModuleBaseT], metaclass=ABCMeta
|
|
):
|
|
"""Custom dict type to provide better value type hints for Module key types."""
|
|
|
|
@overload
|
|
def __getitem__(self, key: ModuleName[_ModuleT], /) -> _ModuleT: ...
|
|
@overload
|
|
def __getitem__(self, key: str, /) -> _ModuleBaseT: ...
|
|
@overload
|
|
def __getitem__(
|
|
self, key: ModuleName[_ModuleT] | str, /
|
|
) -> _ModuleT | _ModuleBaseT: ...
|
|
@overload # type: ignore[override]
|
|
def get(self, key: ModuleName[_ModuleT], /) -> _ModuleT | None: ...
|
|
@overload
|
|
def get(self, key: str, /) -> _ModuleBaseT | None: ...
|
|
@overload
|
|
def get(
|
|
self, key: ModuleName[_ModuleT] | str, /
|
|
) -> _ModuleT | _ModuleBaseT | None: ...
|
|
|
|
def _test_module_mapping_typing() -> None:
|
|
"""Test ModuleMapping overloads work as intended.
|
|
|
|
This is tested during the mypy run and needs to be in this file.
|
|
"""
|
|
from typing import Any, NewType, assert_type, cast
|
|
|
|
from .iot.iotmodule import IotModule
|
|
from .module import Module
|
|
from .smart.smartmodule import SmartModule
|
|
|
|
NewCommonModule = NewType("NewCommonModule", Module)
|
|
NewIotModule = NewType("NewIotModule", IotModule)
|
|
NewSmartModule = NewType("NewSmartModule", SmartModule)
|
|
NotModule = NewType("NotModule", list)
|
|
|
|
NEW_COMMON_MODULE: ModuleName[NewCommonModule] = ModuleName("NewCommonModule")
|
|
NEW_IOT_MODULE: ModuleName[NewIotModule] = ModuleName("NewIotModule")
|
|
NEW_SMART_MODULE: ModuleName[NewSmartModule] = ModuleName("NewSmartModule")
|
|
|
|
# TODO Enable --warn-unused-ignores
|
|
NOT_MODULE: ModuleName[NotModule] = ModuleName("NotModule") # type: ignore[type-var] # noqa: F841
|
|
NOT_MODULE_2 = ModuleName[NotModule]("NotModule2") # type: ignore[type-var] # noqa: F841
|
|
|
|
device_modules: ModuleMapping[Module] = cast(ModuleMapping[Module], {})
|
|
assert_type(device_modules[NEW_COMMON_MODULE], NewCommonModule)
|
|
assert_type(device_modules[NEW_IOT_MODULE], NewIotModule)
|
|
assert_type(device_modules[NEW_SMART_MODULE], NewSmartModule)
|
|
assert_type(device_modules["foobar"], Module)
|
|
assert_type(device_modules[3], Any) # type: ignore[call-overload]
|
|
|
|
assert_type(device_modules.get(NEW_COMMON_MODULE), NewCommonModule | None)
|
|
assert_type(device_modules.get(NEW_IOT_MODULE), NewIotModule | None)
|
|
assert_type(device_modules.get(NEW_SMART_MODULE), NewSmartModule | None)
|
|
assert_type(device_modules.get(NEW_COMMON_MODULE, default=[1, 2]), Any) # type: ignore[call-overload]
|
|
|
|
iot_modules: ModuleMapping[IotModule] = cast(ModuleMapping[IotModule], {})
|
|
smart_modules: ModuleMapping[SmartModule] = cast(ModuleMapping[SmartModule], {})
|
|
|
|
assert_type(smart_modules["foobar"], SmartModule)
|
|
assert_type(iot_modules["foobar"], IotModule)
|
|
|
|
# Test for covariance
|
|
device_modules_2: ModuleMapping[Module] = iot_modules # noqa: F841
|
|
device_modules_3: ModuleMapping[Module] = smart_modules # noqa: F841
|
|
NEW_MODULE: ModuleName[Module] = NEW_SMART_MODULE # noqa: F841
|
|
NEW_MODULE_2: ModuleName[Module] = NEW_IOT_MODULE # noqa: F841
|