Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-zeroconf for openSUSE:Factory 
checked in at 2022-01-10 23:53:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-zeroconf (Old)
 and      /work/SRC/openSUSE:Factory/.python-zeroconf.new.1892 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-zeroconf"

Mon Jan 10 23:53:19 2022 rev:29 rq:945269 version:0.38.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-zeroconf/python-zeroconf.changes  
2021-12-02 02:25:12.420617506 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-zeroconf.new.1892/python-zeroconf.changes    
    2022-01-10 23:53:46.276813170 +0100
@@ -1,0 +2,9 @@
+Mon Jan  3 10:29:30 UTC 2022 - Dirk M??ller <dmuel...@suse.com>
+
+- update to 0.38.1:
+  * Dropped Python 3.6 support
+  * Handle Service types that end with another service type
+  * Improve performance of query scheduler
+  * Avoid linear type searches in ServiceBrowsers 
+
+-------------------------------------------------------------------

Old:
----
  python-zeroconf-0.37.0.obscpio

New:
----
  python-zeroconf-0.38.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-zeroconf.spec ++++++
--- /var/tmp/diff_new_pack.494Uhp/_old  2022-01-10 23:53:47.296814064 +0100
+++ /var/tmp/diff_new_pack.494Uhp/_new  2022-01-10 23:53:47.300814068 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-zeroconf
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,8 +18,9 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
+%define skip_python36 1
 Name:           python-zeroconf
-Version:        0.37.0
+Version:        0.38.1
 Release:        0
 Summary:        Pure Python Multicast DNS Service Discovery Library 
(Bonjour/Avahi compatible)
 License:        LGPL-2.0-only

++++++ _service ++++++
--- /var/tmp/diff_new_pack.494Uhp/_old  2022-01-10 23:53:47.328814092 +0100
+++ /var/tmp/diff_new_pack.494Uhp/_new  2022-01-10 23:53:47.332814095 +0100
@@ -2,8 +2,9 @@
   <service name="obs_scm" mode="disabled">
     <param name="url">https://github.com/jstasiak/python-zeroconf</param>
     <param name="scm">git</param>
-    <param name="revision">0.37.0</param>
-    <param name="version">0.37.0</param>
+    <param name="revision">0.38.1</param>
+    <param name="versionformat">@PARENT_TAG@</param>
+    <param name="versionrewrite-pattern">(.*)</param>
   </service>
   <service name="set_version" mode="disabled"/>
   <service mode="buildtime" name="tar" />

++++++ python-zeroconf-0.37.0.obscpio -> python-zeroconf-0.38.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/.github/workflows/ci.yml 
new/python-zeroconf-0.38.1/.github/workflows/ci.yml
--- old/python-zeroconf-0.37.0/.github/workflows/ci.yml 2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/.github/workflows/ci.yml 2021-12-24 
03:47:53.000000000 +0100
@@ -14,7 +14,7 @@
     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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/README.rst 
new/python-zeroconf-0.38.1/README.rst
--- old/python-zeroconf-0.37.0/README.rst       2021-11-18 21:30:53.000000000 
+0100
+++ new/python-zeroconf-0.38.1/README.rst       2021-12-24 03:47:53.000000000 
+0100
@@ -44,8 +44,8 @@
 Python compatibility
 --------------------
 
-* CPython 3.6+
-* PyPy3 7.2+
+* CPython 3.7+
+* PyPy3.7 7.3+
 
 Versioning
 ----------
@@ -138,6 +138,21 @@
 Changelog
 =========
 
+0.38.1
+======
+
+* Improve performance of query scheduler (#1043) @bdraco
+* Avoid linear type searches in ServiceBrowsers (#1044) @bdraco
+
+0.38.0
+======
+
+* Handle Service types that end with another service type (#1041) @apworks1
+
+Backwards incompatible:
+
+* Dropped Python 3.6 support (#1009) @bdraco
+
 0.37.0
 ======
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/setup.cfg 
new/python-zeroconf-0.38.1/setup.cfg
--- old/python-zeroconf-0.37.0/setup.cfg        2021-11-18 21:30:53.000000000 
+0100
+++ new/python-zeroconf-0.38.1/setup.cfg        2021-12-24 03:47:53.000000000 
+0100
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.37.0
+current_version = 0.38.1
 commit = True
 tag = True
 tag_name = {new_version}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-zeroconf-0.37.0/tests/services/test_browser.py 
new/python-zeroconf-0.38.1/tests/services/test_browser.py
--- old/python-zeroconf-0.37.0/tests/services/test_browser.py   2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/services/test_browser.py   2021-12-24 
03:47:53.000000000 +0100
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 
 
 """ Unit tests for zeroconf._services.browser. """
@@ -682,7 +681,7 @@
 
     info_service = ServiceInfo(
         type_,
-        '%s.%s' % (name, type_),
+        f'{name}.{type_}',
         80,
         0,
         0,
@@ -902,7 +901,7 @@
     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,
@@ -911,7 +910,7 @@
                 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()
@@ -937,7 +936,7 @@
         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)
 
@@ -976,7 +975,7 @@
 @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()
@@ -984,8 +983,8 @@
 
     # 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()
@@ -1013,8 +1012,91 @@
     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."}
+
+
+def test_service_browser_matching():
+    """Test that the ServiceBrowser matching does not match partial names."""
+
+    # instantiate a zeroconf instance
+    zc = Zeroconf(interfaces=['127.0.0.1'])
+    # start a browser
+    type_ = "_http._tcp.local."
+    registration_name = "xxxyyy.%s" % type_
+    not_match_type_ = "_asustor-looksgood_http._tcp.local."
+    not_match_registration_name = "xxxyyy.%s" % not_match_type_
+    callbacks = []
+
+    class MyServiceListener(r.ServiceListener):
+        def add_service(self, zc, type_, name) -> None:
+            nonlocal callbacks
+            if name == registration_name:
+                callbacks.append(("add", type_, name))
+
+        def remove_service(self, zc, type_, name) -> None:
+            nonlocal callbacks
+            if name == registration_name:
+                callbacks.append(("remove", type_, name))
+
+        def update_service(self, zc, type_, name) -> None:
+            nonlocal callbacks
+            if name == registration_name:
+                callbacks.append(("update", type_, name))
+
+    listener = MyServiceListener()
+
+    browser = r.ServiceBrowser(zc, type_, None, listener)
+
+    desc = {'path': '/~paulsm/'}
+    address_parsed = "10.0.1.2"
+    address = socket.inet_aton(address_parsed)
+    info = ServiceInfo(type_, registration_name, 80, 0, 0, desc, 
"ash-2.local.", addresses=[address])
+    should_not_match = ServiceInfo(
+        not_match_type_, not_match_registration_name, 80, 0, 0, desc, 
"ash-2.local.", addresses=[address]
+    )
+
+    def mock_incoming_msg(records) -> r.DNSIncoming:
+        generated = r.DNSOutgoing(const._FLAGS_QR_RESPONSE)
+        for record in records:
+            generated.add_answer_at_time(record, 0)
+        return r.DNSIncoming(generated.packets()[0])
+
+    _inject_response(
+        zc,
+        mock_incoming_msg([info.dns_pointer(), info.dns_service(), 
info.dns_text(), *info.dns_addresses()]),
+    )
+    _inject_response(
+        zc,
+        mock_incoming_msg(
+            [
+                should_not_match.dns_pointer(),
+                should_not_match.dns_service(),
+                should_not_match.dns_text(),
+                *should_not_match.dns_addresses(),
+            ]
+        ),
+    )
+    time.sleep(0.2)
+    info.port = 400
+    _inject_response(
+        zc,
+        mock_incoming_msg([info.dns_service()]),
+    )
+    should_not_match.port = 400
+    _inject_response(
+        zc,
+        mock_incoming_msg([should_not_match.dns_service()]),
+    )
+    time.sleep(0.2)
+
+    assert callbacks == [
+        ('add', type_, registration_name),
+        ('update', type_, registration_name),
+    ]
+    browser.cancel()
+
+    zc.close()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/tests/services/test_info.py 
new/python-zeroconf-0.38.1/tests/services/test_info.py
--- old/python-zeroconf-0.37.0/tests/services/test_info.py      2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/services/test_info.py      2021-12-24 
03:47:53.000000000 +0100
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 
 
 """ Unit tests for zeroconf._services.info. """
@@ -607,7 +606,7 @@
     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])
@@ -627,7 +626,7 @@
     name = "MyTestHome"
     info_service = ServiceInfo(
         type_,
-        '%s.%s' % (name, type_),
+        f'{name}.{type_}',
         80,
         0,
         0,
@@ -649,7 +648,7 @@
     with pytest.raises(TypeError):
         info_service = ServiceInfo(
             type_,
-            '%s.%s' % (name, type_),
+            f'{name}.{type_}',
             80,
             0,
             0,
@@ -661,7 +660,7 @@
 
     info_service = ServiceInfo(
         type_,
-        '%s.%s' % (name, type_),
+        f'{name}.{type_}',
         80,
         0,
         0,
@@ -680,12 +679,12 @@
     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,
@@ -696,7 +695,7 @@
     assert info_service.dns_text().text == b'\x0epath=/~paulsm/'
     info_service = ServiceInfo(
         type_,
-        '%s.%s' % (name, type_),
+        f'{name}.{type_}',
         80,
         0,
         0,
@@ -707,7 +706,7 @@
     assert info_service.dns_text().text == b'\x0epath=/~paulsm/'
     info_service = ServiceInfo(
         type_,
-        '%s.%s' % (name, type_),
+        f'{name}.{type_}',
         80,
         0,
         0,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-zeroconf-0.37.0/tests/services/test_registry.py 
new/python-zeroconf-0.38.1/tests/services/test_registry.py
--- old/python-zeroconf-0.37.0/tests/services/test_registry.py  2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/services/test_registry.py  2021-12-24 
03:47:53.000000000 +0100
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 
 
 """Unit tests for zeroconf._services.registry."""
@@ -15,7 +14,7 @@
     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(
@@ -32,8 +31,8 @@
         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(
@@ -61,7 +60,7 @@
         """
         type_ = "_test-srvc-type._tcp.local."
         name = "xxxyyy"
-        registration_name = "%s.%s" % (name, type_)
+        registration_name = f"{name}.{type_}"
 
         desc = {'path': '/~paulsm/'}
         info = ServiceInfo(
@@ -77,7 +76,7 @@
     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(
@@ -96,7 +95,7 @@
     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(
@@ -115,7 +114,7 @@
     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(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/tests/services/test_types.py 
new/python-zeroconf-0.38.1/tests/services/test_types.py
--- old/python-zeroconf-0.37.0/tests/services/test_types.py     2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/services/test_types.py     2021-12-24 
03:47:53.000000000 +0100
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 
 
 """Unit tests for zeroconf._services.types."""
@@ -36,7 +35,7 @@
 
         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/'}
@@ -72,7 +71,7 @@
 
         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'])
@@ -109,7 +108,7 @@
 
         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)
@@ -145,8 +144,8 @@
         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/'}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/tests/test_asyncio.py 
new/python-zeroconf-0.38.1/tests/test_asyncio.py
--- old/python-zeroconf-0.37.0/tests/test_asyncio.py    2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/test_asyncio.py    2021-12-24 
03:47:53.000000000 +0100
@@ -923,7 +923,7 @@
                 # Increase simulated time shift by 1/4 of the TTL in seconds
                 time_offset += expected_ttl / 4
                 now = _new_current_time_millis()
-                browser.reschedule_type(type_, now)
+                browser.reschedule_type(type_, now, now)
                 sleep_count += 1
                 await asyncio.wait_for(got_query.wait(), 1)
                 got_query.clear()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/tests/test_exceptions.py 
new/python-zeroconf-0.38.1/tests/test_exceptions.py
--- old/python-zeroconf-0.37.0/tests/test_exceptions.py 2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/test_exceptions.py 2021-12-24 
03:47:53.000000000 +0100
@@ -76,6 +76,8 @@
 
     def test_good_instance_names(self):
         assert r.service_type_name('.._x._tcp.local.') == '_x._tcp.local.'
+        assert r.service_type_name('x.y._http._tcp.local.') == 
'_http._tcp.local.'
+        assert r.service_type_name('1.2.3._mqtt._tcp.local.') == 
'_mqtt._tcp.local.'
         assert r.service_type_name('x.sub._http._tcp.local.') == 
'_http._tcp.local.'
         assert (
             
r.service_type_name('6d86f882b90facee9170ad3439d72a4d6ee9f511._zget._http._tcp.local.')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/tests/test_services.py 
new/python-zeroconf-0.38.1/tests/test_services.py
--- old/python-zeroconf-0.37.0/tests/test_services.py   2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/test_services.py   2021-12-24 
03:47:53.000000000 +0100
@@ -38,12 +38,13 @@
 class ListenerTest(unittest.TestCase):
     def test_integration_with_listener_class(self):
 
+        sub_service_added = Event()
         service_added = Event()
         service_removed = Event()
-        service_updated = Event()
-        service_updated2 = Event()
+        sub_service_updated = Event()
+        duplicate_service_added = Event()
 
-        subtype_name = "My special Subtype"
+        subtype_name = "_printer"
         type_ = "_http._tcp.local."
         subtype = subtype_name + "._sub." + type_
         name = "UPPERxxxyyy??????"
@@ -58,21 +59,32 @@
                 service_removed.set()
 
             def update_service(self, zeroconf, type, name):
-                service_updated2.set()
+                pass
+
+        class DuplicateListener(r.ServiceListener):
+            def add_service(self, zeroconf, type, name):
+                duplicate_service_added.set()
+
+            def remove_service(self, zeroconf, type, name):
+                pass
+
+            def update_service(self, zeroconf, type, name):
+                pass
 
         class MySubListener(r.ServiceListener):
             def add_service(self, zeroconf, type, name):
+                sub_service_added.set()
                 pass
 
             def remove_service(self, zeroconf, type, name):
                 pass
 
             def update_service(self, zeroconf, type, name):
-                service_updated.set()
+                sub_service_updated.set()
 
         listener = MyListener()
         zeroconf_browser = Zeroconf(interfaces=['127.0.0.1'])
-        zeroconf_browser.add_service_listener(subtype, listener)
+        zeroconf_browser.add_service_listener(type_, listener)
 
         properties = dict(
             prop_none=None,
@@ -107,6 +119,11 @@
                 # short pause to allow multicast timers to expire
                 time.sleep(3)
 
+                zeroconf_browser.add_service_listener(type_, 
DuplicateListener())
+                duplicate_service_added.wait(
+                    1
+                )  # Ensure a listener for the same type calls back right away 
from cache
+
                 # clear the answer cache to force query
                 _clear_cache(zeroconf_browser)
 
@@ -160,7 +177,9 @@
 
                 # test TXT record update
                 sublistener = MySubListener()
-                zeroconf_browser.add_service_listener(registration_name, 
sublistener)
+
+                zeroconf_browser.add_service_listener(subtype, sublistener)
+
                 properties['prop_blank'] = b'an updated string'
                 desc.update(properties)
                 info_service = ServiceInfo(
@@ -174,8 +193,9 @@
                     addresses=[socket.inet_aton("10.0.1.2")],
                 )
                 zeroconf_registrar.update_service(info_service)
-                service_updated.wait(1)
-                assert service_updated.is_set()
+
+                sub_service_added.wait(1)  # we cleared the cache above
+                assert sub_service_added.is_set()
 
                 info = zeroconf_browser.get_service_info(type_, 
registration_name)
                 assert info is not None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/tests/utils/test_asyncio.py 
new/python-zeroconf-0.38.1/tests/utils/test_asyncio.py
--- old/python-zeroconf-0.37.0/tests/utils/test_asyncio.py      2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/utils/test_asyncio.py      2021-12-24 
03:47:53.000000000 +0100
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 
 
 """Unit tests for zeroconf._utils.asyncio."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/tests/utils/test_name.py 
new/python-zeroconf-0.38.1/tests/utils/test_name.py
--- old/python-zeroconf-0.37.0/tests/utils/test_name.py 2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/utils/test_name.py 2021-12-24 
03:47:53.000000000 +0100
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 
 
 """Unit tests for zeroconf._utils.name."""
@@ -24,3 +23,25 @@
         
nameutils.service_type_name(f"{long_name}._tivo-videostream._tcp.local.")
     with pytest.raises(BadTypeInNameException):
         
nameutils.service_type_name(f"{long_name}._tivo-videostream._tcp.local.", 
strict=False)
+
+
+def test_possible_types():
+    """Test possible types from name."""
+    assert nameutils.possible_types('.') == set()
+    assert nameutils.possible_types('local.') == set()
+    assert nameutils.possible_types('_tcp.local.') == set()
+    assert nameutils.possible_types('_test-srvc-type._tcp.local.') == 
{'_test-srvc-type._tcp.local.'}
+    assert nameutils.possible_types('_any._tcp.local.') == {'_any._tcp.local.'}
+    assert nameutils.possible_types('.._x._tcp.local.') == {'_x._tcp.local.'}
+    assert nameutils.possible_types('x.y._http._tcp.local.') == 
{'_http._tcp.local.'}
+    assert nameutils.possible_types('1.2.3._mqtt._tcp.local.') == 
{'_mqtt._tcp.local.'}
+    assert nameutils.possible_types('x.sub._http._tcp.local.') == 
{'_http._tcp.local.'}
+    assert 
nameutils.possible_types('6d86f882b90facee9170ad3439d72a4d6ee9f511._zget._http._tcp.local.')
 == {
+        '_http._tcp.local.',
+        '_zget._http._tcp.local.',
+    }
+    assert nameutils.possible_types('my._printer._sub._http._tcp.local.') == {
+        '_http._tcp.local.',
+        '_sub._http._tcp.local.',
+        '_printer._sub._http._tcp.local.',
+    }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/tests/utils/test_net.py 
new/python-zeroconf-0.38.1/tests/utils/test_net.py
--- old/python-zeroconf-0.37.0/tests/utils/test_net.py  2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/tests/utils/test_net.py  2021-12-24 
03:47:53.000000000 +0100
@@ -1,5 +1,4 @@
 #!/usr/bin/env python
-# -*- coding: utf-8 -*-
 
 
 """Unit tests for zeroconf._utils.net."""
@@ -87,7 +86,7 @@
 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)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/zeroconf/__init__.py 
new/python-zeroconf-0.38.1/zeroconf/__init__.py
--- old/python-zeroconf-0.37.0/zeroconf/__init__.py     2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/zeroconf/__init__.py     2021-12-24 
03:47:53.000000000 +0100
@@ -79,7 +79,7 @@
 
 __author__ = 'Paul Scott-Murphy, William McBrine'
 __maintainer__ = 'Jakub Stasiak <ja...@stasiak.at>'
-__version__ = '0.37.0'
+__version__ = '0.38.1'
 __license__ = 'LGPL'
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/zeroconf/_handlers.py 
new/python-zeroconf-0.38.1/zeroconf/_handlers.py
--- old/python-zeroconf-0.37.0/zeroconf/_handlers.py    2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/zeroconf/_handlers.py    2021-12-24 
03:47:53.000000000 +0100
@@ -326,7 +326,7 @@
             self._add_address_answers(question.name, answer_set, 
known_answers, now, type_)
 
         if type_ in (_TYPE_SRV, _TYPE_TXT, _TYPE_ANY):
-            service = self.registry.async_get_info_name(question.name)  # 
type: ignore
+            service = self.registry.async_get_info_name(question.name)
             if service is not None:
                 if type_ in (_TYPE_SRV, _TYPE_ANY):
                     # Add recommended additional answers according to
@@ -515,12 +515,12 @@
         This function must be run from the event loop.
         """
         now = current_time_millis()
-        records: List[RecordUpdate] = []
-        for question in questions:
-            for record in self.cache.async_entries_with_name(question.name):
-                if not record.is_expired(now) and question.answered_by(record):
-                    records.append(RecordUpdate(record, None))
-
+        records: List[RecordUpdate] = [
+            RecordUpdate(record, None)
+            for question in questions
+            for record in self.cache.async_entries_with_name(question.name)
+            if not record.is_expired(now) and question.answered_by(record)
+        ]
         if not records:
             return
         listener.async_update_records(self.zc, now, records)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/zeroconf/_services/browser.py 
new/python-zeroconf-0.38.1/zeroconf/_services/browser.py
--- old/python-zeroconf-0.37.0/zeroconf/_services/browser.py    2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/zeroconf/_services/browser.py    2021-12-24 
03:47:53.000000000 +0100
@@ -26,7 +26,7 @@
 import threading
 import warnings
 from collections import OrderedDict
-from typing import Callable, Dict, List, Optional, Set, TYPE_CHECKING, Tuple, 
Union, cast
+from typing import Callable, Dict, Iterable, List, Optional, Set, 
TYPE_CHECKING, Tuple, Union, cast
 
 from .._dns import DNSAddress, DNSPointer, DNSQuestion, DNSQuestionType, 
DNSRecord
 from .._logger import log
@@ -38,8 +38,7 @@
     SignalRegistrationInterface,
 )
 from .._updates import RecordUpdate, RecordUpdateListener
-from .._utils.asyncio import get_best_available_queue
-from .._utils.name import service_type_name
+from .._utils.name import possible_types, service_type_name
 from .._utils.time import current_time_millis, millis_to_seconds
 from ..const import (
     _BROWSER_BACKOFF_LIMIT,
@@ -145,11 +144,11 @@
     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)
         ):
@@ -293,7 +292,7 @@
         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
@@ -325,9 +324,9 @@
     def service_state_changed(self) -> SignalRegistrationInterface:
         return self._service_state_changed.registration_interface
 
-    def _record_matching_type(self, record: DNSRecord) -> Optional[str]:
-        """Return the type if the record matches one of the types we are 
browsing."""
-        return next((type_ for type_ in self.types if 
record.name.endswith(type_)), None)
+    def _names_matching_types(self, names: Iterable[str]) -> List[Tuple[str, 
str]]:
+        """Return the type and name for records matching the types we are 
browsing."""
+        return [(type_, name) for name in names for type_ in 
self.types.intersection(possible_types(name))]
 
     def _enqueue_callback(
         self,
@@ -353,14 +352,13 @@
     ) -> None:
         """Process a single record update from a batch of updates."""
         if isinstance(record, DNSPointer):
-            if record.name not in self.types:
-                return
-            if old_record is None:
-                self._enqueue_callback(ServiceStateChange.Added, record.name, 
record.alias)
-            elif record.is_expired(now):
-                self._enqueue_callback(ServiceStateChange.Removed, 
record.name, record.alias)
-            else:
-                self.reschedule_type(record.name, 
record.get_expiration_time(_EXPIRE_REFRESH_TIME_PERCENT))
+            for type_ in self.types.intersection(possible_types(record.name)):
+                if old_record is None:
+                    self._enqueue_callback(ServiceStateChange.Added, type_, 
record.alias)
+                elif record.is_expired(now):
+                    self._enqueue_callback(ServiceStateChange.Removed, type_, 
record.alias)
+                else:
+                    self.reschedule_type(type_, now, 
record.get_expiration_time(_EXPIRE_REFRESH_TIME_PERCENT))
             return
 
         # If its expired or already exists in the cache it cannot be updated.
@@ -369,17 +367,14 @@
 
         if isinstance(record, DNSAddress):
             # Iterate through the DNSCache and callback any services that use 
this address
-            for service in 
self.zc.cache.async_entries_with_server(record.name):
-                type_ = self._record_matching_type(service)
-                if type_:
-                    self._enqueue_callback(ServiceStateChange.Updated, type_, 
service.name)
-                    break
-
+            for type_, name in self._names_matching_types(
+                {service.name for service in 
self.zc.cache.async_entries_with_server(record.name)}
+            ):
+                self._enqueue_callback(ServiceStateChange.Updated, type_, name)
             return
 
-        type_ = self._record_matching_type(record)
-        if type_:
-            self._enqueue_callback(ServiceStateChange.Updated, type_, 
record.name)
+        for type_, name in self._names_matching_types((record.name,)):
+            self._enqueue_callback(ServiceStateChange.Updated, type_, name)
 
     def async_update_records(self, zc: 'Zeroconf', now: float, records: 
List[RecordUpdate]) -> None:
         """Callback invoked by Zeroconf when new information arrives.
@@ -431,9 +426,8 @@
         self._cancel_send_timer()
         self.zc.async_remove_listener(self)
 
-    def _generate_ready_queries(self, first_request: bool) -> 
List[DNSOutgoing]:
+    def _generate_ready_queries(self, first_request: bool, now: float) -> 
List[DNSOutgoing]:
         """Generate the service browser query for any type that is due."""
-        now = current_time_millis()
         ready_types = self.query_scheduler.process_ready_types(now)
         if not ready_types:
             return []
@@ -448,40 +442,40 @@
     async def _async_start_query_sender(self) -> None:
         """Start scheduling queries."""
         await self.zc.async_wait_for_start()
-        self._async_send_ready_queries()
-        self._async_schedule_next()
+        self._async_send_ready_queries_schedule_next()
 
     def _cancel_send_timer(self) -> None:
         """Cancel the next send."""
         if self._next_send_timer:
             self._next_send_timer.cancel()
 
-    def reschedule_type(self, type_: str, next_time: float) -> None:
+    def reschedule_type(self, type_: str, now: float, next_time: float) -> 
None:
         """Reschedule a type to be refreshed in the future."""
         if self.query_scheduler.reschedule_type(type_, next_time):
             self._cancel_send_timer()
-            self._async_schedule_next()
-        self._async_send_ready_queries()
+            self._async_schedule_next(now)
+        self._async_send_ready_queries(now)
 
-    def _async_send_ready_queries(self) -> None:
+    def _async_send_ready_queries(self, now: float) -> None:
         """Send any ready queries."""
-        outs = self._generate_ready_queries(self._first_request)
+        outs = self._generate_ready_queries(self._first_request, now)
         if outs:
             self._first_request = False
             for out in outs:
                 self.zc.async_send(out, addr=self.addr, port=self.port)
 
     def _async_send_ready_queries_schedule_next(self) -> None:
-        """Send ready queries and schedule next one."""
+        """Send ready queries and schedule next one checking for done first."""
         if self.done or self.zc.done:
             return
-        self._async_send_ready_queries()
-        self._async_schedule_next()
+        now = current_time_millis()
+        self._async_send_ready_queries(now)
+        self._async_schedule_next(now)
 
-    def _async_schedule_next(self) -> None:
+    def _async_schedule_next(self, now: float) -> None:
         """Scheule the next time."""
         assert self.zc.loop is not None
-        delay = 
millis_to_seconds(self.query_scheduler.millis_to_wait(current_time_millis()))
+        delay = millis_to_seconds(self.query_scheduler.millis_to_wait(now))
         self._next_send_timer = self.zc.loop.call_later(delay, 
self._async_send_ready_queries_schedule_next)
 
 
@@ -511,11 +505,11 @@
         # 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),
         )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/zeroconf/_utils/asyncio.py 
new/python-zeroconf-0.38.1/zeroconf/_utils/asyncio.py
--- old/python-zeroconf-0.37.0/zeroconf/_utils/asyncio.py       2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/zeroconf/_utils/asyncio.py       2021-12-24 
03:47:53.000000000 +0100
@@ -23,8 +23,7 @@
 import asyncio
 import concurrent.futures
 import contextlib
-import queue
-from typing import Any, Awaitable, Coroutine, List, Optional, Set, cast
+from typing import Any, Awaitable, Coroutine, Optional, Set
 
 from .time import millis_to_seconds
 from .._exceptions import EventLoopBlocked
@@ -36,13 +35,6 @@
 _WAIT_FOR_LOOP_TASKS_TIMEOUT = 3  # Must be larger than _TASK_AWAIT_TIMEOUT
 
 
-def get_best_available_queue() -> queue.Queue:
-    """Create the best available queue type."""
-    if hasattr(queue, "SimpleQueue"):
-        return queue.SimpleQueue()  # type: ignore  # pylint: disable=all
-    return queue.Queue()
-
-
 # Switch to asyncio.wait_for once https://bugs.python.org/issue39032 is fixed
 async def wait_event_or_timeout(event: asyncio.Event, timeout: float) -> None:
     """Wait for an event or timeout."""
@@ -67,7 +59,7 @@
             await event_wait
 
 
-async def _async_get_all_tasks(loop: asyncio.AbstractEventLoop) -> 
List[asyncio.Task]:
+async def _async_get_all_tasks(loop: asyncio.AbstractEventLoop) -> 
Set[asyncio.Task]:
     """Return all tasks running."""
     await asyncio.sleep(0)  # flush out any call_soon_threadsafe
     # If there are multiple event loops running, all_tasks is not
@@ -75,10 +67,8 @@
     # under PyPy so we have to try a few times.
     for _ in range(3):
         with contextlib.suppress(RuntimeError):
-            if hasattr(asyncio, 'all_tasks'):
-                return asyncio.all_tasks(loop)  # type: ignore  # pylint: 
disable=no-member
-            return asyncio.Task.all_tasks(loop)  # type: ignore  # pylint: 
disable=no-member
-    return []
+            return asyncio.all_tasks(loop)
+    return set()
 
 
 async def _wait_for_loop_tasks(wait_tasks: Set[asyncio.Task]) -> None:
@@ -116,7 +106,7 @@
     pending_tasks = set(
         asyncio.run_coroutine_threadsafe(_async_get_all_tasks(loop), 
loop).result(_GET_ALL_TASKS_TIMEOUT)
     )
-    pending_tasks -= set(task for task in pending_tasks if task.done())
+    pending_tasks -= {task for task in pending_tasks if task.done()}
     if pending_tasks:
         asyncio.run_coroutine_threadsafe(_wait_for_loop_tasks(pending_tasks), 
loop).result(
             _WAIT_FOR_LOOP_TASKS_TIMEOUT
@@ -128,10 +118,5 @@
 def get_running_loop() -> Optional[asyncio.AbstractEventLoop]:
     """Check if an event loop is already running."""
     with contextlib.suppress(RuntimeError):
-        if hasattr(asyncio, "get_running_loop"):
-            return cast(
-                asyncio.AbstractEventLoop,
-                asyncio.get_running_loop(),  # type: ignore  # pylint: 
disable=no-member  # noqa
-            )
-        return asyncio._get_running_loop()  # pylint: 
disable=no-member,protected-access
+        return asyncio.get_running_loop()
     return None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/zeroconf/_utils/name.py 
new/python-zeroconf-0.38.1/zeroconf/_utils/name.py
--- old/python-zeroconf-0.37.0/zeroconf/_utils/name.py  2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/zeroconf/_utils/name.py  2021-12-24 
03:47:53.000000000 +0100
@@ -20,6 +20,8 @@
     USA
 """
 
+from typing import Set
+
 from .._exceptions import BadTypeInNameException
 from ..const import (
     _HAS_ASCII_CONTROL_CHARS,
@@ -92,7 +94,7 @@
         trailer = type_[-len(_LOCAL_TRAILER) + 1 :]
         has_protocol = False
     else:
-        raise BadTypeInNameException("Type '%s' must end with '%s'" % (type_, 
_LOCAL_TRAILER))
+        raise BadTypeInNameException(f"Type '{type_}' must end with 
'{_LOCAL_TRAILER}'")
 
     if strict or has_protocol:
         service_name = remaining.pop()
@@ -155,3 +157,16 @@
             )
 
     return service_name + trailer
+
+
+def possible_types(name: str) -> Set[str]:
+    """Build a set of all possible types from a fully qualified name."""
+    labels = name.split('.')
+    label_count = len(labels)
+    types = set()
+    for count in range(label_count):
+        parts = labels[label_count - count - 4 :]
+        if not parts[0].startswith('_'):
+            break
+        types.add('.'.join(parts))
+    return types
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-zeroconf-0.37.0/zeroconf/_utils/net.py 
new/python-zeroconf-0.38.1/zeroconf/_utils/net.py
--- old/python-zeroconf-0.37.0/zeroconf/_utils/net.py   2021-11-18 
21:30:53.000000000 +0100
+++ new/python-zeroconf-0.38.1/zeroconf/_utils/net.py   2021-12-24 
03:47:53.000000000 +0100
@@ -71,14 +71,14 @@
 
 
 def get_all_addresses() -> List[str]:
-    return list(set(addr.ip for iface in ifaddr.get_adapters() for addr in 
iface.ips if addr.is_IPv4))
+    return list({addr.ip for iface in ifaddr.get_adapters() for addr in 
iface.ips if addr.is_IPv4})
 
 
 def get_all_addresses_v6() -> List[Tuple[Tuple[str, int, int], int]]:
     # IPv6 multicast uses positive indexes for interfaces
     # TODO: What about multi-address interfaces?
     return list(
-        set((addr.ip, iface.index) for iface in ifaddr.get_adapters() for addr 
in iface.ips if addr.is_IPv6)
+        {(addr.ip, iface.index) for iface in ifaddr.get_adapters() for addr in 
iface.ips if addr.is_IPv6}
     )
 
 
@@ -203,7 +203,7 @@
         try:
             s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
             s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, loop)
-        except socket.error as e:
+        except OSError as e:
             if bind_addr[0] != '' or get_errno(e) != errno.EINVAL:  # Fails to 
set on MacOS
                 raise
 
@@ -286,7 +286,7 @@
         else:
             _value = socket.inet_aton(_MDNS_ADDR) + socket.inet_aton(cast(str, 
interface))
             listen_socket.setsockopt(socket.IPPROTO_IP, 
socket.IP_ADD_MEMBERSHIP, _value)
-    except socket.error as e:
+    except OSError as e:
         _errno = get_errno(e)
         if _errno == errno.EADDRINUSE:
             log.info(

++++++ python-zeroconf.obsinfo ++++++
--- /var/tmp/diff_new_pack.494Uhp/_old  2022-01-10 23:53:47.460814208 +0100
+++ /var/tmp/diff_new_pack.494Uhp/_new  2022-01-10 23:53:47.464814211 +0100
@@ -1,6 +1,5 @@
 name: python-zeroconf
-version: 0.37.0
-mtime: 1637267453
-commit: 2996e642f6b1abba1dbb8242ccca4cd4b96696f6
-
+version: 0.38.1
+mtime: 1640314073
+commit: 6a11f24e1fc9d73f0dbb62efd834f17a9bd451c4
 

Reply via email to