Remove support for python <3.11 (#1273)

Python 3.11 ships with latest Debian Bookworm. 
pypy is not that widely used with this library based on statistics. It could be added back when pypy supports python 3.11.
This commit is contained in:
Steven B.
2024-11-18 18:46:36 +00:00
committed by GitHub
parent 0c40939624
commit a01247d48f
55 changed files with 176 additions and 620 deletions

View File

@@ -28,7 +28,7 @@ async def handle_turn_on(dev, turn_on):
await dev.turn_off()
@pytest.fixture()
@pytest.fixture
def dummy_protocol():
"""Return a smart protocol instance with a mocking-ready dummy transport."""
@@ -95,7 +95,7 @@ def pytest_collection_modifyitems(config, items):
for item in items:
item.add_marker(pytest.mark.enable_socket)
else:
print("Running against ip %s" % config.getoption("--ip"))
print("Running against ip {}".format(config.getoption("--ip")))
requires_dummy = pytest.mark.skip(
reason="test requires to be run against dummy data"
)

View File

@@ -4,8 +4,9 @@ import copy
import glob
import json
import os
from collections.abc import Iterable
from pathlib import Path
from typing import Iterable, NamedTuple
from typing import NamedTuple
import pytest

View File

@@ -2,7 +2,6 @@ from __future__ import annotations
import sys
from datetime import datetime
from typing import Optional
import pytest
from pytest_mock import MockerFixture
@@ -23,7 +22,7 @@ autooff = parametrize(
[
("auto_off_enabled", "enabled", bool),
("auto_off_minutes", "delay", int),
("auto_off_at", "auto_off_at", Optional[datetime]),
("auto_off_at", "auto_off_at", datetime | None),
],
)
@pytest.mark.skipif(

View File

@@ -74,7 +74,7 @@ async def test_update_available_without_cloud(dev: SmartDevice):
pytest.param(False, pytest.raises(KasaException), id="not-available"),
],
)
@pytest.mark.requires_dummy()
@pytest.mark.requires_dummy
async def test_firmware_update(
dev: SmartDevice,
mocker: MockerFixture,

View File

@@ -17,8 +17,7 @@ waterleak = parametrize(
("feature", "prop_name", "type"),
[
("water_alert", "alert", int),
# Can be converted to 'datetime | None' after py3.9 support is dropped
("water_alert_timestamp", "alert_timestamp", (datetime, type(None))),
("water_alert_timestamp", "alert_timestamp", datetime | None),
("water_leak", "status", Enum),
],
)

View File

@@ -2,7 +2,7 @@
from __future__ import annotations
from datetime import datetime, timezone
from datetime import UTC, datetime
from unittest.mock import patch
import pytest
@@ -91,7 +91,7 @@ async def test_hub(dev):
@device_smartcamera
async def test_device_time(dev: Device, freezer: FrozenDateTimeFactory):
"""Test a child device gets the time from it's parent module."""
fallback_time = datetime.now(timezone.utc).astimezone().replace(microsecond=0)
fallback_time = datetime.now(UTC).astimezone().replace(microsecond=0)
assert dev.time != fallback_time
module = dev.modules[Module.Time]
await module.set_time(fallback_time)

View File

@@ -278,7 +278,7 @@ async def test_non_variable_temp(dev: Device):
@dimmable_iot
@turn_on
async def test_dimmable_brightness(dev: IotBulb, turn_on):
assert isinstance(dev, (IotBulb, IotDimmer))
assert isinstance(dev, IotBulb | IotDimmer)
light = dev.modules.get(Module.Light)
assert light
await handle_turn_on(dev, turn_on)
@@ -375,7 +375,7 @@ async def test_list_presets(dev: IotBulb):
]
assert len(presets) == len(raw_presets)
for preset, raw in zip(presets, raw_presets):
for preset, raw in zip(presets, raw_presets, strict=False):
assert preset.index == raw["index"]
assert preset.brightness == raw["brightness"]
assert preset.hue == raw["hue"]

View File

@@ -1,6 +1,5 @@
import inspect
import sys
from datetime import datetime, timezone
from datetime import UTC, datetime
import pytest
from freezegun.api import FrozenDateTimeFactory
@@ -58,10 +57,6 @@ async def test_childdevice_update(dev, dummy_protocol, mocker):
@strip_smart
@pytest.mark.skipif(
sys.version_info < (3, 11),
reason="exceptiongroup requires python3.11+",
)
async def test_childdevice_properties(dev: SmartChildDevice):
"""Check that accessing childdevice properties do not raise exceptions."""
assert len(dev.children) > 0
@@ -125,7 +120,7 @@ async def test_parent_property(dev: Device):
@has_children_smart
@pytest.mark.requires_dummy()
@pytest.mark.requires_dummy
async def test_child_time(dev: Device, freezer: FrozenDateTimeFactory):
"""Test a child device gets the time from it's parent module.
@@ -135,7 +130,7 @@ async def test_child_time(dev: Device, freezer: FrozenDateTimeFactory):
if not dev.children:
pytest.skip(f"Device {dev} fixture does not have any children")
fallback_time = datetime.now(timezone.utc).astimezone().replace(microsecond=0)
fallback_time = datetime.now(UTC).astimezone().replace(microsecond=0)
assert dev.parent is None
for child in dev.children:
assert child.time != fallback_time

View File

@@ -3,12 +3,12 @@ import os
import re
from datetime import datetime
from unittest.mock import ANY
from zoneinfo import ZoneInfo
import asyncclick as click
import pytest
from asyncclick.testing import CliRunner
from pytest_mock import MockerFixture
from zoneinfo import ZoneInfo
from kasa import (
AuthenticationError,
@@ -58,7 +58,7 @@ from .conftest import (
pytestmark = [pytest.mark.requires_dummy]
@pytest.fixture()
@pytest.fixture
def runner():
"""Runner fixture that unsets the KASA_ environment variables for tests."""
KASA_VARS = {k: None for k, v in os.environ.items() if k.startswith("KASA_")}

View File

@@ -1,8 +1,8 @@
from datetime import datetime
from zoneinfo import ZoneInfo
import pytest
from pytest_mock import MockerFixture
from zoneinfo import ZoneInfo
from kasa import Device, LightState, Module

View File

@@ -6,11 +6,11 @@ import importlib
import inspect
import pkgutil
import sys
import zoneinfo
from contextlib import AbstractContextManager, nullcontext
from unittest.mock import AsyncMock, patch
import pytest
import zoneinfo
import kasa
from kasa import Credentials, Device, DeviceConfig, DeviceType, KasaException, Module

View File

@@ -7,11 +7,11 @@ import json
import logging
import re
import socket
from asyncio import timeout as asyncio_timeout
from unittest.mock import MagicMock
import aiohttp
import pytest # type: ignore # https://github.com/pytest-dev/pytest/issues/3342
from async_timeout import timeout as asyncio_timeout
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding as asymmetric_padding

View File

@@ -68,7 +68,7 @@ async def test_get_emeter_realtime(dev):
@has_emeter_iot
@pytest.mark.requires_dummy()
@pytest.mark.requires_dummy
async def test_get_emeter_daily(dev):
emeter = dev.modules[Module.Energy]
@@ -88,7 +88,7 @@ async def test_get_emeter_daily(dev):
@has_emeter_iot
@pytest.mark.requires_dummy()
@pytest.mark.requires_dummy
async def test_get_emeter_monthly(dev):
emeter = dev.modules[Module.Energy]

View File

@@ -1,5 +1,4 @@
import logging
import sys
from unittest.mock import AsyncMock, patch
import pytest
@@ -14,7 +13,7 @@ class DummyDevice:
pass
@pytest.fixture()
@pytest.fixture
def dummy_feature() -> Feature:
# create_autospec for device slows tests way too much, so we use a dummy here
@@ -159,10 +158,6 @@ async def test_precision_hint(dummy_feature, precision_hint):
assert f"{round(dummy_value, precision_hint)} dummyunit" in repr(dummy_feature)
@pytest.mark.skipif(
sys.version_info < (3, 11),
reason="exceptiongroup requires python3.11+",
)
async def test_feature_setters(dev: Device, mocker: MockerFixture):
"""Test that all feature setters query something."""

View File

@@ -1,4 +1,3 @@
import asyncio
import re
import aiohttp
@@ -32,7 +31,7 @@ from kasa.httpclient import HttpClient
"Unable to query the device, timed out: ",
),
(
asyncio.TimeoutError(),
TimeoutError(),
TimeoutError,
"Unable to query the device, timed out: ",
),

View File

@@ -89,7 +89,7 @@ async def test_state_info(dev):
assert isinstance(dev.state_information, dict)
@pytest.mark.requires_dummy()
@pytest.mark.requires_dummy
@device_iot
async def test_invalid_connection(mocker, dev):
mocker.patch.object(FakeIotProtocol, "query", side_effect=KasaException)

View File

@@ -145,7 +145,7 @@ def test_tutorial_examples(readmes_mock):
assert not res["failed"]
@pytest.fixture()
@pytest.fixture
async def readmes_mock(mocker):
fixture_infos = {
"127.0.0.1": get_fixture_info("KP303(UK)_1.0_1.0.3.json", "IOT"), # Strip

View File

@@ -26,7 +26,7 @@ from .conftest import (
@device_smart
@pytest.mark.requires_dummy()
@pytest.mark.requires_dummy
async def test_try_get_response(dev: SmartDevice, caplog):
mock_response: dict = {
"get_device_info": SmartErrorCode.PARAMS_ERROR,
@@ -38,7 +38,7 @@ async def test_try_get_response(dev: SmartDevice, caplog):
@device_smart
@pytest.mark.requires_dummy()
@pytest.mark.requires_dummy
async def test_update_no_device_info(dev: SmartDevice, mocker: MockerFixture):
mock_response: dict = {
"get_device_usage": {},