/update-manager/devel/gsoc09

To get this branch, use:
bzr branch https://alioth.debian.org/scm/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