coverage
[tiramisu.git] / tiramisu / error.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors)
3 #
4 # This program is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Lesser General Public License as published by the
6 # Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
12 # details.
13 #
14 # You should have received a copy of the GNU Lesser General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 # ____________________________________________________________
17 "user defined exceptions"
18 from .i18n import _
19
20
21 def display_list(lst, separator='and'):
22     if separator == 'and':
23         separator = _('and')
24     elif separator == 'or':
25         separator = _('or')
26     if len(lst) == 0:
27         return ''
28     elif len(lst) == 1:
29         ret = lst[0]
30         if isinstance(ret, unicode):
31             ret = ret.encode('utf8')
32         if not isinstance(ret, str):
33             ret = str(ret)
34         return ret
35     else:
36         lst_ = []
37         for l in lst[:-1]:
38             if isinstance(l, unicode):
39                 l = l.encode('utf8')
40             elif not isinstance(l, str):
41                 l = str(l)
42             lst_.append(l)
43         last = lst[-1]
44         if isinstance(last, unicode):
45             last = last.encode('utf8')
46         if not isinstance(last, str):
47             last = str(last)
48         return ', '.join(lst_) + _(' {} ').format(separator) + last
49
50
51 # Exceptions for an Option
52 class PropertiesOptionError(AttributeError):
53     "attempt to access to an option with a property that is not allowed"
54     def __init__(self, msg, proptype, settings=None, datas=None, option_type=None):
55         self.proptype = proptype
56         self._settings = settings
57         self._datas = datas
58         self._type = option_type
59         super(PropertiesOptionError, self).__init__(msg)
60
61     def __str__(self):
62         #this part is a bit slow, so only execute when display
63         if self._settings is None:
64             req = {}
65         else:
66             req = self._settings.apply_requires(**self._datas)
67         if req != {}:
68             msg = []
69             for action, msg_ in req.items():
70                 msg.append('{0} ({1})'.format(action, display_list(msg_)))
71             if len(req) == 1:
72                 prop_msg = _('property')
73             else:
74                 prop_msg = _('properties')
75             msg = display_list(msg)
76             return str(_('cannot access to {0} "{1}" because has {2} {3}').format(self._type, self._datas['opt'].impl_get_display_name(), prop_msg, msg))
77         else:
78             return super(PropertiesOptionError, self).__str__()
79
80
81 #____________________________________________________________
82 # Exceptions for a Config
83 class ConfigError(Exception):
84     """attempt to change an option's owner without a value
85     or in case of `_cfgimpl_descr` is None
86     or if a calculation cannot be carried out"""
87     pass
88
89
90 class ConflictError(Exception):
91     "duplicate options are present in a single config"
92     pass
93
94
95 #____________________________________________________________
96 #┬ámiscellaneous exceptions
97 class RequirementError(Exception):
98     """a recursive loop occurs in the requirements tree
99     requires
100     """
101     pass
102
103
104 class SlaveError(Exception):
105     "problem with a slave's value length"
106     pass
107
108
109 class ConstError(TypeError):
110     "no uniq value in _NameSpace"
111     pass
112
113
114 #Warning
115 class ValueWarning(UserWarning):  # pragma: optional cover
116     """Option could warn user and not raise ValueError.
117
118     Example:
119
120     >>> import warnings
121     >>> from tiramisu.error import ValueWarning
122     >>> from tiramisu.option import StrOption, OptionDescription
123     >>> from tiramisu.config import Config
124     >>> warnings.simplefilter("always", ValueWarning)
125     >>> def a(val):
126     ...  raise ValueError('pouet')
127     ...
128     >>> s=StrOption('s', '', validator=a, warnings_only=True)
129     >>> o=OptionDescription('o', '', [s])
130     >>> c=Config(o)
131     >>> c.s = 'val'
132     StrOption:0: ValueWarning: invalid value val for option s: pouet
133     >>> with warnings.catch_warnings(record=True) as w:
134     ...     c.s = 'val'
135     ...
136     >>> w[0].message.opt == s
137     True
138     >>> print str(w[0].message)
139     invalid value val for option s: pouet
140     """
141     def __init__(self, msg, opt):
142         self.opt = opt
143         super(ValueWarning, self).__init__(msg)