pycares 4.9.0__cp310-cp310-win_arm64.whl
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.
- pycares/__init__.py +1083 -0
- pycares/__main__.py +84 -0
- pycares/_cares.pyd +0 -0
- pycares/_version.py +2 -0
- pycares/errno.py +69 -0
- pycares/py.typed +0 -0
- pycares/utils.py +53 -0
- pycares-4.9.0.dist-info/METADATA +164 -0
- pycares-4.9.0.dist-info/RECORD +12 -0
- pycares-4.9.0.dist-info/WHEEL +5 -0
- pycares-4.9.0.dist-info/licenses/LICENSE +20 -0
- pycares-4.9.0.dist-info/top_level.txt +2 -0
pycares/__main__.py
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
import collections.abc
|
3
|
+
import pycares
|
4
|
+
import select
|
5
|
+
import socket
|
6
|
+
import sys
|
7
|
+
|
8
|
+
|
9
|
+
def wait_channel(channel):
|
10
|
+
while True:
|
11
|
+
read_fds, write_fds = channel.getsock()
|
12
|
+
if not read_fds and not write_fds:
|
13
|
+
break
|
14
|
+
timeout = channel.timeout()
|
15
|
+
if not timeout:
|
16
|
+
channel.process_fd(pycares.ARES_SOCKET_BAD, pycares.ARES_SOCKET_BAD)
|
17
|
+
continue
|
18
|
+
rlist, wlist, xlist = select.select(read_fds, write_fds, [], timeout)
|
19
|
+
for fd in rlist:
|
20
|
+
channel.process_fd(fd, pycares.ARES_SOCKET_BAD)
|
21
|
+
for fd in wlist:
|
22
|
+
channel.process_fd(pycares.ARES_SOCKET_BAD, fd)
|
23
|
+
|
24
|
+
|
25
|
+
def cb(result, error):
|
26
|
+
if error is not None:
|
27
|
+
print('Error: (%d) %s' % (error, pycares.errno.strerror(error)))
|
28
|
+
else:
|
29
|
+
parts = [
|
30
|
+
';; QUESTION SECTION:',
|
31
|
+
';%s\t\t\tIN\t%s' % (hostname, qtype.upper()),
|
32
|
+
'',
|
33
|
+
';; ANSWER SECTION:'
|
34
|
+
]
|
35
|
+
|
36
|
+
if not isinstance(result, collections.abc.Iterable):
|
37
|
+
result = [result]
|
38
|
+
|
39
|
+
for r in result:
|
40
|
+
txt = '%s\t\t%d\tIN\t%s' % (hostname, r.ttl, r.type)
|
41
|
+
if r.type in ('A', 'AAAA'):
|
42
|
+
parts.append('%s\t%s' % (txt, r.host))
|
43
|
+
elif r.type == 'CAA':
|
44
|
+
parts.append('%s\t%d %s "%s"' % (txt, r.critical, r.property, r.value))
|
45
|
+
elif r.type == 'CNAME':
|
46
|
+
parts.append('%s\t%s' % (txt, r.cname))
|
47
|
+
elif r.type == 'MX':
|
48
|
+
parts.append('%s\t%d %s' % (txt, r.priority, r.host))
|
49
|
+
elif r.type == 'NAPTR':
|
50
|
+
parts.append('%s\t%d %d "%s" "%s" "%s" %s' % (txt, r.order, r.preference, r.flags, r.service, r.regex, r.replacement))
|
51
|
+
elif r.type == 'NS':
|
52
|
+
parts.append('%s\t%s' % (txt, r.host))
|
53
|
+
elif r.type == 'PTR':
|
54
|
+
parts.append('%s\t%s' % (txt, r.name))
|
55
|
+
elif r.type == 'SOA':
|
56
|
+
parts.append('%s\t%s %s %d %d %d %d %d' % (txt, r.nsname, r.hostmaster, r.serial, r.refresh, r.retry, r.expires, r.minttl))
|
57
|
+
elif r.type == 'SRV':
|
58
|
+
parts.append('%s\t%d %d %d %s' % (txt, r.priority, r.weight, r.port, r.host))
|
59
|
+
elif r.type == 'TXT':
|
60
|
+
parts.append('%s\t"%s"' % (txt, r.text))
|
61
|
+
|
62
|
+
print('\n'.join(parts))
|
63
|
+
|
64
|
+
|
65
|
+
channel = pycares.Channel()
|
66
|
+
|
67
|
+
if len(sys.argv) not in (2, 3):
|
68
|
+
print('Invalid arguments! Usage: python -m pycares [query_type] hostname')
|
69
|
+
sys.exit(1)
|
70
|
+
|
71
|
+
if len(sys.argv) == 2:
|
72
|
+
_, hostname = sys.argv
|
73
|
+
qtype = 'A'
|
74
|
+
else:
|
75
|
+
_, qtype, hostname = sys.argv
|
76
|
+
|
77
|
+
try:
|
78
|
+
query_type = getattr(pycares, 'QUERY_TYPE_%s' % qtype.upper())
|
79
|
+
except Exception:
|
80
|
+
print('Invalid query type: %s' % qtype)
|
81
|
+
sys.exit(1)
|
82
|
+
|
83
|
+
channel.query(hostname, query_type, cb)
|
84
|
+
wait_channel(channel)
|
pycares/_cares.pyd
ADDED
Binary file
|
pycares/_version.py
ADDED
pycares/errno.py
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
from typing import Union
|
2
|
+
|
3
|
+
from ._cares import ffi as _ffi, lib as _lib
|
4
|
+
from .utils import maybe_str
|
5
|
+
|
6
|
+
ARES_SUCCESS = _lib.ARES_SUCCESS
|
7
|
+
# error codes
|
8
|
+
ARES_ENODATA = _lib.ARES_ENODATA
|
9
|
+
ARES_EFORMERR = _lib.ARES_EFORMERR
|
10
|
+
ARES_ESERVFAIL = _lib.ARES_ESERVFAIL
|
11
|
+
ARES_ENOTFOUND = _lib.ARES_ENOTFOUND
|
12
|
+
ARES_ENOTIMP = _lib.ARES_ENOTIMP
|
13
|
+
ARES_EREFUSED = _lib.ARES_EREFUSED
|
14
|
+
ARES_EBADQUERY = _lib.ARES_EBADQUERY
|
15
|
+
ARES_EBADNAME = _lib.ARES_EBADNAME
|
16
|
+
ARES_EBADFAMILY = _lib.ARES_EBADFAMILY
|
17
|
+
ARES_EBADRESP = _lib.ARES_EBADRESP
|
18
|
+
ARES_ECONNREFUSED = _lib.ARES_ECONNREFUSED
|
19
|
+
ARES_ETIMEOUT = _lib.ARES_ETIMEOUT
|
20
|
+
ARES_EOF = _lib.ARES_EOF
|
21
|
+
ARES_EFILE = _lib.ARES_EFILE
|
22
|
+
ARES_ENOMEM = _lib.ARES_ENOMEM
|
23
|
+
ARES_EDESTRUCTION = _lib.ARES_EDESTRUCTION
|
24
|
+
ARES_EBADSTR = _lib.ARES_EBADSTR
|
25
|
+
ARES_EBADFLAGS = _lib.ARES_EBADFLAGS
|
26
|
+
ARES_ENONAME = _lib.ARES_ENONAME
|
27
|
+
ARES_EBADHINTS = _lib.ARES_EBADHINTS
|
28
|
+
ARES_ENOTINITIALIZED = _lib.ARES_ENOTINITIALIZED
|
29
|
+
ARES_ELOADIPHLPAPI = _lib.ARES_ELOADIPHLPAPI
|
30
|
+
ARES_EADDRGETNETWORKPARAMS = _lib.ARES_EADDRGETNETWORKPARAMS
|
31
|
+
ARES_ECANCELLED = _lib.ARES_ECANCELLED
|
32
|
+
ARES_ESERVICE = _lib.ARES_ESERVICE
|
33
|
+
|
34
|
+
errorcode = {
|
35
|
+
ARES_SUCCESS: "ARES_SUCCESS",
|
36
|
+
# error codes
|
37
|
+
ARES_ENODATA: "ARES_ENODATA",
|
38
|
+
ARES_EFORMERR: "ARES_EFORMERR",
|
39
|
+
ARES_ESERVFAIL: "ARES_ESERVFAIL",
|
40
|
+
ARES_ENOTFOUND: "ARES_ENOTFOUND",
|
41
|
+
ARES_ENOTIMP: "ARES_ENOTIMP",
|
42
|
+
ARES_EREFUSED: "ARES_EREFUSED",
|
43
|
+
ARES_EBADQUERY: "ARES_EBADQUERY",
|
44
|
+
ARES_EBADNAME: "ARES_EBADNAME",
|
45
|
+
ARES_EBADFAMILY: "ARES_EBADFAMILY",
|
46
|
+
ARES_EBADRESP: "ARES_EBADRESP",
|
47
|
+
ARES_ECONNREFUSED: "ARES_ECONNREFUSED",
|
48
|
+
ARES_ETIMEOUT: "ARES_ETIMEOUT",
|
49
|
+
ARES_EOF: "ARES_EOF",
|
50
|
+
ARES_EFILE: "ARES_EFILE",
|
51
|
+
ARES_ENOMEM: "ARES_ENOMEM",
|
52
|
+
ARES_EDESTRUCTION: "ARES_EDESTRUCTION",
|
53
|
+
ARES_EBADSTR: "ARES_EBADSTR",
|
54
|
+
ARES_EBADFLAGS: "ARES_EBADFLAGS",
|
55
|
+
ARES_ENONAME: "ARES_ENONAME",
|
56
|
+
ARES_EBADHINTS: "ARES_EBADHINTS",
|
57
|
+
ARES_ENOTINITIALIZED: "ARES_ENOTINITIALIZED",
|
58
|
+
ARES_ELOADIPHLPAPI: "ARES_ELOADIPHLPAPI",
|
59
|
+
ARES_EADDRGETNETWORKPARAMS: "ARES_EADDRGETNETWORKPARAMS",
|
60
|
+
ARES_ECANCELLED: "ARES_ECANCELLED",
|
61
|
+
ARES_ESERVICE: "ARES_ESERVICE",
|
62
|
+
}
|
63
|
+
|
64
|
+
|
65
|
+
def strerror(code: int) -> Union[str, bytes]:
|
66
|
+
return maybe_str(_ffi.string(_lib.ares_strerror(code)))
|
67
|
+
|
68
|
+
|
69
|
+
__all__ = ("errorcode", "strerror", *errorcode.values())
|
pycares/py.typed
ADDED
File without changes
|
pycares/utils.py
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
from typing import Union
|
3
|
+
|
4
|
+
try:
|
5
|
+
import idna as idna2008
|
6
|
+
except ImportError:
|
7
|
+
idna2008 = None
|
8
|
+
|
9
|
+
|
10
|
+
def ascii_bytes(data):
|
11
|
+
if isinstance(data, str):
|
12
|
+
return data.encode('ascii')
|
13
|
+
if isinstance(data, bytes):
|
14
|
+
return data
|
15
|
+
raise TypeError('only str (ascii encoding) and bytes are supported')
|
16
|
+
|
17
|
+
|
18
|
+
def maybe_str(data):
|
19
|
+
if isinstance(data, str):
|
20
|
+
return data
|
21
|
+
if isinstance(data, bytes):
|
22
|
+
try:
|
23
|
+
return data.decode('ascii')
|
24
|
+
except UnicodeDecodeError:
|
25
|
+
return data
|
26
|
+
raise TypeError('only str (ascii encoding) and bytes are supported')
|
27
|
+
|
28
|
+
|
29
|
+
def parse_name_idna2008(name: str) -> str:
|
30
|
+
parts = name.split('.')
|
31
|
+
r = []
|
32
|
+
for part in parts:
|
33
|
+
if part.isascii():
|
34
|
+
r.append(part.encode('ascii'))
|
35
|
+
else:
|
36
|
+
r.append(idna2008.encode(part))
|
37
|
+
return b'.'.join(r)
|
38
|
+
|
39
|
+
|
40
|
+
def parse_name(name: Union[str, bytes]) -> bytes:
|
41
|
+
if isinstance(name, str):
|
42
|
+
if name.isascii():
|
43
|
+
return name.encode('ascii')
|
44
|
+
if idna2008 is not None:
|
45
|
+
return parse_name_idna2008(name)
|
46
|
+
return name.encode('idna')
|
47
|
+
if isinstance(name, bytes):
|
48
|
+
return name
|
49
|
+
raise TypeError('only str and bytes are supported')
|
50
|
+
|
51
|
+
|
52
|
+
__all__ = ['ascii_bytes', 'maybe_str', 'parse_name']
|
53
|
+
|
@@ -0,0 +1,164 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: pycares
|
3
|
+
Version: 4.9.0
|
4
|
+
Summary: Python interface for c-ares
|
5
|
+
Home-page: http://github.com/saghul/pycares
|
6
|
+
Author: Saúl Ibarra Corretgé
|
7
|
+
Author-email: s@saghul.net
|
8
|
+
License: MIT
|
9
|
+
Platform: POSIX
|
10
|
+
Platform: Microsoft Windows
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
12
|
+
Classifier: Intended Audience :: Developers
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
14
|
+
Classifier: Operating System :: POSIX
|
15
|
+
Classifier: Operating System :: Microsoft :: Windows
|
16
|
+
Classifier: Programming Language :: Python
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
23
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
24
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
25
|
+
Requires-Python: >=3.9
|
26
|
+
Description-Content-Type: text/x-rst
|
27
|
+
License-File: LICENSE
|
28
|
+
Requires-Dist: cffi>=1.5.0
|
29
|
+
Provides-Extra: idna
|
30
|
+
Requires-Dist: idna>=2.1; extra == "idna"
|
31
|
+
Dynamic: author
|
32
|
+
Dynamic: author-email
|
33
|
+
Dynamic: classifier
|
34
|
+
Dynamic: description
|
35
|
+
Dynamic: description-content-type
|
36
|
+
Dynamic: home-page
|
37
|
+
Dynamic: license
|
38
|
+
Dynamic: license-file
|
39
|
+
Dynamic: platform
|
40
|
+
Dynamic: provides-extra
|
41
|
+
Dynamic: requires-dist
|
42
|
+
Dynamic: requires-python
|
43
|
+
Dynamic: summary
|
44
|
+
|
45
|
+
Looking for new maintainers
|
46
|
+
===========================
|
47
|
+
|
48
|
+
https://github.com/saghul/pycares/issues/139
|
49
|
+
|
50
|
+
pycares: Python interface for c-ares
|
51
|
+
====================================
|
52
|
+
|
53
|
+
pycares is a Python module which provides an interface to c-ares.
|
54
|
+
`c-ares <https://c-ares.org>`_ is a C library that performs
|
55
|
+
DNS requests and name resolutions asynchronously.
|
56
|
+
|
57
|
+
|
58
|
+
Documentation
|
59
|
+
-------------
|
60
|
+
|
61
|
+
http://readthedocs.org/docs/pycares/
|
62
|
+
|
63
|
+
|
64
|
+
Bundled c-ares
|
65
|
+
--------------
|
66
|
+
|
67
|
+
pycares currently bundles c-ares as a submodule for ease of building. Using the system
|
68
|
+
provided c-ares is possible if the ``PYCARES_USE_SYSTEM_LIB`` environment variable is
|
69
|
+
set to ``1`` when building.
|
70
|
+
|
71
|
+
NOTE: Versions prior to 4.0.0 used to embed a modified c-ares with extended TTL support.
|
72
|
+
That is no longer the case and as a result only A and AAAA records will have TTL information.
|
73
|
+
Follow this PR in uppstream c-ares, looks like TTLs will be added: https://github.com/c-ares/c-ares/pull/393
|
74
|
+
|
75
|
+
|
76
|
+
Installation
|
77
|
+
------------
|
78
|
+
|
79
|
+
GNU/Linux, macOS, Windows, others:
|
80
|
+
|
81
|
+
::
|
82
|
+
|
83
|
+
pip install pycares
|
84
|
+
|
85
|
+
FreeBSD:
|
86
|
+
|
87
|
+
::
|
88
|
+
|
89
|
+
cd /usr/ports/dns/py-pycares && make install
|
90
|
+
|
91
|
+
|
92
|
+
IDNA 2008 support
|
93
|
+
^^^^^^^^^^^^^^^^^
|
94
|
+
|
95
|
+
If the ``idna`` package is installed, pycares will support IDNA 2008 encoding otherwise the builtin idna codec will be used,
|
96
|
+
which provides IDNA 2003 support.
|
97
|
+
|
98
|
+
You can force this at installation time as follows:
|
99
|
+
|
100
|
+
::
|
101
|
+
|
102
|
+
pip install pycares[idna]
|
103
|
+
|
104
|
+
|
105
|
+
Running the test suite
|
106
|
+
----------------------
|
107
|
+
|
108
|
+
From the top level directory, run: ``python -m unittest -v``
|
109
|
+
|
110
|
+
NOTE: Running the tests requires internet access and are somewhat environment sensitive because real DNS quesries
|
111
|
+
are made, there is no mocking. If you observe a failure that the CI cannot reproduce, please try to setup an
|
112
|
+
environment as close as the current CI.
|
113
|
+
|
114
|
+
|
115
|
+
Using it from the cli, a la dig
|
116
|
+
-------------------------------
|
117
|
+
|
118
|
+
This module can be used directly from the command line in a similar fashion to dig (limited, of course):
|
119
|
+
|
120
|
+
::
|
121
|
+
|
122
|
+
$ python -m pycares google.com
|
123
|
+
;; QUESTION SECTION:
|
124
|
+
;google.com IN A
|
125
|
+
|
126
|
+
;; ANSWER SECTION:
|
127
|
+
google.com 300 IN A 172.217.17.142
|
128
|
+
|
129
|
+
$ python -m pycares mx google.com
|
130
|
+
;; QUESTION SECTION:
|
131
|
+
;google.com IN MX
|
132
|
+
|
133
|
+
;; ANSWER SECTION:
|
134
|
+
google.com 600 IN MX 50 alt4.aspmx.l.google.com
|
135
|
+
google.com 600 IN MX 10 aspmx.l.google.com
|
136
|
+
google.com 600 IN MX 40 alt3.aspmx.l.google.com
|
137
|
+
google.com 600 IN MX 20 alt1.aspmx.l.google.com
|
138
|
+
google.com 600 IN MX 30 alt2.aspmx.l.google.com
|
139
|
+
|
140
|
+
|
141
|
+
Author
|
142
|
+
------
|
143
|
+
|
144
|
+
Saúl Ibarra Corretgé <s@saghul.net>
|
145
|
+
|
146
|
+
|
147
|
+
License
|
148
|
+
-------
|
149
|
+
|
150
|
+
Unless stated otherwise on-file pycares uses the MIT license, check LICENSE file.
|
151
|
+
|
152
|
+
|
153
|
+
Supported Python versions
|
154
|
+
-------------------------
|
155
|
+
|
156
|
+
Python >= 3.9 are supported. Both CPython and PyPy are supported.
|
157
|
+
|
158
|
+
|
159
|
+
Contributing
|
160
|
+
------------
|
161
|
+
|
162
|
+
If you'd like to contribute, fork the project, make a patch and send a pull
|
163
|
+
request. Have a look at the surrounding code and please, make yours look
|
164
|
+
alike :-)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
pycares/__init__.py,sha256=ArtBS_p6Q3mzSQLymfl2Ai5l04bwZfPnVJoEKDmVDXQ,39309
|
2
|
+
pycares/__main__.py,sha256=-WwwGX4NQ8hpOqrNuCy59quCQJt7IAwQXdQjga5s4WA,2880
|
3
|
+
pycares/_cares.pyd,sha256=PGda8yiNifo62YZIZ7HrhdFZH8F_BgT5O5vucwjPc_w,234496
|
4
|
+
pycares/_version.py,sha256=cwSQF2Mr2Air7lTld14ORbGvBY9YVvupK2KA0SGv9wo,25
|
5
|
+
pycares/errno.py,sha256=32f2SnSjYACq7peW9Iqb7cvDvwup6LDpNMWGHWhLnWI,2340
|
6
|
+
pycares/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
pycares/utils.py,sha256=ZzjEdkygbU3_B1g4SVwlDS949PhttJG2gK735_6G5Ps,1344
|
8
|
+
pycares-4.9.0.dist-info/licenses/LICENSE,sha256=ZzIVbIpf5QFzaiLCDSjxhvH5EViAWLVO-W4ZgBzWvb8,1090
|
9
|
+
pycares-4.9.0.dist-info/METADATA,sha256=o2LlsAJHZbyF8M9vohunxfn1fl6nPArn9mL4rpT-hdg,4622
|
10
|
+
pycares-4.9.0.dist-info/WHEEL,sha256=3VTbmYeim8AL3qTE9jWZKYc9au-xBJE3sdtKTLGutAo,101
|
11
|
+
pycares-4.9.0.dist-info/top_level.txt,sha256=nIeo7L2XUVBQZO2YE6pH7tlKaBWTfmmRcXbqe_NWYCw,15
|
12
|
+
pycares-4.9.0.dist-info/RECORD,,
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (C) 2012 by Saúl Ibarra Corretgé
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|