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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.6, 3.7, 3.8, 3.9, "3.10", "pypy-3.6", "pypy-3.7"]
python-version: [3.7, 3.8, 3.9, "3.10", "pypy-3.7"]
include:
- os: ubuntu-latest
venvcmd: . env/bin/activate
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ Compared to some other Zeroconf/Bonjour/Avahi Python packages, python-zeroconf:
Python compatibility
--------------------

* CPython 3.6+
* PyPy3 7.2+
* CPython 3.7+
* PyPy3.7 7.3+

Versioning
----------
Expand Down
19 changes: 9 additions & 10 deletions tests/services/test_browser.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


""" Unit tests for zeroconf._services.browser. """
Expand Down Expand Up @@ -682,7 +681,7 @@ def on_service_state_change(zeroconf, service_type, state_change, name):

info_service = ServiceInfo(
type_,
'%s.%s' % (name, type_),
f'{name}.{type_}',
80,
0,
0,
Expand Down Expand Up @@ -902,7 +901,7 @@ def test_group_ptr_queries_with_known_answers():
now = current_time_millis()
for i in range(120):
name = f"_hap{i}._tcp._local."
questions_with_known_answers[DNSQuestion(name, const._TYPE_PTR, const._CLASS_IN)] = set(
questions_with_known_answers[DNSQuestion(name, const._TYPE_PTR, const._CLASS_IN)] = {
DNSPointer(
name,
const._TYPE_PTR,
Expand All @@ -911,7 +910,7 @@ def test_group_ptr_queries_with_known_answers():
f"zoo{counter}.{name}",
)
for counter in range(i)
)
}
outs = _services_browser._group_ptr_queries_with_known_answers(now, True, questions_with_known_answers)
for out in outs:
packets = out.packets()
Expand All @@ -937,7 +936,7 @@ async def test_generate_service_query_suppress_duplicate_questions():
10000,
f'known-to-other.{name}',
)
other_known_answers = set([answer])
other_known_answers = {answer}
zc.question_history.add_question_at_time(question, now, other_known_answers)
assert zc.question_history.suppresses(question, now, other_known_answers)

Expand Down Expand Up @@ -976,16 +975,16 @@ async def test_generate_service_query_suppress_duplicate_questions():
@pytest.mark.asyncio
async def test_query_scheduler():
delay = const._BROWSER_TIME
types_ = set(["_hap._tcp.local.", "_http._tcp.local."])
types_ = {"_hap._tcp.local.", "_http._tcp.local."}
query_scheduler = _services_browser.QueryScheduler(types_, delay, (0, 0))

now = current_time_millis()
query_scheduler.start(now)

# Test query interval is increasing
assert query_scheduler.millis_to_wait(now - 1) == 1
assert query_scheduler.millis_to_wait(now) is 0
assert query_scheduler.millis_to_wait(now + 1) is 0
assert query_scheduler.millis_to_wait(now) == 0
assert query_scheduler.millis_to_wait(now + 1) == 0

assert set(query_scheduler.process_ready_types(now)) == types_
assert set(query_scheduler.process_ready_types(now)) == set()
Expand Down Expand Up @@ -1013,8 +1012,8 @@ async def test_query_scheduler():
assert set(query_scheduler.process_ready_types(now + delay * 15)) == set()

# Test if we reschedule 1 second later... and its ready for processing
assert set(query_scheduler.process_ready_types(now + delay * 16)) == set(["_hap._tcp.local."])
assert set(query_scheduler.process_ready_types(now + delay * 16)) == {"_hap._tcp.local."}
assert query_scheduler.millis_to_wait(now) == pytest.approx(delay * 31, 0.00001)
assert set(query_scheduler.process_ready_types(now + delay * 20)) == set()

assert set(query_scheduler.process_ready_types(now + delay * 31)) == set(["_http._tcp.local."])
assert set(query_scheduler.process_ready_types(now + delay * 31)) == {"_http._tcp.local."}
17 changes: 8 additions & 9 deletions tests/services/test_info.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


""" Unit tests for zeroconf._services.info. """
Expand Down Expand Up @@ -607,7 +606,7 @@ def test_filter_address_by_type_from_service_info():
desc = {'path': '/~paulsm/'}
type_ = "_homeassistant._tcp.local."
name = "MyTestHome"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"
ipv4 = socket.inet_aton("10.0.1.2")
ipv6 = socket.inet_pton(socket.AF_INET6, "2001:db8::1")
info = ServiceInfo(type_, registration_name, 80, 0, 0, desc, "ash-2.local.", addresses=[ipv4, ipv6])
Expand All @@ -627,7 +626,7 @@ def test_changing_name_updates_serviceinfo_key():
name = "MyTestHome"
info_service = ServiceInfo(
type_,
'%s.%s' % (name, type_),
f'{name}.{type_}',
80,
0,
0,
Expand All @@ -649,7 +648,7 @@ def test_serviceinfo_address_updates():
with pytest.raises(TypeError):
info_service = ServiceInfo(
type_,
'%s.%s' % (name, type_),
f'{name}.{type_}',
80,
0,
0,
Expand All @@ -661,7 +660,7 @@ def test_serviceinfo_address_updates():

info_service = ServiceInfo(
type_,
'%s.%s' % (name, type_),
f'{name}.{type_}',
80,
0,
0,
Expand All @@ -680,12 +679,12 @@ def test_serviceinfo_accepts_bytes_or_string_dict():
addresses = [socket.inet_aton("10.0.1.2")]
server_name = "ash-2.local."
info_service = ServiceInfo(
type_, '%s.%s' % (name, type_), 80, 0, 0, {b'path': b'/~paulsm/'}, server_name, addresses=addresses
type_, f'{name}.{type_}', 80, 0, 0, {b'path': b'/~paulsm/'}, server_name, addresses=addresses
)
assert info_service.dns_text().text == b'\x0epath=/~paulsm/'
info_service = ServiceInfo(
type_,
'%s.%s' % (name, type_),
f'{name}.{type_}',
80,
0,
0,
Expand All @@ -696,7 +695,7 @@ def test_serviceinfo_accepts_bytes_or_string_dict():
assert info_service.dns_text().text == b'\x0epath=/~paulsm/'
info_service = ServiceInfo(
type_,
'%s.%s' % (name, type_),
f'{name}.{type_}',
80,
0,
0,
Expand All @@ -707,7 +706,7 @@ def test_serviceinfo_accepts_bytes_or_string_dict():
assert info_service.dns_text().text == b'\x0epath=/~paulsm/'
info_service = ServiceInfo(
type_,
'%s.%s' % (name, type_),
f'{name}.{type_}',
80,
0,
0,
Expand Down
15 changes: 7 additions & 8 deletions tests/services/test_registry.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


"""Unit tests for zeroconf._services.registry."""
Expand All @@ -15,7 +14,7 @@ class TestServiceRegistry(unittest.TestCase):
def test_only_register_once(self):
type_ = "_test-srvc-type._tcp.local."
name = "xxxyyy"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"

desc = {'path': '/~paulsm/'}
info = ServiceInfo(
Expand All @@ -32,8 +31,8 @@ def test_register_same_server(self):
type_ = "_test-srvc-type._tcp.local."
name = "xxxyyy"
name2 = "xxxyyy2"
registration_name = "%s.%s" % (name, type_)
registration_name2 = "%s.%s" % (name2, type_)
registration_name = f"{name}.{type_}"
registration_name2 = f"{name2}.{type_}"

desc = {'path': '/~paulsm/'}
info = ServiceInfo(
Expand Down Expand Up @@ -61,7 +60,7 @@ def test_unregister_multiple_times(self):
"""
type_ = "_test-srvc-type._tcp.local."
name = "xxxyyy"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"

desc = {'path': '/~paulsm/'}
info = ServiceInfo(
Expand All @@ -77,7 +76,7 @@ def test_unregister_multiple_times(self):
def test_lookups(self):
type_ = "_test-srvc-type._tcp.local."
name = "xxxyyy"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"

desc = {'path': '/~paulsm/'}
info = ServiceInfo(
Expand All @@ -96,7 +95,7 @@ def test_lookups(self):
def test_lookups_upper_case_by_lower_case(self):
type_ = "_test-SRVC-type._tcp.local."
name = "Xxxyyy"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"

desc = {'path': '/~paulsm/'}
info = ServiceInfo(
Expand All @@ -115,7 +114,7 @@ def test_lookups_upper_case_by_lower_case(self):
def test_lookups_lower_case_by_upper_case(self):
type_ = "_test-srvc-type._tcp.local."
name = "xxxyyy"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"

desc = {'path': '/~paulsm/'}
info = ServiceInfo(
Expand Down
11 changes: 5 additions & 6 deletions tests/services/test_types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


"""Unit tests for zeroconf._services.types."""
Expand Down Expand Up @@ -36,7 +35,7 @@ def test_integration_with_listener(self):

type_ = "_test-listen-type._tcp.local."
name = "xxxyyy"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"

zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1'])
desc = {'path': '/~paulsm/'}
Expand Down Expand Up @@ -72,7 +71,7 @@ def test_integration_with_listener_v6_records(self):

type_ = "_test-listenv6rec-type._tcp.local."
name = "xxxyyy"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"
addr = "2606:2800:220:1:248:1893:25c8:1946" # example.com

zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1'])
Expand Down Expand Up @@ -109,7 +108,7 @@ def test_integration_with_listener_ipv6(self):

type_ = "_test-listenv6ip-type._tcp.local."
name = "xxxyyy"
registration_name = "%s.%s" % (name, type_)
registration_name = f"{name}.{type_}"
addr = "2606:2800:220:1:248:1893:25c8:1946" # example.com

zeroconf_registrar = Zeroconf(ip_version=r.IPVersion.V6Only)
Expand Down Expand Up @@ -145,8 +144,8 @@ def test_integration_with_subtype_and_listener(self):
type_ = "_listen._tcp.local."
name = "xxxyyy"
# Note: discovery returns only DNS-SD type not subtype
discovery_type = "%s.%s" % (subtype_, type_)
registration_name = "%s.%s" % (name, type_)
discovery_type = f"{subtype_}.{type_}"
registration_name = f"{name}.{type_}"

zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1'])
desc = {'path': '/~paulsm/'}
Expand Down
1 change: 0 additions & 1 deletion tests/utils/test_asyncio.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


"""Unit tests for zeroconf._utils.asyncio."""
Expand Down
1 change: 0 additions & 1 deletion tests/utils/test_name.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


"""Unit tests for zeroconf._utils.name."""
Expand Down
3 changes: 1 addition & 2 deletions tests/utils/test_net.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-


"""Unit tests for zeroconf._utils.net."""
Expand Down Expand Up @@ -87,7 +86,7 @@ def test_normalize_interface_choice_errors():
def test_add_multicast_member_socket_errors(errno, expected_result):
"""Test we handle socket errors when adding multicast members."""
if errno:
setsockopt_mock = unittest.mock.Mock(side_effect=OSError(errno, "Error: {}".format(errno)))
setsockopt_mock = unittest.mock.Mock(side_effect=OSError(errno, f"Error: {errno}"))
else:
setsockopt_mock = unittest.mock.Mock()
fileno_mock = unittest.mock.PropertyMock(return_value=10)
Expand Down
11 changes: 5 additions & 6 deletions zeroconf/_services/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
SignalRegistrationInterface,
)
from .._updates import RecordUpdate, RecordUpdateListener
from .._utils.asyncio import get_best_available_queue
from .._utils.name import service_type_name
from .._utils.time import current_time_millis, millis_to_seconds
from ..const import (
Expand Down Expand Up @@ -145,11 +144,11 @@ def generate_service_query(
for type_ in types_:
question = DNSQuestion(type_, _TYPE_PTR, _CLASS_IN)
question.unicast = qu_question
known_answers = set(
known_answers = {
cast(DNSPointer, record)
for record in zc.cache.get_all_by_details(type_, _TYPE_PTR, _CLASS_IN)
if not record.is_stale(now)
)
}
if not qu_question and zc.question_history.suppresses(
question, now, cast(Set[DNSRecord], known_answers)
):
Expand Down Expand Up @@ -293,7 +292,7 @@ def __init__(
self._pending_handlers: OrderedDict[Tuple[str, str], ServiceStateChange] = OrderedDict()
self._service_state_changed = Signal()
self.query_scheduler = QueryScheduler(self.types, delay, _FIRST_QUERY_DELAY_RANDOM_INTERVAL)
self.queue: Optional[queue.Queue] = None
self.queue: Optional[queue.SimpleQueue] = None
self.done = False
self._first_request: bool = True
self._next_send_timer: Optional[asyncio.TimerHandle] = None
Expand Down Expand Up @@ -511,11 +510,11 @@ def __init__(
# Add the queue before the listener is installed in _setup
# to ensure that events run in the dedicated thread and do
# not block the event loop
self.queue = get_best_available_queue()
self.queue = queue.SimpleQueue()
self.daemon = True
self.start()
zc.loop.call_soon_threadsafe(self._async_start)
self.name = "zeroconf-ServiceBrowser-%s-%s" % (
self.name = "zeroconf-ServiceBrowser-{}-{}".format(
'-'.join([type_[:-7] for type_ in self.types]),
getattr(self, 'native_id', self.ident),
)
Expand Down
Loading