zeroconf 0.147.4__tar.gz → 0.149.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of zeroconf might be problematic. Click here for more details.
- {zeroconf-0.147.4 → zeroconf-0.149.0}/CHANGELOG.md +14 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/PKG-INFO +4 -5
- {zeroconf-0.147.4 → zeroconf-0.149.0}/README.rst +2 -2
- {zeroconf-0.147.4 → zeroconf-0.149.0}/build_ext.py +2 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/pyproject.toml +4 -4
- {zeroconf-0.147.4 → zeroconf-0.149.0}/setup.py +3 -3
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/__init__.py +1 -1
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_cache.py +2 -2
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_core.py +14 -1
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/__init__.py +2 -1
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/browser.py +1 -2
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_utils/net.py +2 -2
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/asyncio.py +1 -2
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_core.py +30 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/COPYING +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/docs/Makefile +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/docs/_ext/zeroconfautodocfix.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/docs/api.rst +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/docs/conf.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/docs/index.rst +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_cache.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_dns.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_dns.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_engine.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_exceptions.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/__init__.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/answers.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/answers.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/multicast_outgoing_queue.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/multicast_outgoing_queue.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/query_handler.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/query_handler.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/record_manager.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_handlers/record_manager.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_history.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_history.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_listener.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_listener.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_logger.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_protocol/__init__.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_protocol/incoming.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_protocol/incoming.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_protocol/outgoing.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_protocol/outgoing.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_record_update.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_record_update.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/__init__.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/browser.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/info.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/info.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/registry.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/registry.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_services/types.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_transport.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_updates.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_updates.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_utils/__init__.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_utils/asyncio.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_utils/ipaddress.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_utils/ipaddress.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_utils/name.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_utils/time.pxd +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/_utils/time.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/const.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/src/zeroconf/py.typed +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/__init__.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/benchmarks/__init__.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/benchmarks/helpers.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/benchmarks/test_cache.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/benchmarks/test_incoming.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/benchmarks/test_outgoing.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/benchmarks/test_send.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/benchmarks/test_txt_properties.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/conftest.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/services/__init__.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/services/test_browser.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/services/test_info.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/services/test_registry.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/services/test_types.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_asyncio.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_cache.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_circular_imports.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_dns.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_engine.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_exceptions.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_handlers.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_history.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_init.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_listener.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_logger.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_protocol.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_services.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/test_updates.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/utils/__init__.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/utils/test_asyncio.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/utils/test_ipaddress.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/utils/test_name.py +0 -0
- {zeroconf-0.147.4 → zeroconf-0.149.0}/tests/utils/test_net.py +0 -0
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v0.149.0 (2026-05-16)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- Drop Python 3.9 support ([#1688](https://github.com/python-zeroconf/python-zeroconf/pull/1688),
|
|
10
|
+
[`327b93d`](https://github.com/python-zeroconf/python-zeroconf/commit/327b93dc602707e25d53788f0fb14e142f4558b3))
|
|
11
|
+
|
|
12
|
+
### Performance Improvements
|
|
13
|
+
|
|
14
|
+
- **build**: Parallelize cython extension compilation
|
|
15
|
+
([#1689](https://github.com/python-zeroconf/python-zeroconf/pull/1689),
|
|
16
|
+
[`1ea6b94`](https://github.com/python-zeroconf/python-zeroconf/commit/1ea6b940ecbfd7e7654ad022cf7f4f888cf1daa5))
|
|
17
|
+
|
|
18
|
+
|
|
5
19
|
## v0.147.4 (2026-05-16)
|
|
6
20
|
|
|
7
21
|
### Bug Fixes
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zeroconf
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.149.0
|
|
4
4
|
Summary: A pure python implementation of multicast DNS service discovery
|
|
5
5
|
License-Expression: LGPL-2.1-or-later
|
|
6
6
|
License-File: COPYING
|
|
7
7
|
Author: Paul Scott-Murphy
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: Intended Audience :: System Administrators
|
|
@@ -13,7 +13,6 @@ Classifier: Operating System :: MacOS :: MacOS X
|
|
|
13
13
|
Classifier: Operating System :: POSIX
|
|
14
14
|
Classifier: Operating System :: POSIX :: Linux
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -84,8 +83,8 @@ Compared to some other Zeroconf/Bonjour/Avahi Python packages, python-zeroconf:
|
|
|
84
83
|
Python compatibility
|
|
85
84
|
--------------------
|
|
86
85
|
|
|
87
|
-
* CPython 3.
|
|
88
|
-
* PyPy 3.
|
|
86
|
+
* CPython 3.10+
|
|
87
|
+
* PyPy 3.10+
|
|
89
88
|
|
|
90
89
|
Versioning
|
|
91
90
|
----------
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "zeroconf"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.149.0"
|
|
8
8
|
license = "LGPL-2.1-or-later"
|
|
9
9
|
description = "A pure python implementation of multicast DNS service discovery"
|
|
10
10
|
readme = "README.rst"
|
|
@@ -14,7 +14,7 @@ authors = [
|
|
|
14
14
|
{ name = "Jakub Stasiak" },
|
|
15
15
|
{ name = "J. Nick Koston" },
|
|
16
16
|
]
|
|
17
|
-
requires-python = ">=3.
|
|
17
|
+
requires-python = ">=3.10"
|
|
18
18
|
|
|
19
19
|
[project.urls]
|
|
20
20
|
"Repository" = "https://github.com/python-zeroconf/python-zeroconf"
|
|
@@ -80,7 +80,7 @@ match = "(?!(master|release-0.x)$)"
|
|
|
80
80
|
prerelease = true
|
|
81
81
|
|
|
82
82
|
[tool.poetry.dependencies]
|
|
83
|
-
python = "^3.
|
|
83
|
+
python = "^3.10"
|
|
84
84
|
ifaddr = ">=0.1.7"
|
|
85
85
|
|
|
86
86
|
[tool.poetry.group.dev.dependencies]
|
|
@@ -97,7 +97,7 @@ sphinx = "^7.4.7 || ^8.1.3"
|
|
|
97
97
|
sphinx-rtd-theme = "^3.1.0"
|
|
98
98
|
|
|
99
99
|
[tool.ruff]
|
|
100
|
-
target-version = "
|
|
100
|
+
target-version = "py310"
|
|
101
101
|
line-length = 110
|
|
102
102
|
|
|
103
103
|
[tool.ruff.lint]
|
|
@@ -19,9 +19,9 @@ install_requires = \
|
|
|
19
19
|
|
|
20
20
|
setup_kwargs = {
|
|
21
21
|
'name': 'zeroconf',
|
|
22
|
-
'version': '0.
|
|
22
|
+
'version': '0.149.0',
|
|
23
23
|
'description': 'A pure python implementation of multicast DNS service discovery',
|
|
24
|
-
'long_description': 'python-zeroconf\n===============\n\n.. image:: https://github.com/python-zeroconf/python-zeroconf/workflows/CI/badge.svg\n :target: https://github.com/python-zeroconf/python-zeroconf?query=workflow%3ACI+branch%3Amaster\n\n.. image:: https://img.shields.io/pypi/v/zeroconf.svg\n :target: https://pypi.python.org/pypi/zeroconf\n\n.. image:: https://codecov.io/gh/python-zeroconf/python-zeroconf/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/python-zeroconf/python-zeroconf\n\n.. image:: https://img.shields.io/endpoint?url=https://codspeed.io/badge.json\n :target: https://codspeed.io/python-zeroconf/python-zeroconf\n :alt: Codspeed.io status for python-zeroconf\n\n.. image:: https://readthedocs.org/projects/python-zeroconf/badge/?version=latest\n :target: https://python-zeroconf.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n`Documentation <https://python-zeroconf.readthedocs.io/en/latest/>`_.\n\nThis is fork of pyzeroconf, Multicast DNS Service Discovery for Python,\noriginally by Paul Scott-Murphy (https://github.com/paulsm/pyzeroconf),\nmodified by William McBrine (https://github.com/wmcbrine/pyzeroconf).\n\nThe original William McBrine\'s fork note::\n\n This fork is used in all of my TiVo-related projects: HME for Python\n (and therefore HME/VLC), Network Remote, Remote Proxy, and pyTivo.\n Before this, I was tracking the changes for zeroconf.py in three\n separate repos. I figured I should have an authoritative source.\n\n Although I make changes based on my experience with TiVos, I expect that\n they\'re generally applicable. This version also includes patches found\n on the now-defunct (?) Launchpad repo of pyzeroconf, and elsewhere\n around the net -- not always well-documented, sorry.\n\nCompatible with:\n\n* Bonjour\n* Avahi\n\nCompared to some other Zeroconf/Bonjour/Avahi Python packages, python-zeroconf:\n\n* isn\'t tied to Bonjour or Avahi\n* doesn\'t use D-Bus\n* doesn\'t force you to use particular event loop or Twisted (asyncio is used under the hood but not required)\n* is pip-installable\n* has PyPI distribution\n* has an optional cython extension for performance (pure python is supported as well)\n\nPython compatibility\n--------------------\n\n* CPython 3.
|
|
24
|
+
'long_description': 'python-zeroconf\n===============\n\n.. image:: https://github.com/python-zeroconf/python-zeroconf/workflows/CI/badge.svg\n :target: https://github.com/python-zeroconf/python-zeroconf?query=workflow%3ACI+branch%3Amaster\n\n.. image:: https://img.shields.io/pypi/v/zeroconf.svg\n :target: https://pypi.python.org/pypi/zeroconf\n\n.. image:: https://codecov.io/gh/python-zeroconf/python-zeroconf/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/python-zeroconf/python-zeroconf\n\n.. image:: https://img.shields.io/endpoint?url=https://codspeed.io/badge.json\n :target: https://codspeed.io/python-zeroconf/python-zeroconf\n :alt: Codspeed.io status for python-zeroconf\n\n.. image:: https://readthedocs.org/projects/python-zeroconf/badge/?version=latest\n :target: https://python-zeroconf.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n`Documentation <https://python-zeroconf.readthedocs.io/en/latest/>`_.\n\nThis is fork of pyzeroconf, Multicast DNS Service Discovery for Python,\noriginally by Paul Scott-Murphy (https://github.com/paulsm/pyzeroconf),\nmodified by William McBrine (https://github.com/wmcbrine/pyzeroconf).\n\nThe original William McBrine\'s fork note::\n\n This fork is used in all of my TiVo-related projects: HME for Python\n (and therefore HME/VLC), Network Remote, Remote Proxy, and pyTivo.\n Before this, I was tracking the changes for zeroconf.py in three\n separate repos. I figured I should have an authoritative source.\n\n Although I make changes based on my experience with TiVos, I expect that\n they\'re generally applicable. This version also includes patches found\n on the now-defunct (?) Launchpad repo of pyzeroconf, and elsewhere\n around the net -- not always well-documented, sorry.\n\nCompatible with:\n\n* Bonjour\n* Avahi\n\nCompared to some other Zeroconf/Bonjour/Avahi Python packages, python-zeroconf:\n\n* isn\'t tied to Bonjour or Avahi\n* doesn\'t use D-Bus\n* doesn\'t force you to use particular event loop or Twisted (asyncio is used under the hood but not required)\n* is pip-installable\n* has PyPI distribution\n* has an optional cython extension for performance (pure python is supported as well)\n\nPython compatibility\n--------------------\n\n* CPython 3.10+\n* PyPy 3.10+\n\nVersioning\n----------\n\nThis project uses semantic versioning.\n\nStatus\n------\n\nThis project is actively maintained.\n\nTraffic Reduction\n-----------------\n\nBefore version 0.32, most traffic reduction techniques described in https://datatracker.ietf.org/doc/html/rfc6762#section-7\nwhere not implemented which could lead to excessive network traffic. It is highly recommended that version 0.32 or later\nis used if this is a concern.\n\nIPv6 support\n------------\n\nIPv6 support is relatively new and currently limited, specifically:\n\n* `InterfaceChoice.All` is an alias for `InterfaceChoice.Default` on non-POSIX\n systems.\n* Dual-stack IPv6 sockets are used, which may not be supported everywhere (some\n BSD variants do not have them).\n* Listening on localhost (`::1`) does not work. Help with understanding why is\n appreciated.\n\nHow to get python-zeroconf?\n===========================\n\n* PyPI page https://pypi.org/project/zeroconf/\n* GitHub project https://github.com/python-zeroconf/python-zeroconf\n\nThe easiest way to install python-zeroconf is using pip::\n\n pip install zeroconf\n\n\n\nHow do I use it?\n================\n\nHere\'s an example of browsing for a service:\n\n.. code-block:: python\n\n from zeroconf import ServiceBrowser, ServiceListener, Zeroconf\n\n\n class MyListener(ServiceListener):\n\n def update_service(self, zc: Zeroconf, type_: str, name: str) -> None:\n print(f"Service {name} updated")\n\n def remove_service(self, zc: Zeroconf, type_: str, name: str) -> None:\n print(f"Service {name} removed")\n\n def add_service(self, zc: Zeroconf, type_: str, name: str) -> None:\n info = zc.get_service_info(type_, name)\n print(f"Service {name} added, service info: {info}")\n\n\n zeroconf = Zeroconf()\n listener = MyListener()\n browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener)\n try:\n input("Press enter to exit...\\n\\n")\n finally:\n zeroconf.close()\n\n.. note::\n\n Discovery and service registration use *all* available network interfaces by default.\n If you want to customize that you need to specify ``interfaces`` argument when\n constructing ``Zeroconf`` object (see the code for details).\n\nIf you don\'t know the name of the service you need to browse for, try:\n\n.. code-block:: python\n\n from zeroconf import ZeroconfServiceTypes\n print(\'\\n\'.join(ZeroconfServiceTypes.find()))\n\nSee examples directory for more.\n\nChangelog\n=========\n\n`Changelog <CHANGELOG.md>`_\n\nLicense\n=======\n\nLGPL, see COPYING file for details.\n',
|
|
25
25
|
'author': 'Paul Scott-Murphy',
|
|
26
26
|
'author_email': 'None',
|
|
27
27
|
'maintainer': 'None',
|
|
@@ -31,7 +31,7 @@ setup_kwargs = {
|
|
|
31
31
|
'packages': packages,
|
|
32
32
|
'package_data': package_data,
|
|
33
33
|
'install_requires': install_requires,
|
|
34
|
-
'python_requires': '>=3.
|
|
34
|
+
'python_requires': '>=3.10',
|
|
35
35
|
}
|
|
36
36
|
from build_ext import *
|
|
37
37
|
build(setup_kwargs)
|
|
@@ -88,7 +88,7 @@ from ._utils.time import ( # noqa # import needed for backwards compat
|
|
|
88
88
|
|
|
89
89
|
__author__ = "Paul Scott-Murphy, William McBrine"
|
|
90
90
|
__maintainer__ = "Jakub Stasiak <jakub@stasiak.at>"
|
|
91
|
-
__version__ = "0.
|
|
91
|
+
__version__ = "0.149.0"
|
|
92
92
|
__license__ = "LGPL"
|
|
93
93
|
|
|
94
94
|
|
|
@@ -24,7 +24,7 @@ from __future__ import annotations
|
|
|
24
24
|
|
|
25
25
|
from collections.abc import Iterable
|
|
26
26
|
from heapq import heapify, heappop, heappush
|
|
27
|
-
from typing import
|
|
27
|
+
from typing import cast
|
|
28
28
|
|
|
29
29
|
from ._dns import (
|
|
30
30
|
DNSAddress,
|
|
@@ -40,7 +40,7 @@ from ._utils.time import current_time_millis
|
|
|
40
40
|
from .const import _ONE_SECOND, _TYPE_PTR
|
|
41
41
|
|
|
42
42
|
_UNIQUE_RECORD_TYPES = (DNSAddress, DNSHinfo, DNSPointer, DNSText, DNSService)
|
|
43
|
-
_UniqueRecordsType =
|
|
43
|
+
_UniqueRecordsType = DNSAddress | DNSHinfo | DNSPointer | DNSText | DNSService
|
|
44
44
|
_DNSRecordCacheType = dict[str, dict[DNSRecord, DNSRecord]]
|
|
45
45
|
_DNSRecord = DNSRecord
|
|
46
46
|
_str = str
|
|
@@ -154,6 +154,7 @@ class Zeroconf(QuietLogger):
|
|
|
154
154
|
unicast: bool = False,
|
|
155
155
|
ip_version: IPVersion | None = None,
|
|
156
156
|
apple_p2p: bool = False,
|
|
157
|
+
use_asyncio: bool | None = None,
|
|
157
158
|
) -> None:
|
|
158
159
|
"""Creates an instance of the Zeroconf class, establishing
|
|
159
160
|
multicast communications, listening and reaping threads.
|
|
@@ -169,6 +170,14 @@ class Zeroconf(QuietLogger):
|
|
|
169
170
|
:param ip_version: IP versions to support. If `choice` is a list, the default is detected
|
|
170
171
|
from it. Otherwise defaults to V4 only for backward compatibility.
|
|
171
172
|
:param apple_p2p: use AWDL interface (only macOS)
|
|
173
|
+
:param use_asyncio: explicitly control whether to attach to the running
|
|
174
|
+
asyncio event loop (``True``) or run an internal thread with its
|
|
175
|
+
own loop (``False``). ``None`` (default) keeps the historic
|
|
176
|
+
behavior: attach if an event loop is running, otherwise start a
|
|
177
|
+
thread. Set to ``False`` when running inside an environment that
|
|
178
|
+
already has an event loop (e.g. Jupyter) but you want blocking
|
|
179
|
+
semantics. ``True`` raises :class:`RuntimeError` immediately if no
|
|
180
|
+
running event loop is found, instead of falling back to the thread.
|
|
172
181
|
"""
|
|
173
182
|
if ip_version is None:
|
|
174
183
|
ip_version = autodetect_ip_version(interfaces)
|
|
@@ -178,7 +187,11 @@ class Zeroconf(QuietLogger):
|
|
|
178
187
|
if apple_p2p and sys.platform != "darwin":
|
|
179
188
|
raise RuntimeError("Option `apple_p2p` is not supported on non-Apple platforms.")
|
|
180
189
|
|
|
190
|
+
if use_asyncio is True and get_running_loop() is None:
|
|
191
|
+
raise RuntimeError("use_asyncio=True requires a running asyncio event loop")
|
|
192
|
+
|
|
181
193
|
self.unicast = unicast
|
|
194
|
+
self._use_asyncio = use_asyncio
|
|
182
195
|
listen_socket, respond_sockets = create_sockets(interfaces, unicast, ip_version, apple_p2p=apple_p2p)
|
|
183
196
|
log.debug("Listen socket %s, respond sockets %s", listen_socket, respond_sockets)
|
|
184
197
|
|
|
@@ -216,7 +229,7 @@ class Zeroconf(QuietLogger):
|
|
|
216
229
|
|
|
217
230
|
def start(self) -> None:
|
|
218
231
|
"""Start Zeroconf."""
|
|
219
|
-
self.loop = get_running_loop()
|
|
232
|
+
self.loop = None if self._use_asyncio is False else get_running_loop()
|
|
220
233
|
if self.loop:
|
|
221
234
|
self.engine.setup(self.loop, None)
|
|
222
235
|
return
|
|
@@ -30,13 +30,12 @@ import random
|
|
|
30
30
|
import threading
|
|
31
31
|
import time
|
|
32
32
|
import warnings
|
|
33
|
-
from collections.abc import Iterable
|
|
33
|
+
from collections.abc import Callable, Iterable
|
|
34
34
|
from functools import partial
|
|
35
35
|
from types import TracebackType # used in type hints
|
|
36
36
|
from typing import (
|
|
37
37
|
TYPE_CHECKING,
|
|
38
38
|
Any,
|
|
39
|
-
Callable,
|
|
40
39
|
cast,
|
|
41
40
|
)
|
|
42
41
|
|
|
@@ -30,7 +30,7 @@ import struct
|
|
|
30
30
|
import sys
|
|
31
31
|
import warnings
|
|
32
32
|
from collections.abc import Iterable, Sequence
|
|
33
|
-
from typing import Any,
|
|
33
|
+
from typing import Any, cast
|
|
34
34
|
|
|
35
35
|
import ifaddr
|
|
36
36
|
|
|
@@ -44,7 +44,7 @@ class InterfaceChoice(enum.Enum):
|
|
|
44
44
|
All = 2
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
InterfacesType =
|
|
47
|
+
InterfacesType = Sequence[str | int | tuple[tuple[str, int, int], int]] | InterfaceChoice
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
@enum.unique
|
|
@@ -24,9 +24,8 @@ from __future__ import annotations
|
|
|
24
24
|
|
|
25
25
|
import asyncio
|
|
26
26
|
import contextlib
|
|
27
|
-
from collections.abc import Awaitable
|
|
27
|
+
from collections.abc import Awaitable, Callable
|
|
28
28
|
from types import TracebackType # used in type hints
|
|
29
|
-
from typing import Callable
|
|
30
29
|
|
|
31
30
|
from ._core import Zeroconf
|
|
32
31
|
from ._dns import DNSQuestionType
|
|
@@ -154,6 +154,36 @@ class Framework(unittest.TestCase):
|
|
|
154
154
|
rv = r.Zeroconf(apple_p2p=True)
|
|
155
155
|
rv.close()
|
|
156
156
|
|
|
157
|
+
def test_use_asyncio_false_forces_thread_when_loop_running(self):
|
|
158
|
+
"""use_asyncio=False starts a thread even with a running event loop."""
|
|
159
|
+
|
|
160
|
+
async def run() -> r.Zeroconf:
|
|
161
|
+
return r.Zeroconf(interfaces=["127.0.0.1"], use_asyncio=False)
|
|
162
|
+
|
|
163
|
+
loop = asyncio.new_event_loop()
|
|
164
|
+
zc: r.Zeroconf | None = None
|
|
165
|
+
try:
|
|
166
|
+
zc = loop.run_until_complete(run())
|
|
167
|
+
assert zc._loop_thread is not None
|
|
168
|
+
assert zc.loop is not loop
|
|
169
|
+
finally:
|
|
170
|
+
if zc is not None:
|
|
171
|
+
zc.close()
|
|
172
|
+
loop.close()
|
|
173
|
+
|
|
174
|
+
def test_use_asyncio_true_requires_running_loop(self):
|
|
175
|
+
"""use_asyncio=True without a running loop raises RuntimeError."""
|
|
176
|
+
with pytest.raises(RuntimeError, match="requires a running asyncio event loop"):
|
|
177
|
+
r.Zeroconf(interfaces=["127.0.0.1"], use_asyncio=True)
|
|
178
|
+
|
|
179
|
+
def test_use_asyncio_default_starts_thread_without_loop(self):
|
|
180
|
+
"""use_asyncio=None (default) keeps the historic auto-detect behavior."""
|
|
181
|
+
zc = r.Zeroconf(interfaces=["127.0.0.1"])
|
|
182
|
+
try:
|
|
183
|
+
assert zc._loop_thread is not None
|
|
184
|
+
finally:
|
|
185
|
+
zc.close()
|
|
186
|
+
|
|
157
187
|
def test_async_updates_from_response(self):
|
|
158
188
|
def mock_incoming_msg(
|
|
159
189
|
service_state_change: r.ServiceStateChange,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|