Package flumotion :: Package common :: Module messages
[hide private]

Source Code for Module flumotion.common.messages

  1  # -*- Mode: Python; test-case-name: flumotion.test.test_common_messages -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  """serializable translatable messages. 
 19  support for serializable translatable messages from component/manager to admin 
 20  """ 
 21   
 22  import time 
 23   
 24  from twisted.spread import pb 
 25   
 26  from flumotion.common import log 
 27  from flumotion.configure import configure 
 28  from flumotion.common.i18n import FancyEqMixin, Translatable 
 29  from flumotion.common.i18n import * 
 30   
 31  __version__ = "$Rev$" 
 32   
 33  (ERROR, 
 34   WARNING, 
 35   INFO) = range(1, 4) 
 36   
 37   
 38  # NOTE: same caveats apply for FancyEqMixin as above 
 39  # this might be a little heavy; we could consider only comparing 
 40  # on id, once we verify that all id's are unique 
 41   
 42   
43 -class Message(pb.Copyable, pb.RemoteCopy, FancyEqMixin):
44 """ 45 I am a message to be shown in a UI. 46 47 Projects should subclass this base class to provide default project 48 and version class attributes. 49 50 @ivar section: name of the section in which the message is described. 51 @type section: str 52 @ivar anchor: name of the anchor in which the message is described. 53 @type anchor: str 54 @ivar description: the link text to show 55 @type description: L{flumotion.common.messages.Translatable} 56 """ 57 project = configure.PACKAGE 58 version = configure.version 59 60 # these properties allow linking to the documentation 61 section = None 62 anchor = None 63 description = None 64 65 compareAttributes = ["level", "translatables", "debug", "mid", "priority", 66 "timestamp"] 67
68 - def __init__(self, level, translatable, debug=None, mid=None, priority=50, 69 timestamp=None):
70 """ 71 Create a new message. 72 73 The mid identifies this kind of message, and serves two purposes. 74 75 The first purpose is to serve as a key by which a kind of 76 message might be removed from a set of messages. For example, a 77 firewire component detecting that a cable has been plugged in 78 will remove any message that the cable is unplugged. 79 80 Secondly it serves so that the message viewers that watch the 81 'current state' of some object only see the latest message of a 82 given type. For example when messages are stored in persistent 83 state objects that can be transferred over the network, it 84 becomes inefficient to store the whole history of status 85 messages. Message stores can keep only the latest message of a 86 given ID. 87 88 @param level: ERROR, WARNING or INFO 89 @param translatable: a translatable possibly with markup for 90 linking to documentation or running commands. 91 @param debug: further, untranslated, debug information, not 92 always shown 93 @param priority: priority compared to other messages of the same 94 level 95 @param timestamp: time since epoch at which the message was 96 generated, in seconds. 97 @param mid: A unique id for this kind of message, as 98 discussed above. If not given, will be 99 generated from the contents of the 100 translatable. 101 """ 102 self.level = level 103 self.translatables = [] 104 self.debug = debug 105 106 # FIXME: untranslated is a really poor choice of id 107 self.id = mid or translatable.untranslated() 108 self.priority = priority 109 self.timestamp = timestamp or time.time() 110 # -1 is in __init__, -2 is in the subclass __init__, 111 # -3 is in the caller 112 log.doLog(log.DEBUG, None, 'messages', 113 'creating message %r', self, where=-3) 114 log.doLog(log.DEBUG, None, 'messages', 115 'message debug %s', debug) 116 self.add(translatable)
117
118 - def __repr__(self):
119 return '<Message %r at %r>' % (self.id, id(self))
120
121 - def add(self, translatable):
122 if not isinstance(translatable, Translatable): 123 raise ValueError('%r is not Translatable' % translatable) 124 self.translatables.append(translatable) 125 log.doLog(log.DEBUG, None, 'messages', 126 'message %r: adding %r', (id(self), translatable.untranslated()), 127 where=-2)
128
129 - def getTimeStamp(self):
130 """Get the timestamp for the message 131 @returns: the timestamp or None 132 @rtype: int 133 """ 134 # F0.4: timestamp was added in 0.4.2 135 return getattr(self, 'timestamp', None)
136
137 - def getDescription(self):
138 """Get the description for the message 139 @returns: the description or None 140 @rtype: str 141 """ 142 return getattr(self, 'description', None)
143 144 pb.setUnjellyableForClass(Message, Message) 145 146 # these are implemented as factory functions instead of classes because 147 # properly proxying to the correct subclass is hard with Copyable/RemoteCopy 148 149
150 -def Error(*args, **kwargs):
151 """ 152 Create a L{Message} at ERROR level, indicating a failure that needs 153 intervention to be resolved. 154 """ 155 return Message(ERROR, *args, **kwargs)
156 157 # FIXME: figure out a way to not be shadowing the Warning builtin without 158 # breaking all other code 159 __pychecker__ = 'no-shadowbuiltin' 160 161
162 -def Warning(*args, **kwargs):
163 """ 164 Create a L{Message} at WARNING level, indicating a potential problem. 165 """ 166 return Message(WARNING, *args, **kwargs)
167 __pychecker__ = '' 168 169
170 -def Info(*args, **kwargs):
171 """ 172 Create a L{Message} at INFO level. 173 """ 174 return Message(INFO, *args, **kwargs)
175 176
177 -class Result(pb.Copyable, pb.RemoteCopy):
178 """ 179 I am used in worker checks to return a result. 180 181 @ivar value: the result value of the check 182 @ivar failed: whether or not the check failed. Typically triggered 183 by adding an ERROR message to the result. 184 @ivar messages: list of messages 185 @type messages: list of L{Message} 186 """ 187
188 - def __init__(self):
189 self.messages = [] 190 self.value = None 191 self.failed = False
192
193 - def succeed(self, value):
194 """ 195 Make the result be successful, setting the given result value. 196 """ 197 self.value = value
198
199 - def add(self, message):
200 """ 201 Add a message to the result. 202 203 @type message: L{Message} 204 """ 205 self.messages.append(message) 206 if message.level == ERROR: 207 self.failed = True 208 self.value = None
209 pb.setUnjellyableForClass(Result, Result) 210