# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose with or without fee is hereby granted,
# provided that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""Common DNS Exceptions."""


class DNSException(Exception):
    """Abstract base class shared by all dnspython exceptions.

    It supports two basic modes of operation:

    a) Old/compatible mode is used if __init__ was called with
       empty **kwargs.
    In compatible mode all *args are passed to standard Python Exception class
    as before and all *args are printed by standard __str__ implementation.

    b) New/parametrized mode is used if __init__ was called with
       non-empty **kwargs.
    In the new mode *args has to be empty and all kwargs has to exactly match
    set in class variable self.supp_kwargs. All kwargs are stored inside
    self.kwargs and used in new __str__ implementation to construct
    formated message based on self.fmt string.

    In the simplest case it is enough to override supp_kwargs and fmt
    class variables to get nice parametrized messages.
    """
    supp_kwargs = set()
    fmt = None

    def __init__(self, *args, **kwargs):
        self._check_params(*args, **kwargs)
        self._check_kwargs(**kwargs)
        self.kwargs = kwargs
        if args:
            super(DNSException, self).__init__(*args)
        else:
            # doc string is better implicit message than empty string
            super(DNSException, self).__init__(self.__doc__)

    def _check_params(self, *args, **kwargs):
        """Old exceptions supported only args and not kwargs.

        For sanity we do not allow to mix old and new behavior."""
        if args or kwargs:
            assert bool(args) != bool(kwargs), \
                'keyword arguments are mutually exclusive with positional args'

    def _check_kwargs(self, **kwargs):
        if kwargs:
            assert set(kwargs.keys()) == self.supp_kwargs, \
                'following set of keyword args is required: %s' % (
                    self.supp_kwargs)

    def __str__(self):
        if self.kwargs and self.fmt:
            # provide custom message constructed from keyword arguments
            return self.fmt.format(**self.kwargs)
        else:
            # print *args directly in the same way as old DNSException
            return super(DNSException, self).__str__()


class FormError(DNSException):
    """DNS message is malformed."""

class SyntaxError(DNSException):
    """Text input is malformed."""

class UnexpectedEnd(SyntaxError):
    """Text input ended unexpectedly."""

class TooBig(DNSException):
    """The DNS message is too big."""

class Timeout(DNSException):
    """The DNS operation timed out."""

@@ -2654,16 +2654,688 @@
 wargs)%0A%0A
+    def _fmt_kwargs(self, **kwargs):%0A        %22%22%22Format kwargs before printing them.%0A%0A        Resulting dictionary has to have keys necessary for str.format call%0A        on fmt class variable.%0A        %22%22%22%0A        fmtargs = %7B%7D%0A        for kw, data in kwargs.items():%0A            if isinstance(data, (list, set)):%0A                # convert list of %3Csomeobj%3E to list of str(%3Csomeobj%3E)%0A                fmtargs%5Bkw%5D = list(map(str, data))%0A                if len(fmtargs%5Bkw%5D) == 1:%0A                    # remove list brackets %5B%5D from single-item lists%0A                    fmtargs%5Bkw%5D = fmtargs%5Bkw%5D.pop()%0A            else:%0A                fmtargs%5Bkw%5D = data%0A        return fmtargs%0A%0A
     def 
@@ -3349,16 +3349,16 @@
 (self):%0A
-
         
@@ -3458,16 +3458,70 @@
 guments%0A
+            fmtargs = self._fmt_kwargs(**self.kwargs)%0A
         
@@ -3549,23 +3549,19 @@
 ormat(**
-self.kw
+fmt
 args)%0A  

Add list pretty-printing for parametrized exceptions.