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
4 changes: 2 additions & 2 deletions .claude/skills/pr-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ CI runs three jobs:
the PR title against Conventional Commits. If it fails, fix
the title in the GitHub UI or with `gh pr edit --title "..."`;
the workflow re-runs on the edit, no push needed.
- `test` — the full pytest matrix across CPython 3.10–3.14,
3.14t (free-threaded), and PyPy 3.10, on Linux + macOS +
- `test` — the full pytest matrix across CPython 3.11–3.15,
3.14t and 3.15t (free-threaded), and PyPy 3.11, on Linux + macOS +
Windows. The free-threaded entry is the canary for unguarded
shared-state bugs; failures there are often genuine even when
the GIL-enabled rows pass.
Expand Down
17 changes: 4 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,14 @@ jobs:
fail-fast: false
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
- "3.14t"
- "3.15"
- "3.15t"
- "pypy-3.10"
- "pypy-3.11"
os:
- ubuntu-latest
- macos-latest
Expand All @@ -94,9 +93,9 @@ jobs:
- os: windows-latest
extension: use_cython
- os: windows-latest
python-version: "pypy-3.10"
python-version: "pypy-3.11"
- os: macos-latest
python-version: "pypy-3.10"
python-version: "pypy-3.11"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
Expand Down Expand Up @@ -271,10 +270,6 @@ jobs:
musl: "musllinux"
# qemu is slow, make a single
# runner per Python version
- os: ubuntu-24.04-arm
qemu: armv7l
musl: "musllinux"
pyver: cp310
- os: ubuntu-24.04-arm
qemu: armv7l
musl: "musllinux"
Expand All @@ -297,10 +292,6 @@ jobs:
pyver: cp314t
# qemu is slow, make a single
# runner per Python version
- os: ubuntu-24.04-arm
qemu: armv7l
musl: ""
pyver: cp310
- os: ubuntu-24.04-arm
qemu: armv7l
musl: ""
Expand Down Expand Up @@ -366,7 +357,7 @@ jobs:
uses: pypa/cibuildwheel@e090b81e30c4d855ea63bf4b6e59204c09a101ae # v4.2.1
# to supply options, put them in 'env', like:
env:
CIBW_SKIP: cp38-* cp39-* pp38-* pp39-* ${{ matrix.musl == 'musllinux' && '*manylinux*' || '*musllinux*' }}
CIBW_SKIP: cp38-* cp39-* cp310-* pp38-* pp39-* pp310-* ${{ matrix.musl == 'musllinux' && '*manylinux*' || '*musllinux*' }}
CIBW_BEFORE_ALL_LINUX: apt install -y gcc || yum install -y gcc || apk add gcc
CIBW_ARCHS_MACOS: arm64
REQUIRE_CYTHON: 1
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ repos:
rev: v3.22.0
hooks:
- id: pyupgrade
args: [--py310-plus]
args: [--py311-plus]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.17.2
hooks:
Expand Down
10 changes: 5 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ path. The authoritative list of cythonized modules lives in
and `zeroconf/asyncio.py` re-export.

- **Line length**: 110 (ruff `line-length = 110`).
`requires-python = ">=3.10"`, `target-version = "py310"` for
ruff; pyupgrade runs `--py310-plus`.
`requires-python = ">=3.11"`, `target-version = "py311"` for
ruff; pyupgrade runs `--py311-plus`.

- **Imports**: ruff/isort sorted, `profile = "black"`,
`known_first_party = ["zeroconf", "tests"]`. Prefer
`from __future__ import annotations` so modern type syntax
works on 3.10.
works on 3.11.

- **Generated `.c` files are not lint-targets.** `*.c` files
next to each cythonized module are Cython output — never hand-
Expand Down Expand Up @@ -135,8 +135,8 @@ CodSpeed benchmarks live under `tests/benchmarks/` and run in CI
through `CodSpeedHQ/action`. Ad-hoc microbenchmarks for manual
profiling live under `bench/` — those don't run in CI.

The CI matrix includes CPython 3.10 – 3.14, the free-threaded
3.14t build, and PyPy 3.10. Don't add anything that breaks
The CI matrix includes CPython 3.11 – 3.15, the free-threaded
3.14t and 3.15t builds, and PyPy 3.11. Don't add anything that breaks
on the free-threaded build (no module-level mutable globals
mutated from multiple threads without locks; no
`PyDict_Next`-style escape hatches in Cython).
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ Compared to some other Zeroconf/Bonjour/Avahi Python packages, python-zeroconf:
Python compatibility
--------------------

* CPython 3.10+
* PyPy 3.10+
* CPython 3.11+
* PyPy 3.11+

Versioning
----------
Expand Down
87 changes: 3 additions & 84 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ authors = [
maintainers = [
{ name = "J. Nick Koston", email = "[email protected]" },
]
requires-python = ">=3.10"
requires-python = ">=3.11"

[project.urls]
"Repository" = "https://github.com/python-zeroconf/python-zeroconf"
Expand Down Expand Up @@ -80,7 +80,7 @@ match = "(?!(master|release-0.x)$)"
prerelease = true

[tool.poetry.dependencies]
python = "^3.10"
python = "^3.11"
ifaddr = ">=0.1.7"

[tool.poetry.group.dev.dependencies]
Expand All @@ -99,7 +99,7 @@ sphinx = "^7.4.7 || ^8.1.3"
sphinx-rtd-theme = "^3.1.0"

[tool.ruff]
target-version = "py310"
target-version = "py311"
line-length = 110

[tool.ruff.lint]
Expand All @@ -117,10 +117,10 @@ ignore = [
"PGH004", # too many to fix
"PGH003", # too many to fix
"SIM110", # this is slower
"PYI034", # enable when we drop Py3.10
"PYI032", # breaks Cython
"PYI041", # breaks Cython
"PERF401", # Cython: closures inside cpdef functions not yet supported
"ASYNC109", # timeout params are public API
]
select = [
"ASYNC", # async rules
Expand Down
3 changes: 2 additions & 1 deletion src/zeroconf/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import threading
from collections.abc import Awaitable
from types import TracebackType
from typing import Self

from ._cache import DNSCache
from ._dns import DNSQuestion, DNSQuestionType
Expand Down Expand Up @@ -212,7 +213,7 @@ def __init__(

self.start()

def __enter__(self) -> Zeroconf:
def __enter__(self) -> Self:
return self

def __exit__( # pylint: disable=useless-return
Expand Down
3 changes: 2 additions & 1 deletion src/zeroconf/_services/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from typing import (
TYPE_CHECKING,
Any,
Self,
cast,
)

Expand Down Expand Up @@ -762,7 +763,7 @@ def __init__(
getattr(self, "native_id", self.ident),
)

def __enter__(self) -> ServiceBrowser:
def __enter__(self) -> Self:
return self

def __exit__( # pylint: disable=useless-return
Expand Down
3 changes: 1 addition & 2 deletions src/zeroconf/_utils/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import asyncio
import concurrent.futures
import contextlib
import sys
from collections.abc import Awaitable, Coroutine
from typing import Any

Expand Down Expand Up @@ -58,7 +57,7 @@ async def wait_future_or_timeout(future: asyncio.Future[bool | None], timeout: f
try:
await future
except asyncio.CancelledError:
if sys.version_info >= (3, 11) and (task := asyncio.current_task()) and task.cancelling():
if (task := asyncio.current_task()) and task.cancelling():
raise
finally:
handle.cancel()
Expand Down
5 changes: 3 additions & 2 deletions src/zeroconf/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import contextlib
from collections.abc import Awaitable, Callable
from types import TracebackType # used in type hints
from typing import Self

from ._core import Zeroconf
from ._dns import DNSQuestionType
Expand Down Expand Up @@ -48,7 +49,7 @@ def __init__(
super().__init__(zeroconf, type_, handlers, listener, addr, port, delay, question_type)
self._async_start()

async def __aenter__(self) -> AsyncServiceBrowser:
async def __aenter__(self) -> Self:
return self

async def __aexit__(
Expand Down Expand Up @@ -138,7 +139,7 @@ def __init__(
)
self.async_browsers: dict[ServiceListener, AsyncServiceBrowser] = {}

async def __aenter__(self) -> AsyncZeroconf:
async def __aenter__(self) -> Self:
return self

async def __aexit__(
Expand Down
Loading
Loading