Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5142603
Add support for pycares 5
bdraco Dec 11, 2025
9d8a68e
Add support for pycares 5
bdraco Dec 11, 2025
361fb62
Add support for pycares 5
bdraco Dec 11, 2025
212aa30
fixes
bdraco Dec 11, 2025
db65ca3
fixes
bdraco Dec 11, 2025
78e350d
fixes
bdraco Dec 11, 2025
ce2d3f4
fixes
bdraco Dec 11, 2025
1cb6720
fixes
bdraco Dec 11, 2025
b264b62
fixes
bdraco Dec 11, 2025
dc2aab9
fixes
bdraco Dec 11, 2025
5419903
compat tests
bdraco Dec 11, 2025
4dd4f80
fixes
bdraco Dec 11, 2025
741a22f
fixes
bdraco Dec 11, 2025
2801db7
minimize change
bdraco Dec 11, 2025
bf68807
minimize change
bdraco Dec 11, 2025
f218c46
minimize change
bdraco Dec 11, 2025
4a29cad
minimize change
bdraco Dec 11, 2025
5061ac0
minimize change
bdraco Dec 11, 2025
f119bce
more typing fixes
bdraco Dec 11, 2025
a5b24b8
more typing fixes
bdraco Dec 11, 2025
42b7419
more typing fixes
bdraco Dec 11, 2025
3dc5199
more typing fixes
bdraco Dec 11, 2025
e5d7690
more typing fixes
bdraco Dec 11, 2025
2e0af6f
socket state fallback path test
bdraco Dec 11, 2025
824ea45
fix win32 test
bdraco Dec 11, 2025
3a9fce0
more typing
bdraco Dec 11, 2025
a5ef8f7
add missing coverage
bdraco Dec 11, 2025
84c4ed8
more windows test fixes
bdraco Dec 11, 2025
f8b5ce3
pycares no longer works with pypy
bdraco Dec 11, 2025
d3f7f69
make sure it works on 3.14t as well
bdraco Dec 11, 2025
ea162cd
fix missing coverage
bdraco Dec 11, 2025
b299d69
restore some lost coverage
bdraco Dec 11, 2025
fad285d
typing fixes
bdraco Dec 11, 2025
6540001
restore some missing coverage
bdraco Dec 11, 2025
e98a218
restore some missing coverage
bdraco Dec 11, 2025
450166d
missing classifer
bdraco Dec 11, 2025
108ac66
tweaks
bdraco Dec 11, 2025
2fc55b1
revert
bdraco Dec 11, 2025
6f88df0
back compat for nameservers
bdraco Dec 11, 2025
9428d46
deprecate query, add query_dns
bdraco Dec 11, 2025
c76550c
update docs
bdraco Dec 11, 2025
68cb7a0
add some more cover
bdraco Dec 11, 2025
2858193
add some more cover
bdraco Dec 11, 2025
d297fdf
ensure bytes/str types match pycares 4
bdraco Jan 8, 2026
83e8076
lint docs
bdraco Jan 8, 2026
fd50623
weakref comment
bdraco Jan 8, 2026
aadf9ee
preen, add dep warning to gethostbyname
bdraco Jan 8, 2026
969e959
deprecate gethostbyname
bdraco Jan 8, 2026
c98aa51
remove legacy types
bdraco Jan 8, 2026
64ec571
cleanup
bdraco Jan 8, 2026
1039fed
import from compat in tests
bdraco Jan 8, 2026
9821f07
cleanup
bdraco Jan 8, 2026
b2cd50a
cleanup
bdraco Jan 8, 2026
9980ea4
fix ptr back compat
bdraco Jan 8, 2026
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
8 changes: 1 addition & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13', '3.14' ]
exclude:
- os: macos-latest
python-version: 3.9
include:
- python-version: pypy-3.9
os: ubuntu-latest
python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14', '3.14t' ]
Comment thread
bdraco marked this conversation as resolved.
timeout-minutes: 15
steps:
- name: Checkout
Expand Down
82 changes: 60 additions & 22 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@ Example
import asyncio
import aiodns

loop = asyncio.get_event_loop()
resolver = aiodns.DNSResolver(loop=loop)
async def main():
resolver = aiodns.DNSResolver()
result = await resolver.query_dns('google.com', 'A')
for record in result.answer:
print(record.data.addr)

async def query(name, query_type):
return await resolver.query(name, query_type)

coro = query('google.com', 'A')
result = loop.run_until_complete(coro)
asyncio.run(main())


The following query types are supported: A, AAAA, ANY, CAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, TXT.
Expand All @@ -37,27 +36,66 @@ API

The API is pretty simple, the following functions are provided in the ``DNSResolver`` class:

* ``query(host, type)``: Do a DNS resolution of the given type for the given hostname. It returns an
instance of ``asyncio.Future``. The actual result of the DNS query is taken directly from pycares.
As of version 1.0.0 of aiodns (and pycares, for that matter) results are always namedtuple-like
objects with different attributes. Please check the `documentation
<http://pycares.readthedocs.org/latest/channel.html#pycares.Channel.query>`_
for the result fields.
* ``gethostbyname(host, socket_family)``: Do a DNS resolution for the given
hostname and the desired type of address family (i.e. ``socket.AF_INET``).
While ``query()`` always performs a request to a DNS server,
``gethostbyname()`` first looks into ``/etc/hosts`` and thus can resolve
local hostnames (such as ``localhost``). Please check `the documentation
<http://pycares.readthedocs.io/latest/channel.html#pycares.Channel.gethostbyname>`_
for the result fields. The actual result of the call is a ``asyncio.Future``.
* ``query_dns(host, type)``: Do a DNS resolution of the given type for the given hostname. It returns an
instance of ``asyncio.Future``. The result is a ``pycares.DNSResult`` object with ``answer``,
``authority``, and ``additional`` attributes containing lists of ``pycares.DNSRecord`` objects.
Each record has ``type``, ``ttl``, and ``data`` attributes. Check the `pycares documentation
<https://pycares.readthedocs.io/>`_ for details on the data attributes for each record type.
* ``query(host, type)``: **Deprecated** - use ``query_dns()`` instead. This method returns results
in a legacy format compatible with aiodns 3.x for backward compatibility.
* ``gethostbyname(host, socket_family)``: **Deprecated** - use ``getaddrinfo()`` instead.
Do a DNS resolution for the given hostname and the desired type of address family
(i.e. ``socket.AF_INET``). The actual result of the call is a ``asyncio.Future``.
* ``gethostbyaddr(name)``: Make a reverse lookup for an address.
* ``getaddrinfo(host, family, port, proto, type, flags)``: Resolve a host and port into a list of
address info entries.
* ``getnameinfo(sockaddr, flags)``: Resolve a socket address to a host and port.
* ``cancel()``: Cancel all pending DNS queries. All futures will get ``DNSError`` exception set, with
``ARES_ECANCELLED`` errno.
* ``close()``: Close the resolver. This releases all resources and cancels any pending queries. It must be called
when the resolver is no longer needed (e.g., application shutdown). The resolver should only be closed from the
event loop that created the resolver.


Migrating from aiodns 3.x
=========================

aiodns 4.x introduces a new ``query_dns()`` method that returns native pycares 5.x result types.
Comment thread
bdraco marked this conversation as resolved.
See the `pycares documentation <https://pycares.readthedocs.io/latest/channel.html#pycares.Channel.query>`_
for details on the result types. The old ``query()`` method is deprecated but continues to work
for backward compatibility.

.. code:: python

# Old API (deprecated)
result = await resolver.query('example.com', 'MX')
for record in result:
print(record.host, record.priority)

# New API (recommended)
result = await resolver.query_dns('example.com', 'MX')
for record in result.answer:
print(record.data.exchange, record.data.priority)


Future migration to aiodns 5.x
------------------------------

The temporary ``query_dns()`` naming allows gradual migration without breaking changes:

+-----------+---------------------------------------+--------------------------------------------+
| Version | ``query()`` | ``query_dns()`` |
+===========+=======================================+============================================+
| **4.x** | Deprecated, returns compat types | New API, returns pycares 5.x types |
+-----------+---------------------------------------+--------------------------------------------+
| **5.x** | New API, returns pycares 5.x types | Alias to ``query()`` for back compat |
+-----------+---------------------------------------+--------------------------------------------+

In aiodns 5.x, ``query()`` will become the primary API returning native pycares 5.x types,
and ``query_dns()`` will remain as an alias for backward compatibility. This allows downstream
projects to migrate at their own pace.


Async Context Manager Support
=============================

Expand All @@ -67,7 +105,7 @@ for scenarios where automatic cleanup is desired:
.. code:: python

async with aiodns.DNSResolver() as resolver:
result = await resolver.query('example.com', 'A')
result = await resolver.query_dns('example.com', 'A')
# resolver.close() is called automatically when exiting the context

**Important**: This pattern is discouraged for most applications because ``DNSResolver`` instances
Expand Down Expand Up @@ -101,7 +139,7 @@ This may have other implications for the rest of your codebase, so make sure to
Running the test suite
======================

To run the test suite: ``python tests.py``
To run the test suite: ``python -m pytest tests/``


Author
Expand Down
Loading