From: Petr Spacek Date: Thu, 19 Mar 2015 16:55:30 +0000 (+0100) Subject: Add support for parametrizable __str__ in DNSException. X-Git-Tag: v1.13.0~27^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dfe8f47a98b349bbd31ea64d6ab0a7df0672a8f8;p=thirdparty%2Fdnspython.git Add support for parametrizable __str__ in DNSException. This change makes __init__ and __str__ parametrization simpler and keeps backward compatiblity with old code which does not use keyword arguments in raise(). Parametrized __str__ can be implemented simply by defining "fmt" and "supp_kwargs" class variables in particular exception class. Doc string is used in cases where specific message parameters were not provided during instantiation/raise. --- diff --git a/dns/exception.py b/dns/exception.py index 60b49129..9c578265 100644 --- a/dns/exception.py +++ b/dns/exception.py @@ -15,15 +15,63 @@ """Common DNS Exceptions.""" + class DNSException(Exception): - """Abstract base class shared by all dnspython exceptions.""" - def __init__(self, *args): + """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."""