Growl Notification Transport Protocol for Python
80
The gntp.errors module provides a comprehensive exception hierarchy for handling all GNTP-related error conditions. These exceptions are raised by all GNTP operations and provide detailed error information with appropriate error codes.
All GNTP exceptions inherit from a common base class and include error codes that correspond to GNTP protocol error codes.
class BaseError(Exception):
"""
Base exception class for all GNTP errors.
All GNTP exceptions inherit from this class.
"""
class ParseError(BaseError):
"""
Error parsing GNTP message.
Raised when GNTP message format is invalid, required headers are missing,
or message structure cannot be understood.
Attributes:
- errorcode (int): 500 (Internal Server Error)
- errordesc (str): 'Error parsing the message'
"""
class AuthError(BaseError):
"""
Error with GNTP authentication.
Raised when password is incorrect, missing when required, or hash
validation fails.
Attributes:
- errorcode (int): 400 (Bad Request)
- errordesc (str): 'Error with authorization'
"""
class UnsupportedError(BaseError):
"""
Currently unsupported operation or feature.
Raised when attempting to use unsupported hash algorithms, protocol
features, or operations not implemented in gntp.py.
Attributes:
- errorcode (int): 500 (Internal Server Error)
- errordesc (str): 'Currently unsupported by gntp.py'
"""
class NetworkError(BaseError):
"""
Error connecting to Growl server.
Raised when socket connection fails, server is unreachable, connection
times out, or other network-related issues occur.
Attributes:
- errorcode (int): 500 (Internal Server Error)
- errordesc (str): 'Error connecting to growl server'
"""import gntp.notifier
import gntp.errors
try:
growl = gntp.notifier.GrowlNotifier(hostname="unreachable-server.com")
growl.register()
growl.notify("Test", "Title", "Message")
except gntp.errors.NetworkError as e:
print(f"Cannot connect to Growl server: {e}")
print(f"Error code: {e.errorcode}")
except gntp.errors.AuthError as e:
print(f"Authentication failed: {e}")
print(f"Error code: {e.errorcode}")
except gntp.errors.ParseError as e:
print(f"Invalid response from server: {e}")
print(f"Error code: {e.errorcode}")
except gntp.errors.BaseError as e:
print(f"GNTP error: {e}")
print(f"Error code: {e.errorcode}")import gntp.notifier
import gntp.errors
def send_notification_with_retry(message, max_retries=3):
for attempt in range(max_retries):
try:
growl = gntp.notifier.GrowlNotifier(
hostname="growl.company.com",
socketTimeout=5 # 5 second timeout
)
growl.register()
return growl.notify("Alert", "Status", message)
except gntp.errors.NetworkError as e:
print(f"Attempt {attempt + 1} failed: {e}")
if attempt == max_retries - 1:
print("All retry attempts failed")
raise
time.sleep(2 ** attempt) # Exponential backoffimport gntp.notifier
import gntp.errors
def authenticate_with_fallback(app_name, message):
passwords = ["primary-password", "backup-password", None]
for password in passwords:
try:
growl = gntp.notifier.GrowlNotifier(
applicationName=app_name,
password=password
)
growl.register()
return growl.notify("Message", "Title", message)
except gntp.errors.AuthError:
if password is None:
print("All authentication methods failed")
raise
print(f"Password '{password}' failed, trying next...")
continueimport gntp.core
import gntp.errors
def parse_server_response(raw_data):
try:
response = gntp.core.parse_gntp(raw_data)
return response
except gntp.errors.ParseError as e:
print(f"Cannot parse server response: {e}")
print(f"Raw data: {raw_data[:100]}...") # First 100 chars
# Try to extract any readable information
if b'GNTP/' in raw_data:
print("Response appears to be GNTP format but invalid")
else:
print("Response does not appear to be GNTP format")
raiseimport gntp.core
import gntp.errors
def create_secure_message(title, description):
try:
notice = gntp.core.GNTPNotice(title=title)
notice.add_header('Notification-Text', description)
# Try to use most secure hash algorithm
notice.set_password("secure-password", "SHA512")
return notice
except gntp.errors.UnsupportedError as e:
print(f"SHA512 not supported: {e}")
# Fall back to supported algorithm
notice.set_password("secure-password", "SHA256")
return noticeimport gntp.notifier
import gntp.errors
import logging
class NotificationService:
def __init__(self, hostname="localhost", password=None):
self.hostname = hostname
self.password = password
self.logger = logging.getLogger(__name__)
def send_notification(self, title, message, priority=0):
"""Send notification with comprehensive error handling."""
try:
growl = gntp.notifier.GrowlNotifier(
applicationName="Notification Service",
notifications=["Alert", "Info", "Warning"],
hostname=self.hostname,
password=self.password
)
# Try to register
result = growl.register()
if result is not True:
self.logger.error(f"Registration failed: {result}")
return False
# Send notification
result = growl.notify("Alert", title, message, priority=priority)
if result is not True:
self.logger.error(f"Notification failed: {result}")
return False
self.logger.info("Notification sent successfully")
return True
except gntp.errors.NetworkError as e:
self.logger.error(f"Network error connecting to {self.hostname}: {e}")
return False
except gntp.errors.AuthError as e:
self.logger.error(f"Authentication failed: {e}")
return False
except gntp.errors.ParseError as e:
self.logger.error(f"Server response parsing failed: {e}")
return False
except gntp.errors.UnsupportedError as e:
self.logger.error(f"Unsupported operation: {e}")
return False
except gntp.errors.BaseError as e:
self.logger.error(f"Unexpected GNTP error: {e}")
return False
except Exception as e:
self.logger.error(f"Unexpected system error: {e}")
return False
# Usage
service = NotificationService("growl.company.com", "password123")
success = service.send_notification("Build Failed", "Unit tests failed", priority=2)import gntp.notifier
import gntp.errors
import logging
import json
from datetime import datetime
def log_gntp_error(error, context=None):
"""Log GNTP errors with structured information."""
error_info = {
"timestamp": datetime.utcnow().isoformat(),
"error_type": type(error).__name__,
"error_code": getattr(error, 'errorcode', None),
"error_description": getattr(error, 'errordesc', None),
"error_message": str(error),
"context": context or {}
}
logging.error("GNTP Error: %s", json.dumps(error_info))
# Usage example
try:
gntp.notifier.mini("Test message", hostname="bad-server")
except gntp.errors.NetworkError as e:
log_gntp_error(e, {
"operation": "send_notification",
"hostname": "bad-server",
"message": "Test message"
})import gntp.notifier
import gntp.errors
import sys
def notify_with_fallback(message, title="Notification"):
"""Try Growl notification, fall back to console if it fails."""
try:
gntp.notifier.mini(message, title=title)
return "growl"
except gntp.errors.BaseError as e:
# Growl failed, fall back to console output
print(f"NOTIFICATION: {title} - {message}")
return "console"import gntp.notifier
import gntp.errors
import time
class GrowlCircuitBreaker:
def __init__(self, failure_threshold=5, timeout=60):
self.failure_threshold = failure_threshold
self.timeout = timeout
self.failure_count = 0
self.last_failure_time = None
self.state = "CLOSED" # CLOSED, OPEN, HALF_OPEN
def send_notification(self, message, **kwargs):
if self.state == "OPEN":
if time.time() - self.last_failure_time > self.timeout:
self.state = "HALF_OPEN"
else:
raise gntp.errors.NetworkError("Circuit breaker is OPEN")
try:
result = gntp.notifier.mini(message, **kwargs)
# Success - reset circuit breaker
self.failure_count = 0
self.state = "CLOSED"
return result
except gntp.errors.BaseError as e:
self.failure_count += 1
self.last_failure_time = time.time()
if self.failure_count >= self.failure_threshold:
self.state = "OPEN"
raise| Exception | Error Code | Description | Common Causes |
|---|---|---|---|
AuthError | 400 | Bad Request | Wrong password, missing authentication |
ParseError | 500 | Internal Server Error | Invalid message format, missing headers |
UnsupportedError | 500 | Internal Server Error | Unsupported hash algorithm, unimplemented feature |
NetworkError | 500 | Internal Server Error | Connection refused, timeout, network unreachable |
These error codes correspond to GNTP protocol error codes and can be used for protocol-level error handling and server implementation.
Install with Tessl CLI
npx tessl i tessl/pypi-gntpevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10