Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

# Authors: 

#   Petr Viktorin <pviktori@redhat.com> 

# 

# Copyright (C) 2012  Red Hat 

# see file 'COPYING' for use and warranty inmsgion 

# 

# This program is free software; you can redistribute it and/or modify 

# it under the terms of the GNU General Public License as published by 

# the Free Software Foundation, either version 3 of the License, or 

# (at your option) any later version. 

# 

# This program is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

# GNU General Public License for more details. 

# 

# You should have received a copy of the GNU General Public License 

# along with this program.  If not, see <http://www.gnu.org/licenses/>. 

 

""" 

Custom message (debug, info, wraning) classes passed through RPC. 

 

These are added to the "messages" entry in a RPC response, and printed to the 

user as log messages. 

 

Each message class has a unique numeric "errno" attribute from the 10000-10999 

range, so that it does not clash with PublicError numbers. 

 

Messages also have the 'type' argument, set to one of 'debug', 'info', 

'warning', 'error'. This determines the severity of themessage. 

""" 

 

from inspect import isclass 

 

from ipalib.constants import TYPE_ERROR 

from ipalib.text import _ as ugettext 

from ipalib.text import Gettext, NGettext 

from ipalib.capabilities import client_has_capability 

 

 

def add_message(version, result, message): 

    if client_has_capability(version, 'messages'): 

        result.setdefault('messages', []).append(message.to_dict()) 

 

 

def process_message_arguments(obj, format=None, message=None, **kw): 

    obj.kw = kw 

    name = obj.__class__.__name__ 

    if obj.format is not None and format is not None: 

        raise ValueError( 

            'non-generic %r needs format=None; got format=%r' % ( 

                name, format) 

        ) 

    if message is None: 

        if obj.format is None: 

            if format is None: 

                raise ValueError( 

                    '%s.format is None yet format=None, message=None' % name 

                ) 

            obj.format = format 

        obj.forwarded = False 

        obj.msg = obj.format % kw 

        if isinstance(obj.format, basestring): 

            obj.strerror = ugettext(obj.format) % kw 

        else: 

            obj.strerror = obj.format % kw 

        if 'instructions' in kw: 

            def convert_instructions(value): 

                if isinstance(value, list): 

                    result = u'\n'.join(map(lambda line: unicode(line), value)) 

                    return result 

                return value 

            instructions = u'\n'.join((unicode(_('Additional instructions:')), 

                                    convert_instructions(kw['instructions']))) 

            obj.strerror = u'\n'.join((obj.strerror, instructions)) 

    else: 

        if isinstance(message, (Gettext, NGettext)): 

            message = unicode(message) 

        elif type(message) is not unicode: 

            raise TypeError( 

                TYPE_ERROR % ('message', unicode, message, type(message)) 

            ) 

        obj.forwarded = True 

        obj.msg = message 

        obj.strerror = message 

    for (key, value) in kw.iteritems(): 

        assert not hasattr(obj, key), 'conflicting kwarg %s.%s = %r' % ( 

            name, key, value, 

        ) 

        setattr(obj, key, value) 

 

 

_texts = [] 

 

def _(message): 

    _texts.append(message) 

    return message 

 

 

class PublicMessage(UserWarning): 

    """ 

    **10000** Base class for messages that can be forwarded in an RPC response. 

    """ 

    def __init__(self, format=None, message=None, **kw): 

        process_message_arguments(self, format, message, **kw) 

        super(PublicMessage, self).__init__(self.msg) 

 

    errno = 10000 

    format = None 

 

    def to_dict(self): 

        """Export this message to a dict that can be sent through RPC""" 

        return dict( 

            type=unicode(self.type), 

            name=unicode(type(self).__name__), 

            message=self.strerror, 

            code=self.errno, 

        ) 

 

 

class VersionMissing(PublicMessage): 

    """ 

    **13001** Used when client did not send the API version. 

 

    For example: 

 

    >>> VersionMissing(server_version='2.123').strerror 

    u"API Version number was not sent, forward compatibility not guaranteed. Assuming server's API version, 2.123" 

 

    """ 

 

    errno = 13001 

    type = 'warning' 

    format = _("API Version number was not sent, forward compatibility not " 

        "guaranteed. Assuming server's API version, %(server_version)s") 

 

 

def iter_messages(variables, base): 

    """Return a tuple with all subclasses 

    """ 

    for (key, value) in variables.items(): 

        if key.startswith('_') or not isclass(value): 

            continue 

        if issubclass(value, base): 

            yield value 

 

 

public_messages = tuple(sorted( 

    iter_messages(globals(), PublicMessage), key=lambda E: E.errno)) 

 

def print_report(label, classes): 

    for cls in classes: 

        print '%d\t%s' % (cls.errno, cls.__name__) 

    print '(%d %s)' % (len(classes), label) 

 

if __name__ == '__main__': 

    print_report('public messages', public_messages)