Describe the feature you want to add
The thread-local adapters (Issue #2) provide full concurrency for multi-threaded applications. However, threading.local() does not propagate values into asyncio tasks or coroutines. Applications using asyncio with thread pools, or frameworks like aiohttp that run synchronous code in executors, will not see the correct filter.
We need an adapter that is both thread-safe and async-safe, correctly propagating the address family filter across context boundaries.
Describe your proposed solution
Introduce IPv4ContextVarAdapter and IPv6ContextVarAdapter that use contextvars.ContextVar (Python 3.7+):
- Same dispatch pattern as thread-local:
socket.getaddrinfo is replaced once with a dispatcher
- The dispatcher reads from a
ContextVar instead of threading.local()
- Each adapter's
send() uses the token-based set()/reset() API to scope the filter precisely to the current call
ContextVar values automatically propagate into asyncio.Task and loop.run_in_executor() contexts
Key properties:
- Fully concurrent (no locks during request)
- Async-safe: correct in
asyncio, trio, and hybrid thread+async applications
- Compatible with Python 3.7+ (contextvars is in stdlib since 3.7)
Describe alternatives you've considered, if relevant
No response
Additional context
No response
Describe the feature you want to add
The thread-local adapters (Issue #2) provide full concurrency for multi-threaded applications. However,
threading.local()does not propagate values into asyncio tasks or coroutines. Applications usingasynciowith thread pools, or frameworks likeaiohttpthat run synchronous code in executors, will not see the correct filter.We need an adapter that is both
thread-safeandasync-safe, correctly propagating the address family filter across context boundaries.Describe your proposed solution
Introduce
IPv4ContextVarAdapterandIPv6ContextVarAdapterthat usecontextvars.ContextVar(Python 3.7+):socket.getaddrinfois replaced once with a dispatcherContextVarinstead ofthreading.local()send()uses the token-basedset()/reset()API to scope the filter precisely to the current callContextVarvalues automatically propagate intoasyncio.Taskandloop.run_in_executor()contextsKey properties:
asyncio,trio, and hybrid thread+async applicationsDescribe alternatives you've considered, if relevant
No response
Additional context
No response