try: from tiramisu.error import APIError, ValueWarning, ValueOptionError, ValueErrorWarning, PropertiesOptionError except ModuleNotFoundError: import weakref from .i18n import _ def display_list(lst, separator='and', add_quote=False): if separator == 'and': separator = _('and') elif separator == 'or': separator = _('or') if isinstance(lst, tuple) or isinstance(lst, frozenset): lst = list(lst) if len(lst) == 1: ret = lst[0] if not isinstance(ret, str): ret = str(ret) if add_quote: ret = '"{}"'.format(ret) return ret else: lst.sort() lst_ = [] for l in lst[:-1]: if not isinstance(l, str): l = str(l) if add_quote: l = '"{}"'.format(l) lst_.append(_(l)) last = lst[-1] if not isinstance(last, str): last = str(_(last)) if add_quote: last = '"{}"'.format(last) return ', '.join(lst_) + _(' {} ').format(separator) + '{}'.format(last) class APIError(Exception): pass # Warning class ValueWarning(UserWarning): """Option could warn user and not raise ValueError. Example: >>> import warnings >>> from tiramisu.error import ValueWarning >>> from tiramisu.option import StrOption, OptionDescription >>> from tiramisu import Config >>> warnings.simplefilter("always", ValueWarning) >>> def a(val): ... raise ValueError('pouet') ... >>> s=StrOption('s', '', validator=a, warnings_only=True) >>> o=OptionDescription('o', '', [s]) >>> c=Config(o) >>> c.s = 'val' StrOption:0: ValueWarning: invalid value val for option s: pouet >>> with warnings.catch_warnings(record=True) as w: ... c.s = 'val' ... >>> w[0].message.opt() == s True >>> print(str(w[0].message)) invalid value val for option s: pouet """ def __init__(self, msg, opt): self.opt = opt self.value_error = msg super(ValueWarning, self).__init__(msg) class ValueOptionError(ValueError): def __init__(self, val, display_type, opt, err_msg): self.prefix = _('"{0}" is an invalid {1} for "{2}"' '').format(val, display_type, opt.impl_get_display_name()) self.opt = weakref.ref(opt) self.err_msg = err_msg def __str__(self): msg = self.prefix if self.err_msg: if msg: msg += ', {}'.format(self.err_msg) else: msg = self.err_msg if not msg: msg = _('invalid value') return msg class ValueErrorWarning(ValueWarning): def __init__(self, value_error): super(ValueErrorWarning, self).__init__(value_error, value_error.opt) # Exceptions for an Option class PropertiesOptionError(AttributeError): "attempt to access to an option with a property that is not allowed" def __init__(self, option_bag, proptype, settings, opt_type=None, requires=None, name=None, orig_opt=None): if opt_type: self._opt_type = opt_type self._requires = requires self._name = name self._orig_opt = orig_opt else: if option_bag.option.impl_is_optiondescription(): self._opt_type = 'optiondescription' else: self._opt_type = 'option' self._requires = option_bag.option.impl_getrequires() self._name = option_bag.option.impl_get_display_name() self._orig_opt = None self._option_bag = option_bag self.proptype = proptype self._settings = settings self.msg = None super(PropertiesOptionError, self).__init__(None) def set_orig_opt(self, opt): self._orig_opt = opt def __str__(self): # this part is a bit slow, so only execute when display if self.msg: return self.msg req = self._settings.apply_requires(self._option_bag, True) # if req != {} or self._orig_opt is not None: if req != {}: only_one = len(req) == 1 msg = [] for action, msg_ in req.items(): msg.append('"{0}" ({1})'.format(action, display_list(msg_))) msg = display_list(msg) else: only_one = len(self.proptype) == 1 msg = display_list(list(self.proptype), add_quote=True) if only_one: prop_msg = _('property') else: prop_msg = _('properties') if self._orig_opt: self.msg = str(_('cannot access to {0} "{1}" because "{2}" has {3} {4}' '').format(self._opt_type, self._orig_opt.impl_get_display_name(), self._name, prop_msg, msg)) else: self.msg = str(_('cannot access to {0} "{1}" because has {2} {3}' '').format(self._opt_type, self._name, prop_msg, msg)) del self._requires, self._opt_type, self._name, self._option_bag del self._settings, self._orig_opt return self.msg