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