Commits

Lucas Taylor  committed 518b483

Add a basic setup.py and reorg package structure

  • Participants
  • Parent commits ac1e552

Comments (0)

Files changed (7)

File __init__.py

-from protocol import GrowlClient
-from observer import GrowlObserver

File observer.py

-"""observer.py
-
-Register an instance of the GrowlObserver to receive all log events:
-
-    twisted.python.log.addObserver(GrowlObserver())
-    
-"""
-from txGrowl import GrowlClient
-
-class GrowlObserver(GrowlClient):
-    """GrowlObserver"""
-    def __init__(self, app_name="txGrowl", password=None, destinations='127.0.0.1', required_key=None):
-        GrowlClient.__init__(self, app_name, password, destinations)
-        
-        self.required_key = required_key
-        
-        self.observed = []
-        self.defaultNotification = "Default"
-        self.addNotification("Default")
-        self.addNotification("Error")
-
-
-    def __call__(self, event):
-        if self.required_key not in event:
-            return
-            
-        isError = event['isError']
-        required_key = event[self.required_key]
-        title = event.get('title', self.app_name)
-        priority = event.get('priority', 0)
-        notification = event.get('notification', self.defaultNotification)
-
-        
-        if isError:
-            notification = "Error"
-            try:
-                msg = event['failure'].getErrorMessage()
-            except:
-                msg = '\n'.join(event['message'])
-        else:
-            msg = '\n'.join(event['message'])
-            
-        self.notify(notification, title, msg, priority)
-        self.observed.append((title, msg, priority))

File protocol.py

-"""protocol.py
-Growl UDP protocol implementation
-
-Packet encoding and constants provided by the growl sdk
-See <http://growl.info/> for more information.
-
-"""
-import struct, md5
-
-from twisted.internet.protocol import DatagramProtocol
-from twisted.internet import reactor
-from twisted.python import log
-from twisted.python.failure import Failure
-
-# Growl constants from pygrowl
-GROWL_UDP_PORT = 9887
-GROWL_PROTOCOL_VERSION = 1
-
-GROWL_TYPE_REGISTRATION_MD5 = 0 #The packet type of registration packets with MD5 authentication.
-GROWL_TYPE_REGISTRATION_SHA256 = 2 #The packet type of registration packets with SHA-256 authentication.
-GROWL_TYPE_REGISTRATION_NOAUTH = 4 #The packet type of registration packets without authentication.
-GROWL_TYPE_NOTIFICATION_MD5 = 1 #The packet type of notification packets with MD5 authentication.
-GROWL_TYPE_NOTIFICATION_SHA256 = 3 #The packet type of notification packets with SHA-256 authentication.
-GROWL_TYPE_NOTIFICATION_NOAUTH = 5 #The packet type of notification packets without authentication.
-
-
-GROWL_TYPE_REGISTRATION = GROWL_TYPE_REGISTRATION_MD5
-GROWL_TYPE_NOTIFICATION = GROWL_TYPE_NOTIFICATION_MD5
-
-
-
-GROWL_APP_NAME="ApplicationName"
-GROWL_APP_ICON="ApplicationIcon"
-GROWL_NOTIFICATIONS_DEFAULT="DefaultNotifications"
-GROWL_NOTIFICATIONS_ALL="AllNotifications"
-GROWL_NOTIFICATIONS_USER_SET="AllowedUserNotifications"
-
-GROWL_NOTIFICATION_NAME="NotificationName"
-GROWL_NOTIFICATION_TITLE="NotificationTitle"
-GROWL_NOTIFICATION_DESCRIPTION="NotificationDescription"
-GROWL_NOTIFICATION_ICON="NotificationIcon"
-GROWL_NOTIFICATION_APP_ICON="NotificationAppIcon"
-GROWL_NOTIFICATION_PRIORITY="NotificationPriority"
-		
-GROWL_NOTIFICATION_STICKY="NotificationSticky"
-
-GROWL_APP_REGISTRATION="GrowlApplicationRegistrationNotification"
-GROWL_APP_REGISTRATION_CONF="GrowlApplicationRegistrationConfirmationNotification"
-GROWL_NOTIFICATION="GrowlNotification"
-GROWL_SHUTDOWN="GrowlShutdown"
-GROWL_PING="Growl Ping"
-GROWL_PONG="Growl Pong"
-GROWL_IS_READY="Lend Me Some Sugar; I Am Your Neighbor!"
-
-
-
-class GrowlProtocol(DatagramProtocol):
-    
-    def __init__(self, app_name="txGrowl", password=None, destinations=None):
-        self.app_name = app_name
-        self.password = password
-
-        if isinstance(destinations, str):
-            destinations = [destinations]
-        self.destinations = destinations or ['127.0.0.1']
-        
-    
-    def register(self, notifications=None, defaultNotifications=None):
-        """Register application with Growl server"""
-        notifications = notifications or []
-        defaultNotifications = defaultNotifications or []
-        if notifications:
-            data = self.encodeRegistration(notifications, defaultNotifications)
-            self.sendDatagram(data)
-    
-    
-    def encodeRegistration(self, notifications, defaultNotifications):
-        """Encode and return a Growl registration packet"""
-        data = struct.pack("!BBH",
-                           GROWL_PROTOCOL_VERSION,
-                           GROWL_TYPE_REGISTRATION,
-                           len(self.app_name) )
-        data += struct.pack("BB",
-                            len(notifications),
-                            len(defaultNotifications) )
-        data += self.app_name
-        for i in notifications:
-            encoded = i.encode("utf-8")
-            data += struct.pack("!H", len(encoded))
-            data += encoded
-        for i in defaultNotifications:
-            data += struct.pack("B", i)
-        return self.encodePassword(data)
-        
-    
-    def notify(self, notification, title, message, priority):
-        """Send Notification to Growl daemon"""
-        data = self.encodeNotify(notification, title, message, priority)
-        self.sendDatagram(data)
-        
-    
-    def encodeNotify(self, notification, title, message, priority=0, sticky=False):
-        """Encode and return Growl notification packet"""
-        application  = self.app_name.encode("utf-8")
-        notification = notification.encode("utf-8")
-        title       = title.encode("utf-8")
-        message  = message.encode("utf-8")
-        flags = (priority & 0x07) * 2
-        if priority < 0: 
-            flags |= 0x08
-        if sticky: 
-            flags = flags | 0x0001
-        data = struct.pack("!BBHHHHH",
-                           GROWL_PROTOCOL_VERSION,
-                           GROWL_TYPE_NOTIFICATION,
-                           flags,
-                           len(notification),
-                           len(title),
-                           len(message),
-                           len(application) )
-        data += notification
-        data += title
-        data += message
-        data += application
-        return self.encodePassword(data)
-        
-    
-    def encodePassword(self, data):
-        """Return md5 encoded data and password (if present)"""
-        checksum = md5.new()
-        checksum.update(data)
-        if self.password:
-           checksum.update(self.password)
-        data += checksum.digest()
-        return data
-        
-    
-    def sendDatagram(self, data):
-        """
-        Send any pending Growl notifications
-        """
-        self.transport.write(data)
-        
-    
-    def startProtocol(self):
-        for dest in self.destinations:
-            self.transport.connect(dest, GROWL_UDP_PORT)
-
-
-    def datagramReceived(self, data):
-        log.msg("Rx from Growl: %s" % data)
-
-
-    def connectionRefused(self):
-        log.msg("Growl connection refused")
-
-
-
-class GrowlClient(object):
-    """Basic protocol wrapper for Growl"""
-    priorities = {
-        "Very Low":-2,
-        "Moderate":-1,
-        "Normal":0,
-        "High":1,
-        "Emergency":2
-    }
-
-
-    def __init__(self, app_name=None, password=None, destinations=None):
-        self.app_name = app_name
-        self.password = password
-        self.destinations = destinations or []
-        self.notifications = []
-        self.defaults = [] # default in gui
-        
-        self.protocol = GrowlProtocol(self.app_name, self.password, self.destinations)
-        self.lport = reactor.listenUDP(0, self.protocol)
-        
-    
-    def addNotification(self, notification="Default", gui_enabled=True):
-        """Adds a notification type and sets whether it is enabled in Growl preferences"""
-        if notification not in self.notifications:
-            self.notifications.append(notification)
-            if gui_enabled:
-                self.defaults.append(len(self.notifications)-1)
-        
-    
-    def register(self):
-        """Register application with all destination Growl daemons"""
-        if self.notifications:
-            self.protocol.register(self.notifications, self.defaults)
-        
-    
-    def notify(self, notification=None, title=None, message=None, priority=0):
-        if message is not None:
-            self.protocol.notify(notification, title, message, priority)
-
-
+import os
+
+try:
+    from setuptools import setup, find_packages
+except ImportError:
+    from ez_setup import use_setuptools
+    use_setuptools()
+    from setuptools import setup, find_packages
+
+def read(fname):
+    return open(os.path.join(os.path.dirname(__file__), fname)).read()
+
+tests_require = [
+    'twisted',
+]
+
+setup(
+    name='txGrowl',
+    version='0.5',
+    author='Lucas Taylor',
+    author_email='ltaylor.volks@gmail.com',
+    url='https://bitbucket.org/ltvolks/txgrowl',
+    description = read('README'),
+    packages=find_packages(),
+    zip_safe=False,
+    install_requires=[
+        'twisted',
+    ],
+    tests_require=tests_require,
+    include_package_data=True,
+    classifiers=[
+        'Framework :: Twisted',
+        'Intended Audience :: Developers',
+        'Operating System :: OS Independent',
+        'Topic :: Software Development',
+        'Development Status :: 3 - Alpha'
+    ],
+)

File txGrowl/__init__.py

+from protocol import GrowlClient
+from observer import GrowlObserver

File txGrowl/observer.py

+"""observer.py
+
+Register an instance of the GrowlObserver to receive all log events:
+
+    twisted.python.log.addObserver(GrowlObserver())
+    
+"""
+from txGrowl import GrowlClient
+
+class GrowlObserver(GrowlClient):
+    """GrowlObserver"""
+    def __init__(self, app_name="txGrowl", password=None, destinations='127.0.0.1', required_key=None):
+        GrowlClient.__init__(self, app_name, password, destinations)
+        
+        self.required_key = required_key
+        
+        self.observed = []
+        self.defaultNotification = "Default"
+        self.addNotification("Default")
+        self.addNotification("Error")
+
+
+    def __call__(self, event):
+        if self.required_key not in event:
+            return
+            
+        isError = event['isError']
+        required_key = event[self.required_key]
+        title = event.get('title', self.app_name)
+        priority = event.get('priority', 0)
+        notification = event.get('notification', self.defaultNotification)
+
+        
+        if isError:
+            notification = "Error"
+            try:
+                msg = event['failure'].getErrorMessage()
+            except:
+                msg = '\n'.join(event['message'])
+        else:
+            msg = '\n'.join(event['message'])
+            
+        self.notify(notification, title, msg, priority)
+        self.observed.append((title, msg, priority))

File txGrowl/protocol.py

+"""protocol.py
+Growl UDP protocol implementation
+
+Packet encoding and constants provided by the growl sdk
+See <http://growl.info/> for more information.
+
+"""
+import struct, md5
+
+from twisted.internet.protocol import DatagramProtocol
+from twisted.internet import reactor
+from twisted.python import log
+from twisted.python.failure import Failure
+
+# Growl constants from pygrowl
+GROWL_UDP_PORT = 9887
+GROWL_PROTOCOL_VERSION = 1
+
+GROWL_TYPE_REGISTRATION_MD5 = 0 #The packet type of registration packets with MD5 authentication.
+GROWL_TYPE_REGISTRATION_SHA256 = 2 #The packet type of registration packets with SHA-256 authentication.
+GROWL_TYPE_REGISTRATION_NOAUTH = 4 #The packet type of registration packets without authentication.
+GROWL_TYPE_NOTIFICATION_MD5 = 1 #The packet type of notification packets with MD5 authentication.
+GROWL_TYPE_NOTIFICATION_SHA256 = 3 #The packet type of notification packets with SHA-256 authentication.
+GROWL_TYPE_NOTIFICATION_NOAUTH = 5 #The packet type of notification packets without authentication.
+
+
+GROWL_TYPE_REGISTRATION = GROWL_TYPE_REGISTRATION_MD5
+GROWL_TYPE_NOTIFICATION = GROWL_TYPE_NOTIFICATION_MD5
+
+
+
+GROWL_APP_NAME="ApplicationName"
+GROWL_APP_ICON="ApplicationIcon"
+GROWL_NOTIFICATIONS_DEFAULT="DefaultNotifications"
+GROWL_NOTIFICATIONS_ALL="AllNotifications"
+GROWL_NOTIFICATIONS_USER_SET="AllowedUserNotifications"
+
+GROWL_NOTIFICATION_NAME="NotificationName"
+GROWL_NOTIFICATION_TITLE="NotificationTitle"
+GROWL_NOTIFICATION_DESCRIPTION="NotificationDescription"
+GROWL_NOTIFICATION_ICON="NotificationIcon"
+GROWL_NOTIFICATION_APP_ICON="NotificationAppIcon"
+GROWL_NOTIFICATION_PRIORITY="NotificationPriority"
+		
+GROWL_NOTIFICATION_STICKY="NotificationSticky"
+
+GROWL_APP_REGISTRATION="GrowlApplicationRegistrationNotification"
+GROWL_APP_REGISTRATION_CONF="GrowlApplicationRegistrationConfirmationNotification"
+GROWL_NOTIFICATION="GrowlNotification"
+GROWL_SHUTDOWN="GrowlShutdown"
+GROWL_PING="Growl Ping"
+GROWL_PONG="Growl Pong"
+GROWL_IS_READY="Lend Me Some Sugar; I Am Your Neighbor!"
+
+
+
+class GrowlProtocol(DatagramProtocol):
+    
+    def __init__(self, app_name="txGrowl", password=None, destinations=None):
+        self.app_name = app_name
+        self.password = password
+
+        if isinstance(destinations, str):
+            destinations = [destinations]
+        self.destinations = destinations or ['127.0.0.1']
+        
+    
+    def register(self, notifications=None, defaultNotifications=None):
+        """Register application with Growl server"""
+        notifications = notifications or []
+        defaultNotifications = defaultNotifications or []
+        if notifications:
+            data = self.encodeRegistration(notifications, defaultNotifications)
+            self.sendDatagram(data)
+    
+    
+    def encodeRegistration(self, notifications, defaultNotifications):
+        """Encode and return a Growl registration packet"""
+        data = struct.pack("!BBH",
+                           GROWL_PROTOCOL_VERSION,
+                           GROWL_TYPE_REGISTRATION,
+                           len(self.app_name) )
+        data += struct.pack("BB",
+                            len(notifications),
+                            len(defaultNotifications) )
+        data += self.app_name
+        for i in notifications:
+            encoded = i.encode("utf-8")
+            data += struct.pack("!H", len(encoded))
+            data += encoded
+        for i in defaultNotifications:
+            data += struct.pack("B", i)
+        return self.encodePassword(data)
+        
+    
+    def notify(self, notification, title, message, priority):
+        """Send Notification to Growl daemon"""
+        data = self.encodeNotify(notification, title, message, priority)
+        self.sendDatagram(data)
+        
+    
+    def encodeNotify(self, notification, title, message, priority=0, sticky=False):
+        """Encode and return Growl notification packet"""
+        application  = self.app_name.encode("utf-8")
+        notification = notification.encode("utf-8")
+        title       = title.encode("utf-8")
+        message  = message.encode("utf-8")
+        flags = (priority & 0x07) * 2
+        if priority < 0: 
+            flags |= 0x08
+        if sticky: 
+            flags = flags | 0x0001
+        data = struct.pack("!BBHHHHH",
+                           GROWL_PROTOCOL_VERSION,
+                           GROWL_TYPE_NOTIFICATION,
+                           flags,
+                           len(notification),
+                           len(title),
+                           len(message),
+                           len(application) )
+        data += notification
+        data += title
+        data += message
+        data += application
+        return self.encodePassword(data)
+        
+    
+    def encodePassword(self, data):
+        """Return md5 encoded data and password (if present)"""
+        checksum = md5.new()
+        checksum.update(data)
+        if self.password:
+           checksum.update(self.password)
+        data += checksum.digest()
+        return data
+        
+    
+    def sendDatagram(self, data):
+        """
+        Send any pending Growl notifications
+        """
+        self.transport.write(data)
+        
+    
+    def startProtocol(self):
+        for dest in self.destinations:
+            self.transport.connect(dest, GROWL_UDP_PORT)
+
+
+    def datagramReceived(self, data):
+        log.msg("Rx from Growl: %s" % data)
+
+
+    def connectionRefused(self):
+        log.msg("Growl connection refused")
+
+
+
+class GrowlClient(object):
+    """Basic protocol wrapper for Growl"""
+    priorities = {
+        "Very Low":-2,
+        "Moderate":-1,
+        "Normal":0,
+        "High":1,
+        "Emergency":2
+    }
+
+
+    def __init__(self, app_name=None, password=None, destinations=None):
+        self.app_name = app_name
+        self.password = password
+        self.destinations = destinations or []
+        self.notifications = []
+        self.defaults = [] # default in gui
+        
+        self.protocol = GrowlProtocol(self.app_name, self.password, self.destinations)
+        self.lport = reactor.listenUDP(0, self.protocol)
+        
+    
+    def addNotification(self, notification="Default", gui_enabled=True):
+        """Adds a notification type and sets whether it is enabled in Growl preferences"""
+        if notification not in self.notifications:
+            self.notifications.append(notification)
+            if gui_enabled:
+                self.defaults.append(len(self.notifications)-1)
+        
+    
+    def register(self):
+        """Register application with all destination Growl daemons"""
+        if self.notifications:
+            self.protocol.register(self.notifications, self.defaults)
+        
+    
+    def notify(self, notification=None, title=None, message=None, priority=0):
+        if message is not None:
+            self.protocol.notify(notification, title, message, priority)
+
+