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 the standard Python Exception class as before and all *args*
| 26 | |
| 27 | |
| 28 | class DNSException(Exception): |
| 29 | """Abstract base class shared by all dnspython exceptions. |
| 30 | |
| 31 | It supports two basic modes of operation: |
| 32 | |
| 33 | a) Old/compatible mode is used if ``__init__`` was called with |
| 34 | empty *kwargs*. In compatible mode all *args* are passed |
| 35 | to the standard Python Exception class as before and all *args* are |
| 36 | printed by the standard ``__str__`` implementation. Class variable |
| 37 | ``msg`` (or doc string if ``msg`` is ``None``) is returned from ``str()`` |
| 38 | if *args* is empty. |
| 39 | |
| 40 | b) New/parametrized mode is used if ``__init__`` was called with |
| 41 | non-empty *kwargs*. |
| 42 | In the new mode *args* must be empty and all kwargs must match |
| 43 | those set in class variable ``supp_kwargs``. All kwargs are stored inside |
| 44 | ``self.kwargs`` and used in a new ``__str__`` implementation to construct |
| 45 | a formatted message based on the ``fmt`` class variable, a ``string``. |
| 46 | |
| 47 | In the simplest case it is enough to override the ``supp_kwargs`` |
| 48 | and ``fmt`` class variables to get nice parametrized messages. |
| 49 | """ |
| 50 | |
| 51 | msg: str | None = None # non-parametrized message |
| 52 | supp_kwargs: Set[str] = set() # accepted parameters for _fmt_kwargs (sanity check) |
| 53 | fmt: str | None = None # message parametrized with results from _fmt_kwargs |
| 54 | |
| 55 | def __init__(self, *args, **kwargs): |
| 56 | self._check_params(*args, **kwargs) |
| 57 | if kwargs: |
| 58 | # This call to a virtual method from __init__ is ok in our usage |
| 59 | self.kwargs = self._check_kwargs(**kwargs) # lgtm[py/init-calls-subclass] |
| 60 | self.msg = str(self) |
| 61 | else: |
| 62 | self.kwargs = dict() # defined but empty for old mode exceptions |
| 63 | if self.msg is None: |
| 64 | # doc string is better implicit message than empty string |
| 65 | self.msg = self.__doc__ |
| 66 | if args: |
| 67 | super().__init__(*args) |
| 68 | else: |
| 69 | super().__init__(self.msg) |
| 70 | |
| 71 | def _check_params(self, *args, **kwargs): |
| 72 | """Old exceptions supported only args and not kwargs. |
| 73 | |
| 74 | For sanity we do not allow to mix old and new behavior.""" |
| 75 | if args or kwargs: |
| 76 | assert bool(args) != bool( |
| 77 | kwargs |
| 78 | ), "keyword arguments are mutually exclusive with positional args" |
| 79 | |
| 80 | def _check_kwargs(self, **kwargs): |
| 81 | if kwargs: |
| 82 | assert ( |
| 83 | set(kwargs.keys()) == self.supp_kwargs |
| 84 | ), f"following set of keyword args is required: {self.supp_kwargs}" |
| 85 | return kwargs |
no outgoing calls
searching dependent graphs…