bzr branch
/loggerhead/update-manager/devel/gsoc09
|
1399
by Stephan Peijnik
Updated license notices to reflect recent copyright assignment to Canonical. |
1 | # UpdateManager/Util/enum.py
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
2 | #
|
|
1399
by Stephan Peijnik
Updated license notices to reflect recent copyright assignment to Canonical. |
3 | # Copyright (c) 2009 Canonical
|
|
1466
by Stephan Peijnik
Source file header update. |
4 | # 2009 Stephan Peijnik
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
5 | #
|
| 6 | # Author: Stephan Peijnik <debian@sp.or.at>
|
|
| 7 | #
|
|
| 8 | # This program is free software; you can redistribute it and/or
|
|
| 9 | # modify it under the terms of the GNU General Public License as
|
|
| 10 | # published by the Free Software Foundation; either version 2 of the
|
|
| 11 | # License, or (at your option) any later version.
|
|
| 12 | #
|
|
| 13 | # This program is distributed in the hope that it will be useful,
|
|
| 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 16 | # GNU General Public License for more details.
|
|
| 17 | #
|
|
| 18 | # You should have received a copy of the GNU General Public License
|
|
| 19 | # along with this program; if not, write to the Free Software
|
|
|
1399
by Stephan Peijnik
Updated license notices to reflect recent copyright assignment to Canonical. |
20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
| 21 | # USA.
|
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
22 | |
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
23 | """ Implementation of autodoc-aware Enum for Python """
|
| 24 | ||
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
25 | class Enum(object): |
| 26 | """ Simple autodoc-aware C-like enumeration.
|
|
| 27 | ||
| 28 | All enumeration names must be upper case and may not contain spaces, see
|
|
| 29 | below for examples.
|
|
| 30 |
|
|
| 31 | >>> ReturnCodes = Enum('SUCCESS', ERROR='A non-fatal error occured',
|
|
| 32 | FATAL='A fatal error occured')
|
|
| 33 | >>> ReturnCodes.SUCCESS
|
|
| 34 | 0
|
|
|
1447
by Stephan Peijnik
Fixed bug in UpdateManager.Util.enum and wrote unit test for that bug. |
35 | |
| 36 | ||
| 37 | .. note:: When using values with docstring the values are ordered
|
|
| 38 | alphabetically by their name. This is caused by how the dict type
|
|
| 39 | works.
|
|
| 40 |
|
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
41 | """
|
| 42 | ||
| 43 | _enum_name = ':class:`Enum<UpdateManager.Util.enum.Enum>`' |
|
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
44 | _allowed_characters = None |
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
45 | |
| 46 | def __init__(self, *names, **names_with_doc): |
|
| 47 | """
|
|
| 48 | Creates an enumeration and updates the docstring of the generated
|
|
| 49 | object.
|
|
| 50 | ||
| 51 | :param *names: A list of enumeration names without a docstring.
|
|
| 52 | :param **names_with_doc: A dictionary of enumeration names and their
|
|
| 53 | docstrings. The key forms the name, whilst the value represents
|
|
| 54 | the docstring.
|
|
| 55 | ||
| 56 | All enumeration names must be upper case and may not contain spaces.
|
|
| 57 | ||
| 58 | Example::
|
|
| 59 | ReturnCodes = Enum('SUCCESS', ERROR='A non-fatal error occured',
|
|
| 60 | FATAL='A fatal error occured')
|
|
| 61 | NegativeCodes = Enum('UI_ERROR', negative=True,
|
|
| 62 | BACKEND_ERROR='Backend error')
|
|
| 63 | """
|
|
| 64 | self.__doc__ = '''%s: |
|
| 65 | ||
| 66 | ''' % (self._enum_name) |
|
| 67 | ||
| 68 | for i in range(0, len(names)): |
|
| 69 | value = self._nodoc_id_to_value(i) |
|
| 70 | ||
| 71 | self._name_sanity_check(names[i]) |
|
| 72 | ||
| 73 | self.__dict__[names[i]] = value |
|
| 74 | self.__doc__ += '''**%s** = *%d* |
|
| 75 | ||
| 76 | ''' % (names[i], value) |
|
| 77 | ||
| 78 | i = self._doc_first_value(len(names)) |
|
| 79 | ||
| 80 | for name in names_with_doc.keys(): |
|
| 81 | self._name_sanity_check(name) |
|
| 82 | ||
| 83 | self.__dict__[name] = i |
|
| 84 | docstring = names_with_doc[name] |
|
| 85 | ||
| 86 | if type(docstring) != str: |
|
| 87 | raise TypeError('Values of kwargs must be (doc-)strings.') |
|
| 88 | ||
| 89 | self.__doc__ += '''**%s** = *%d* |
|
| 90 | %s |
|
| 91 | ||
| 92 | ''' % (name, i, names_with_doc[name]) |
|
| 93 | ||
| 94 | i = self._doc_next_value(i) |
|
| 95 | ||
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
96 | self.__doc__ += '\n' |
| 97 | ||
| 98 | @classmethod
|
|
| 99 | def _nodoc_id_to_value(cls, identity): |
|
| 100 | """ Map ids of names without a docstring to a value
|
|
| 101 | ||
| 102 | :param id: Name id
|
|
| 103 | """
|
|
| 104 | return identity |
|
| 105 | ||
| 106 | @classmethod
|
|
| 107 | def _doc_next_value(cls, value): |
|
| 108 | """ Gets the next value """
|
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
109 | return value+1 |
| 110 | ||
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
111 | @classmethod
|
| 112 | def _doc_first_value(cls, nodoc_max_value): |
|
| 113 | """ Gets the first value """
|
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
114 | return nodoc_max_value |
| 115 | ||
| 116 | def _name_sanity_check(self, name): |
|
| 117 | """ Checks an enum name for sanity.
|
|
| 118 | ||
| 119 | Names may only consist of uppercase, characters and are limited
|
|
| 120 | to the values A-Z, 0-9 and _ (underscore).
|
|
| 121 | """
|
|
| 122 | if getattr(self, '_allowed_characters', None): |
|
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
123 | allowed_characters = self._allowed_characters |
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
124 | else: |
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
125 | allowed_characters = '_' |
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
126 | |
| 127 | # Build the allowed character list.
|
|
|
1446
by Stephan Peijnik
UI update, list download gtk frontend now operational, but buggy (threading issue). |
128 | for i in range(ord('A'), ord('Z')+1): |
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
129 | allowed_characters += chr(i) |
|
1446
by Stephan Peijnik
UI update, list download gtk frontend now operational, but buggy (threading issue). |
130 | for i in range(ord('0'), ord('9')+1): |
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
131 | allowed_characters += chr(i) |
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
132 | |
| 133 | for i in range(0, len(name)): |
|
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
134 | char = name[i] |
| 135 | if char not in allowed_characters: |
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
136 | e_msg = 'Enumeration names may only consist of '+\ |
| 137 | 'uppercase letters, numbers and underscores:\n' |
|
| 138 | e_msg += '%s\n' % (name) |
|
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
139 | j = 0 |
| 140 | while (j < i): |
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
141 | e_msg += ' ' |
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
142 | j += 1 |
| 143 | ||
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
144 | e_msg += '^' |
| 145 | raise TypeError(e_msg) |
|
| 146 | ||
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
147 | def __getattr__(self, name): |
| 148 | """ Custom attribute resolution """
|
|
| 149 | if name in self.__dict__: |
|
| 150 | return self.__dict__['name'] |
|
| 151 | raise AttributeError(name) |
|
| 152 | ||
| 153 | ||
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
154 | def __setattr__(self, name, value): |
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
155 | """ Only the __doc__ attribute may be set """
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
156 | if name != '__doc__': |
| 157 | raise TypeError('Cannot set values of %s objects.' \ |
|
| 158 | % (self.__class__.__name__)) |
|
| 159 | else: |
|
| 160 | self.__dict__['__doc__'] = value |
|
| 161 | ||
| 162 | def __delattr__(self, name): |
|
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
163 | """ No attributes may be deleted """
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
164 | raise TypeError('Cannot delete values of %s objects.' \ |
| 165 | % (self.__class__.__name__)) |
|
| 166 | ||
| 167 | class NegativeEnum(Enum): |
|
| 168 | """
|
|
| 169 | Simple autodoc-aware C-like negative enumeration.
|
|
| 170 | ||
| 171 | The difference to :class:`Enum` is that values are assigned starting at
|
|
| 172 | *-1* downwards.
|
|
| 173 | ||
| 174 | >>> NegativeCodes = Enum('UI_ERROR', negative=True,
|
|
| 175 | BACKEND_ERROR='Backend error')
|
|
| 176 | >>> NegativeCodes.UI_ERROR
|
|
| 177 | -1
|
|
| 178 |
|
|
| 179 | """
|
|
| 180 | _enum_name = ':class:`NegativeEnum<UpdateManager.Util.enum.NegativeEnum>`' |
|
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
181 | |
| 182 | @classmethod
|
|
| 183 | def _nodoc_id_to_value(cls, identity): |
|
| 184 | """ Map ids of names without a docstring to a value
|
|
| 185 |
|
|
| 186 | :param id: Name id
|
|
| 187 | """
|
|
| 188 | return -(identity+1) |
|
| 189 | ||
| 190 | @classmethod
|
|
| 191 | def _doc_next_value(cls, value): |
|
| 192 | """ Gets next value """
|
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
193 | return value-1 |
| 194 | ||
|
1433
by Stephan Peijnik
Pylint checking & fixing, take one. |
195 | @classmethod
|
| 196 | def _doc_first_value(cls, nodoc_max_value): |
|
| 197 | """ Gets first value """
|
|
|
1392
by Stephan Peijnik
Added UpdateManager.Util.enum (C-like Enum classes that are sphinx-aware). |
198 | return (nodoc_max_value*-1)-1 |