liveplots.filemonitor
Covered: 80 lines
Missed: 9 lines
Skipped 17 lines
Percent: 89 %
  1
'''
  2
Created on 15/04/2010
  4
@author: fccoelho
  5
'''
  6
import sys
  7
try:
  8
    import pyinotify
  9
except:
 10
    raise TypeError('Filemonitor cannot cannot be used on %s platform'%sys.platform)
 12
class Monitor(object):
 13
    '''
 14
    Monitors a file for changes and triggers a visualization action
 15
    '''
 16
    ValidEvents ={'create':pyinotify.IN_CREATE,
 17
                  'delete':pyinotify.IN_DELETE,
 18
                  'close_write':pyinotify.IN_CLOSE_WRITE,
 19
                  "close_nowrite":pyinotify.IN_CLOSE_NOWRITE,
 20
                  'access':pyinotify.IN_ACCESS,
 21
                  'attrib':pyinotify.IN_ATTRIB,
 22
                  'modify':pyinotify.IN_MODIFY}
 23
    def __init__(self,filepath,events,visaction,**kwargs):
 24
        '''
 25
        Sets up monitoring of a file 
 27
        :Parameters:
 28
            - `filepath`: full path of the file to monitor
 29
            - `event`: events to monitor: list of strings
 30
            - `visaction`: Callable which will perform the action which takes filepath as argument
 31
        '''
 32
        self.filepath = filepath
 33
        self.events = events
 34
        self.visaction = visaction
 36
        self.wm = pyinotify.WatchManager()
 37
        self.mask = self._get_mask(events)
 38
        self.handler = _HandleEvents()
 39
        if 'debug' in kwargs:
 40
            self.handler.debug = kwargs['debug']
 41
        self.handler.set_action(self.visaction)
 42
        self.notifier = pyinotify.ThreadedNotifier(self.wm, self.handler)
 43
        self.notifier.start()
 44
        wdd = self.wm.add_watch(self.filepath, self.mask, rec=True)
 47
    def _get_mask(self, events):
 48
        '''
 49
        Returns the mask for the notifier
 50
        '''
 51
        try:
 52
            codes = [self.ValidEvents[e] for e in events]
 53
        except KeyError:
 54
            raise KeyError('%s is not a valid event'%e)
 55
        if len(codes) > 1:
 56
            mask = codes[0]
 57
            for c in codes[1:]:
 58
                mask = mask | c
 59
        else:
 60
            mask = codes[0]
 61
        return mask
 63
    def stop(self):
 64
        self.notifier.stop()
 68
class _HandleEvents(pyinotify.ProcessEvent):
 69
    debug = 0
 70
    def set_action(self,action):
 71
        self.action = action
 73
    def process_IN_CREATE(self, event):
 74
        if self.debug:
 75
            print "Creating:", event.pathname
 76
        self.action(event.pathname)
 78
    def process_IN_DELETE(self, event):
 79
        if self.debug:
 80
            print "Removing:", event.pathname
 81
        self.action(event.pathname)
 83
    def process_IN_ACCESS(self,event):
 84
        if self.debug:
 85
            print "Accessing:", event.pathname
 86
        self.action(event.pathname)
 88
    def process_IN_ATTRIB(self,event):
 89
        if self.debug:
 90
            print "Changing metadata:", event.pathname
 91
        self.action(event.pathname)
 93
    def process_IN_MODIFY(self,event):
 94
        if self.debug:
 95
            print "Modifying:", event.pathname
 96
        self.action(event.pathname)
 98
    def process_IN_CLOSE_WRITE(self,event):
 99
        if self.debug:
100
            print "Closing writable file:", event.pathname
101
        self.action(event.pathname)
103
    def process_IN_CLOSE_NOWRITE(self,event):
104
        if self.debug:
105
            print "Closing read-only file:", event.pathname
106
        self.action(event.pathname)