summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Wellington <bwelling@xbill.org>2020-07-01 10:35:12 -0700
committerBrian Wellington <bwelling@xbill.org>2020-07-01 10:35:12 -0700
commit8521b63293bf704412c67ef69cee0a1e2ad47298 (patch)
tree49d901b8f9b63e1184ecd433fb090b59c8189678
parent7482b94a28dfcd9a98a3518effcec2a6085235d1 (diff)
parent5765181c220b96b1543395faaf5e43eb778a45ff (diff)
downloaddnspython-8521b63293bf704412c67ef69cee0a1e2ad47298.tar.gz
Merge remote-tracking branch 'upstream/master' into amtrelay
-rw-r--r--.travis.yml2
-rw-r--r--README.md2
-rw-r--r--azure-pipelines.yml19
-rw-r--r--codecov.yml5
-rw-r--r--dns/dnssec.py2
-rw-r--r--dns/message.pyi5
-rw-r--r--dns/resolver.py100
-rw-r--r--dns/version.py2
-rw-r--r--doc/whatsnew.rst9
-rw-r--r--pyproject.toml2
-rwxr-xr-xsetup.py2
-rw-r--r--tests/test_query.py60
-rw-r--r--tests/test_resolver.py58
-rw-r--r--tox.ini46
14 files changed, 192 insertions, 122 deletions
diff --git a/.travis.yml b/.travis.yml
index 2d416a5..584f4a7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,6 @@ install:
- curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
- ~/.poetry/bin/poetry install -E dnssec -E doh -E idna -E trio -E curio
script:
- - ~/.poetry/bin/poetry run pytest --cov=dns --cov-report=xml:coverage.xml
+ - ~/.poetry/bin/poetry run pytest --cov=. --cov-report=xml:coverage.xml
after_success:
- bash <(curl -s https://codecov.io/bash)
diff --git a/README.md b/README.md
index 1fae17b..8cb4299 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ to facilitate the testing of DNS software.
## ABOUT THIS RELEASE
-This is the dnspython 2.0.0 development branch.
+This is dnspython 2.0.0rc2.
Please read
[What's New](https://dnspython.readthedocs.io/en/latest/whatsnew.html) for
information about the changes in this release.
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 8af2647..5185c7c 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -23,7 +23,11 @@ jobs:
- script: |
python -m pip install --upgrade pip
pip install -e .[dnssec,idna,doh,trio,curio]
- displayName: 'Install dependencies'
+ displayName: 'Install python dependencies'
+
+ - script: |
+ dotnet tool install --global Codecov.Tool
+ displayName: 'Install Codecov.Tool'
- script: |
pip install pytest pytest-cov pytest-azurepipelines
@@ -36,8 +40,11 @@ jobs:
testResultsFiles: '**/test-*.xml'
testRunTitle: 'Publish test results for Python $(python.version)'
- - task: PublishCodeCoverageResults@1
- inputs:
- codeCoverageTool: Cobertura
- summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
- reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov'
+# - task: PublishCodeCoverageResults@1
+# inputs:
+# codeCoverageTool: Cobertura
+# summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
+
+ - script: |
+ codecov -f coverage.xml
+ displayName: 'Upload to codecov'
diff --git a/codecov.yml b/codecov.yml
index 1b44632..002b105 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -4,3 +4,8 @@ coverage:
default:
target: auto
threshold: 2%
+ignore:
+ - 'tests/*'
+ - 'examples/*'
+ - 'doc/*'
+ - 'setup.py'
diff --git a/dns/dnssec.py b/dns/dnssec.py
index 0be9f71..c50abf8 100644
--- a/dns/dnssec.py
+++ b/dns/dnssec.py
@@ -423,7 +423,7 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
# since if the algorithm is really unknown we'd already have
# raised an exception above
raise ValidationFailure('unknown algorithm %u' %
- rrsig.algorithm) # pragma: no cover
+ rrsig.algorithm) # pragma: no cover
# If we got here, we successfully verified so we can return
# without error
return
diff --git a/dns/message.pyi b/dns/message.pyi
index 8829db3..c939b52 100644
--- a/dns/message.pyi
+++ b/dns/message.pyi
@@ -12,10 +12,7 @@ class Message:
def __init__(self, id : Optional[int] =None) -> None:
self.id : int
self.flags = 0
- self.question : List[rrset.RRset] = []
- self.answer : List[rrset.RRset] = []
- self.authority : List[rrset.RRset] = []
- self.additional : List[rrset.RRset] = []
+ self.sections : List[List[rrset.RRset]] = [[], [], [], []]
self.opt : rrset.RRset = None
self.request_payload = 0
self.keyring = None
diff --git a/dns/resolver.py b/dns/resolver.py
index 6c6f502..f4a07b4 100644
--- a/dns/resolver.py
+++ b/dns/resolver.py
@@ -780,22 +780,22 @@ class Resolver:
if len(self.nameservers) == 0:
raise NoResolverConfiguration
- def _determine_split_char(self, entry): # pragma: no cover
+ def _determine_split_char(self, entry):
#
# The windows registry irritatingly changes the list element
# delimiter in between ' ' and ',' (and vice-versa) in various
# versions of windows.
#
- if entry.find(' ') >= 0:
+ if entry.find(' ') >= 0: # pragma: no cover
split_char = ' '
- elif entry.find(',') >= 0:
+ elif entry.find(',') >= 0: # pragma: no cover
split_char = ','
else:
# probably a singleton; treat as a space-separated list.
split_char = ' '
return split_char
- def _config_win32_nameservers(self, nameservers): # pragma: no cover
+ def _config_win32_nameservers(self, nameservers):
# we call str() on nameservers to convert it from unicode to ascii
nameservers = str(nameservers)
split_char = self._determine_split_char(nameservers)
@@ -817,7 +817,7 @@ class Resolver:
if s not in self.search:
self.search.append(dns.name.from_text(s))
- def _config_win32_fromkey(self, key, always_try_domain): # pragma: no cover
+ def _config_win32_fromkey(self, key, always_try_domain):
try:
servers, rtype = winreg.QueryValueEx(key, 'NameServer')
except WindowsError: # pylint: disable=undefined-variable
@@ -829,76 +829,66 @@ class Resolver:
dom, rtype = winreg.QueryValueEx(key, 'Domain')
if dom:
self._config_win32_domain(dom)
- except WindowsError: # pylint: disable=undefined-variable
+ except WindowsError: # pragma: no cover
pass
else:
try:
servers, rtype = winreg.QueryValueEx(key, 'DhcpNameServer')
- except WindowsError: # pylint: disable=undefined-variable
+ except WindowsError: # pragma: no cover
servers = None
- if servers:
+ if servers: # pragma: no cover
self._config_win32_nameservers(servers)
try:
dom, rtype = winreg.QueryValueEx(key, 'DhcpDomain')
- if dom:
+ if dom: # pragma: no cover
self._config_win32_domain(dom)
- except WindowsError: # pylint: disable=undefined-variable
+ except WindowsError: # pragma: no cover
pass
try:
search, rtype = winreg.QueryValueEx(key, 'SearchList')
except WindowsError: # pylint: disable=undefined-variable
search = None
- if search:
+ if search: # pragma: no cover
self._config_win32_search(search)
- def read_registry(self): # pragma: no cover
+ def read_registry(self):
"""Extract resolver configuration from the Windows registry."""
lm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
- want_scan = False
try:
- try:
- # XP, 2000
- tcp_params = winreg.OpenKey(lm,
- r'SYSTEM\CurrentControlSet'
- r'\Services\Tcpip\Parameters')
- want_scan = True
- except EnvironmentError:
- # ME
- tcp_params = winreg.OpenKey(lm,
- r'SYSTEM\CurrentControlSet'
- r'\Services\VxD\MSTCP')
+ tcp_params = winreg.OpenKey(lm,
+ r'SYSTEM\CurrentControlSet'
+ r'\Services\Tcpip\Parameters')
try:
self._config_win32_fromkey(tcp_params, True)
finally:
tcp_params.Close()
- if want_scan:
- interfaces = winreg.OpenKey(lm,
- r'SYSTEM\CurrentControlSet'
- r'\Services\Tcpip\Parameters'
- r'\Interfaces')
- try:
- i = 0
- while True:
+ interfaces = winreg.OpenKey(lm,
+ r'SYSTEM\CurrentControlSet'
+ r'\Services\Tcpip\Parameters'
+ r'\Interfaces')
+ try:
+ i = 0
+ while True:
+ try:
+ guid = winreg.EnumKey(interfaces, i)
+ i += 1
+ key = winreg.OpenKey(interfaces, guid)
+ if not self._win32_is_nic_enabled(lm, guid, key):
+ continue
try:
- guid = winreg.EnumKey(interfaces, i)
- i += 1
- key = winreg.OpenKey(interfaces, guid)
- if not self._win32_is_nic_enabled(lm, guid, key):
- continue
- try:
- self._config_win32_fromkey(key, False)
- finally:
- key.Close()
- except EnvironmentError:
- break
- finally:
- interfaces.Close()
+ self._config_win32_fromkey(key, False)
+ finally:
+ key.Close()
+ except EnvironmentError: # pragma: no cover
+ break
+ finally:
+ interfaces.Close()
finally:
lm.Close()
def _win32_is_nic_enabled(self, lm, guid,
- interface_key): # pragma: no cover
+ interface_key):
# Look in the Windows Registry to determine whether the network
# interface corresponding to the given guid is enabled.
#
@@ -918,7 +908,7 @@ class Resolver:
(pnp_id, ttype) = winreg.QueryValueEx(
connection_key, 'PnpInstanceID')
- if ttype != winreg.REG_SZ:
+ if ttype != winreg.REG_SZ: # pragma: no cover
raise ValueError
device_key = winreg.OpenKey(
@@ -929,7 +919,7 @@ class Resolver:
(flags, ttype) = winreg.QueryValueEx(
device_key, 'ConfigFlags')
- if ttype != winreg.REG_DWORD:
+ if ttype != winreg.REG_DWORD: # pragma: no cover
raise ValueError
# Based on experimentation, bit 0x1 indicates that the
@@ -940,18 +930,8 @@ class Resolver:
device_key.Close()
finally:
connection_key.Close()
- except (EnvironmentError, ValueError):
- # Pre-vista, enabled interfaces seem to have a non-empty
- # NTEContextList; this was how dnspython detected enabled
- # nics before the code above was contributed. We've retained
- # the old method since we don't know if the code above works
- # on Windows 95/98/ME.
- try:
- (nte, ttype) = winreg.QueryValueEx(interface_key,
- 'NTEContextList')
- return nte is not None
- except WindowsError: # pylint: disable=undefined-variable
- return False
+ except Exception: # pragma: no cover
+ return False
def _compute_timeout(self, start, lifetime=None):
lifetime = self.lifetime if lifetime is None else lifetime
diff --git a/dns/version.py b/dns/version.py
index d897395..dcdbbe0 100644
--- a/dns/version.py
+++ b/dns/version.py
@@ -24,7 +24,7 @@ MINOR = 0
#: MICRO
MICRO = 0
#: RELEASELEVEL
-RELEASELEVEL = 0x00
+RELEASELEVEL = 0x0c
#: SERIAL
SERIAL = 2
diff --git a/doc/whatsnew.rst b/doc/whatsnew.rst
index 801e0f6..dd7e48d 100644
--- a/doc/whatsnew.rst
+++ b/doc/whatsnew.rst
@@ -64,3 +64,12 @@ What's New in dnspython 2.0.0
in the python 2 style on both python 2 and 3.
* The resolver will now do negative caching if a cache has been configured.
+
+* TSIG and OPT now have rdata types.
+
+* The class for query messages is now QueryMessage. Class Message is now a
+ base class, and is also used for messages for which we don't have a better
+ class. Update messages are now class UpdateMessage, though class Update
+ is retained for compatibility.
+
+* Support for Windows 95, 98, and ME has been removed.
diff --git a/pyproject.toml b/pyproject.toml
index 21ca001..970d92f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "dnspython"
-version = "2.0.0dev2"
+version = "2.0.0rc2"
description = "DNS toolkit"
authors = ["Bob Halley <halley@dnspython.org>"]
license = "ISC"
diff --git a/setup.py b/setup.py
index 3451d9e..a375211 100755
--- a/setup.py
+++ b/setup.py
@@ -20,7 +20,7 @@
import sys
from setuptools import setup
-version = '2.0.0dev2'
+version = '2.0.0rc2'
try:
sys.argv.remove("--cython-compile")
diff --git a/tests/test_query.py b/tests/test_query.py
index 895dc0d..f1ec55c 100644
--- a/tests/test_query.py
+++ b/tests/test_query.py
@@ -16,6 +16,8 @@
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import socket
+import sys
+import time
import unittest
try:
@@ -236,6 +238,31 @@ class DestinationAndSourceTests(unittest.TestCase):
(af, d, s) = _d_and_s('1::2', 53, None, 12345)
self.assertEqual(s, ('::', 12345, 0, 0))
+
+class AddressesEqualTestCase(unittest.TestCase):
+
+ def test_v4(self):
+ self.assertTrue(dns.query._addresses_equal(socket.AF_INET,
+ ('10.0.0.1', 53),
+ ('10.0.0.1', 53)))
+ self.assertFalse(dns.query._addresses_equal(socket.AF_INET,
+ ('10.0.0.1', 53),
+ ('10.0.0.2', 53)))
+
+ def test_v6(self):
+ self.assertTrue(dns.query._addresses_equal(socket.AF_INET6,
+ ('1::1', 53),
+ ('0001:0000::1', 53)))
+ self.assertFalse(dns.query._addresses_equal(socket.AF_INET6,
+ ('::1', 53),
+ ('::2', 53)))
+
+ def test_mixed(self):
+ self.assertFalse(dns.query._addresses_equal(socket.AF_INET,
+ ('10.0.0.1', 53),
+ ('::2', 53)))
+
+
axfr_zone = '''
$ORIGIN example.
$TTL 300
@@ -482,3 +509,36 @@ class TsigTests(unittest.TestCase):
self.assertTrue(rrs is not None)
seen = set([rdata.address for rdata in rrs])
self.assertTrue('1.2.3.4' in seen)
+
+@unittest.skipIf(sys.platform == 'win32',
+ 'low level tests do not work on win32')
+class LowLevelWaitTests(unittest.TestCase):
+
+ def test_wait_for(self):
+ try:
+ (l, r) = socket.socketpair()
+ # already expired
+ with self.assertRaises(dns.exception.Timeout):
+ dns.query._wait_for(l, True, True, True, 0)
+ # simple timeout
+ with self.assertRaises(dns.exception.Timeout):
+ dns.query._wait_for(l, False, False, False, time.time() + 0.05)
+ # writable no timeout (not hanging is passing)
+ dns.query._wait_for(l, False, True, False, None)
+ finally:
+ l.close()
+ r.close()
+
+ def test_select_for(self):
+ # we test this explicitly in case _wait_for didn't test it (i.e.
+ # if the default polling backing is _poll_for)
+ try:
+ (l, r) = socket.socketpair()
+ # simple timeout
+ self.assertFalse(dns.query._select_for(l, False, False, False,
+ 0.05))
+ # writable no timeout
+ self.assertTrue(dns.query._select_for(l, False, True, False, None))
+ finally:
+ l.close()
+ r.close()
diff --git a/tests/test_resolver.py b/tests/test_resolver.py
index 373ecb9..2a9c63d 100644
--- a/tests/test_resolver.py
+++ b/tests/test_resolver.py
@@ -64,6 +64,34 @@ search search1 search2
options rotate timeout:1 edns0 ndots:2
"""
+bad_timeout_1 = """
+nameserver 10.0.0.1
+nameserver 10.0.0.2
+options rotate timeout
+"""
+
+bad_timeout_2 = """
+nameserver 10.0.0.1
+nameserver 10.0.0.2
+options rotate timeout:bogus
+"""
+
+bad_ndots_1 = """
+nameserver 10.0.0.1
+nameserver 10.0.0.2
+options rotate ndots
+"""
+
+bad_ndots_2 = """
+nameserver 10.0.0.1
+nameserver 10.0.0.2
+options rotate ndots:bogus
+"""
+
+no_nameservers = """
+options rotate
+"""
+
message_text = """id 1234
opcode QUERY
rcode NOERROR
@@ -139,6 +167,36 @@ class BaseResolverTests(unittest.TestCase):
self.assertEqual(r.ndots, 2)
self.assertEqual(r.edns, 0)
+ def testReadOptionsBadTimeouts(self):
+ f = StringIO(bad_timeout_1)
+ r = dns.resolver.Resolver(configure=False)
+ r.read_resolv_conf(f)
+ # timeout should still be default
+ self.assertEqual(r.timeout, 2.0)
+ f = StringIO(bad_timeout_2)
+ r = dns.resolver.Resolver(configure=False)
+ r.read_resolv_conf(f)
+ # timeout should still be default
+ self.assertEqual(r.timeout, 2.0)
+
+ def testReadOptionsBadNdots(self):
+ f = StringIO(bad_ndots_1)
+ r = dns.resolver.Resolver(configure=False)
+ r.read_resolv_conf(f)
+ # ndots should still be default
+ self.assertEqual(r.ndots, None)
+ f = StringIO(bad_ndots_2)
+ r = dns.resolver.Resolver(configure=False)
+ r.read_resolv_conf(f)
+ # ndots should still be default
+ self.assertEqual(r.ndots, None)
+
+ def testReadNoNameservers(self):
+ f = StringIO(no_nameservers)
+ r = dns.resolver.Resolver(configure=False)
+ with self.assertRaises(dns.resolver.NoResolverConfiguration):
+ r.read_resolv_conf(f)
+
def testCacheExpiration(self):
message = dns.message.from_text(message_text)
name = dns.name.from_text('example.')
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index 6417f2d..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,46 +0,0 @@
-[tox]
-envlist =
- py36,
- py37,
- flake8,
- pylint,
- mypy,
- coverage
-
-[testenv]
-
-commands=
- python setup.py test
-
-deps=
-
-[testenv:flake8]
-commands =
- pip install flake8
- flake8 dns
-
-[testenv:pylint]
-commands =
- pip install pylint
- pylint dns
-
-[testenv:mypy]
-commands =
- pip install mypy
- mypy examples tests
-
-[testenv:coverage]
-basepython = python2
-
-deps =
- coverage
-
-commands =
- python setup.py install
- coverage run --rcfile=.coverage.ini setup.py test
- coverage report
-
-[pep8]
-show-pep8 = True
-show-source = True
-