dnspython  1.16.0
About: dnspython is a DNS toolkit (for Python 2.x) that supports almost all record types.
  Fossies Dox: dnspython-1.16.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

exception.py
Go to the documentation of this file.
1 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
2 
3 # Copyright (C) 2003-2017 Nominum, Inc.
4 #
5 # Permission to use, copy, modify, and distribute this software and its
6 # documentation for any purpose with or without fee is hereby granted,
7 # provided that the above copyright notice and this permission notice
8 # appear in all copies.
9 #
10 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
11 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
13 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18 """Common DNS Exceptions.
19 
20 Dnspython modules may also define their own exceptions, which will
21 always be subclasses of ``DNSException``.
22 """
23 
24 class DNSException(Exception):
25  """Abstract base class shared by all dnspython exceptions.
26 
27  It supports two basic modes of operation:
28 
29  a) Old/compatible mode is used if ``__init__`` was called with
30  empty *kwargs*. In compatible mode all *args* are passed
31  to the standard Python Exception class as before and all *args* are
32  printed by the standard ``__str__`` implementation. Class variable
33  ``msg`` (or doc string if ``msg`` is ``None``) is returned from ``str()``
34  if *args* is empty.
35 
36  b) New/parametrized mode is used if ``__init__`` was called with
37  non-empty *kwargs*.
38  In the new mode *args* must be empty and all kwargs must match
39  those set in class variable ``supp_kwargs``. All kwargs are stored inside
40  ``self.kwargs`` and used in a new ``__str__`` implementation to construct
41  a formatted message based on the ``fmt`` class variable, a ``string``.
42 
43  In the simplest case it is enough to override the ``supp_kwargs``
44  and ``fmt`` class variables to get nice parametrized messages.
45  """
46 
47  msg = None # non-parametrized message
48  supp_kwargs = set() # accepted parameters for _fmt_kwargs (sanity check)
49  fmt = None # message parametrized with results from _fmt_kwargs
50 
51  def __init__(self, *args, **kwargs):
52  self._check_params(*args, **kwargs)
53  if kwargs:
54  self.kwargs = self._check_kwargs(**kwargs)
55  self.msg = str(self)
56  else:
57  self.kwargs = dict() # defined but empty for old mode exceptions
58  if self.msg is None:
59  # doc string is better implicit message than empty string
60  self.msg = self.__doc__
61  if args:
62  super(DNSException, self).__init__(*args)
63  else:
64  super(DNSException, self).__init__(self.msg)
65 
66  def _check_params(self, *args, **kwargs):
67  """Old exceptions supported only args and not kwargs.
68 
69  For sanity we do not allow to mix old and new behavior."""
70  if args or kwargs:
71  assert bool(args) != bool(kwargs), \
72  'keyword arguments are mutually exclusive with positional args'
73 
74  def _check_kwargs(self, **kwargs):
75  if kwargs:
76  assert set(kwargs.keys()) == self.supp_kwargs, \
77  'following set of keyword args is required: %s' % (
78  self.supp_kwargs)
79  return kwargs
80 
81  def _fmt_kwargs(self, **kwargs):
82  """Format kwargs before printing them.
83 
84  Resulting dictionary has to have keys necessary for str.format call
85  on fmt class variable.
86  """
87  fmtargs = {}
88  for kw, data in kwargs.items():
89  if isinstance(data, (list, set)):
90  # convert list of <someobj> to list of str(<someobj>)
91  fmtargs[kw] = list(map(str, data))
92  if len(fmtargs[kw]) == 1:
93  # remove list brackets [] from single-item lists
94  fmtargs[kw] = fmtargs[kw].pop()
95  else:
96  fmtargs[kw] = data
97  return fmtargs
98 
99  def __str__(self):
100  if self.kwargs and self.fmt:
101  # provide custom message constructed from keyword arguments
102  fmtargs = self._fmt_kwargs(**self.kwargs)
103  return self.fmt.format(**fmtargs)
104  else:
105  # print *args directly in the same way as old DNSException
106  return super(DNSException, self).__str__()
107 
108 
110  """DNS message is malformed."""
111 
112 
113 class SyntaxError(DNSException):
114  """Text input is malformed."""
115 
116 
118  """Text input ended unexpectedly."""
119 
120 
122  """The DNS message is too big."""
123 
124 
126  """The DNS operation timed out."""
127  supp_kwargs = {'timeout'}
128  fmt = "The DNS operation timed out after {timeout} seconds"
dns.exception.DNSException._check_params
def _check_params(self, *args, **kwargs)
Definition: exception.py:66
dns.exception.FormError
Definition: exception.py:109
dns.exception.SyntaxError
Definition: exception.py:113
dns.exception.Timeout
Definition: exception.py:125
dns.exception.DNSException
Definition: exception.py:24
dns.exception.TooBig
Definition: exception.py:121
dns.exception.DNSException.supp_kwargs
supp_kwargs
Definition: exception.py:48
dns.exception.UnexpectedEnd
Definition: exception.py:117
dns.exception.DNSException.kwargs
kwargs
Definition: exception.py:54
dns.exception.DNSException._check_kwargs
def _check_kwargs(self, **kwargs)
Definition: exception.py:74
dns.exception.DNSException.__str__
def __str__(self)
Definition: exception.py:99
dns.exception.DNSException.fmt
fmt
Definition: exception.py:49
dns.exception.DNSException.__init__
def __init__(self, *args, **kwargs)
Definition: exception.py:51
dns.exception.DNSException.msg
msg
Definition: exception.py:47
dns.exception.DNSException._fmt_kwargs
def _fmt_kwargs(self, **kwargs)
Definition: exception.py:81