Patch by Charles Lepple to fix two of the assertions in our Python bindings.
In Python, assert is a statement, not a function. With the parentheses, Python takes the parentheses and everything between them as a tuple, and uses this as the condition; since it contains two items, it is not empty, which means it is true, which means the assertion would always pass.
The fix is to remove the parentheses. Then, the assertion statement has its usual two arguments (formerly the items in the tuple).
2 A Python module that enables posting notifications to the Growl daemon.
3 See <http://growl.info/> for more information.
6 __author__ = "Mark Rowe <bdash@users.sourceforge.net>"
7 __copyright__ = "(C) 2003 Mark Rowe <bdash@users.sourceforge.net>. Released under the BSD license."
8 __contributors__ = ["Ingmar J Stein (Growl Team)",
9 "Rui Carmo (http://the.taoofmac.com)",
10 "Jeremy Rossi <jeremy@jeremyrossi.com>",
11 "Peter Hosey <http://boredzo.org/> (Growl Team)",
21 GROWL_PROTOCOL_VERSION=1
22 GROWL_TYPE_REGISTRATION=0
23 GROWL_TYPE_NOTIFICATION=1
25 GROWL_APP_NAME="ApplicationName"
26 GROWL_APP_ICON="ApplicationIcon"
27 GROWL_NOTIFICATIONS_DEFAULT="DefaultNotifications"
28 GROWL_NOTIFICATIONS_ALL="AllNotifications"
29 GROWL_NOTIFICATIONS_USER_SET="AllowedUserNotifications"
31 GROWL_NOTIFICATION_NAME="NotificationName"
32 GROWL_NOTIFICATION_TITLE="NotificationTitle"
33 GROWL_NOTIFICATION_DESCRIPTION="NotificationDescription"
34 GROWL_NOTIFICATION_ICON="NotificationIcon"
35 GROWL_NOTIFICATION_APP_ICON="NotificationAppIcon"
36 GROWL_NOTIFICATION_PRIORITY="NotificationPriority"
38 GROWL_NOTIFICATION_STICKY="NotificationSticky"
40 GROWL_APP_REGISTRATION="GrowlApplicationRegistrationNotification"
41 GROWL_APP_REGISTRATION_CONF="GrowlApplicationRegistrationConfirmationNotification"
42 GROWL_NOTIFICATION="GrowlNotification"
43 GROWL_SHUTDOWN="GrowlShutdown"
44 GROWL_PING="Honey, Mind Taking Out The Trash"
45 GROWL_PONG="What Do You Want From Me, Woman"
46 GROWL_IS_READY="Lend Me Some Sugar; I Am Your Neighbor!"
49 growlPriority = {"Very Low":-2,"Moderate":-1,"Normal":0,"High":1,"Emergency":2}
52 """Builds a Growl Network Registration packet.
53 Defaults to emulating the command-line growlnotify utility."""
55 __notAllowed__ = [GROWL_APP_ICON, GROWL_NOTIFICATION_ICON, GROWL_NOTIFICATION_APP_ICON]
57 def __init__(self, hostname, password ):
58 self.hostname = hostname
59 self.password = password
60 self.socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
63 self.socket.sendto(data, (self.hostname, GROWL_UDP_PORT))
65 def PostNotification(self, userInfo):
66 if userInfo.has_key(GROWL_NOTIFICATION_PRIORITY):
67 priority = userInfo[GROWL_NOTIFICATION_PRIORITY]
70 if userInfo.has_key(GROWL_NOTIFICATION_STICKY):
71 sticky = userInfo[GROWL_NOTIFICATION_STICKY]
74 data = self.encodeNotify(userInfo[GROWL_APP_NAME],
75 userInfo[GROWL_NOTIFICATION_NAME],
76 userInfo[GROWL_NOTIFICATION_TITLE],
77 userInfo[GROWL_NOTIFICATION_DESCRIPTION],
80 return self.send(data)
82 def PostRegistration(self, userInfo):
83 data = self.encodeRegistration(userInfo[GROWL_APP_NAME],
84 userInfo[GROWL_NOTIFICATIONS_ALL],
85 userInfo[GROWL_NOTIFICATIONS_DEFAULT])
86 return self.send(data)
88 def encodeRegistration(self, application, notifications, defaultNotifications):
89 data = struct.pack("!BBH",
90 GROWL_PROTOCOL_VERSION,
91 GROWL_TYPE_REGISTRATION,
93 data += struct.pack("BB",
95 len(defaultNotifications) )
97 for i in notifications:
98 encoded = i.encode("utf-8")
99 data += struct.pack("!H", len(encoded))
101 for i in defaultNotifications:
102 data += struct.pack("B", i)
103 return self.encodePassword(data)
105 def encodeNotify(self, application, notification, title, description,
106 priority = 0, sticky = False):
108 application = application.encode("utf-8")
109 notification = notification.encode("utf-8")
110 title = title.encode("utf-8")
111 description = description.encode("utf-8")
112 flags = (priority & 0x07) * 2
116 flags = flags | 0x0001
117 data = struct.pack("!BBHHHHH",
118 GROWL_PROTOCOL_VERSION,
119 GROWL_TYPE_NOTIFICATION,
129 return self.encodePassword(data)
131 def encodePassword(self, data):
133 checksum.update(data)
135 checksum.update(self.password)
136 data += checksum.digest()
139 class _ImageHook(type):
140 def __getattribute__(self, attr):
143 from _growlImage import Image
145 return getattr(Image, attr)
148 __metaclass__ = _ImageHook
150 class _RawImage(object):
151 def __init__(self, data): self.rawImageData = data
153 class GrowlNotifier(object):
155 A class that abstracts the process of registering and posting
156 notifications to the Growl daemon.
158 You can either pass `applicationName', `notifications',
159 `defaultNotifications' and `applicationIcon' to the constructor
160 or you may define them as class-level variables in a sub-class.
162 `defaultNotifications' is optional, and defaults to the value of
163 `notifications'. `applicationIcon' is also optional but defaults
164 to a pointless icon so is better to be specified.
167 applicationName = 'GrowlNotifier'
169 defaultNotifications = []
170 applicationIcon = None
171 _notifyMethod = _growl
173 def __init__(self, applicationName=None, notifications=None, defaultNotifications=None, applicationIcon=None, hostname=None, password=None):
175 self.applicationName = applicationName
176 assert self.applicationName, 'An application name is required.'
179 self.notifications = list(notifications)
180 assert self.notifications, 'A sequence of one or more notification names is required.'
182 if defaultNotifications is not None:
183 self.defaultNotifications = list(defaultNotifications)
184 elif not self.defaultNotifications:
185 self.defaultNotifications = list(self.notifications)
187 if applicationIcon is not None:
188 self.applicationIcon = self._checkIcon(applicationIcon)
189 elif self.applicationIcon is not None:
190 self.applicationIcon = self._checkIcon(self.applicationIcon)
192 if hostname is not None and password is not None:
193 self._notifyMethod = netgrowl(hostname, password)
194 elif hostname is not None or password is not None:
195 raise KeyError, "Hostname and Password are both required for a network notification"
197 def _checkIcon(self, data):
198 if isinstance(data, str):
199 return _RawImage(data)
204 if self.applicationIcon is not None:
205 self.applicationIcon = self._checkIcon(self.applicationIcon)
207 regInfo = {GROWL_APP_NAME: self.applicationName,
208 GROWL_NOTIFICATIONS_ALL: self.notifications,
209 GROWL_NOTIFICATIONS_DEFAULT: self.defaultNotifications,
210 GROWL_APP_ICON:self.applicationIcon,
212 self._notifyMethod.PostRegistration(regInfo)
214 def notify(self, noteType, title, description, icon=None, sticky=False, priority=None):
215 assert noteType in self.notifications
216 notifyInfo = {GROWL_NOTIFICATION_NAME: noteType,
217 GROWL_APP_NAME: self.applicationName,
218 GROWL_NOTIFICATION_TITLE: title,
219 GROWL_NOTIFICATION_DESCRIPTION: description,
222 notifyInfo[GROWL_NOTIFICATION_STICKY] = 1
224 if priority is not None:
225 notifyInfo[GROWL_NOTIFICATION_PRIORITY] = priority
228 notifyInfo[GROWL_NOTIFICATION_ICON] = self._checkIcon(icon)
230 self._notifyMethod.PostNotification(notifyInfo)