summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Halley <halley@dnspython.org>2021-04-24 11:04:28 -0700
committerBob Halley <halley@dnspython.org>2021-04-24 11:04:28 -0700
commit1f8b41a9e2144c714d865b2f9c4a78eccaa122dd (patch)
tree69fe9c6e46ad092dbc07d7f9cdc4b43c386dba7c
parent59f5b365e62a37565eb7dead521d82604b208334 (diff)
downloaddnspython-1f8b41a9e2144c714d865b2f9c4a78eccaa122dd.tar.gz
Return error trace in LifetimeTimeout
-rw-r--r--dns/asyncresolver.py3
-rw-r--r--dns/resolver.py50
2 files changed, 38 insertions, 15 deletions
diff --git a/dns/asyncresolver.py b/dns/asyncresolver.py
index a60cf77..e94c6fd 100644
--- a/dns/asyncresolver.py
+++ b/dns/asyncresolver.py
@@ -71,7 +71,8 @@ class Resolver(dns.resolver.BaseResolver):
(nameserver, port, tcp, backoff) = resolution.next_nameserver()
if backoff:
await backend.sleep(backoff)
- timeout = self._compute_timeout(start, lifetime)
+ timeout = self._compute_timeout(start, lifetime,
+ resolution.errors)
try:
if dns.inet.is_address(nameserver):
if tcp:
diff --git a/dns/resolver.py b/dns/resolver.py
index 8d7c805..e1de8cf 100644
--- a/dns/resolver.py
+++ b/dns/resolver.py
@@ -132,11 +132,34 @@ class NXDOMAIN(dns.exception.DNSException):
class YXDOMAIN(dns.exception.DNSException):
"""The DNS query name is too long after DNAME substitution."""
-# The definition of the Timeout exception has moved from here to the
-# dns.exception module. We keep dns.resolver.Timeout defined for
-# backwards compatibility.
-Timeout = dns.exception.Timeout
+def _errors_to_text(errors):
+ """Turn a resolution errors trace into a list of text."""
+ texts = []
+ for err in errors:
+ # pylint: disable=bad-continuation
+ texts.append('Server {} {} port {} answered {}'.format(err[0],
+ 'TCP' if err[1] else 'UDP', err[2], err[3]))
+ return texts
+
+
+class LifetimeTimeout(dns.exception.Timeout):
+ """The resolution lifetime expired."""
+
+ msg = "The resolution lifetime expired."
+ fmt = "%s after {timeout} seconds: {errors}" % msg[:-1]
+ supp_kwargs = {'timeout', 'errors'}
+
+ def _fmt_kwargs(self, **kwargs):
+ srv_msgs = _errors_to_text(kwargs['errors'])
+ return super()._fmt_kwargs(timeout=kwargs['timeout'],
+ errors='; '.join(srv_msgs))
+
+
+# We added more detail to resolution timeouts, but they are still
+# subclasses of dns.exception.Timeout for backwards compatibility. We also
+# keep dns.resolver.Timeout defined for backwards compatibility.
+Timeout = LifetimeTimeout
class NoAnswer(dns.exception.DNSException):
@@ -163,11 +186,7 @@ class NoNameservers(dns.exception.DNSException):
supp_kwargs = {'request', 'errors'}
def _fmt_kwargs(self, **kwargs):
- srv_msgs = []
- for err in kwargs['errors']:
- # pylint: disable=bad-continuation
- srv_msgs.append('Server {} {} port {} answered {}'.format(err[0],
- 'TCP' if err[1] else 'UDP', err[2], err[3]))
+ srv_msgs = _errors_to_text(kwargs['errors'])
return super()._fmt_kwargs(query=kwargs['request'].question,
errors='; '.join(srv_msgs))
@@ -984,21 +1003,23 @@ class BaseResolver:
except Exception: # pragma: no cover
return False
- def _compute_timeout(self, start, lifetime=None):
+ def _compute_timeout(self, start, lifetime=None, errors=None):
lifetime = self.lifetime if lifetime is None else lifetime
now = time.time()
duration = now - start
+ if errors is None:
+ errors = []
if duration < 0:
if duration < -1:
# Time going backwards is bad. Just give up.
- raise Timeout(timeout=duration)
+ raise LifetimeTimeout(timeout=duration, errors=errors)
else:
# Time went backwards, but only a little. This can
# happen, e.g. under vmware with older linux kernels.
# Pretend it didn't happen.
now = start
if duration >= lifetime:
- raise Timeout(timeout=duration)
+ raise LifetimeTimeout(timeout=duration, errors=errors)
return min(lifetime - duration, self.timeout)
def _get_qnames_to_try(self, qname, search):
@@ -1141,7 +1162,7 @@ class Resolver(BaseResolver):
which causes the value of the resolver's
``use_search_by_default`` attribute to be used.
- Raises ``dns.exception.Timeout`` if no answers could be found
+ Raises ``dns.resolver.LifetimeTimeout`` if no answers could be found
in the specified lifetime.
Raises ``dns.resolver.NXDOMAIN`` if the query name does not exist.
@@ -1177,7 +1198,8 @@ class Resolver(BaseResolver):
(nameserver, port, tcp, backoff) = resolution.next_nameserver()
if backoff:
time.sleep(backoff)
- timeout = self._compute_timeout(start, lifetime)
+ timeout = self._compute_timeout(start, lifetime,
+ resolution.errors)
try:
if dns.inet.is_address(nameserver):
if tcp: