Package dns :: Module exception |
[hide private]
[frames] | no frames]

# Source Code for Module dns.exception

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