CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-gntp

Growl Notification Transport Protocol for Python

80

1.25x
Overview
Eval results
Files

errors.mddocs/

Error Handling

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.

Exception Hierarchy

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'
    """

Usage Examples

Basic Error Handling

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}")

Specific Error Scenarios

Network Connectivity Issues

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 backoff

Authentication Problems

import 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...")
            continue

Message Parsing Issues

import 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")
            
        raise

Unsupported Features

import 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 notice

Comprehensive Error Handling Strategy

import 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)

Error Logging and Monitoring

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"
    })

Error Recovery Patterns

Graceful Degradation

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"

Circuit Breaker Pattern

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

Error Codes Reference

ExceptionError CodeDescriptionCommon Causes
AuthError400Bad RequestWrong password, missing authentication
ParseError500Internal Server ErrorInvalid message format, missing headers
UnsupportedError500Internal Server ErrorUnsupported hash algorithm, unimplemented feature
NetworkError500Internal Server ErrorConnection 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-gntp

docs

cli.md

config-api.md

errors.md

high-level-api.md

index.md

protocol.md

tile.json