From 2dc6faf79e3fe56172fa8d5f29a581475c831344 Mon Sep 17 00:00:00 2001 From: "Teemu R." Date: Sun, 27 Oct 2024 01:48:39 +0200 Subject: [PATCH] Drop python3.8 support (#1979) --- .github/workflows/ci.yml | 2 +- .pre-commit-config.yaml | 2 +- devtools/containers.py | 24 +- docs/conf.py | 2 +- miio/cli.py | 6 +- miio/click_common.py | 10 +- miio/cloud.py | 8 +- miio/descriptors.py | 8 +- miio/device.py | 6 +- miio/devicefactory.py | 12 +- miio/deviceinfo.py | 4 +- miio/devicestatus.py | 17 +- miio/devtools/pcapparser.py | 5 +- miio/devtools/simulators/miiosimulator.py | 14 +- miio/devtools/simulators/miotsimulator.py | 6 +- miio/discovery.py | 6 +- miio/extract_tokens.py | 2 +- .../airdog/airpurifier/airpurifier_airdog.py | 4 +- .../chuangmi/camera/chuangmi_camera.py | 6 +- .../chuangmi/plug/chuangmi_plug.py | 4 +- .../chuangmi/remote/chuangmi_ir.py | 6 +- miio/integrations/chunmi/cooker/cooker.py | 4 +- .../chunmi/cooker_multi/cooker_multi.py | 3 +- .../deerma/humidifier/airhumidifier_jsqs.py | 4 +- .../deerma/humidifier/airhumidifier_mjjsq.py | 4 +- .../dmaker/airfresh/airfresh_t2017.py | 4 +- miio/integrations/dmaker/fan/fan.py | 4 +- miio/integrations/dmaker/fan/fan_miot.py | 6 +- .../dreame/vacuum/dreamevacuum_miot.py | 8 +- miio/integrations/genericmiot/genericmiot.py | 8 +- miio/integrations/genericmiot/status.py | 5 +- miio/integrations/huayi/light/huizuo.py | 4 +- miio/integrations/ijai/vacuum/pro2vacuum.py | 5 +- .../ksmb/walkingpad/walkingpad.py | 4 +- miio/integrations/leshow/fan/fan_leshow.py | 4 +- miio/integrations/lumi/camera/aqaracamera.py | 4 +- .../lumi/curtain/curtain_youpin.py | 4 +- .../lumi/gateway/devices/subdevice.py | 8 +- miio/integrations/lumi/gateway/gateway.py | 8 +- .../lumi/gateway/gatewaydevice.py | 4 +- miio/integrations/lumi/gateway/light.py | 6 +- miio/integrations/mijia/vacuum/g1vacuum.py | 3 +- .../mmgg/petwaterdispenser/device.py | 34 +- .../mmgg/petwaterdispenser/status.py | 4 +- .../nwt/dehumidifier/airdehumidifier.py | 4 +- miio/integrations/philips/light/ceil.py | 4 +- .../philips/light/philips_bulb.py | 4 +- .../philips/light/philips_eyecare.py | 4 +- .../philips/light/philips_moonlight.py | 12 +- .../philips/light/philips_rwread.py | 4 +- miio/integrations/pwzn/relay/pwzn_relay.py | 6 +- .../roborock/vacuum/updatehelper.py | 4 +- miio/integrations/roborock/vacuum/vacuum.py | 18 +- .../roborock/vacuum/vacuum_cli.py | 2 +- .../roborock/vacuum/vacuum_tui.py | 3 +- .../roborock/vacuum/vacuumcontainers.py | 26 +- .../roidmi/vacuum/roidmivacuum_miot.py | 3 +- .../shuii/humidifier/airhumidifier_jsq.py | 4 +- .../tinymu/toiletlid/toiletlid.py | 6 +- miio/integrations/viomi/vacuum/viomivacuum.py | 14 +- .../viomi/viomidishwasher/viomidishwasher.py | 8 +- .../aircondition/airconditioner_miot.py | 4 +- .../dual_switch/yeelight_dual_switch.py | 4 +- .../yeelight/light/spec_helper.py | 5 +- miio/integrations/yeelight/light/yeelight.py | 16 +- .../yunmi/waterpurifier/waterpurifier.py | 4 +- .../waterpurifier/waterpurifier_yunmi.py | 6 +- .../zhimi/airpurifier/airfilter_util.py | 4 +- .../zhimi/airpurifier/airfresh.py | 4 +- .../zhimi/airpurifier/airpurifier.py | 4 +- .../zhimi/airpurifier/airpurifier_miot.py | 4 +- miio/integrations/zhimi/fan/fan.py | 6 +- miio/integrations/zhimi/fan/zhimi_miot.py | 4 +- miio/integrations/zhimi/heater/heater.py | 6 +- miio/integrations/zhimi/heater/heater_miot.py | 4 +- .../zhimi/humidifier/airhumidifier.py | 4 +- .../zhimi/humidifier/airhumidifier_miot.py | 8 +- .../zimi/powerstrip/powerstrip.py | 4 +- miio/miioprotocol.py | 8 +- miio/miot_cloud.py | 10 +- miio/miot_device.py | 6 +- miio/miot_models.py | 34 +- miio/protocol.py | 8 +- miio/push_server/server.py | 6 +- miio/utils.py | 7 +- poetry.lock | 430 ++++++++---------- pyproject.toml | 2 +- tox.ini | 50 -- 88 files changed, 484 insertions(+), 590 deletions(-) delete mode 100644 tox.ini diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4953f233..ad7614418 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3.8"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.9"] os: [ubuntu-latest, macos-latest, windows-latest] # Exclude example, in case needed again in the future: # exclude: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 995a61d8c..aa04a88dd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -58,4 +58,4 @@ repos: rev: v3.15.0 hooks: - id: pyupgrade - args: ['--py38-plus'] + args: ['--py39-plus'] diff --git a/devtools/containers.py b/devtools/containers.py index 7a85517a4..8e8ae206c 100644 --- a/devtools/containers.py +++ b/devtools/containers.py @@ -1,7 +1,7 @@ import logging from dataclasses import dataclass, field from operator import attrgetter -from typing import Any, Dict, List, Optional +from typing import Any, Optional from dataclasses_json import DataClassJsonMixin, config @@ -45,7 +45,7 @@ def filename(self) -> str: @dataclass class ModelMapping(DataClassJsonMixin): - instances: List[InstanceInfo] + instances: list[InstanceInfo] def info_for_model(self, model: str, *, status_filter="released") -> InstanceInfo: matches = [inst for inst in self.instances if inst.model == model] @@ -76,12 +76,12 @@ class Property(DataClassJsonMixin): type: str description: str format: str - access: List[str] + access: list[str] - value_list: Optional[List[Dict[str, Any]]] = field( + value_list: Optional[list[dict[str, Any]]] = field( default_factory=list, metadata=config(field_name="value-list") ) # type: ignore - value_range: Optional[List[int]] = field( + value_range: Optional[list[int]] = field( default=None, metadata=config(field_name="value-range") ) @@ -156,8 +156,8 @@ class Action(DataClassJsonMixin): iid: int type: str description: str - out: List[Any] = field(default_factory=list) - in_: List[Any] = field(default_factory=list, metadata=config(field_name="in")) + out: list[Any] = field(default_factory=list) + in_: list[Any] = field(default_factory=list, metadata=config(field_name="in")) def __repr__(self): return f"aiid {self.iid} {self.description}: in: {self.in_} -> out: {self.out}" @@ -178,7 +178,7 @@ class Event(DataClassJsonMixin): iid: int type: str description: str - arguments: List[int] + arguments: list[int] def __repr__(self): return f"eiid {self.iid} ({self.description}): (args: {self.arguments})" @@ -189,9 +189,9 @@ class Service(DataClassJsonMixin): iid: int type: str description: str - properties: List[Property] = field(default_factory=list) - actions: List[Action] = field(default_factory=list) - events: List[Event] = field(default_factory=list) + properties: list[Property] = field(default_factory=list) + actions: list[Action] = field(default_factory=list) + events: list[Event] = field(default_factory=list) def __repr__(self): return f"siid {self.iid}: ({self.description}): {len(self.properties)} props, {len(self.actions)} actions" @@ -220,7 +220,7 @@ def as_code(self): class Device(DataClassJsonMixin): type: str description: str - services: List[Service] = field(default_factory=list) + services: list[Service] = field(default_factory=list) def as_code(self): s = "" diff --git a/docs/conf.py b/docs/conf.py index d464e7f4c..c4f7d6a02 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -183,7 +183,7 @@ ) ] -intersphinx_mapping = {"python": ("https://docs.python.org/3.8", None)} +intersphinx_mapping = {"python": ("https://docs.python.org/3", None)} apidoc_module_dir = "../miio" apidoc_output_dir = "api" diff --git a/miio/cli.py b/miio/cli.py index 696574e03..e13617583 100644 --- a/miio/cli.py +++ b/miio/cli.py @@ -1,5 +1,5 @@ import logging -from typing import Any, Dict +from typing import Any import click @@ -30,7 +30,7 @@ @click.version_option(package_name="python-miio") @click.pass_context def cli(ctx, debug: int, output: str): - logging_config: Dict[str, Any] = { + logging_config: dict[str, Any] = { "level": logging.DEBUG if debug > 0 else logging.INFO } try: @@ -56,7 +56,7 @@ def cli(ctx, debug: int, output: str): for device_class in DeviceGroupMeta._device_classes: - cli.add_command(device_class.get_device_group()) + cli.add_command(device_class.get_device_group()) # type: ignore[attr-defined] @click.command() diff --git a/miio/click_common.py b/miio/click_common.py index f5f3730d1..30c6f9dda 100644 --- a/miio/click_common.py +++ b/miio/click_common.py @@ -9,7 +9,7 @@ import logging import re from functools import partial, wraps -from typing import Any, Callable, ClassVar, Dict, List, Optional, Set, Type, Union +from typing import Any, Callable, ClassVar, Optional, Union import click @@ -111,9 +111,9 @@ def __init__(self, debug: int = 0, output: Optional[Callable] = None): class DeviceGroupMeta(type): - _device_classes: Set[Type] = set() - _supported_models: ClassVar[List[str]] - _mappings: ClassVar[Dict[str, Any]] + _device_classes: set[type] = set() + _supported_models: ClassVar[list[str]] + _mappings: ClassVar[dict[str, Any]] def __new__(mcs, name, bases, namespace): commands = {} @@ -150,7 +150,7 @@ def get_device_group(dcls): return cls @property - def supported_models(cls) -> List[str]: + def supported_models(cls) -> list[str]: """Return list of supported models.""" return list(cls._mappings.keys()) or cls._supported_models diff --git a/miio/cloud.py b/miio/cloud.py index a02015adb..c45066714 100644 --- a/miio/cloud.py +++ b/miio/cloud.py @@ -1,6 +1,6 @@ import json import logging -from typing import TYPE_CHECKING, Dict, Optional +from typing import TYPE_CHECKING, Optional import click @@ -127,14 +127,14 @@ def _parse_device_list(self, data, locale): return devs @classmethod - def available_locales(cls) -> Dict[str, str]: + def available_locales(cls) -> dict[str, str]: """Return available locales. The value is the human-readable name of the locale. """ return AVAILABLE_LOCALES - def get_devices(self, locale: Optional[str] = None) -> Dict[str, CloudDeviceInfo]: + def get_devices(self, locale: Optional[str] = None) -> dict[str, CloudDeviceInfo]: """Return a list of available devices keyed with a device id. If no locale is given, all known locales are browsed. If a device id is already @@ -147,7 +147,7 @@ def get_devices(self, locale: Optional[str] = None) -> Dict[str, CloudDeviceInfo self._micloud.get_devices(country=locale), locale=locale ) - all_devices: Dict[str, CloudDeviceInfo] = {} + all_devices: dict[str, CloudDeviceInfo] = {} for loc in AVAILABLE_LOCALES: if loc == "all": continue diff --git a/miio/descriptors.py b/miio/descriptors.py index 76b0e0f20..e7934103c 100644 --- a/miio/descriptors.py +++ b/miio/descriptors.py @@ -10,7 +10,7 @@ """ from enum import Enum, Flag, auto -from typing import Any, Callable, Dict, List, Optional, Type +from typing import Any, Callable, Optional import attr @@ -55,7 +55,7 @@ class Descriptor: #: Name of the attribute in the status container that contains the value, if applicable. status_attribute: Optional[str] = None #: Additional data related to this descriptor. - extras: Dict = attr.ib(factory=dict, repr=False) + extras: dict = attr.ib(factory=dict, repr=False) #: Access flags (read, write, execute) for the described item. access: AccessFlags = attr.ib(default=AccessFlags(0)) @@ -84,7 +84,7 @@ class ActionDescriptor(Descriptor): method: Optional[Callable] = attr.ib(default=None, repr=False) #: Name of the method in the device class that can be used to execute the action. method_name: Optional[str] = attr.ib(default=None, repr=False) - inputs: Optional[List[Any]] = attr.ib(default=None, repr=True) + inputs: Optional[list[Any]] = attr.ib(default=None, repr=True) access: AccessFlags = attr.ib(default=AccessFlags.Execute) @@ -153,7 +153,7 @@ class EnumDescriptor(PropertyDescriptor): #: Name of the attribute in the device class that returns the choices. choices_attribute: Optional[str] = attr.ib(default=None, repr=False) #: Enum class containing the available choices. - choices: Optional[Type[Enum]] = attr.ib(default=None, repr=False) + choices: Optional[type[Enum]] = attr.ib(default=None, repr=False) @property def __cli_output__(self) -> str: diff --git a/miio/device.py b/miio/device.py index ab3448048..b8e699509 100644 --- a/miio/device.py +++ b/miio/device.py @@ -36,8 +36,8 @@ class Device(metaclass=DeviceGroupMeta): retry_count = 3 timeout = 5 - _mappings: Dict[str, Any] = {} - _supported_models: List[str] = [] + _mappings: dict[str, Any] = {} + _supported_models: list[str] = [] def __init_subclass__(cls, **kwargs): """Overridden to register all integrations to the factory.""" @@ -182,7 +182,7 @@ def raw_id(self) -> int: return self._protocol.raw_id @property - def supported_models(self) -> List[str]: + def supported_models(self) -> list[str]: """Return a list of supported models.""" return list(self._mappings.keys()) or self._supported_models diff --git a/miio/devicefactory.py b/miio/devicefactory.py index ff8116fba..63422f055 100644 --- a/miio/devicefactory.py +++ b/miio/devicefactory.py @@ -1,5 +1,5 @@ import logging -from typing import Dict, List, Optional, Type +from typing import Optional import click @@ -22,11 +22,11 @@ class DeviceFactory: dev = DeviceFactory.create("127.0.0.1", 32*"0") """ - _integration_classes: List[Type[Device]] = [] - _supported_models: Dict[str, Type[Device]] = {} + _integration_classes: list[type[Device]] = [] + _supported_models: dict[str, type[Device]] = {} @classmethod - def register(cls, integration_cls: Type[Device]): + def register(cls, integration_cls: type[Device]): """Register class for to the registry.""" cls._integration_classes.append(integration_cls) _LOGGER.debug("Registering %s", integration_cls.__name__) @@ -44,13 +44,13 @@ def register(cls, integration_cls: Type[Device]): cls._supported_models[model] = integration_cls @classmethod - def supported_models(cls) -> Dict[str, Type[Device]]: + def supported_models(cls) -> dict[str, type[Device]]: """Return a dictionary of models and their corresponding implementation classes.""" return cls._supported_models @classmethod - def integrations(cls) -> List[Type[Device]]: + def integrations(cls) -> list[type[Device]]: """Return the list of integration classes.""" return cls._integration_classes diff --git a/miio/deviceinfo.py b/miio/deviceinfo.py index 4f2e44901..19ff3fa9d 100644 --- a/miio/deviceinfo.py +++ b/miio/deviceinfo.py @@ -1,4 +1,4 @@ -from typing import Dict, Optional +from typing import Optional class DeviceInfo: @@ -40,7 +40,7 @@ def __repr__(self): ) @property - def network_interface(self) -> Dict: + def network_interface(self) -> dict: """Information about network configuration. If unavailable, returns an empty dictionary. diff --git a/miio/devicestatus.py b/miio/devicestatus.py index bbc7fb525..64811a6d4 100644 --- a/miio/devicestatus.py +++ b/miio/devicestatus.py @@ -1,18 +1,9 @@ import inspect import logging import warnings +from collections.abc import Iterable from enum import Enum -from typing import ( - Callable, - Dict, - Iterable, - Optional, - Type, - Union, - get_args, - get_origin, - get_type_hints, -) +from typing import Callable, Optional, Union, get_args, get_origin, get_type_hints import attr @@ -37,7 +28,7 @@ def __new__(metacls, name, bases, namespace, **kwargs): cls._descriptors: DescriptorCollection[PropertyDescriptor] = {} cls._parent: Optional["DeviceStatus"] = None - cls._embedded: Dict[str, "DeviceStatus"] = {} + cls._embedded: dict[str, "DeviceStatus"] = {} for n in namespace: prop = getattr(namespace[n], "fget", None) @@ -222,7 +213,7 @@ def setting( max_value: Optional[int] = None, step: Optional[int] = None, range_attribute: Optional[str] = None, - choices: Optional[Type[Enum]] = None, + choices: Optional[type[Enum]] = None, choices_attribute: Optional[str] = None, **kwargs, ): diff --git a/miio/devtools/pcapparser.py b/miio/devtools/pcapparser.py index 22d808be0..010986133 100644 --- a/miio/devtools/pcapparser.py +++ b/miio/devtools/pcapparser.py @@ -3,7 +3,6 @@ from collections import Counter, defaultdict from ipaddress import ip_address from pprint import pformat as pf -from typing import List import click @@ -16,7 +15,7 @@ from miio import Message -def read_payloads_from_file(file, tokens: List[str]): +def read_payloads_from_file(file, tokens: list[str]): """Read the given pcap file and yield src, dst, and result.""" try: import dpkt @@ -86,7 +85,7 @@ def read_payloads_from_file(file, tokens: List[str]): @click.command() @click.argument("file", type=click.File("rb")) @click.argument("token", nargs=-1) -def parse_pcap(file, token: List[str]): +def parse_pcap(file, token: list[str]): """Read PCAP file and output decrypted miio communication.""" for src_addr, dst_addr, payload in read_payloads_from_file(file, token): echo(f"{src_addr:<15} -> {dst_addr:<15} {pf(payload)}") diff --git a/miio/devtools/simulators/miiosimulator.py b/miio/devtools/simulators/miiosimulator.py index 1b090a9ea..186c090b2 100644 --- a/miio/devtools/simulators/miiosimulator.py +++ b/miio/devtools/simulators/miiosimulator.py @@ -3,7 +3,7 @@ import asyncio import json import logging -from typing import List, Optional, Union +from typing import Optional, Union import click @@ -43,7 +43,7 @@ class MiioProperty(BaseModel): name: str type: Format value: Optional[Union[str, bool, int]] - models: List[str] = Field(default=[]) + models: list[str] = Field(default=[]) setter: Optional[str] = None description: Optional[str] = None min: Optional[int] = None @@ -61,7 +61,7 @@ class MiioMethod(BaseModel): """Simulated method.""" name: str - result: Optional[List] = None + result: Optional[list] = None result_json: Optional[str] = None @@ -76,11 +76,11 @@ class SimulatedMiio(BaseModel): """Simulated device model for miio devices.""" name: Optional[str] = Field(default="Unnamed integration") - models: List[MiioModel] + models: list[MiioModel] type: str - properties: List[MiioProperty] = Field(default=[]) - actions: List[MiioAction] = Field(default=[]) - methods: List[MiioMethod] = Field(default=[]) + properties: list[MiioProperty] = Field(default=[]) + actions: list[MiioAction] = Field(default=[]) + methods: list[MiioMethod] = Field(default=[]) _model: Optional[str] = PrivateAttr(default=None) class Config: diff --git a/miio/devtools/simulators/miotsimulator.py b/miio/devtools/simulators/miotsimulator.py index dc79691a0..fdac969e8 100644 --- a/miio/devtools/simulators/miotsimulator.py +++ b/miio/devtools/simulators/miotsimulator.py @@ -3,7 +3,7 @@ import logging import random from collections import defaultdict -from typing import List, Union +from typing import Union import click @@ -92,13 +92,13 @@ class Config: class SimulatedMiotService(MiotService): """Overridden to allow simulated properties.""" - properties: List[SimulatedMiotProperty] = Field(default=[], repr=False) + properties: list[SimulatedMiotProperty] = Field(default=[], repr=False) class SimulatedDeviceModel(DeviceModel): """Overridden to allow simulated properties.""" - services: List[SimulatedMiotService] + services: list[SimulatedMiotService] class MiotSimulator: diff --git a/miio/discovery.py b/miio/discovery.py index 3f9ad3eee..b9454a51e 100644 --- a/miio/discovery.py +++ b/miio/discovery.py @@ -1,7 +1,7 @@ import logging import time from ipaddress import ip_address -from typing import Dict, Optional +from typing import Optional import zeroconf @@ -14,7 +14,7 @@ class Listener(zeroconf.ServiceListener): """mDNS listener creating Device objects for detected devices.""" def __init__(self): - self.found_devices: Dict[str, Device] = {} + self.found_devices: dict[str, Device] = {} def create_device(self, info, addr) -> Optional[Device]: """Get a device instance for a mdns response.""" @@ -63,7 +63,7 @@ class Discovery: """ @staticmethod - def discover_mdns(*, timeout=5) -> Dict[str, Device]: + def discover_mdns(*, timeout=5) -> dict[str, Device]: """Discover devices with mdns.""" _LOGGER.info("Discovering devices with mDNS for %s seconds...", timeout) diff --git a/miio/extract_tokens.py b/miio/extract_tokens.py index 92c23e2d4..cf23cfb4d 100644 --- a/miio/extract_tokens.py +++ b/miio/extract_tokens.py @@ -2,8 +2,8 @@ import logging import sqlite3 import tempfile +from collections.abc import Iterator from pprint import pformat as pf -from typing import Iterator import attr import click diff --git a/miio/integrations/airdog/airpurifier/airpurifier_airdog.py b/miio/integrations/airdog/airpurifier/airpurifier_airdog.py index 10c571482..6d8ca06ba 100644 --- a/miio/integrations/airdog/airpurifier/airpurifier_airdog.py +++ b/miio/integrations/airdog/airpurifier/airpurifier_airdog.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -38,7 +38,7 @@ class OperationModeMapping(enum.Enum): class AirDogStatus(DeviceStatus): """Container for status reports from the air dog x3.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Air Dog X3 (airdog.airpurifier.x3): {'power: 'on', 'mode': 'sleep', 'speed': 1, 'lock': 'unlock', diff --git a/miio/integrations/chuangmi/camera/chuangmi_camera.py b/miio/integrations/chuangmi/camera/chuangmi_camera.py index b1d6eb28d..b53867209 100644 --- a/miio/integrations/chuangmi/camera/chuangmi_camera.py +++ b/miio/integrations/chuangmi/camera/chuangmi_camera.py @@ -4,7 +4,7 @@ import ipaddress import logging import socket -from typing import Any, Dict +from typing import Any from urllib.parse import urlparse import click @@ -79,7 +79,7 @@ class NASVideoRetentionTime(enum.IntEnum): class CameraStatus(DeviceStatus): """Container for status reports from the Xiaomi Chuangmi Camera.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """ Request: ["power", "motion_record", "light", "full_color", "flip", "improve_program", "wdr", @@ -382,7 +382,7 @@ def set_nas_config( ): """Set NAS configuration.""" - params: Dict[str, Any] = { + params: dict[str, Any] = { "state": state, "sync_interval": sync_interval, "video_retention_time": video_retention_time, diff --git a/miio/integrations/chuangmi/plug/chuangmi_plug.py b/miio/integrations/chuangmi/plug/chuangmi_plug.py index fc79e8904..f60e616aa 100644 --- a/miio/integrations/chuangmi/plug/chuangmi_plug.py +++ b/miio/integrations/chuangmi/plug/chuangmi_plug.py @@ -1,6 +1,6 @@ import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -34,7 +34,7 @@ class ChuangmiPlugStatus(DeviceStatus): """Container for status reports from the plug.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Chuangmi Plug V1 (chuangmi.plug.v1) { 'power': True, 'usb_on': True, 'temperature': 32 } diff --git a/miio/integrations/chuangmi/remote/chuangmi_ir.py b/miio/integrations/chuangmi/remote/chuangmi_ir.py index 9b64c4c09..773f96ae0 100644 --- a/miio/integrations/chuangmi/remote/chuangmi_ir.py +++ b/miio/integrations/chuangmi/remote/chuangmi_ir.py @@ -1,6 +1,6 @@ import base64 import re -from typing import Callable, Set, Tuple +from typing import Callable import click from construct import ( @@ -98,7 +98,7 @@ def play_pronto(self, pronto: str, repeats: int = 1, length: int = -1): return self.play_raw(command, frequency, length) @classmethod - def pronto_to_raw(cls, pronto: str, repeats: int = 1) -> Tuple[str, int]: + def pronto_to_raw(cls, pronto: str, repeats: int = 1) -> tuple[str, int]: """Play a Pronto Hex encoded IR command. Supports only raw Pronto format, starting with 0000. @@ -116,7 +116,7 @@ def pronto_to_raw(cls, pronto: str, repeats: int = 1) -> Tuple[str, int]: if len(pronto_data.intro) == 0: repeats += 1 - times: Set[int] = set() + times: set[int] = set() for pair in pronto_data.intro + pronto_data.repeat * (1 if repeats else 0): times.add(pair.pulse) times.add(pair.gap) diff --git a/miio/integrations/chunmi/cooker/cooker.py b/miio/integrations/chunmi/cooker/cooker.py index fecc09742..3470b5916 100644 --- a/miio/integrations/chunmi/cooker/cooker.py +++ b/miio/integrations/chunmi/cooker/cooker.py @@ -3,7 +3,7 @@ import string from collections import defaultdict from datetime import time -from typing import List, Optional +from typing import Optional import click @@ -126,7 +126,7 @@ def __init__(self, data: str): self.data = [] @property - def temperatures(self) -> List[int]: + def temperatures(self) -> list[int]: return self.data @property diff --git a/miio/integrations/chunmi/cooker_multi/cooker_multi.py b/miio/integrations/chunmi/cooker_multi/cooker_multi.py index 29f88efea..b67349f80 100644 --- a/miio/integrations/chunmi/cooker_multi/cooker_multi.py +++ b/miio/integrations/chunmi/cooker_multi/cooker_multi.py @@ -2,7 +2,6 @@ import logging import math from collections import defaultdict -from typing import List import click @@ -108,7 +107,7 @@ def __init__(self, data: str): self.data = [] @property - def temperatures(self) -> List[int]: + def temperatures(self) -> list[int]: return self.data @property diff --git a/miio/integrations/deerma/humidifier/airhumidifier_jsqs.py b/miio/integrations/deerma/humidifier/airhumidifier_jsqs.py index 5fa30ed71..84d4b3837 100644 --- a/miio/integrations/deerma/humidifier/airhumidifier_jsqs.py +++ b/miio/integrations/deerma/humidifier/airhumidifier_jsqs.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -63,7 +63,7 @@ class AirHumidifierJsqsStatus(DeviceStatus): ] """ - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: self.data = data # Air Humidifier diff --git a/miio/integrations/deerma/humidifier/airhumidifier_mjjsq.py b/miio/integrations/deerma/humidifier/airhumidifier_mjjsq.py index 38a5fa9fa..5a85bc3d2 100644 --- a/miio/integrations/deerma/humidifier/airhumidifier_mjjsq.py +++ b/miio/integrations/deerma/humidifier/airhumidifier_mjjsq.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -44,7 +44,7 @@ class OperationMode(enum.Enum): class AirHumidifierStatus(DeviceStatus): """Container for status reports from the air humidifier mjjsq.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Air Humidifier (deerma.humidifier.mjjsq): {'Humidifier_Gear': 4, 'Humidity_Value': 44, 'HumiSet_Value': 54, diff --git a/miio/integrations/dmaker/airfresh/airfresh_t2017.py b/miio/integrations/dmaker/airfresh/airfresh_t2017.py index 933f30121..00c873cbf 100644 --- a/miio/integrations/dmaker/airfresh/airfresh_t2017.py +++ b/miio/integrations/dmaker/airfresh/airfresh_t2017.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -68,7 +68,7 @@ class DisplayOrientation(enum.Enum): class AirFreshStatus(DeviceStatus): """Container for status reports from the air fresh t2017.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """ Response of a Air Fresh A1 (dmaker.airfresh.a1): { diff --git a/miio/integrations/dmaker/fan/fan.py b/miio/integrations/dmaker/fan/fan.py index a8e408c67..443796ec9 100644 --- a/miio/integrations/dmaker/fan/fan.py +++ b/miio/integrations/dmaker/fan/fan.py @@ -1,5 +1,5 @@ import enum -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -39,7 +39,7 @@ class OperationMode(enum.Enum): class FanStatusP5(DeviceStatus): """Container for status reports from the Xiaomi Mi Smart Pedestal Fan DMaker P5.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Fan (dmaker.fan.p5): {'power': False, 'mode': 'normal', 'speed': 35, 'roll_enable': False, diff --git a/miio/integrations/dmaker/fan/fan_miot.py b/miio/integrations/dmaker/fan/fan_miot.py index f3e0e5578..33a072ffa 100644 --- a/miio/integrations/dmaker/fan/fan_miot.py +++ b/miio/integrations/dmaker/fan/fan_miot.py @@ -1,5 +1,5 @@ import enum -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -163,7 +163,7 @@ class OperationModeMiotP45(enum.Enum): class FanStatusMiot(DeviceStatus): """Container for status reports for Xiaomi Mi Smart Pedestal Fan DMaker P9/P10.""" - def __init__(self, data: Dict[str, Any], model: str) -> None: + def __init__(self, data: dict[str, Any], model: str) -> None: """ Response of a FanMiot (dmaker.fan.p10): @@ -244,7 +244,7 @@ def child_lock(self) -> bool: class FanStatus1C(DeviceStatus): """Container for status reports for Xiaomi Mi Smart Pedestal Fan DMaker 1C.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Fan1C (dmaker.fan.1c): { diff --git a/miio/integrations/dreame/vacuum/dreamevacuum_miot.py b/miio/integrations/dreame/vacuum/dreamevacuum_miot.py index ef1337c20..de51a55cf 100644 --- a/miio/integrations/dreame/vacuum/dreamevacuum_miot.py +++ b/miio/integrations/dreame/vacuum/dreamevacuum_miot.py @@ -3,7 +3,7 @@ import logging import threading from enum import Enum -from typing import Dict, Optional +from typing import Optional import click @@ -164,7 +164,7 @@ "play_sound": {"siid": 7, "aiid": 2}, } -MIOT_MAPPING: Dict[str, MiotMapping] = { +MIOT_MAPPING: dict[str, MiotMapping] = { DREAME_1C: _DREAME_1C_MAPPING, DREAME_F9: _DREAME_F9_MAPPING, DREAME_D9: _DREAME_F9_MAPPING, @@ -589,7 +589,7 @@ def set_fan_speed(self, speed: int): return self.set_property("cleaning_mode", fanspeed.value) @command() - def fan_speed_presets(self) -> Dict[str, int]: + def fan_speed_presets(self) -> dict[str, int]: """Return available fan speed presets.""" fanspeeds_enum = _get_cleaning_mode_enum_class(self.model) if not fanspeeds_enum: @@ -634,7 +634,7 @@ def set_waterflow(self, value: int): return self.set_property("water_flow", waterflow.value) @command() - def waterflow_presets(self) -> Dict[str, int]: + def waterflow_presets(self) -> dict[str, int]: """Return dictionary containing supported water flow.""" mapping = self._get_mapping() if "water_flow" not in mapping: diff --git a/miio/integrations/genericmiot/genericmiot.py b/miio/integrations/genericmiot/genericmiot.py index 90ddc887f..12e076079 100644 --- a/miio/integrations/genericmiot/genericmiot.py +++ b/miio/integrations/genericmiot/genericmiot.py @@ -1,6 +1,6 @@ import logging from functools import partial -from typing import Dict, List, Optional +from typing import Optional from miio import MiotDevice from miio.click_common import command @@ -43,9 +43,9 @@ def __init__( self._model = model self._miot_model: Optional[DeviceModel] = None - self._actions: Dict[str, ActionDescriptor] = {} - self._properties: Dict[str, PropertyDescriptor] = {} - self._status_query: List[Dict] = [] + self._actions: dict[str, ActionDescriptor] = {} + self._properties: dict[str, PropertyDescriptor] = {} + self._status_query: list[dict] = [] def initialize_model(self): """Initialize the miot model and create descriptions.""" diff --git a/miio/integrations/genericmiot/status.py b/miio/integrations/genericmiot/status.py index 4931ced25..4dbcf1682 100644 --- a/miio/integrations/genericmiot/status.py +++ b/miio/integrations/genericmiot/status.py @@ -1,5 +1,6 @@ import logging -from typing import TYPE_CHECKING, Dict, Iterable +from collections.abc import Iterable +from typing import TYPE_CHECKING from miio import DeviceStatus from miio.miot_models import DeviceModel, MiotAccess, MiotProperty @@ -97,7 +98,7 @@ def device(self) -> "GenericMiot": """Return the device which returned this status.""" return self._dev - def property_dict(self) -> Dict[str, MiotProperty]: + def property_dict(self) -> dict[str, MiotProperty]: """Return name-keyed dictionary of properties.""" res = {} diff --git a/miio/integrations/huayi/light/huizuo.py b/miio/integrations/huayi/light/huizuo.py index 24c80d79b..60811e67c 100644 --- a/miio/integrations/huayi/light/huizuo.py +++ b/miio/integrations/huayi/light/huizuo.py @@ -5,7 +5,7 @@ """ import logging -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -113,7 +113,7 @@ class HuizuoStatus(DeviceStatus): - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: self.data = data @property diff --git a/miio/integrations/ijai/vacuum/pro2vacuum.py b/miio/integrations/ijai/vacuum/pro2vacuum.py index d0c303dab..af5335c52 100644 --- a/miio/integrations/ijai/vacuum/pro2vacuum.py +++ b/miio/integrations/ijai/vacuum/pro2vacuum.py @@ -1,7 +1,6 @@ import logging from datetime import timedelta from enum import Enum -from typing import Dict import click @@ -52,7 +51,7 @@ } } -ERROR_CODES: Dict[int, str] = {2105: "Fully charged"} +ERROR_CODES: dict[int, str] = {2105: "Fully charged"} def _enum_as_dict(cls): @@ -307,7 +306,7 @@ def set_fan_speed(self, fan_speed: FanSpeedMode): return self.set_property("fan_speed", fan_speed) @command() - def fan_speed_presets(self) -> Dict[str, int]: + def fan_speed_presets(self) -> dict[str, int]: """Return available fan speed presets.""" return _enum_as_dict(FanSpeedMode) diff --git a/miio/integrations/ksmb/walkingpad/walkingpad.py b/miio/integrations/ksmb/walkingpad/walkingpad.py index bc009cc95..290791c69 100644 --- a/miio/integrations/ksmb/walkingpad/walkingpad.py +++ b/miio/integrations/ksmb/walkingpad/walkingpad.py @@ -1,7 +1,7 @@ import enum import logging from datetime import timedelta -from typing import Any, Dict +from typing import Any import click @@ -39,7 +39,7 @@ class WalkingpadStatus(DeviceStatus): 'time': 121} """ - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: self.data = data @property diff --git a/miio/integrations/leshow/fan/fan_leshow.py b/miio/integrations/leshow/fan/fan_leshow.py index 51f1c3b9f..bcbece3fa 100644 --- a/miio/integrations/leshow/fan/fan_leshow.py +++ b/miio/integrations/leshow/fan/fan_leshow.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict +from typing import Any import click @@ -36,7 +36,7 @@ class OperationMode(enum.Enum): class FanLeshowStatus(DeviceStatus): """Container for status reports from the Xiaomi Rosou SS4 Ventilator.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Leshow Fan SS4 (leshow.fan.ss4): {'power': 1, 'mode': 2, 'blow': 100, 'timer': 0, diff --git a/miio/integrations/lumi/camera/aqaracamera.py b/miio/integrations/lumi/camera/aqaracamera.py index db4b96e14..1a16723b7 100644 --- a/miio/integrations/lumi/camera/aqaracamera.py +++ b/miio/integrations/lumi/camera/aqaracamera.py @@ -10,7 +10,7 @@ import logging from enum import IntEnum -from typing import Any, Dict +from typing import Any import attr import click @@ -62,7 +62,7 @@ class MotionDetectionSensitivity(IntEnum): class CameraStatus(DeviceStatus): """Container for status reports from the Aqara Camera.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a lumi.camera.aq1: {"p2p_id":"#################","app_type":"celing", diff --git a/miio/integrations/lumi/curtain/curtain_youpin.py b/miio/integrations/lumi/curtain/curtain_youpin.py index b0373f4c4..bad091f7d 100644 --- a/miio/integrations/lumi/curtain/curtain_youpin.py +++ b/miio/integrations/lumi/curtain/curtain_youpin.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict +from typing import Any import click @@ -55,7 +55,7 @@ class Polarity(enum.Enum): class CurtainStatus(DeviceStatus): - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response from device. {'id': 1, 'result': [ diff --git a/miio/integrations/lumi/gateway/devices/subdevice.py b/miio/integrations/lumi/gateway/devices/subdevice.py index 91e6f31e6..d68f8ef2f 100644 --- a/miio/integrations/lumi/gateway/devices/subdevice.py +++ b/miio/integrations/lumi/gateway/devices/subdevice.py @@ -1,7 +1,7 @@ """Xiaomi Gateway subdevice base class.""" import logging -from typing import TYPE_CHECKING, Dict, List, Optional +from typing import TYPE_CHECKING, Optional import attr import click @@ -36,7 +36,7 @@ def __init__( self, gw: "Gateway", dev_info: SubDeviceInfo, - model_info: Optional[Dict] = None, + model_info: Optional[dict] = None, ) -> None: self._gw = gw self.sid = dev_info.sid @@ -63,8 +63,8 @@ def __init__( self.setter = model_info.get("setter") self.push_events = model_info.get("push_properties", []) - self._event_ids: List[str] = [] - self._registered_callbacks: Dict[str, GatewayCallback] = {} + self._event_ids: list[str] = [] + self._registered_callbacks: dict[str, GatewayCallback] = {} def __repr__(self): return "".format( diff --git a/miio/integrations/lumi/gateway/gateway.py b/miio/integrations/lumi/gateway/gateway.py index 973b4d30c..a6eee5494 100644 --- a/miio/integrations/lumi/gateway/gateway.py +++ b/miio/integrations/lumi/gateway/gateway.py @@ -3,7 +3,7 @@ import logging import os import sys -from typing import Callable, Dict, List, Optional +from typing import Callable, Optional import click import yaml @@ -107,13 +107,13 @@ def __init__( self._radio = Radio(parent=self) self._zigbee = Zigbee(parent=self) self._light = Light(parent=self) - self._devices: Dict[str, SubDevice] = {} + self._devices: dict[str, SubDevice] = {} self._info = None self._subdevice_model_map = None self._push_server = push_server - self._event_ids: List[str] = [] - self._registered_callbacks: Dict[str, GatewayCallback] = {} + self._event_ids: list[str] = [] + self._registered_callbacks: dict[str, GatewayCallback] = {} if self._push_server is not None: self._push_server.register_miio_device(self, self.push_callback) diff --git a/miio/integrations/lumi/gateway/gatewaydevice.py b/miio/integrations/lumi/gateway/gatewaydevice.py index d2c271916..353505a90 100644 --- a/miio/integrations/lumi/gateway/gatewaydevice.py +++ b/miio/integrations/lumi/gateway/gatewaydevice.py @@ -1,7 +1,7 @@ """Xiaomi Gateway device base class.""" import logging -from typing import TYPE_CHECKING, List, Optional +from typing import TYPE_CHECKING, Optional from miio import DeviceException @@ -28,4 +28,4 @@ def __init__( ) self._gateway = parent - self._event_ids: List[str] = [] + self._event_ids: list[str] = [] diff --git a/miio/integrations/lumi/gateway/light.py b/miio/integrations/lumi/gateway/light.py index 3f39cbd40..8d1163f87 100644 --- a/miio/integrations/lumi/gateway/light.py +++ b/miio/integrations/lumi/gateway/light.py @@ -1,7 +1,5 @@ """Xiaomi Gateway Light implementation.""" -from typing import Tuple - from miio.utils import brightness_and_color_to_int, int_to_brightness, int_to_rgb from .gatewaydevice import GatewayDevice @@ -59,13 +57,13 @@ def night_light_status(self): return {"is_on": is_on, "brightness": brightness, "rgb": rgb} - def set_rgb(self, brightness: int, rgb: Tuple[int, int, int]): + def set_rgb(self, brightness: int, rgb: tuple[int, int, int]): """Set gateway light using brightness and rgb tuple.""" brightness_and_color = brightness_and_color_to_int(brightness, rgb) return self._gateway.send("set_rgb", [brightness_and_color]) - def set_night_light(self, brightness: int, rgb: Tuple[int, int, int]): + def set_night_light(self, brightness: int, rgb: tuple[int, int, int]): """Set gateway night light using brightness and rgb tuple.""" brightness_and_color = brightness_and_color_to_int(brightness, rgb) diff --git a/miio/integrations/mijia/vacuum/g1vacuum.py b/miio/integrations/mijia/vacuum/g1vacuum.py index 59826fe41..0e6cc6c56 100644 --- a/miio/integrations/mijia/vacuum/g1vacuum.py +++ b/miio/integrations/mijia/vacuum/g1vacuum.py @@ -1,7 +1,6 @@ import logging from datetime import timedelta from enum import Enum -from typing import Dict import click @@ -379,7 +378,7 @@ def set_fan_speed(self, fan_speed: G1FanSpeed): return self.set_property("fan_speed", fan_speed.value) @command() - def fan_speed_presets(self) -> Dict[str, int]: + def fan_speed_presets(self) -> dict[str, int]: """Return available fan speed presets.""" return {x.name: x.value for x in G1FanSpeed} diff --git a/miio/integrations/mmgg/petwaterdispenser/device.py b/miio/integrations/mmgg/petwaterdispenser/device.py index a2e543398..250c0b353 100644 --- a/miio/integrations/mmgg/petwaterdispenser/device.py +++ b/miio/integrations/mmgg/petwaterdispenser/device.py @@ -1,5 +1,5 @@ import logging -from typing import Any, Dict, List +from typing import Any import click @@ -14,10 +14,10 @@ MODEL_MMGG_PET_WATERER_S4 = "mmgg.pet_waterer.s4" MODEL_MMGG_PET_WATERER_WI11 = "mmgg.pet_waterer.wi11" -S_MODELS: List[str] = [MODEL_MMGG_PET_WATERER_S1, MODEL_MMGG_PET_WATERER_S4] -WI_MODELS: List[str] = [MODEL_MMGG_PET_WATERER_WI11] +S_MODELS: list[str] = [MODEL_MMGG_PET_WATERER_S1, MODEL_MMGG_PET_WATERER_S4] +WI_MODELS: list[str] = [MODEL_MMGG_PET_WATERER_WI11] -_MAPPING_COMMON: Dict[str, Dict[str, int]] = { +_MAPPING_COMMON: dict[str, dict[str, int]] = { "mode": {"siid": 2, "piid": 3}, "filter_left_time": {"siid": 3, "piid": 1}, "reset_filter_life": {"siid": 3, "aiid": 1}, @@ -35,12 +35,12 @@ "location": {"siid": 9, "piid": 2}, } -_MAPPING_S: Dict[str, Dict[str, int]] = { +_MAPPING_S: dict[str, dict[str, int]] = { "fault": {"siid": 2, "piid": 1}, "on": {"siid": 2, "piid": 2}, } -_MAPPING_WI: Dict[str, Dict[str, int]] = { +_MAPPING_WI: dict[str, dict[str, int]] = { "on": {"siid": 2, "piid": 1}, "fault": {"siid": 2, "piid": 2}, } @@ -87,12 +87,12 @@ def status(self) -> PetWaterDispenserStatus: return PetWaterDispenserStatus(data) @command(default_output=format_output("Turning device on")) - def on(self) -> List[Dict[str, Any]]: + def on(self) -> list[dict[str, Any]]: """Turn device on.""" return self.set_property("on", True) @command(default_output=format_output("Turning device off")) - def off(self) -> List[Dict[str, Any]]: + def off(self) -> list[dict[str, Any]]: """Turn device off.""" return self.set_property("on", False) @@ -102,7 +102,7 @@ def off(self) -> List[Dict[str, Any]]: lambda led: "Turning LED on" if led else "Turning LED off" ), ) - def set_led(self, led: bool) -> List[Dict[str, Any]]: + def set_led(self, led: bool) -> list[dict[str, Any]]: """Toggle indicator light on/off.""" if led: return self.set_property("indicator_light", True) @@ -112,32 +112,32 @@ def set_led(self, led: bool) -> List[Dict[str, Any]]: click.argument("mode", type=EnumType(OperatingMode)), default_output=format_output('Changing mode to "{mode.name}"'), ) - def set_mode(self, mode: OperatingMode) -> List[Dict[str, Any]]: + def set_mode(self, mode: OperatingMode) -> list[dict[str, Any]]: """Switch operation mode.""" return self.set_property("mode", mode.value) @command(default_output=format_output("Resetting sponge filter")) - def reset_sponge_filter(self) -> Dict[str, Any]: + def reset_sponge_filter(self) -> dict[str, Any]: """Reset sponge filter.""" return self.call_action_from_mapping("reset_filter_life") @command(default_output=format_output("Resetting cotton filter")) - def reset_cotton_filter(self) -> Dict[str, Any]: + def reset_cotton_filter(self) -> dict[str, Any]: """Reset cotton filter.""" return self.call_action_from_mapping("reset_cotton_life") @command(default_output=format_output("Resetting all filters")) - def reset_all_filters(self) -> List[Dict[str, Any]]: + def reset_all_filters(self) -> list[dict[str, Any]]: """Reset all filters [cotton, sponge].""" return [self.reset_cotton_filter(), self.reset_sponge_filter()] @command(default_output=format_output("Resetting cleaning time")) - def reset_cleaning_time(self) -> Dict[str, Any]: + def reset_cleaning_time(self) -> dict[str, Any]: """Reset cleaning time counter.""" return self.call_action_from_mapping("reset_clean_time") @command(default_output=format_output("Resetting device")) - def reset(self) -> Dict[str, Any]: + def reset(self) -> dict[str, Any]: """Reset device.""" return self.call_action_from_mapping("reset_device") @@ -145,7 +145,7 @@ def reset(self) -> Dict[str, Any]: click.argument("timezone", type=click.IntRange(-12, 12)), default_output=format_output('Changing timezone to "{timezone}"'), ) - def set_timezone(self, timezone: int) -> List[Dict[str, Any]]: + def set_timezone(self, timezone: int) -> list[dict[str, Any]]: """Change timezone.""" return self.set_property("timezone", timezone) @@ -153,6 +153,6 @@ def set_timezone(self, timezone: int) -> List[Dict[str, Any]]: click.argument("location", type=str), default_output=format_output('Changing location to "{location}"'), ) - def set_location(self, location: str) -> List[Dict[str, Any]]: + def set_location(self, location: str) -> list[dict[str, Any]]: """Change location.""" return self.set_property("location", location) diff --git a/miio/integrations/mmgg/petwaterdispenser/status.py b/miio/integrations/mmgg/petwaterdispenser/status.py index 4fabd4640..2704bc281 100644 --- a/miio/integrations/mmgg/petwaterdispenser/status.py +++ b/miio/integrations/mmgg/petwaterdispenser/status.py @@ -1,6 +1,6 @@ import enum from datetime import timedelta -from typing import Any, Dict +from typing import Any from miio.miot_device import DeviceStatus @@ -13,7 +13,7 @@ class OperatingMode(enum.Enum): class PetWaterDispenserStatus(DeviceStatus): """Container for status reports from Pet Water Dispenser.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of Pet Water Dispenser (mmgg.pet_waterer.s1) [ {'code': 0, 'did': 'cotton_left_time', 'piid': 1, 'siid': 5, 'value': 10}, diff --git a/miio/integrations/nwt/dehumidifier/airdehumidifier.py b/miio/integrations/nwt/dehumidifier/airdehumidifier.py index 5a8cafcf1..d9db0e0ff 100644 --- a/miio/integrations/nwt/dehumidifier/airdehumidifier.py +++ b/miio/integrations/nwt/dehumidifier/airdehumidifier.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -49,7 +49,7 @@ class FanSpeed(enum.Enum): class AirDehumidifierStatus(DeviceStatus): """Container for status reports from the air dehumidifier.""" - def __init__(self, data: Dict[str, Any], device_info: DeviceInfo) -> None: + def __init__(self, data: dict[str, Any], device_info: DeviceInfo) -> None: """Response of a Air Dehumidifier (nwt.derh.wdh318efw1): {'on_off': 'on', 'mode': 'auto', 'fan_st': 2, diff --git a/miio/integrations/philips/light/ceil.py b/miio/integrations/philips/light/ceil.py index 111ec8313..ed401dab7 100644 --- a/miio/integrations/philips/light/ceil.py +++ b/miio/integrations/philips/light/ceil.py @@ -1,6 +1,6 @@ import logging from collections import defaultdict -from typing import Any, Dict +from typing import Any import click @@ -16,7 +16,7 @@ class CeilStatus(DeviceStatus): """Container for status reports from Xiaomi Philips LED Ceiling Lamp.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: # {'power': 'off', 'bright': 0, 'snm': 4, 'dv': 0, # 'cctsw': [[0, 3], [0, 2], [0, 1]], 'bl': 1, # 'mb': 1, 'ac': 1, 'mssw': 1, 'cct': 99} diff --git a/miio/integrations/philips/light/philips_bulb.py b/miio/integrations/philips/light/philips_bulb.py index 3c675757f..66a38f12b 100644 --- a/miio/integrations/philips/light/philips_bulb.py +++ b/miio/integrations/philips/light/philips_bulb.py @@ -1,6 +1,6 @@ import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -32,7 +32,7 @@ class PhilipsBulbStatus(DeviceStatus): """Container for status reports from Xiaomi Philips LED Ceiling Lamp.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: # {'power': 'on', 'bright': 85, 'cct': 9, 'snm': 0, 'dv': 0} self.data = data diff --git a/miio/integrations/philips/light/philips_eyecare.py b/miio/integrations/philips/light/philips_eyecare.py index c1e1ac47a..1d34ca0e8 100644 --- a/miio/integrations/philips/light/philips_eyecare.py +++ b/miio/integrations/philips/light/philips_eyecare.py @@ -1,6 +1,6 @@ import logging from collections import defaultdict -from typing import Any, Dict +from typing import Any import click @@ -13,7 +13,7 @@ class PhilipsEyecareStatus(DeviceStatus): """Container for status reports from Xiaomi Philips Eyecare Smart Lamp 2.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: # ['power': 'off', 'bright': 5, 'notifystatus': 'off', # 'ambstatus': 'off', 'ambvalue': 41, 'eyecare': 'on', # 'scene_num': 3, 'bls': 'on', 'dvalue': 0] diff --git a/miio/integrations/philips/light/philips_moonlight.py b/miio/integrations/philips/light/philips_moonlight.py index 1a8e08622..d5e90bfcf 100644 --- a/miio/integrations/philips/light/philips_moonlight.py +++ b/miio/integrations/philips/light/philips_moonlight.py @@ -1,6 +1,6 @@ import logging from collections import defaultdict -from typing import Any, Dict, List, Tuple +from typing import Any import click @@ -14,7 +14,7 @@ class PhilipsMoonlightStatus(DeviceStatus): """Container for status reports from Xiaomi Philips Zhirui Bedside Lamp.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Moonlight (philips.light.moonlight): {'pow': 'off', 'sta': 0, 'bri': 1, 'rgb': 16741971, 'cct': 1, 'snm': 0, 'spr': 0, @@ -39,7 +39,7 @@ def color_temperature(self) -> int: return self.data["cct"] @property - def rgb(self) -> Tuple[int, int, int]: + def rgb(self) -> tuple[int, int, int]: """Return color in RGB.""" return int_to_rgb(int(self.data["rgb"])) @@ -77,7 +77,7 @@ def brand(self) -> bool: return self.data["mb"] == 1 @property - def wake_up_time(self) -> List[int]: + def wake_up_time(self) -> list[int]: # Example: [weekdays?, hour, minute] return self.data["wkp"] @@ -158,7 +158,7 @@ def off(self): click.argument("rgb", default=[255] * 3, type=click.Tuple([int, int, int])), default_output=format_output("Setting color to {rgb}"), ) - def set_rgb(self, rgb: Tuple[int, int, int]): + def set_rgb(self, rgb: tuple[int, int, int]): """Set color in RGB.""" for color in rgb: if color < 0 or color > 255: @@ -212,7 +212,7 @@ def set_brightness_and_color_temperature(self, brightness: int, cct: int): "Setting brightness to {brightness} and color to {rgb}" ), ) - def set_brightness_and_rgb(self, brightness: int, rgb: Tuple[int, int, int]): + def set_brightness_and_rgb(self, brightness: int, rgb: tuple[int, int, int]): """Set brightness level and the color.""" if brightness < 1 or brightness > 100: raise ValueError("Invalid brightness: %s" % brightness) diff --git a/miio/integrations/philips/light/philips_rwread.py b/miio/integrations/philips/light/philips_rwread.py index bf34ded80..5d3f5d4ca 100644 --- a/miio/integrations/philips/light/philips_rwread.py +++ b/miio/integrations/philips/light/philips_rwread.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict +from typing import Any import click @@ -26,7 +26,7 @@ class MotionDetectionSensitivity(enum.Enum): class PhilipsRwreadStatus(DeviceStatus): """Container for status reports from Xiaomi Philips RW Read.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a RW Read (philips.light.rwread): {'power': 'on', 'bright': 53, 'dv': 0, 'snm': 1, diff --git a/miio/integrations/pwzn/relay/pwzn_relay.py b/miio/integrations/pwzn/relay/pwzn_relay.py index 0d937bc7e..889cf3556 100644 --- a/miio/integrations/pwzn/relay/pwzn_relay.py +++ b/miio/integrations/pwzn/relay/pwzn_relay.py @@ -1,6 +1,6 @@ import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -59,7 +59,7 @@ class PwznRelayStatus(DeviceStatus): """Container for status reports from the plug.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a PWZN Relay Apple (pwzn.relay.apple) { 'relay_status': 9, 'on_count': 2, 'name0': 'channel1', 'name1': '', @@ -77,7 +77,7 @@ def relay_state(self) -> Optional[int]: return None @property - def relay_names(self) -> Dict[int, str]: + def relay_names(self) -> dict[int, str]: def _extract_index_from_key(name) -> int: """extract the index from the variable.""" return int(name[4:]) diff --git a/miio/integrations/roborock/vacuum/updatehelper.py b/miio/integrations/roborock/vacuum/updatehelper.py index e2737fb21..92b4ed545 100644 --- a/miio/integrations/roborock/vacuum/updatehelper.py +++ b/miio/integrations/roborock/vacuum/updatehelper.py @@ -1,5 +1,5 @@ import logging -from typing import Callable, Dict +from typing import Callable from miio import DeviceException, DeviceStatus @@ -17,7 +17,7 @@ class UpdateHelper: """ def __init__(self, main_update_method: Callable): - self._update_methods: Dict[str, Callable] = {} + self._update_methods: dict[str, Callable] = {} self._main_update_method = main_update_method def add_update_method(self, name: str, update_method: Callable): diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index 756c7df43..0f09e6ccf 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -8,7 +8,7 @@ import pathlib import time from enum import Enum -from typing import Any, Dict, List, Optional, Type +from typing import Any, Optional import click import pytz @@ -285,7 +285,7 @@ def goto(self, x_coord: int, y_coord: int): return self.send("app_goto_target", [x_coord, y_coord]) @command(click.argument("zones", type=LiteralParamType(), required=True)) - def zoned_clean(self, zones: List): + def zoned_clean(self, zones: list): """Clean zones. :param List zones: List of zones to clean: [[x1,y1,x2,y2, iterations],[x1,y1,x2,y2, iterations]] @@ -415,7 +415,7 @@ def get_maps(self) -> MapList: self._maps = MapList(self.send("get_multi_maps_list")[0]) return self._maps - def _map_enum(self) -> Optional[Type[Enum]]: + def _map_enum(self) -> Optional[type[Enum]]: """Enum of the available map names.""" if self._map_enum_cache is not None: return self._map_enum_cache @@ -559,9 +559,9 @@ def find(self): return self.send("find_me", [""]) @command() - def timer(self) -> List[Timer]: + def timer(self) -> list[Timer]: """Return a list of timers.""" - timers: List[Timer] = list() + timers: list[Timer] = list() res = self.send("get_timer", [""]) if not res: return timers @@ -656,7 +656,7 @@ def fan_speed(self): return self.send("get_custom_mode")[0] @command() - def fan_speed_presets(self) -> Dict[str, int]: + def fan_speed_presets(self) -> dict[str, int]: """Return available fan speed presets.""" def _enum_as_dict(cls): @@ -665,7 +665,7 @@ def _enum_as_dict(cls): if self.model is None: return _enum_as_dict(FanspeedV1) - fanspeeds: Type[FanspeedEnum] = FanspeedV1 + fanspeeds: type[FanspeedEnum] = FanspeedV1 if self.model == ROCKROBO_V1: _LOGGER.debug("Got robov1, checking for firmware version") @@ -900,7 +900,7 @@ def resume_segment_clean(self): @command(click.argument("segments", type=LiteralParamType(), required=True)) @command(click.argument("repeat", type=int, required=False, default=1)) - def segment_clean(self, segments: List, repeat: int = 1): + def segment_clean(self, segments: list, repeat: int = 1): """Clean segments. :param List segments: List of segments to clean: [16,17,18] @@ -1055,7 +1055,7 @@ def stop_mop_drying(self) -> bool: return self.send("app_set_dryer_status", {"status": 0})[0] == "ok" @command() - def firmware_features(self) -> List[int]: + def firmware_features(self) -> list[int]: """Return a list of available firmware features. Information: https://github.com/marcelrv/XiaomiRobotVacuumProtocol/blob/master/fw_features.md diff --git a/miio/integrations/roborock/vacuum/vacuum_cli.py b/miio/integrations/roborock/vacuum/vacuum_cli.py index a0f9ac0ba..d2064c295 100644 --- a/miio/integrations/roborock/vacuum/vacuum_cli.py +++ b/miio/integrations/roborock/vacuum/vacuum_cli.py @@ -218,7 +218,7 @@ def goto(vac: RoborockVacuum, x_coord: int, y_coord: int): @cli.command() @pass_dev @click.argument("zones", type=LiteralParamType(), required=True) -def zoned_clean(vac: RoborockVacuum, zones: List): +def zoned_clean(vac: RoborockVacuum, zones: list): """Clean zone.""" click.echo("Cleaning zone(s) : %s" % vac.zoned_clean(zones)) diff --git a/miio/integrations/roborock/vacuum/vacuum_tui.py b/miio/integrations/roborock/vacuum/vacuum_tui.py index 32cbf35ac..9bec40a1f 100644 --- a/miio/integrations/roborock/vacuum/vacuum_tui.py +++ b/miio/integrations/roborock/vacuum/vacuum_tui.py @@ -6,7 +6,6 @@ curses_available = False import enum -from typing import Tuple from .vacuum import RoborockVacuum as Vacuum @@ -62,7 +61,7 @@ def loop(self, win) -> None: win.addstr(text) win.refresh() - def handle_key(self, key: str) -> Tuple[str, bool]: + def handle_key(self, key: str) -> tuple[str, bool]: try: ctl = Control(key) except ValueError as e: diff --git a/miio/integrations/roborock/vacuum/vacuumcontainers.py b/miio/integrations/roborock/vacuum/vacuumcontainers.py index ea42451f2..cd6c430c8 100644 --- a/miio/integrations/roborock/vacuum/vacuumcontainers.py +++ b/miio/integrations/roborock/vacuum/vacuumcontainers.py @@ -1,7 +1,7 @@ import logging from datetime import datetime, time, timedelta from enum import IntEnum -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union from urllib import parse from croniter import croniter @@ -101,7 +101,7 @@ def pretty_area(x: float) -> float: class MapList(DeviceStatus): """Contains a information about the maps/floors of the vacuum.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: # {'max_multi_map': 4, 'max_bak_map': 1, 'multi_map_count': 3, 'map_info': [ # {'mapFlag': 0, 'add_time': 1664448893, 'length': 10, 'name': 'Downstairs', 'bak_maps': [{'mapFlag': 4, 'add_time': 1663577737}]}, # {'mapFlag': 1, 'add_time': 1663580330, 'length': 8, 'name': 'Upstairs', 'bak_maps': [{'mapFlag': 5, 'add_time': 1663577752}]}, @@ -119,17 +119,17 @@ def map_count(self) -> int: return self.data["multi_map_count"] @property - def map_id_list(self) -> List[int]: + def map_id_list(self) -> list[int]: """List of map ids.""" return list(self._map_name_dict.values()) @property - def map_list(self) -> List[Dict[str, Any]]: + def map_list(self) -> list[dict[str, Any]]: """List of map info.""" return self.data["map_info"] @property - def map_name_dict(self) -> Dict[str, int]: + def map_name_dict(self) -> dict[str, int]: """Dictionary of map names (keys) with there ids (values).""" return self._map_name_dict @@ -137,7 +137,7 @@ def map_name_dict(self) -> Dict[str, int]: class VacuumStatus(DeviceStatus): """Container for status reports from the vacuum.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: # {'result': [{'state': 8, 'dnd_enabled': 1, 'clean_time': 0, # 'msg_ver': 4, 'map_present': 1, 'error_code': 0, 'in_cleaning': 0, # 'clean_area': 0, 'battery': 100, 'fan_power': 20, 'msg_seq': 320}], @@ -484,7 +484,7 @@ def mop_dryer_remaining_seconds(self) -> Optional[timedelta]: class CleaningSummary(DeviceStatus): """Contains summarized information about available cleaning runs.""" - def __init__(self, data: Union[List[Any], Dict[str, Any]]) -> None: + def __init__(self, data: Union[list[Any], dict[str, Any]]) -> None: # total duration, total area, amount of cleans # [ list, of, ids ] # { "result": [ 174145, 2410150000, 82, @@ -542,7 +542,7 @@ def count(self) -> int: return int(self.data["clean_count"]) @property - def ids(self) -> List[int]: + def ids(self) -> list[int]: """A list of available cleaning IDs, see also :class:`CleaningDetails`.""" return list(self.data["records"]) @@ -565,7 +565,7 @@ def dust_collection_count(self) -> Optional[int]: class CleaningDetails(DeviceStatus): """Contains details about a specific cleaning run.""" - def __init__(self, data: Union[List[Any], Dict[str, Any]]) -> None: + def __init__(self, data: Union[list[Any], dict[str, Any]]) -> None: # start, end, duration, area, unk, complete # { "result": [ [ 1488347071, 1488347123, 16, 0, 0, 0 ] ], "id": 1 } # newer models return a dict @@ -662,7 +662,7 @@ class ConsumableStatus(DeviceStatus): - Filter: 150 hours """ - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: # {'id': 1, 'result': [{'filter_work_time': 32454, # 'sensor_dirty_time': 3798, # 'side_brush_work_time': 32454, @@ -816,7 +816,7 @@ def cleaning_brush_cleaned_count(self) -> Optional[int]: class DNDStatus(DeviceStatus): """A container for the do-not-disturb status.""" - def __init__(self, data: Dict[str, Any]): + def __init__(self, data: dict[str, Any]): # {'end_minute': 0, 'enabled': 1, 'start_minute': 0, # 'start_hour': 22, 'end_hour': 8} self.data = data @@ -859,7 +859,7 @@ class Timer(DeviceStatus): the creation time. """ - def __init__(self, data: List[Any], timezone: BaseTzInfo) -> None: + def __init__(self, data: list[Any], timezone: BaseTzInfo) -> None: # id / timestamp, enabled, ['', ['command', 'params'] # [['1488667794112', 'off', ['49 22 * * 6', ['start_clean', '']]], # ['1488667777661', 'off', ['49 21 * * 3,4,5,6', ['start_clean', '']] @@ -1030,7 +1030,7 @@ def current_integral(self) -> int: class MopDryerSettings(DeviceStatus): """Container for mop dryer add-on.""" - def __init__(self, data: Dict[str, Any]): + def __init__(self, data: dict[str, Any]): # {'status': 0, 'on': {'cliff_on': 1, 'cliff_off': 1, 'count': 10, 'dry_time': 10800}, # 'off': {'cliff_on': 2, 'cliff_off': 1, 'count': 10}} self.data = data diff --git a/miio/integrations/roidmi/vacuum/roidmivacuum_miot.py b/miio/integrations/roidmi/vacuum/roidmivacuum_miot.py index fcea53b4d..b99f0bf5c 100644 --- a/miio/integrations/roidmi/vacuum/roidmivacuum_miot.py +++ b/miio/integrations/roidmi/vacuum/roidmivacuum_miot.py @@ -5,7 +5,6 @@ import math from datetime import timedelta from enum import Enum -from typing import Dict import click @@ -650,7 +649,7 @@ def set_fanspeed(self, fanspeed_mode: FanSpeed): return self.set_property("fanspeed_mode", fanspeed_mode.value) @command() - def fan_speed_presets(self) -> Dict[str, int]: + def fan_speed_presets(self) -> dict[str, int]: """Return available fan speed presets.""" return {"Sweep": 0, "Silent": 1, "Basic": 2, "Strong": 3, "FullSpeed": 4} diff --git a/miio/integrations/shuii/humidifier/airhumidifier_jsq.py b/miio/integrations/shuii/humidifier/airhumidifier_jsq.py index 13dc985de..80ccb5a21 100644 --- a/miio/integrations/shuii/humidifier/airhumidifier_jsq.py +++ b/miio/integrations/shuii/humidifier/airhumidifier_jsq.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -46,7 +46,7 @@ class LedBrightness(enum.Enum): class AirHumidifierStatus(DeviceStatus): """Container for status reports from the air humidifier jsq.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Status of an Air Humidifier (shuii.humidifier.jsq001): [24, 30, 1, 1, 0, 2, 0, 0, 0] diff --git a/miio/integrations/tinymu/toiletlid/toiletlid.py b/miio/integrations/tinymu/toiletlid/toiletlid.py index 9c53605de..2584feba9 100644 --- a/miio/integrations/tinymu/toiletlid/toiletlid.py +++ b/miio/integrations/tinymu/toiletlid/toiletlid.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict, List +from typing import Any import click @@ -36,7 +36,7 @@ class ToiletlidOperatingMode(enum.Enum): class ToiletlidStatus(DeviceStatus): - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: # {"work_state": 1,"filter_use_flux": 100,"filter_use_time": 180, "ambient_light": "Red"} self.data = data @@ -128,7 +128,7 @@ def get_ambient_light(self, xiaomi_id: str = "") -> str: return "Unknown" @command(default_output=format_output("Get user list.")) - def get_all_user_info(self) -> List[Dict]: + def get_all_user_info(self) -> list[dict]: """Get All bind user.""" users = self.send("get_all_user_info") return users diff --git a/miio/integrations/viomi/vacuum/viomivacuum.py b/miio/integrations/viomi/vacuum/viomivacuum.py index 08c058a51..5c9dd6169 100644 --- a/miio/integrations/viomi/vacuum/viomivacuum.py +++ b/miio/integrations/viomi/vacuum/viomivacuum.py @@ -48,7 +48,7 @@ from collections import defaultdict from datetime import timedelta from enum import Enum -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Optional import click @@ -156,7 +156,7 @@ class ViomiConsumableStatus(ConsumableStatus): which it doesn't report. """ - def __init__(self, data: List[int]) -> None: + def __init__(self, data: list[int]) -> None: # [17, 17, 17, 17] self.data = { "main_brush_work_time": data[0] * 60 * 60, @@ -541,7 +541,7 @@ def zone_data(self) -> int: return self.data["zone_data"] -def _get_rooms_from_schedules(schedules: List[str]) -> Tuple[bool, Dict]: +def _get_rooms_from_schedules(schedules: list[str]) -> tuple[bool, dict]: """Read the result of "get_ordertime" command to extract room names and ids. The `schedules` input needs to follow the following format @@ -610,7 +610,7 @@ def __init__( model=model, ) self.manual_seqnum = -1 - self._cache: Dict[str, Any] = {"edge_state": None, "rooms": {}, "maps": {}} + self._cache: dict[str, Any] = {"edge_state": None, "rooms": {}, "maps": {}} @command() def status(self) -> ViomiVacuumStatus: @@ -793,7 +793,7 @@ def set_fan_speed(self, speed: ViomiVacuumSpeed): self.send("set_suction", [speed.value]) @command() - def fan_speed_presets(self) -> Dict[str, int]: + def fan_speed_presets(self) -> dict[str, int]: """Return available fan speed presets.""" return {x.name: x.value for x in list(ViomiVacuumSpeed)} @@ -814,7 +814,7 @@ def set_water_grade(self, watergrade: ViomiWaterGrade): """ self.send("set_suction", [watergrade.value]) - def get_positions(self, plan_multiplicator=1) -> List[ViomiPositionPoint]: + def get_positions(self, plan_multiplicator=1) -> list[ViomiPositionPoint]: """Return the last positions. plan_multiplicator scale up the coordinates values @@ -933,7 +933,7 @@ def set_remember_map(self, state: bool): # MISSING: Virtual wall/restricted area @command() - def get_maps(self) -> List[Dict[str, Any]]: + def get_maps(self) -> list[dict[str, Any]]: """Return map list. [{'name': 'MapName1', 'id': 1598622255, 'cur': False}, diff --git a/miio/integrations/viomi/viomidishwasher/viomidishwasher.py b/miio/integrations/viomi/viomidishwasher/viomidishwasher.py index d7e9b669d..8d28fb1d9 100644 --- a/miio/integrations/viomi/viomidishwasher/viomidishwasher.py +++ b/miio/integrations/viomi/viomidishwasher/viomidishwasher.py @@ -2,7 +2,7 @@ import logging from collections import defaultdict from datetime import datetime, timedelta -from typing import Any, Dict, List, Optional +from typing import Any, Optional import click @@ -81,7 +81,7 @@ class SystemStatus(enum.IntEnum): class ViomiDishwasherStatus(DeviceStatus): - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """A ViomiDishwasherStatus representing the most important values for the device. @@ -213,7 +213,7 @@ def program_progress(self) -> ProgramStatus: return ProgramStatus.Unknown @property - def errors(self) -> List[SystemStatus]: + def errors(self) -> list[SystemStatus]: """Returns list of errors if detected in the system.""" errors = [] @@ -424,7 +424,7 @@ def continue_program(self) -> str: click.argument("time", type=int), default_output=format_output("Setting air refresh to '{time}'"), ) - def airrefresh(self, time: int) -> List[str]: + def airrefresh(self, time: int) -> list[str]: """Set air refresh interval.""" return self.send("set_freshdry_interval_t", [time]) diff --git a/miio/integrations/xiaomi/aircondition/airconditioner_miot.py b/miio/integrations/xiaomi/aircondition/airconditioner_miot.py index 573e4229a..6eaf34c42 100644 --- a/miio/integrations/xiaomi/aircondition/airconditioner_miot.py +++ b/miio/integrations/xiaomi/aircondition/airconditioner_miot.py @@ -1,7 +1,7 @@ import enum import logging from datetime import timedelta -from typing import Any, Dict +from typing import Any import click @@ -159,7 +159,7 @@ def time_left(self) -> timedelta: class AirConditionerMiotStatus(DeviceStatus): """Container for status reports from the air conditioner (MIoT).""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """ Response (MIoT format) of a Mi Smart Air Conditioner A (xiaomi.aircondition.mc4) [ diff --git a/miio/integrations/yeelight/dual_switch/yeelight_dual_switch.py b/miio/integrations/yeelight/dual_switch/yeelight_dual_switch.py index c5bd9c547..84e118745 100644 --- a/miio/integrations/yeelight/dual_switch/yeelight_dual_switch.py +++ b/miio/integrations/yeelight/dual_switch/yeelight_dual_switch.py @@ -1,5 +1,5 @@ import enum -from typing import Any, Dict +from typing import Any import click @@ -40,7 +40,7 @@ class Switch(enum.Enum): class DualControlModuleStatus(DeviceStatus): - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """ Response of Yeelight Dual Control Module { diff --git a/miio/integrations/yeelight/light/spec_helper.py b/miio/integrations/yeelight/light/spec_helper.py index 7bd618bdf..695cf9286 100644 --- a/miio/integrations/yeelight/light/spec_helper.py +++ b/miio/integrations/yeelight/light/spec_helper.py @@ -1,7 +1,6 @@ import logging import os from enum import IntEnum -from typing import Dict import attr import yaml @@ -26,11 +25,11 @@ class YeelightLampInfo: class YeelightModelInfo: model: str night_light: bool - lamps: Dict[YeelightSubLightType, YeelightLampInfo] + lamps: dict[YeelightSubLightType, YeelightLampInfo] class YeelightSpecHelper: - _models: Dict[str, YeelightModelInfo] = {} + _models: dict[str, YeelightModelInfo] = {} def __init__(self): if not YeelightSpecHelper._models: diff --git a/miio/integrations/yeelight/light/yeelight.py b/miio/integrations/yeelight/light/yeelight.py index 71a84eb1c..2c571b691 100644 --- a/miio/integrations/yeelight/light/yeelight.py +++ b/miio/integrations/yeelight/light/yeelight.py @@ -1,6 +1,6 @@ import logging from enum import IntEnum -from typing import List, Optional, Tuple +from typing import Optional import click @@ -54,7 +54,7 @@ def brightness(self) -> int: return int(self.data[self.get_prop_name("bright")]) @property - def rgb(self) -> Optional[Tuple[int, int, int]]: + def rgb(self) -> Optional[tuple[int, int, int]]: """Return color in RGB if RGB mode is active.""" rgb_int = self.rgb_int if rgb_int is not None: @@ -79,7 +79,7 @@ def color_mode(self) -> Optional[YeelightMode]: return None @property - def hsv(self) -> Optional[Tuple[int, int, int]]: + def hsv(self) -> Optional[tuple[int, int, int]]: """Return current color in HSV if HSV mode is active.""" hue = self.data[self.get_prop_name("hue")] sat = self.data[self.get_prop_name("sat")] @@ -140,7 +140,7 @@ def brightness(self) -> int: return self.lights[0].brightness @property - def rgb(self) -> Optional[Tuple[int, int, int]]: + def rgb(self) -> Optional[tuple[int, int, int]]: """Return color in RGB if RGB mode is active.""" return self.lights[0].rgb @@ -160,7 +160,7 @@ def color_mode(self) -> Optional[YeelightMode]: @sensor( "HSV", setter_name="set_hsv" ) # TODO: we need to extend @setting to support tuples to fix this - def hsv(self) -> Optional[Tuple[int, int, int]]: + def hsv(self) -> Optional[tuple[int, int, int]]: """Return current color in HSV if HSV mode is active.""" return self.lights[0].hsv @@ -243,7 +243,7 @@ def moonlight_mode_brightness(self) -> Optional[int]: return None @property - def lights(self) -> List[YeelightSubLight]: + def lights(self) -> list[YeelightSubLight]: """Return list of sub lights.""" sub_lights = list({YeelightSubLight(self.data, YeelightSubLightType.Main)}) bg_power = self.data[ @@ -269,7 +269,7 @@ class Yeelight(Device): """ _spec_helper = YeelightSpecHelper() - _supported_models: List[str] = _spec_helper.supported_models + _supported_models: list[str] = _spec_helper.supported_models def __init__( self, @@ -416,7 +416,7 @@ def set_color_temperature(self, level, transition=500): click.argument("rgb", default=[255] * 3, type=click.Tuple([int, int, int])), default_output=format_output("Setting color to {rgb}"), ) - def set_rgb(self, rgb: Tuple[int, int, int]): + def set_rgb(self, rgb: tuple[int, int, int]): """Set color in RGB.""" for color in rgb: if color < 0 or color > 255: diff --git a/miio/integrations/yunmi/waterpurifier/waterpurifier.py b/miio/integrations/yunmi/waterpurifier/waterpurifier.py index 932fbcb57..a6e435d8e 100644 --- a/miio/integrations/yunmi/waterpurifier/waterpurifier.py +++ b/miio/integrations/yunmi/waterpurifier/waterpurifier.py @@ -1,5 +1,5 @@ import logging -from typing import Any, Dict +from typing import Any from miio import Device, DeviceStatus from miio.click_common import command, format_output @@ -10,7 +10,7 @@ class WaterPurifierStatus(DeviceStatus): """Container for status reports from the water purifier.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: self.data = data @property diff --git a/miio/integrations/yunmi/waterpurifier/waterpurifier_yunmi.py b/miio/integrations/yunmi/waterpurifier/waterpurifier_yunmi.py index bfcd6d5b9..8009c6300 100644 --- a/miio/integrations/yunmi/waterpurifier/waterpurifier_yunmi.py +++ b/miio/integrations/yunmi/waterpurifier/waterpurifier_yunmi.py @@ -1,6 +1,6 @@ import logging from datetime import timedelta -from typing import Any, Dict, List +from typing import Any from miio import Device, DeviceStatus from miio.click_common import command, format_output @@ -95,14 +95,14 @@ def __init__(self, operation_status: int): ] @property - def errors(self) -> List: + def errors(self) -> list: return self.err_list class WaterPurifierYunmiStatus(DeviceStatus): """Container for status reports from the water purifier (Yunmi model).""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Status of a Water Purifier C1 (yummi.waterpuri.lx11): [0, 7200, 8640, 520, 379, 7200, 17280, 2110, 4544, diff --git a/miio/integrations/zhimi/airpurifier/airfilter_util.py b/miio/integrations/zhimi/airpurifier/airfilter_util.py index 0c469c2c6..708f3e191 100644 --- a/miio/integrations/zhimi/airpurifier/airfilter_util.py +++ b/miio/integrations/zhimi/airpurifier/airfilter_util.py @@ -1,6 +1,6 @@ import enum import re -from typing import Dict, Optional +from typing import Optional class FilterType(enum.Enum): @@ -20,7 +20,7 @@ class FilterType(enum.Enum): class FilterTypeUtil: """Utility class for determining xiaomi air filter type.""" - _filter_type_cache: Dict[str, Optional[FilterType]] = {} + _filter_type_cache: dict[str, Optional[FilterType]] = {} def determine_filter_type( self, rfid_tag: Optional[str], product_id: Optional[str] diff --git a/miio/integrations/zhimi/airpurifier/airfresh.py b/miio/integrations/zhimi/airpurifier/airfresh.py index 932c09962..f74bf5a69 100644 --- a/miio/integrations/zhimi/airpurifier/airfresh.py +++ b/miio/integrations/zhimi/airpurifier/airfresh.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -60,7 +60,7 @@ class LedBrightness(enum.Enum): class AirFreshStatus(DeviceStatus): """Container for status reports from the air fresh.""" - def __init__(self, data: Dict[str, Any], model: str) -> None: + def __init__(self, data: dict[str, Any], model: str) -> None: """ Response of a Air Fresh VA4 (zhimi.airfresh.va4): diff --git a/miio/integrations/zhimi/airpurifier/airpurifier.py b/miio/integrations/zhimi/airpurifier/airpurifier.py index 3d98771b0..e30853dd4 100644 --- a/miio/integrations/zhimi/airpurifier/airpurifier.py +++ b/miio/integrations/zhimi/airpurifier/airpurifier.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -61,7 +61,7 @@ class LedBrightness(enum.Enum): class AirPurifierStatus(DeviceStatus): """Container for status reports from the air purifier.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Air Purifier Pro (zhimi.airpurifier.v6): {'power': 'off', 'aqi': 7, 'average_aqi': 18, 'humidity': 45, diff --git a/miio/integrations/zhimi/airpurifier/airpurifier_miot.py b/miio/integrations/zhimi/airpurifier/airpurifier_miot.py index e36b28270..46e48408e 100644 --- a/miio/integrations/zhimi/airpurifier/airpurifier_miot.py +++ b/miio/integrations/zhimi/airpurifier/airpurifier_miot.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -338,7 +338,7 @@ class AirPurifierMiotStatus(DeviceStatus): ] """ - def __init__(self, data: Dict[str, Any], model: str) -> None: + def __init__(self, data: dict[str, Any], model: str) -> None: self.filter_type_util = FilterTypeUtil() self.data = data self.model = model diff --git a/miio/integrations/zhimi/fan/fan.py b/miio/integrations/zhimi/fan/fan.py index 4e6aec324..119fac8c9 100644 --- a/miio/integrations/zhimi/fan/fan.py +++ b/miio/integrations/zhimi/fan/fan.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -66,7 +66,7 @@ class LedBrightness(enum.Enum): class FanStatus(DeviceStatus): """Container for status reports from the Xiaomi Mi Smart Pedestal Fan.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Fan (zhimi.fan.v3): {'temp_dec': 232, 'humidity': 46, 'angle': 118, 'speed': 298, @@ -229,7 +229,7 @@ def button_pressed(self) -> Optional[str]: class FanStatusZA4(FanStatus): """Container for status reports from the Xiaomi Mi Smart Pedestal Fan Zhimi ZA4.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: self.data = data @property diff --git a/miio/integrations/zhimi/fan/zhimi_miot.py b/miio/integrations/zhimi/fan/zhimi_miot.py index 3d761a413..6f7f15749 100644 --- a/miio/integrations/zhimi/fan/zhimi_miot.py +++ b/miio/integrations/zhimi/fan/zhimi_miot.py @@ -1,5 +1,5 @@ import enum -from typing import Any, Dict +from typing import Any import click @@ -57,7 +57,7 @@ class OperationModeFanZA5(enum.Enum): class FanStatusZA5(DeviceStatus): """Container for status reports for FanZA5.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of FanZA5 (zhimi.fan.za5): {'code': -4005, 'did': 'set_move', 'piid': 3, 'siid': 6}, diff --git a/miio/integrations/zhimi/heater/heater.py b/miio/integrations/zhimi/heater/heater.py index 990dd060b..e42ff6e93 100644 --- a/miio/integrations/zhimi/heater/heater.py +++ b/miio/integrations/zhimi/heater/heater.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -24,7 +24,7 @@ AVAILABLE_PROPERTIES_ZA1 = ["poweroff_time", "relative_humidity"] AVAILABLE_PROPERTIES_MA1 = ["poweroff_level", "poweroff_value"] -SUPPORTED_MODELS: Dict[str, Dict[str, Any]] = { +SUPPORTED_MODELS: dict[str, dict[str, Any]] = { MODEL_HEATER_ZA1: { "available_properties": AVAILABLE_PROPERTIES_COMMON + AVAILABLE_PROPERTIES_ZA1, "temperature_range": (16, 32), @@ -47,7 +47,7 @@ class Brightness(enum.Enum): class HeaterStatus(DeviceStatus): """Container for status reports from the Smartmi Zhimi Heater.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Response of a Heater (zhimi.heater.za1): {'power': 'off', 'target_temperature': 24, 'brightness': 1, diff --git a/miio/integrations/zhimi/heater/heater_miot.py b/miio/integrations/zhimi/heater/heater_miot.py index 445aa1d1a..7d6104754 100644 --- a/miio/integrations/zhimi/heater/heater_miot.py +++ b/miio/integrations/zhimi/heater/heater_miot.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -103,7 +103,7 @@ class LedBrightness(enum.Enum): class HeaterMiotStatus(DeviceStatus): """Container for status reports from the Xiaomi Smart Space Heater S and 1S.""" - def __init__(self, data: Dict[str, Any], model: str) -> None: + def __init__(self, data: dict[str, Any], model: str) -> None: """ Response (MIoT format) of Xiaomi Smart Space Heater S (zhimi.heater.mc2): diff --git a/miio/integrations/zhimi/humidifier/airhumidifier.py b/miio/integrations/zhimi/humidifier/airhumidifier.py index e19b5c101..fb8fa59e8 100644 --- a/miio/integrations/zhimi/humidifier/airhumidifier.py +++ b/miio/integrations/zhimi/humidifier/airhumidifier.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -64,7 +64,7 @@ class LedBrightness(enum.Enum): class AirHumidifierStatus(DeviceStatus): """Container for status reports from the air humidifier.""" - def __init__(self, data: Dict[str, Any], device_info: DeviceInfo) -> None: + def __init__(self, data: dict[str, Any], device_info: DeviceInfo) -> None: """Response of a Air Humidifier (zhimi.humidifier.v1): {'power': 'off', 'mode': 'high', 'temp_dec': 294, diff --git a/miio/integrations/zhimi/humidifier/airhumidifier_miot.py b/miio/integrations/zhimi/humidifier/airhumidifier_miot.py index 5cf4f49c3..7ae9306a0 100644 --- a/miio/integrations/zhimi/humidifier/airhumidifier_miot.py +++ b/miio/integrations/zhimi/humidifier/airhumidifier_miot.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -124,7 +124,7 @@ class PressedButton(enum.Enum): class AirHumidifierMiotCommonStatus(DeviceStatus): """Container for status reports from the air humidifier. Common features for CA4 and CA6 models.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: self.data = data _LOGGER.debug( "Status Common: %s, __cli_output__ %s", repr(self), self.__cli_output__ @@ -288,7 +288,7 @@ class AirHumidifierMiotStatus(AirHumidifierMiotCommonStatus): ] """ - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: self.data = data super().__init__(self.data) self.embed("common", AirHumidifierMiotCommonStatus(self.data)) @@ -568,7 +568,7 @@ class AirHumidifierMiotCA6Status(AirHumidifierMiotCommonStatus): ] """ - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: self.data = data super().__init__(self.data) self.embed("common", AirHumidifierMiotCommonStatus(self.data)) diff --git a/miio/integrations/zimi/powerstrip/powerstrip.py b/miio/integrations/zimi/powerstrip/powerstrip.py index d82011c49..22992f12d 100644 --- a/miio/integrations/zimi/powerstrip/powerstrip.py +++ b/miio/integrations/zimi/powerstrip/powerstrip.py @@ -1,7 +1,7 @@ import enum import logging from collections import defaultdict -from typing import Any, Dict, Optional +from typing import Any, Optional import click @@ -46,7 +46,7 @@ class PowerMode(enum.Enum): class PowerStripStatus(DeviceStatus): """Container for status reports from the power strip.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: dict[str, Any]) -> None: """Supported device models: qmi.powerstrip.v1, zimi.powerstrip.v2. Response of a Power Strip 2 (zimi.powerstrip.v2): diff --git a/miio/miioprotocol.py b/miio/miioprotocol.py index 3d0a1471f..5feb67c93 100644 --- a/miio/miioprotocol.py +++ b/miio/miioprotocol.py @@ -10,7 +10,7 @@ import socket from datetime import datetime, timedelta, timezone from pprint import pformat as pf -from typing import Any, Dict, List, Optional +from typing import Any, Optional import construct @@ -106,7 +106,7 @@ def discover(addr: Optional[str] = None, timeout: int = 5) -> Any: :param str addr: Target IP address """ is_broadcast = addr is None - seen_addrs: List[str] = [] + seen_addrs: list[str] = [] if is_broadcast: addr = "" is_broadcast = True @@ -151,7 +151,7 @@ def send( parameters: Optional[Any] = None, retry_count: int = 3, *, - extra_parameters: Optional[Dict] = None + extra_parameters: Optional[dict] = None ) -> Any: """Build and send the given command. Note that this will implicitly call :func:`send_handshake` to do a handshake, and will re-try in case of errors @@ -282,7 +282,7 @@ def _handle_error(self, error): raise DeviceError(error) def _create_request( - self, command: str, parameters: Any, extra_parameters: Optional[Dict] = None + self, command: str, parameters: Any, extra_parameters: Optional[dict] = None ): """Create request payload.""" request = {"id": self._id, "method": command} diff --git a/miio/miot_cloud.py b/miio/miot_cloud.py index cea72cb10..724509e60 100644 --- a/miio/miot_cloud.py +++ b/miio/miot_cloud.py @@ -5,7 +5,7 @@ from datetime import datetime, timedelta, timezone from operator import attrgetter from pathlib import Path -from typing import Dict, List, Optional +from typing import Optional import platformdirs from micloud.miotspec import MiotSpec @@ -37,7 +37,7 @@ def filename(self) -> str: class ReleaseList(BaseModel): """Model for miotspec release list.""" - releases: List[ReleaseInfo] = Field(alias="instances") + releases: list[ReleaseInfo] = Field(alias="instances") def info_for_model(self, model: str, *, status_filter="released") -> ReleaseInfo: releases = [inst for inst in self.releases if inst.model == model] @@ -93,7 +93,7 @@ def get_device_model(self, model: str) -> DeviceModel: return DeviceModel.parse_obj(self.get_model_schema(model)) - def get_model_schema(self, model: str) -> Dict: + def get_model_schema(self, model: str) -> dict: """Get the preferred schema for the model.""" specs = self.get_release_list() release_info = specs.info_for_model(model) @@ -110,13 +110,13 @@ def get_model_schema(self, model: str) -> Dict: return spec - def _write_to_cache(self, file: Path, data: Dict): + def _write_to_cache(self, file: Path, data: dict): """Write given *data* to cache file *file*.""" file.parent.mkdir(parents=True, exist_ok=True) written = file.write_text(json.dumps(data)) _LOGGER.debug("Written %s bytes to %s", written, file) - def _file_from_cache(self, file, cache_hours=6) -> Dict: + def _file_from_cache(self, file, cache_hours=6) -> dict: def _valid_cache(): expiration = timedelta(hours=cache_hours) if datetime.fromtimestamp( diff --git a/miio/miot_device.py b/miio/miot_device.py index b58391588..615e4d70a 100644 --- a/miio/miot_device.py +++ b/miio/miot_device.py @@ -1,7 +1,7 @@ import logging from enum import Enum from functools import partial -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union import click @@ -24,7 +24,7 @@ def _str2bool(x): Str = str -MiotMapping = Dict[str, Dict[str, Any]] +MiotMapping = dict[str, dict[str, Any]] def _filter_request_fields(req): @@ -58,7 +58,7 @@ class MiotDevice(Device): """ mapping: MiotMapping # Deprecated, use _mappings instead - _mappings: Dict[str, MiotMapping] = {} + _mappings: dict[str, MiotMapping] = {} def __init__( self, diff --git a/miio/miot_models.py b/miio/miot_models.py index 53592a5ba..1269946d5 100644 --- a/miio/miot_models.py +++ b/miio/miot_models.py @@ -1,7 +1,7 @@ import logging from datetime import timedelta from enum import Enum -from typing import Any, Dict, List, Optional +from typing import Any, Optional try: from pydantic.v1 import BaseModel, Field, PrivateAttr, root_validator @@ -32,7 +32,7 @@ class URN(BaseModel): internal_id: str model: str version: int - unexpected: Optional[List[str]] + unexpected: Optional[list[str]] parent_urn: Optional["URN"] = Field(None, repr=False) @@ -112,7 +112,7 @@ class MiotBaseModel(BaseModel): urn: URN = Field(alias="type") description: str - extras: Dict = Field(default_factory=dict, repr=False) + extras: dict = Field(default_factory=dict, repr=False) service: Optional["MiotService"] = None # backref to containing service def fill_from_parent(self, service: "MiotService"): @@ -212,12 +212,12 @@ class MiotProperty(MiotBaseModel): piid: int = Field(alias="iid") format: MiotFormat - access: List[MiotAccess] = Field(default=["read"]) + access: list[MiotAccess] = Field(default=["read"]) unit: Optional[str] = None - range: Optional[List[int]] = Field(alias="value-range") - choices: Optional[List[MiotEnumValue]] = Field(alias="value-list") - gatt_access: Optional[List[Any]] = Field(alias="gatt-access") + range: Optional[list[int]] = Field(alias="value-range") + choices: Optional[list[MiotEnumValue]] = Field(alias="value-list") + gatt_access: Optional[list[Any]] = Field(alias="gatt-access") # TODO: currently just used to pass the data for miiocli # there must be a better way to do this.. @@ -305,7 +305,7 @@ def get_descriptor(self) -> PropertyDescriptor: return desc - def _miot_access_list_to_access(self, access_list: List[MiotAccess]) -> AccessFlags: + def _miot_access_list_to_access(self, access_list: list[MiotAccess]) -> AccessFlags: """Convert miot access list to property access list.""" access = AccessFlags(0) if MiotAccess.Read in access_list: @@ -392,12 +392,12 @@ class MiotService(BaseModel): urn: URN = Field(alias="type") description: str - properties: List[MiotProperty] = Field(default_factory=list, repr=False) - events: List[MiotEvent] = Field(default_factory=list, repr=False) - actions: List[MiotAction] = Field(default_factory=list, repr=False) + properties: list[MiotProperty] = Field(default_factory=list, repr=False) + events: list[MiotEvent] = Field(default_factory=list, repr=False) + actions: list[MiotAction] = Field(default_factory=list, repr=False) - _property_by_id: Dict[int, MiotProperty] = PrivateAttr(default_factory=dict) - _action_by_id: Dict[int, MiotAction] = PrivateAttr(default_factory=dict) + _property_by_id: dict[int, MiotProperty] = PrivateAttr(default_factory=dict) + _action_by_id: dict[int, MiotAction] = PrivateAttr(default_factory=dict) def __init__(self, *args, **kwargs): """Initialize a service. @@ -446,14 +446,14 @@ class DeviceModel(BaseModel): description: str urn: URN = Field(alias="type") - services: List[MiotService] = Field(repr=False) + services: list[MiotService] = Field(repr=False) # internal mappings to simplify accesses - _services_by_id: Dict[int, MiotService] = PrivateAttr(default_factory=dict) - _properties_by_id: Dict[int, Dict[int, MiotProperty]] = PrivateAttr( + _services_by_id: dict[int, MiotService] = PrivateAttr(default_factory=dict) + _properties_by_id: dict[int, dict[int, MiotProperty]] = PrivateAttr( default_factory=dict ) - _properties_by_name: Dict[str, Dict[str, MiotProperty]] = PrivateAttr( + _properties_by_name: dict[str, dict[str, MiotProperty]] = PrivateAttr( default_factory=dict ) diff --git a/miio/protocol.py b/miio/protocol.py index 8d66e02a6..f90ab1e25 100644 --- a/miio/protocol.py +++ b/miio/protocol.py @@ -17,7 +17,7 @@ import hashlib import json import logging -from typing import Any, Dict, Tuple, Union +from typing import Any, Union from construct import ( Adapter, @@ -63,7 +63,7 @@ def md5(data: bytes) -> bytes: return checksum.digest() @staticmethod - def key_iv(token: bytes) -> Tuple[bytes, bytes]: + def key_iv(token: bytes) -> tuple[bytes, bytes]: """Generate an IV used for encryption based on given token.""" key = Utils.md5(token) iv = Utils.md5(key + token) @@ -112,7 +112,7 @@ def decrypt(ciphertext: bytes, token: bytes) -> bytes: return unpadded_plaintext @staticmethod - def checksum_field_bytes(ctx: Dict[str, Any]) -> bytearray: + def checksum_field_bytes(ctx: dict[str, Any]) -> bytearray: """Gather bytes for checksum calculation.""" x = bytearray(ctx["header"].data) x += ctx["_"]["token"] @@ -160,7 +160,7 @@ def _encode(self, obj, context, path): json.dumps(obj).encode("utf-8") + b"\x00", context["_"]["token"] ) - def _decode(self, obj, context, path) -> Union[Dict, bytes]: + def _decode(self, obj, context, path) -> Union[dict, bytes]: """Decrypts the payload using the token stored in the context.""" # Missing payload is expected for discovery messages. if not obj: diff --git a/miio/push_server/server.py b/miio/push_server/server.py index 670725294..91f086e7e 100644 --- a/miio/push_server/server.py +++ b/miio/push_server/server.py @@ -3,7 +3,7 @@ import socket from json import dumps from random import randint -from typing import Callable, Dict, Optional, Union +from typing import Callable, Optional, Union from ..device import Device from ..protocol import Utils @@ -17,7 +17,7 @@ FAKE_DEVICE_MODEL = "chuangmi.plug.v3" PushServerCallback = Callable[[str, str, str], None] -MethodDict = Dict[str, Union[Dict, Callable]] +MethodDict = dict[str, Union[dict, Callable]] def calculated_token_enc(token): @@ -96,7 +96,7 @@ async def stop(self): self._listen_couroutine = None self._loop = None - def add_method(self, name: str, response: Union[Dict, Callable]): + def add_method(self, name: str, response: Union[dict, Callable]): """Add a method to server. The response can be either a callable or a dictionary to send back as response. diff --git a/miio/utils.py b/miio/utils.py index 8657e9a5b..8146b77b6 100644 --- a/miio/utils.py +++ b/miio/utils.py @@ -2,7 +2,6 @@ import inspect import warnings from datetime import datetime, timedelta -from typing import Tuple def deprecated(reason): @@ -86,7 +85,7 @@ def pretty_time(x: float) -> datetime: return datetime.fromtimestamp(x) -def int_to_rgb(x: int) -> Tuple[int, int, int]: +def int_to_rgb(x: int) -> tuple[int, int, int]: """Return a RGB tuple from integer.""" red = (x >> 16) & 0xFF green = (x >> 8) & 0xFF @@ -94,7 +93,7 @@ def int_to_rgb(x: int) -> Tuple[int, int, int]: return red, green, blue -def rgb_to_int(x: Tuple[int, int, int]) -> int: +def rgb_to_int(x: tuple[int, int, int]) -> int: """Return an integer from RGB tuple.""" return int(x[0] << 16 | x[1] << 8 | x[2]) @@ -104,5 +103,5 @@ def int_to_brightness(x: int) -> int: return x >> 24 -def brightness_and_color_to_int(brightness: int, color: Tuple[int, int, int]) -> int: +def brightness_and_color_to_int(brightness: int, color: tuple[int, int, int]) -> int: return int(brightness << 24 | color[0] << 16 | color[1] << 8 | color[2]) diff --git a/poetry.lock b/poetry.lock index 45c860210..6261564dc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,13 +2,13 @@ [[package]] name = "alabaster" -version = "0.7.13" -description = "A configurable sidebar-enabled Sphinx theme" +version = "0.7.16" +description = "A light, configurable Sphinx theme" optional = true -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, - {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, + {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, + {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, ] [[package]] @@ -32,9 +32,6 @@ files = [ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} - [[package]] name = "async-timeout" version = "4.0.3" @@ -76,40 +73,9 @@ files = [ {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, ] -[package.dependencies] -pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} - [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] -[[package]] -name = "backports-zoneinfo" -version = "0.2.1" -description = "Backport of the standard library zoneinfo module" -optional = false -python-versions = ">=3.6" -files = [ - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win32.whl", hash = "sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08"}, - {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win32.whl", hash = "sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b"}, - {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328"}, - {file = "backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6"}, - {file = "backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"}, -] - -[package.extras] -tzdata = ["tzdata"] - [[package]] name = "cachetools" version = "5.5.0" @@ -388,83 +354,73 @@ extras = ["arrow", "cloudpickle", "cryptography", "lz4", "numpy", "ruamel.yaml"] [[package]] name = "coverage" -version = "7.6.1" +version = "7.6.4" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.8" -files = [ - {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, - {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, - {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, - {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, - {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, - {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, - {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, - {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, - {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, - {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, - {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, - {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, - {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, - {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, - {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, - {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, - {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, - {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, - {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, - {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, - {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, - {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, - {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, - {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, - {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, - {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, - {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, - {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, - {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, - {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, +python-versions = ">=3.9" +files = [ + {file = "coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07"}, + {file = "coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0"}, + {file = "coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72"}, + {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51"}, + {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea"}, + {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a"}, + {file = "coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa"}, + {file = "coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172"}, + {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, + {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, + {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, + {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, + {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, + {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, + {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, + {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, + {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, + {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, + {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, + {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, + {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, + {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, + {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, + {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, + {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, + {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, + {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, + {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, + {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, + {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, + {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, + {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, + {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, + {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, + {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, + {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, + {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, + {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, + {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, + {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, + {file = "coverage-7.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3"}, + {file = "coverage-7.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00a1d69c112ff5149cabe60d2e2ee948752c975d95f1e1096742e6077affd376"}, + {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f76846299ba5c54d12c91d776d9605ae33f8ae2b9d1d3c3703cf2db1a67f2c0"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111"}, + {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901"}, + {file = "coverage-7.6.4-cp39-cp39-win32.whl", hash = "sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09"}, + {file = "coverage-7.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f"}, + {file = "coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e"}, + {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, ] [package.dependencies] @@ -607,13 +563,13 @@ tomli = ["tomli (>=2.0.0,<3.0.0)"] [[package]] name = "docutils" -version = "0.20.1" +version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, - {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] [[package]] @@ -787,71 +743,72 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "2.1.5" +version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = true -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +python-versions = ">=3.9" +files = [ + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, ] [[package]] @@ -1095,13 +1052,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.5.0" +version = "4.0.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, - {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, + {file = "pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878"}, + {file = "pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2"}, ] [package.dependencies] @@ -1540,38 +1497,39 @@ files = [ [[package]] name = "sphinx" -version = "7.1.2" +version = "7.4.7" description = "Python documentation generator" optional = true -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "sphinx-7.1.2-py3-none-any.whl", hash = "sha256:d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe"}, - {file = "sphinx-7.1.2.tar.gz", hash = "sha256:780f4d32f1d7d1126576e0e5ecc19dc32ab76cd24e950228dcf7b1f6d3d9e22f"}, + {file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"}, + {file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"}, ] [package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=2.9" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.18.1,<0.21" +alabaster = ">=0.7.14,<0.8.0" +babel = ">=2.13" +colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} +docutils = ">=0.20,<0.22" imagesize = ">=1.3" -importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} -Jinja2 = ">=3.0" -packaging = ">=21.0" -Pygments = ">=2.13" -requests = ">=2.25.0" -snowballstemmer = ">=2.0" +importlib-metadata = {version = ">=6.0", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.1" +packaging = ">=23.0" +Pygments = ">=2.17" +requests = ">=2.30.0" +snowballstemmer = ">=2.2" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" sphinxcontrib-htmlhelp = ">=2.0.0" sphinxcontrib-jsmath = "*" sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.5" +sphinxcontrib-serializinghtml = ">=1.1.9" +tomli = {version = ">=2", markers = "python_version < \"3.11\""} [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] -test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] +lint = ["flake8 (>=6.0)", "importlib-metadata (>=6.0)", "mypy (==1.10.1)", "pytest (>=6.0)", "ruff (==0.5.2)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-docutils (==0.21.0.20240711)", "types-requests (>=2.30.0)"] +test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] [[package]] name = "sphinx-click" @@ -1625,47 +1583,50 @@ Sphinx = ">=5.0.0" [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.4" +version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = true -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, - {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, + {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, + {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" -version = "1.0.2" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +version = "2.0.0" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = true -python-versions = ">=3.5" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, - {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, + {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, + {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.1" +version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = true -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, - {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, + {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, + {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] test = ["html5lib", "pytest"] [[package]] @@ -1698,32 +1659,34 @@ test = ["flake8", "mypy", "pytest"] [[package]] name = "sphinxcontrib-qthelp" -version = "1.0.3" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +version = "2.0.0" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = true -python-versions = ">=3.5" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, - {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, + {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, + {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] +test = ["defusedxml (>=0.7.1)", "pytest"] [[package]] name = "sphinxcontrib-serializinghtml" -version = "1.1.5" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +version = "2.0.0" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = true -python-versions = ">=3.5" +python-versions = ">=3.9" files = [ - {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, - {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, + {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, + {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] +standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] @@ -1832,7 +1795,6 @@ files = [ ] [package.dependencies] -"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""} tzdata = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] @@ -1992,5 +1954,5 @@ updater = ["netifaces"] [metadata] lock-version = "2.0" -python-versions = "^3.8" -content-hash = "88d9eb2844296b674063cd2e19fc9c95a027aca30359ce953f8a066a70d54106" +python-versions = "^3.9" +content-hash = "e287b5b30cfb9a06ec50705bc0f40e355b840fdb54983c3abd5bd485896bda06" diff --git a/pyproject.toml b/pyproject.toml index 6ccd03cf3..8f702cc7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ miio-extract-tokens = "miio.extract_tokens:main" miiocli = "miio.cli:create_cli" [tool.poetry.dependencies] -python = "^3.8" +python = "^3.9" click = ">=8" cryptography = ">=35" construct = "^2.10.56" diff --git a/tox.ini b/tox.ini deleted file mode 100644 index fa7c51c06..000000000 --- a/tox.ini +++ /dev/null @@ -1,50 +0,0 @@ -[tox] -envlist=py36,py37,py38,py39,py310,lint,docs,pypi-description -skip_missing_interpreters = True -isolated_build = True - -[testenv] -deps= - pytest - pytest-cov - pytest-mock - voluptuous - pyyaml - flake8 - coverage[toml] -commands= - pytest --cov miio - -[testenv:docs] -basepython=python -extras=docs -deps= - sphinx - doc8 - pyyaml - restructuredtext_lint - sphinx-autodoc-typehints - sphinx-click - pydantic -commands= - doc8 docs - rst-lint README.rst docs/*.rst - sphinx-build -W -b html -d {envtmpdir}/docs docs {envtmpdir}/html - -[doc8] -ignore-path = docs/_build*,.tox -max-line-length = 120 - -[testenv:lint] -deps = pre-commit -skip_install = true -commands = pre-commit run --all-files - -[testenv:pypi-description] -skip_install = true -deps = - twine - pip >= 18.0.0 -commands = - pip wheel -w {envtmpdir}/build --no-deps . - twine check {envtmpdir}/build/*