6
Reads notifications in the notify-osd.log format specified at:
7
https://wiki.ubuntu.com/NotifyOSD#Logging notifications
13
from LogWatcher import LogWatcher
15
message_header = re.compile("""
17
\[ # [timestamp, process-name, status?]
19
\d{4}-\d{2}-\d{2} # date YYYY-mm-dd
21
\d{2}:\d{2}:\d{2} # time HH-MM-SS
22
([Zz]|[+-]\d{2}:\d{2}) # time offset
25
([^,\]]+) # process name
26
(,([^\]]+))? # optional status
32
class Message(object):
33
"""A notification message"""
34
def __init__(self, timestamp, process_name, status, title):
35
self.timestamp = timestamp
36
self.process_name = process_name
41
def append_body(self, body):
42
"""Appends a body line to the message."""
45
def formatted_time(self):
46
"""Returned the time in a different format."""
47
t = time.strptime(self.timestamp.upper(), "%Y-%m-%dT%H:%M:%S-00:00")
48
return time.strftime("%B %d, %Y at %I:%M:%S %p", t)
50
class Notifications(object):
51
"""Reads notifications from a log file and sends them to the listeners."""
52
def __init__(self, path):
54
self._listeners = set()
56
def add_listener(self, f):
57
"""A listener is a function of a single argument, the messages
59
self._listeners.add(f)
61
def remove_listener(self, f):
62
"""Removes f from the set of listeners."""
63
self._listeners.remove(f)
66
"""Reads the previous messages, sends them to the listeners and starts
67
watching for more messages."""
68
# Get the previous messages
69
f = open(self._path, "r")
72
self._message_received(None, messages)
74
self._watcher = LogWatcher(self._path)
75
self._watcher.connect("changed", self._message_received)
80
"""Stops watching for more messages."""
83
def _notify_listeners(self, messages):
84
"""Notifies the listeners of new messages."""
85
for f in self._listeners:
88
def _message_received(self, watcher, messages):
89
"""Callback that parses messages and adds them to the queue."""
90
queue = self._parse_messages(messages)
92
self._notify_listeners(queue)
94
def _parse_messages(self, messages):
95
"""Returns a list of parsed messages."""
96
lines = messages.splitlines()
101
# Try to parse a new message, discard the line if the header
104
m = message_header.match(line)
107
timestamp = header[0].strip()
108
process_name = header[2].strip()
110
# Status may not exist
114
status = status.strip()
115
title = header[5].strip()
116
message = Message(timestamp, process_name, status, title)
117
# Messages are delimited by a blank line
119
if line.strip() == "":
120
queue.append(message)
123
message.append_body(line)
125
# Don't forget the last message (should probably never happen)
127
queue.append(message)