Back to index

moin  1.9.0~rc2
__init__.py
Go to the documentation of this file.
00001 # -*- coding: iso-8859-1 -*-
00002 """
00003     MoinMoin - event (notification) framework
00004 
00005     This code abstracts event handling in MoinMoin,
00006     currently for notifications. It implements the observer pattern.
00007 
00008     @copyright: 2007 by Karol Nowak <grywacz@gmail.com>
00009     @license: GNU GPL, see COPYING for details.
00010 """
00011 
00012 from MoinMoin import log
00013 logging = log.getLogger(__name__)
00014 
00015 from MoinMoin import wikiutil
00016 from MoinMoin.util import pysupport
00017 from MoinMoin.wikiutil import PluginAttributeError
00018 
00019 # Create a list of extension actions from the package directory
00020 modules = pysupport.getPackageModules(__file__)
00021 
00022 # Dummy pseudo-getText function used in event descriptions,
00023 # so that they get into .po files
00024 _ = lambda x: x
00025 
00026 
00027 class Event(object):
00028     """A class handling information common to all events."""
00029 
00030     # NOTE: each Event subclass must have a unique name attribute
00031     name = u"Event"
00032 
00033     def __init__(self, request):
00034         self.request = request
00035 
00036 
00037 class PageEvent(Event):
00038     """An event related to a page change"""
00039 
00040     name = u"PageEvent"
00041 
00042     def __init__(self, request):
00043         Event.__init__(self, request)
00044 
00045 
00046 class PageChangedEvent(PageEvent):
00047 
00048     name = u"PageChangedEvent"
00049     description = _(u"""Page has been modified""")
00050     req_superuser = False
00051 
00052     def __init__(self, request, page, comment):
00053         PageEvent.__init__(self, request)
00054         self.page = page
00055         self.comment = comment
00056 
00057 
00058 class TrivialPageChangedEvent(PageEvent):
00059 
00060     name = u"TrivialPageChangedEvent"
00061     description = _(u"Page has been modified in a trivial fashion")
00062     req_superuser = False
00063 
00064     def __init__(self, request, page, comment):
00065         PageEvent.__init__(self, request)
00066         self.page = page
00067         self.comment = comment
00068 
00069 
00070 class PageRenamedEvent(PageEvent):
00071 
00072     name = u"PageRenamedEvent"
00073     description = _(u"""Page has been renamed""")
00074     req_superuser = False
00075 
00076     def __init__(self, request, page, old_page, comment=""):
00077         PageEvent.__init__(self, request)
00078         self.page = page
00079         self.old_page = old_page
00080         self.comment = comment
00081 
00082 
00083 class PageDeletedEvent(PageEvent):
00084 
00085     name = u"PageDeletedEvent"
00086     description = _(u"""Page has been deleted""")
00087     req_superuser = False
00088 
00089     def __init__(self, request, page, comment):
00090         PageEvent.__init__(self, request)
00091         self.page = page
00092         self.comment = comment
00093 
00094 
00095 class PageCopiedEvent(PageEvent):
00096 
00097     name = u"PageCopiedEvent"
00098     description = _(u"""Page has been copied""")
00099     req_superuser = False
00100 
00101     def __init__(self, request, page, old_page, comment):
00102         PageEvent.__init__(self, request)
00103         self.page = page
00104         self.old_page = old_page
00105         self.comment = comment
00106 
00107 
00108 class FileAttachedEvent(PageEvent):
00109 
00110     name = u"FileAttachedEvent"
00111     description = _(u"""A new attachment has been added""")
00112     req_superuser = False
00113 
00114     def __init__(self, request, pagename, filename, size):
00115         PageEvent.__init__(self, request)
00116         self.request = request
00117         self.pagename = pagename
00118         self.filename = filename
00119         self.size = size
00120 
00121 
00122 class FileRemovedEvent(PageEvent):
00123 
00124     name = u"FileRemovedEvent"
00125     description = _(u"""An attachment has been removed""")
00126     req_superuser = False
00127 
00128     def __init__(self, request, pagename, filename, size):
00129         PageEvent.__init__(self, request)
00130         self.request = request
00131         self.pagename = pagename
00132         self.filename = filename
00133         self.size = size
00134 
00135 
00136 class PageRevertedEvent(PageEvent):
00137 
00138     name = u"PageRevertedEvent"
00139     description = _(u"""A page has been reverted to a previous state""")
00140     req_superuser = False
00141 
00142     def __init__(self, request, pagename, previous, current):
00143         PageEvent.__init__(self, request)
00144         self.pagename = pagename
00145         self.previous = previous
00146         self.current = current
00147 
00148 
00149 class SubscribedToPageEvent(PageEvent):
00150 
00151     name = u"SubscribedToPageEvent"
00152     description = _(u"""A user has subscribed to a page""")
00153     req_superuser = True
00154 
00155     def __init__(self, request, pagename, username):
00156         PageEvent.__init__(self, request)
00157         self.pagename = pagename
00158         self.username = username
00159 
00160 
00161 class JabberIDSetEvent(Event):
00162     """ Sent when user changes her Jabber ID """
00163 
00164     def __init__(self, request, jid):
00165         Event.__init__(self, request)
00166         self.jid = jid
00167 
00168 
00169 class JabberIDUnsetEvent(Event):
00170     """ Sent when Jabber ID is no longer used
00171 
00172     Obviously this will be usually sent along with JabberIDSetEvent,
00173     because we require user's jabber id to be unique by default.
00174 
00175     """
00176     def __init__(self, request, jid):
00177         Event.__init__(self, request)
00178         self.jid = jid
00179 
00180 
00181 class UserCreatedEvent(Event):
00182     """ Sent when a new user has been created """
00183 
00184     name = u"UserCreatedEvent"
00185     description = _(u"""A new account has been created""")
00186     req_superuser = True
00187 
00188     def __init__(self, request, user):
00189         Event.__init__(self, request)
00190         self.user = user
00191 
00192 
00193 class PagePreSaveEvent(Event):
00194     """ Event sent when a page is about to be saved
00195 
00196     This can be used to abort a save, for instance, if handler returns Abort.
00197     """
00198 
00199     name = u"PagePreSaveEvent"
00200 
00201     def __init__(self, request, page_editor, new_text):
00202         Event.__init__(self, request)
00203         self.page_editor = page_editor
00204         self.new_text = new_text
00205 
00206 
00207 class EventResult:
00208     """ This is a base class for messages passed from event handlers """
00209     pass
00210 
00211 
00212 class Abort(EventResult):
00213     """ Result returned if handler wants to abort operation that sent the event """
00214     def __init__(self, reason):
00215         """
00216         @param reason: human-readable reason of failure
00217         """
00218         self.reason = reason
00219 
00220 
00221 def get_handlers(cfg):
00222     """Create a list of available event handlers.
00223 
00224     Each handler is a handle() function defined in a plugin,
00225     pretty much like in case of actions.
00226 
00227     TODO: maybe make it less dumb? ;-)
00228     """
00229     event_handlers = []
00230     names = wikiutil.getPlugins("events", cfg)
00231 
00232     for name in names:
00233         try:
00234             handler = wikiutil.importPlugin(cfg, "events", name, "handle")
00235         except PluginAttributeError:
00236             handler = None
00237 
00238         if handler is not None:
00239             event_handlers.append(handler)
00240 
00241     return event_handlers
00242 
00243 
00244 def send_event(event):
00245     """Function called from outside to process an event
00246 
00247     @return: a list of messages returned by handlers
00248     @rtype: list
00249     """
00250 
00251     # A list of messages generated by event handlers, passed back to caller
00252     msg = []
00253     cfg = event.request.cfg
00254 
00255     # Try to handle the event with each available handler (for now)
00256     for handle in cfg.event_handlers:
00257         retval = handle(event)
00258 
00259         assert retval is None or isinstance(retval, EventResult)
00260 
00261         if retval:
00262             msg.append(retval)
00263 
00264     return msg
00265 
00266 
00267 def get_subscribable_events():
00268     """Create and return a list of user-visible events
00269 
00270     @return: A list of user-visible events described by dictionaries
00271     @rtype: dict
00272     """
00273     defs = globals()
00274     subscribable_events = {}
00275 
00276     for ev in defs.values():
00277         if type(ev) is type and issubclass(ev, Event) and ev.__dict__.has_key("description") and ev.__dict__.has_key("name"):
00278             subscribable_events[ev.name] = {'desc': ev.description, 'superuser': ev.req_superuser}
00279 
00280     return subscribable_events
00281 
00282 # Get rid of the dummy getText so that it doesn't get imported with *
00283 del _
00284