Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ ci:

repos:
- repo: https://github.com/commitizen-tools/commitizen
rev: v4.1.1
rev: v4.2.1
hooks:
- id: commitizen
stages: [commit-msg]
Expand Down Expand Up @@ -38,9 +38,9 @@ repos:
rev: v3.19.1
hooks:
- id: pyupgrade
args: [--py38-plus]
args: [--py39-plus]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.4
rev: v0.9.5
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand All @@ -54,7 +54,7 @@ repos:
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.1
rev: v1.15.0
hooks:
- id: mypy
additional_dependencies: []
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ sphinx = "^7.4.7 || ^8.1.3"
sphinx-rtd-theme = "^3.0.2"

[tool.ruff]
target-version = "py38"
target-version = "py39"
line-length = 110

[tool.ruff.lint]
Expand Down
5 changes: 3 additions & 2 deletions src/zeroconf/_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@

from __future__ import annotations

from collections.abc import Iterable
from heapq import heapify, heappop, heappush
from typing import Dict, Iterable, Union, cast
from typing import Union, cast

from ._dns import (
DNSAddress,
Expand All @@ -40,7 +41,7 @@

_UNIQUE_RECORD_TYPES = (DNSAddress, DNSHinfo, DNSPointer, DNSText, DNSService)
_UniqueRecordsType = Union[DNSAddress, DNSHinfo, DNSPointer, DNSText, DNSService]
_DNSRecordCacheType = Dict[str, Dict[DNSRecord, DNSRecord]]
_DNSRecordCacheType = dict[str, dict[DNSRecord, DNSRecord]]
_DNSRecord = DNSRecord
_str = str
_float = float
Expand Down
2 changes: 1 addition & 1 deletion src/zeroconf/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import logging
import sys
import threading
from collections.abc import Awaitable
from types import TracebackType
from typing import Awaitable

from ._cache import DNSCache
from ._dns import DNSQuestion, DNSQuestionType
Expand Down
3 changes: 1 addition & 2 deletions src/zeroconf/_handlers/answers.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@
from __future__ import annotations

from operator import attrgetter
from typing import Dict, Set

from .._dns import DNSQuestion, DNSRecord
from .._protocol.outgoing import DNSOutgoing
from ..const import _FLAGS_AA, _FLAGS_QR_RESPONSE

_AnswerWithAdditionalsType = Dict[DNSRecord, Set[DNSRecord]]
_AnswerWithAdditionalsType = dict[DNSRecord, set[DNSRecord]]

int_ = int

Expand Down
4 changes: 2 additions & 2 deletions src/zeroconf/_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import logging
import random
from functools import partial
from typing import TYPE_CHECKING, Tuple, cast
from typing import TYPE_CHECKING, cast

from ._logger import QuietLogger, log
from ._protocol.incoming import DNSIncoming
Expand Down Expand Up @@ -134,7 +134,7 @@ def _process_datagram_at_time(
addr, port = addrs # type: ignore
addr_port = addrs
if TYPE_CHECKING:
addr_port = cast(Tuple[str, int], addr_port)
addr_port = cast(tuple[str, int], addr_port)
scope = None
else:
# https://github.com/python/mypy/issues/1178
Expand Down
3 changes: 2 additions & 1 deletion src/zeroconf/_protocol/outgoing.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@

import enum
import logging
from collections.abc import Sequence
from struct import Struct
from typing import TYPE_CHECKING, Sequence
from typing import TYPE_CHECKING

from .._dns import DNSPointer, DNSQuestion, DNSRecord
from .._exceptions import NamePartTooLongException
Expand Down
13 changes: 5 additions & 8 deletions src/zeroconf/_services/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,13 @@
import threading
import time
import warnings
from collections.abc import Iterable
from functools import partial
from types import TracebackType # used in type hints
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
Iterable,
List,
Set,
cast,
)

Expand Down Expand Up @@ -96,7 +93,7 @@
bool_ = bool
str_ = str

_QuestionWithKnownAnswers = Dict[DNSQuestion, Set[DNSPointer]]
_QuestionWithKnownAnswers = dict[DNSQuestion, set[DNSPointer]]

heappop = heapq.heappop
heappush = heapq.heappush
Expand Down Expand Up @@ -282,7 +279,7 @@ def generate_service_query(
log.debug("Asking %s was suppressed by the question history", question)
continue
if TYPE_CHECKING:
pointer_known_answers = cast(Set[DNSPointer], known_answers)
pointer_known_answers = cast(set[DNSPointer], known_answers)
else:
pointer_known_answers = known_answers
questions_with_known_answers[question] = pointer_known_answers
Expand Down Expand Up @@ -618,10 +615,10 @@ def __init__(
self._query_sender_task: asyncio.Task | None = None

if hasattr(handlers, "add_service"):
listener = cast("ServiceListener", handlers)
listener = cast(ServiceListener, handlers)
handlers = None

handlers = cast(List[Callable[..., None]], handlers or [])
handlers = cast(list[Callable[..., None]], handlers or [])

if listener:
handlers.append(_service_state_changed_from_listener(listener))
Expand Down
10 changes: 5 additions & 5 deletions src/zeroconf/_services/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

import asyncio
import random
from typing import TYPE_CHECKING, Dict, List, Optional, cast
from typing import TYPE_CHECKING, cast

from .._cache import DNSCache
from .._dns import (
Expand Down Expand Up @@ -395,7 +395,7 @@ def _set_properties(self, properties: dict[str | bytes, str | bytes | None]) ->
# as-is, without decoding them, otherwise calling
# self.properties will lazy decode them, which is expensive.
if TYPE_CHECKING:
self._properties = cast("Dict[bytes, Optional[bytes]]", properties)
self._properties = cast(dict[bytes, bytes | None], properties)
else:
self._properties = properties
self.text = result
Expand Down Expand Up @@ -462,7 +462,7 @@ def _set_ipv6_addresses_from_cache(self, zc: Zeroconf, now: float_) -> None:
"""Set IPv6 addresses from the cache."""
if TYPE_CHECKING:
self._ipv6_addresses = cast(
"List[ZeroconfIPv6Address]",
list[ZeroconfIPv6Address],
self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_AAAA),
)
else:
Expand All @@ -472,7 +472,7 @@ def _set_ipv4_addresses_from_cache(self, zc: Zeroconf, now: float_) -> None:
"""Set IPv4 addresses from the cache."""
if TYPE_CHECKING:
self._ipv4_addresses = cast(
"List[ZeroconfIPv4Address]",
list[ZeroconfIPv4Address],
self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A),
)
else:
Expand Down Expand Up @@ -724,7 +724,7 @@ def _get_address_records_from_cache_by_type(self, zc: Zeroconf, _type: int_) ->
cache = zc.cache
if TYPE_CHECKING:
records = cast(
"List[DNSAddress]",
list[DNSAddress],
cache.get_all_by_details(self.server_key, _type, _CLASS_IN),
)
else:
Expand Down
3 changes: 2 additions & 1 deletion src/zeroconf/_utils/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
import concurrent.futures
import contextlib
import sys
from typing import Any, Awaitable, Coroutine
from collections.abc import Awaitable, Coroutine
from typing import Any

from .._exceptions import EventLoopBlocked
from ..const import _LOADED_SYSTEM_TIMEOUT
Expand Down
11 changes: 6 additions & 5 deletions src/zeroconf/_utils/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
import socket
import struct
import sys
from typing import Any, Sequence, Tuple, Union, cast
from collections.abc import Sequence
from typing import Any, Union, cast

import ifaddr

Expand All @@ -42,7 +43,7 @@ class InterfaceChoice(enum.Enum):
All = 2


InterfacesType = Union[Sequence[Union[str, int, Tuple[Tuple[str, int, int], int]]], InterfaceChoice]
InterfacesType = Union[Sequence[Union[str, int, tuple[tuple[str, int, int], int]]], InterfaceChoice]


@enum.unique
Expand Down Expand Up @@ -93,7 +94,7 @@ def ip6_to_address_and_index(adapters: list[Any], ip: str) -> tuple[tuple[str, i
# IPv6 addresses are represented as tuples
if isinstance(adapter_ip.ip, tuple) and ipaddress.ip_address(adapter_ip.ip[0]) == ipaddr:
return (
cast(Tuple[str, int, int], adapter_ip.ip),
cast(tuple[str, int, int], adapter_ip.ip),
cast(int, adapter.index),
)

Expand All @@ -106,7 +107,7 @@ def interface_index_to_ip6_address(adapters: list[Any], index: int) -> tuple[str
for adapter_ip in adapter.ips:
# IPv6 addresses are represented as tuples
if isinstance(adapter_ip.ip, tuple):
return cast(Tuple[str, int, int], adapter_ip.ip)
return cast(tuple[str, int, int], adapter_ip.ip)

raise RuntimeError(f"No adapter found for index {index}")

Expand Down Expand Up @@ -340,7 +341,7 @@ def new_respond_socket(
respond_socket = new_socket(
ip_version=(IPVersion.V6Only if is_v6 else IPVersion.V4Only),
apple_p2p=apple_p2p,
bind_addr=cast(Tuple[Tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
bind_addr=cast(tuple[tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
)
if not respond_socket:
return None
Expand Down
3 changes: 2 additions & 1 deletion src/zeroconf/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@

import asyncio
import contextlib
from collections.abc import Awaitable
from types import TracebackType # used in type hints
from typing import Awaitable, Callable
from typing import Callable

from ._core import Zeroconf
from ._dns import DNSQuestionType
Expand Down
8 changes: 5 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ def verify_threads_ended():
@pytest.fixture
def run_isolated():
"""Change the mDNS port to run the test in isolation."""
with patch.object(query_handler, "_MDNS_PORT", 5454), patch.object(
_core, "_MDNS_PORT", 5454
), patch.object(const, "_MDNS_PORT", 5454):
with (
patch.object(query_handler, "_MDNS_PORT", 5454),
patch.object(_core, "_MDNS_PORT", 5454),
patch.object(const, "_MDNS_PORT", 5454),
):
yield


Expand Down
7 changes: 4 additions & 3 deletions tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,10 @@ def test_large_packet_exception_log_handling(self):
# instantiate a zeroconf instance
zc = Zeroconf(interfaces=["127.0.0.1"])

with patch("zeroconf._logger.log.warning") as mocked_log_warn, patch(
"zeroconf._logger.log.debug"
) as mocked_log_debug:
with (
patch("zeroconf._logger.log.warning") as mocked_log_warn,
patch("zeroconf._logger.log.debug") as mocked_log_debug,
):
# now that we have a long packet in our possession, let's verify the
# exception handling.
out = r.DNSOutgoing(const._FLAGS_QR_RESPONSE | const._FLAGS_AA)
Expand Down
5 changes: 3 additions & 2 deletions tests/test_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ def test_guard_against_oversized_packets():

try:
# We are patching to generate an oversized packet
with patch.object(outgoing, "_MAX_MSG_ABSOLUTE", 100000), patch.object(
outgoing, "_MAX_MSG_TYPICAL", 100000
with (
patch.object(outgoing, "_MAX_MSG_ABSOLUTE", 100000),
patch.object(outgoing, "_MAX_MSG_TYPICAL", 100000),
):
over_sized_packet = generated.packets()[0]
assert len(over_sized_packet) > const._MAX_MSG_ABSOLUTE
Expand Down
42 changes: 24 additions & 18 deletions tests/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,19 @@ def test_log_warning_once():
"""Test we only log with warning level once."""
QuietLogger._seen_logs = {}
quiet_logger = QuietLogger()
with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
"zeroconf._logger.log.debug"
) as mock_log_debug:
with (
patch("zeroconf._logger.log.warning") as mock_log_warning,
patch("zeroconf._logger.log.debug") as mock_log_debug,
):
quiet_logger.log_warning_once("the warning")

assert mock_log_warning.mock_calls
assert not mock_log_debug.mock_calls

with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
"zeroconf._logger.log.debug"
) as mock_log_debug:
with (
patch("zeroconf._logger.log.warning") as mock_log_warning,
patch("zeroconf._logger.log.debug") as mock_log_debug,
):
quiet_logger.log_warning_once("the warning")

assert not mock_log_warning.mock_calls
Expand All @@ -48,17 +50,19 @@ def test_log_exception_warning():
"""Test we only log with warning level once."""
QuietLogger._seen_logs = {}
quiet_logger = QuietLogger()
with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
"zeroconf._logger.log.debug"
) as mock_log_debug:
with (
patch("zeroconf._logger.log.warning") as mock_log_warning,
patch("zeroconf._logger.log.debug") as mock_log_debug,
):
quiet_logger.log_exception_warning("the exception warning")

assert mock_log_warning.mock_calls
assert not mock_log_debug.mock_calls

with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
"zeroconf._logger.log.debug"
) as mock_log_debug:
with (
patch("zeroconf._logger.log.warning") as mock_log_warning,
patch("zeroconf._logger.log.debug") as mock_log_debug,
):
quiet_logger.log_exception_warning("the exception warning")

assert not mock_log_warning.mock_calls
Expand All @@ -85,17 +89,19 @@ def test_log_exception_once():
QuietLogger._seen_logs = {}
quiet_logger = QuietLogger()
exc = Exception()
with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
"zeroconf._logger.log.debug"
) as mock_log_debug:
with (
patch("zeroconf._logger.log.warning") as mock_log_warning,
patch("zeroconf._logger.log.debug") as mock_log_debug,
):
quiet_logger.log_exception_once(exc, "the exceptional exception warning")

assert mock_log_warning.mock_calls
assert not mock_log_debug.mock_calls

with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
"zeroconf._logger.log.debug"
) as mock_log_debug:
with (
patch("zeroconf._logger.log.warning") as mock_log_warning,
patch("zeroconf._logger.log.debug") as mock_log_debug,
):
quiet_logger.log_exception_once(exc, "the exceptional exception warning")

assert not mock_log_warning.mock_calls
Expand Down
Loading