From de0d40efbb597036de847905ce0e12f40cc37051 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 16 Jan 2019 09:42:22 +0100 Subject: [PATCH] can use tiramisu-json-api without tiramisu --- tiramisu_json_api/api.py | 9 +- tiramisu_json_api/error.py | 171 +++++++++++++++++++++++++++++++++++ tiramisu_json_api/i18n.py | 6 ++ tiramisu_json_api/setting.py | 11 +++ 4 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 tiramisu_json_api/error.py create mode 100644 tiramisu_json_api/i18n.py create mode 100644 tiramisu_json_api/setting.py diff --git a/tiramisu_json_api/api.py b/tiramisu_json_api/api.py index 240c8fb..c620fe4 100644 --- a/tiramisu_json_api/api.py +++ b/tiramisu_json_api/api.py @@ -3,12 +3,9 @@ import warnings import re -from tiramisu.error import APIError, ValueWarning, ValueOptionError, ValueErrorWarning, PropertiesOptionError -from tiramisu.setting import undefined - -# FIXME -def _(val): - return val +from .error import APIError, ValueWarning, ValueOptionError, ValueErrorWarning, PropertiesOptionError +from .setting import undefined +from .i18n import _ class Option: diff --git a/tiramisu_json_api/error.py b/tiramisu_json_api/error.py new file mode 100644 index 0000000..dc457b7 --- /dev/null +++ b/tiramisu_json_api/error.py @@ -0,0 +1,171 @@ +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 diff --git a/tiramisu_json_api/i18n.py b/tiramisu_json_api/i18n.py new file mode 100644 index 0000000..a2f02d6 --- /dev/null +++ b/tiramisu_json_api/i18n.py @@ -0,0 +1,6 @@ +try: + from tiramisu.i18n import _ +except ModuleNotFoundError: + # FIXME + def _(val): + return val diff --git a/tiramisu_json_api/setting.py b/tiramisu_json_api/setting.py new file mode 100644 index 0000000..4a39241 --- /dev/null +++ b/tiramisu_json_api/setting.py @@ -0,0 +1,11 @@ +try: + from tiramisu.setting import undefined +except ModuleNotFoundError: + class Undefined(object): + def __str__(self): + return 'Undefined' + + __repr__ = __str__ + + + undefined = Undefined()