generated from deepin-community/template-repository-main
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1a98a3d
commit b92fba2
Showing
27 changed files
with
797 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# python specific | ||
*.pyc | ||
*.so | ||
*.pyd | ||
build/* | ||
dist/* | ||
MANIFEST | ||
__pycache__/ | ||
*.egg-info/ | ||
|
||
# generic files to ignore | ||
*~ | ||
*.lock | ||
*.DS_Store | ||
*.swp | ||
*.out | ||
|
||
.tox/ | ||
deps/ | ||
docs/_build/ | ||
.mypy_cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
3.0.0 | ||
===== | ||
- Release wheels and source to PyPI with GH actions | ||
- Try to make tests more resilient | ||
- Don't build universal wheels | ||
- Migrate CI to GH Actions | ||
- Fix TXT CHAOS test | ||
- Add support for CAA queries | ||
- Support Python >= 3.6 | ||
- Bump pycares dependency | ||
- Drop tasks.py | ||
- Allow specifying dnsclass for queries | ||
- Set URL to https | ||
- Add license args in setup.py | ||
- Converted Type Annotations to Py3 syntax Closes | ||
- Only run mypy on cpython versions | ||
- Also fix all type errors with latest mypy - pycares seems to have no typing / stubs so lets ignore it via `mypy.ini` | ||
- setup: typing exists since Python 3.5 | ||
- Fix type annotation of gethostbyname() | ||
- Updated README | ||
|
||
2.0.0 | ||
===== | ||
(changes since version 1.x) | ||
|
||
- Drop support for Python < 3.5 | ||
- Add support for ANY queries | ||
- Raise pycares dependency | ||
|
||
2.0.0b2 | ||
======= | ||
- Raise pycares dependency | ||
|
||
2.0.0b1 | ||
======= | ||
- Fix using typing on Python 3.7 | ||
|
||
2.0.0b0 | ||
======= | ||
- Drop support for Python < 3.5 | ||
- Add support for ANY queries | ||
- Raise pycares dependency | ||
|
||
1.2.0 | ||
===== | ||
- Add support for Python 3.7 | ||
- Fix CNAME test | ||
- Add examples with `async` and `await` | ||
- Fix Python version check | ||
- Add gethostbyaddr | ||
|
||
1.1.1 | ||
===== | ||
- Use per-version requires for wheels | ||
|
||
1.1.0 | ||
===== | ||
- Add DNSResolver.gethostbyname() | ||
- Build universal wheels | ||
|
||
1.0.1 | ||
===== | ||
- Fix including tests and ChangeLog in source distributions | ||
|
||
1.0.0 | ||
===== | ||
- Use pycares >= 1.0.0 | ||
- Fix tests | ||
|
||
0.3.2 | ||
===== | ||
- setup: Fix decoding in non-UTF-8 environments | ||
|
||
0.3.1 | ||
===== | ||
- Adapt to Trollius package rename | ||
- Fixed stopping watching file descriptor | ||
|
||
0.3.0 | ||
===== | ||
- Add DNSResolver.cancel method | ||
- Handle case when the Future returned by query() is cancelled | ||
|
||
0.2.0 | ||
===== | ||
- Add support for Trollius | ||
- Don't make query() a coroutine, just return the future | ||
- Raise ValueError if specified query type is invalid | ||
|
||
0.1.0 | ||
===== | ||
- Initial release | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Copyright (C) 2014 by Saúl Ibarra Corretgé | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
include README.rst LICENSE ChangeLog | ||
include setup.py tests.py | ||
recursive-exclude * __pycache__ | ||
recursive-exclude * *.py[co] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
=============================== | ||
Simple DNS resolver for asyncio | ||
=============================== | ||
|
||
.. image:: https://badge.fury.io/py/aiodns.png | ||
:target: https://pypi.org/project/aiodns/ | ||
|
||
.. image:: https://github.com/saghul/aiodns/workflows/CI/badge.svg | ||
:target: https://github.com/saghul/aiodns/actions | ||
|
||
aiodns provides a simple way for doing asynchronous DNS resolutions using `pycares <https://github.com/saghul/pycares>`_. | ||
|
||
|
||
Example | ||
======= | ||
|
||
.. code:: python | ||
import asyncio | ||
import aiodns | ||
loop = asyncio.get_event_loop() | ||
resolver = aiodns.DNSResolver(loop=loop) | ||
async def query(name, query_type): | ||
return await resolver.query(name, query_type) | ||
coro = query('google.com', 'A') | ||
result = loop.run_until_complete(coro) | ||
The following query types are supported: A, AAAA, ANY, CAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, TXT. | ||
|
||
|
||
API | ||
=== | ||
|
||
The API is pretty simple, three 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/en/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/en/latest/channel.html#pycares.Channel.gethostbyname>`_ | ||
for the result fields. The actual result of the call is a ``asyncio.Future``. | ||
* ``gethostbyaddr(name)``: Make a reverse lookup for an address. | ||
* ``cancel()``: Cancel all pending DNS queries. All futures will get ``DNSError`` exception set, with | ||
``ARES_ECANCELLED`` errno. | ||
|
||
|
||
Running the test suite | ||
====================== | ||
|
||
To run the test suite: ``python tests.py`` | ||
|
||
|
||
Author | ||
====== | ||
|
||
Saúl Ibarra Corretgé <[email protected]> | ||
|
||
|
||
License | ||
======= | ||
|
||
aiodns uses the MIT license, check LICENSE file. | ||
|
||
|
||
Python versions | ||
=============== | ||
|
||
Python >= 3.6 are supported. | ||
|
||
|
||
Contributing | ||
============ | ||
|
||
If you'd like to contribute, fork the project, make a patch and send a pull | ||
request. Have a look at the surrounding code and please, make yours look | ||
alike :-) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
|
||
import asyncio | ||
import functools | ||
import pycares | ||
import socket | ||
|
||
from typing import ( | ||
Any, | ||
List, | ||
Optional, | ||
Set | ||
) | ||
|
||
from . import error | ||
|
||
|
||
__version__ = '3.0.0' | ||
|
||
__all__ = ('DNSResolver', 'error') | ||
|
||
|
||
READ = 1 | ||
WRITE = 2 | ||
|
||
query_type_map = {'A' : pycares.QUERY_TYPE_A, | ||
'AAAA' : pycares.QUERY_TYPE_AAAA, | ||
'ANY' : pycares.QUERY_TYPE_ANY, | ||
'CAA' : pycares.QUERY_TYPE_CAA, | ||
'CNAME' : pycares.QUERY_TYPE_CNAME, | ||
'MX' : pycares.QUERY_TYPE_MX, | ||
'NAPTR' : pycares.QUERY_TYPE_NAPTR, | ||
'NS' : pycares.QUERY_TYPE_NS, | ||
'PTR' : pycares.QUERY_TYPE_PTR, | ||
'SOA' : pycares.QUERY_TYPE_SOA, | ||
'SRV' : pycares.QUERY_TYPE_SRV, | ||
'TXT' : pycares.QUERY_TYPE_TXT | ||
} | ||
|
||
query_class_map = {'IN' : pycares.QUERY_CLASS_IN, | ||
'CHAOS' : pycares.QUERY_CLASS_CHAOS, | ||
'HS' : pycares.QUERY_CLASS_HS, | ||
'NONE' : pycares.QUERY_CLASS_NONE, | ||
'ANY' : pycares.QUERY_CLASS_ANY | ||
} | ||
|
||
class DNSResolver: | ||
def __init__(self, nameservers: Optional[List[str]] = None, | ||
loop: Optional[asyncio.AbstractEventLoop] = None, | ||
**kwargs: Any) -> None: | ||
self.loop = loop or asyncio.get_event_loop() | ||
assert self.loop is not None | ||
kwargs.pop('sock_state_cb', None) | ||
self._channel = pycares.Channel(sock_state_cb=self._sock_state_cb, **kwargs) | ||
if nameservers: | ||
self.nameservers = nameservers | ||
self._read_fds = set() # type: Set[int] | ||
self._write_fds = set() # type: Set[int] | ||
self._timer = None # type: Optional[asyncio.TimerHandle] | ||
|
||
@property | ||
def nameservers(self) -> pycares.Channel: | ||
return self._channel.servers | ||
|
||
@nameservers.setter | ||
def nameservers(self, value: List[str]) -> None: | ||
self._channel.servers = value | ||
|
||
@staticmethod | ||
def _callback(fut: asyncio.Future, result: Any, errorno: int) -> None: | ||
if fut.cancelled(): | ||
return | ||
if errorno is not None: | ||
fut.set_exception(error.DNSError(errorno, pycares.errno.strerror(errorno))) | ||
else: | ||
fut.set_result(result) | ||
|
||
def query(self, host: str, qtype: str, qclass: str=None) -> asyncio.Future: | ||
try: | ||
qtype = query_type_map[qtype] | ||
except KeyError: | ||
raise ValueError('invalid query type: {}'.format(qtype)) | ||
if qclass is not None: | ||
try: | ||
qclass = query_class_map[qclass] | ||
except KeyError: | ||
raise ValueError('invalid query class: {}'.format(qclass)) | ||
|
||
fut = asyncio.Future(loop=self.loop) # type: asyncio.Future | ||
cb = functools.partial(self._callback, fut) | ||
self._channel.query(host, qtype, cb, query_class=qclass) | ||
return fut | ||
|
||
def gethostbyname(self, host: str, family: socket.AddressFamily) -> asyncio.Future: | ||
fut = asyncio.Future(loop=self.loop) # type: asyncio.Future | ||
cb = functools.partial(self._callback, fut) | ||
self._channel.gethostbyname(host, family, cb) | ||
return fut | ||
|
||
def gethostbyaddr(self, name: str) -> asyncio.Future: | ||
fut = asyncio.Future(loop=self.loop) # type: asyncio.Future | ||
cb = functools.partial(self._callback, fut) | ||
self._channel.gethostbyaddr(name, cb) | ||
return fut | ||
|
||
def cancel(self) -> None: | ||
self._channel.cancel() | ||
|
||
def _sock_state_cb(self, fd: int, readable: bool, writable: bool) -> None: | ||
if readable or writable: | ||
if readable: | ||
self.loop.add_reader(fd, self._handle_event, fd, READ) | ||
self._read_fds.add(fd) | ||
if writable: | ||
self.loop.add_writer(fd, self._handle_event, fd, WRITE) | ||
self._write_fds.add(fd) | ||
if self._timer is None: | ||
self._timer = self.loop.call_later(1.0, self._timer_cb) | ||
else: | ||
# socket is now closed | ||
if fd in self._read_fds: | ||
self._read_fds.discard(fd) | ||
self.loop.remove_reader(fd) | ||
|
||
if fd in self._write_fds: | ||
self._write_fds.discard(fd) | ||
self.loop.remove_writer(fd) | ||
|
||
if not self._read_fds and not self._write_fds and self._timer is not None: | ||
self._timer.cancel() | ||
self._timer = None | ||
|
||
def _handle_event(self, fd: int, event: Any) -> None: | ||
read_fd = pycares.ARES_SOCKET_BAD | ||
write_fd = pycares.ARES_SOCKET_BAD | ||
if event == READ: | ||
read_fd = fd | ||
elif event == WRITE: | ||
write_fd = fd | ||
self._channel.process_fd(read_fd, write_fd) | ||
|
||
def _timer_cb(self) -> None: | ||
if self._read_fds or self._write_fds: | ||
self._channel.process_fd(pycares.ARES_SOCKET_BAD, pycares.ARES_SOCKET_BAD) | ||
self._timer = self.loop.call_later(1.0, self._timer_cb) | ||
else: | ||
self._timer = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
import pycares | ||
|
||
for code, name in pycares.errno.errorcode.items(): | ||
globals()[name] = code | ||
|
||
|
||
class DNSError(Exception): | ||
pass | ||
|
Oops, something went wrong.