CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pony

Pony Object-Relational Mapper for Python with Pythonic query syntax using generator expressions

Pending
Overview
Eval results
Files

exception-handling.mddocs/

Exception Handling

Comprehensive exception hierarchy covering database errors, ORM-specific errors, query errors, and transaction errors. Proper exception handling is crucial for building robust applications with Pony ORM.

Capabilities

ORM-Level Exceptions

Core ORM exceptions that handle entity operations, queries, and object lifecycle errors.

class OrmError(Exception):
    """Base exception class for all ORM-related errors."""

class ObjectNotFound(OrmError):
    """Raised when get() or [] operator finds no matching entity."""

class MultipleObjectsFoundError(OrmError):
    """Raised when get() finds multiple entities when expecting one."""

class TooManyObjectsFoundError(MultipleObjectsFoundError):
    """Raised when query returns more objects than expected limit."""

class OperationWithDeletedObjectError(OrmError):
    """Raised when attempting operations on deleted entity objects."""

class CacheIndexError(OrmError):
    """Raised when entity cache index operations fail."""

class MappingError(OrmError):   
    """Raised when entity mapping or schema definition is invalid."""

class ERDiagramError(OrmError):
    """Raised when entity relationship diagram generation fails."""

class BindingError(OrmError):
    """Raised when database binding or connection configuration fails."""

Database-Level Exceptions

Standard database API exceptions that correspond to DB-API 2.0 specification errors.

class DBException(Exception):
    """Base exception class for all database-related errors."""

class Warning(DBException):
    """Exception for important database warnings."""

class Error(DBException):
    """Base exception class for database errors."""

class InterfaceError(Error):
    """Exception for database interface errors."""

class DatabaseError(Error):
    """Exception for database-specific errors."""

class DataError(DatabaseError):
    """Exception for data processing errors (invalid data, numeric overflow, etc.)."""

class OperationalError(DatabaseError):
    """Exception for database operation errors (connection lost, memory allocation, etc.)."""

class IntegrityError(DatabaseError):
    """Exception for database constraint violations (foreign key, unique, etc.)."""

class InternalError(DatabaseError):
    """Exception for internal database errors."""

class ProgrammingError(DatabaseError):
    """Exception for programming errors (table not found, syntax error, etc.)."""

class NotSupportedError(DatabaseError):
    """Exception for unsupported database operations or methods."""

Schema and Table Exceptions

Exceptions related to database schema operations and table management.

class DBSchemaError(OrmError):
    """Raised when database schema operations fail."""

class TableDoesNotExist(DBSchemaError):
    """Raised when referencing non-existent database table."""

class TableIsNotEmpty(DBSchemaError):
    """Raised when attempting operations that require empty table."""

class ConstraintError(DBSchemaError):
    """Raised when database constraint operations fail."""

Query and Result Exceptions

Exceptions specific to query operations and result processing.

class RowNotFound(DBException):
    """Raised when database query returns no rows when expecting results."""

class MultipleRowsFound(DBException):
    """Raised when database query returns multiple rows when expecting one."""

class TooManyRowsFound(MultipleRowsFound):
    """Raised when query returns more rows than specified limit."""

Transaction Exceptions

Exceptions related to transaction management and concurrency control.

class TransactionError(OrmError):
    """Base exception class for transaction-related errors."""

class ConnectionClosedError(TransactionError):
    """Raised when database connection is unexpectedly closed."""

class TransactionIntegrityError(TransactionError):
    """Raised when transaction integrity is compromised."""

class IsolationError(TransactionError):
    """Raised when transaction isolation level conflicts occur."""

class CommitException(TransactionError):
    """Raised when transaction commit operation fails."""

class RollbackException(TransactionError):
    """Raised when transaction rollback operation fails."""

class UnrepeatableReadError(TransactionError):
    """Raised when repeatable read isolation is violated."""

class OptimisticCheckError(TransactionError):
    """Raised when optimistic concurrency control check fails."""

class UnresolvableCyclicDependency(TransactionError):
    """Raised when circular dependencies prevent transaction completion."""

class UnexpectedError(TransactionError):
    """Raised for unexpected transaction-related errors."""

class DatabaseSessionIsOver(TransactionError):
    """Raised when attempting operations outside active database session."""

Translation and Runtime Exceptions

Exceptions related to query translation and runtime operations.

class TranslationError(OrmError):
    """Raised when generator expression cannot be translated to SQL."""

class ExprEvalError(OrmError):
    """Raised when expression evaluation fails during query processing."""

class PonyRuntimeWarning(UserWarning):
    """Warning class for runtime issues that don't prevent execution."""

class DatabaseContainsIncorrectValue(PonyRuntimeWarning):
    """Warning when database contains values that don't match expected format."""

class DatabaseContainsIncorrectEmptyValue(PonyRuntimeWarning):  
    """Warning when database contains empty values in unexpected contexts."""

Security and Permission Exceptions

Exceptions related to security and access control operations.

class PermissionError(OrmError):
    """Raised when security permission checks fail."""

Usage Examples

Basic Exception Handling

from pony.orm import *

@db_session
def safe_user_lookup(email):
    try:
        user = User.get(email=email)
        return user
    except ObjectNotFound:
        print(f"No user found with email: {email}")
        return None
    except MultipleObjectsFoundError:
        print(f"Multiple users found with email: {email}")
        # This shouldn't happen if email is unique
        raise

@db_session  
def handle_entity_operations():
    try:
        # Try to create user
        user = User(name="Alice", email="alice@example.com")
        commit()
        
    except IntegrityError as e:
        print(f"Database constraint violation: {e}")
        rollback()
        # Handle duplicate email, etc.
        
    except DatabaseError as e:
        print(f"Database error occurred: {e}")
        rollback()
        raise

Transaction Exception Handling

@db_session
def handle_transaction_errors():
    try:
        # Risky operations that might conflict
        user = User.get(name="Alice")
        user.balance += 100
        
        # Force a flush to detect conflicts early
        flush()
        
        # More operations...
        order = Order(user=user, total=50.0)
        commit()
        
    except OptimisticCheckError as e:
        print(f"Concurrent modification detected: {e}")
        rollback()
        # Retry logic or user notification
        
    except ConnectionClosedError as e:
        print(f"Database connection lost: {e}")
        # Reconnection logic
        
    except TransactionError as e:
        print(f"Transaction failed: {e}")
        rollback()
        raise

# Retry pattern for handling optimistic concurrency
def retry_on_conflict(func, max_retries=3):
    for attempt in range(max_retries):
        try:
            return func()
        except OptimisticCheckError:
            if attempt == max_retries - 1:
                raise
            print(f"Retry attempt {attempt + 1}")
            # Brief delay before retry
            import time
            time.sleep(0.1 * (attempt + 1))

Query Exception Handling

@db_session
def safe_query_operations():
    try:
        # Query that might return no results
        admin = User.get(role="admin")
        
    except ObjectNotFound:
        print("No admin user found, creating default admin")
        admin = User(name="Admin", role="admin", email="admin@example.com")
        
    try:
        # Query that might return multiple results unexpectedly
        primary_contact = Contact.get(is_primary=True, company_id=123)
        
    except MultipleObjectsFoundError:
        print("Multiple primary contacts found, using first one")
        primary_contact = Contact.select(
            lambda c: c.is_primary and c.company_id == 123
        ).first()
        
    except ObjectNotFound:
        print("No primary contact found")
        primary_contact = None

# Handle translation errors for complex queries
@db_session
def handle_query_translation():
    try:
        # Complex query that might not translate properly
        result = select(u for u in User 
                       if some_complex_python_function(u.data))
        
    except TranslationError as e:
        print(f"Query cannot be translated to SQL: {e}")
        # Fall back to Python filtering
        all_users = User.select()
        result = [u for u in all_users 
                 if some_complex_python_function(u.data)]

Schema and Database Exception Handling

def handle_database_setup():
    try:
        db.bind('postgresql', host='localhost', user='app', password='secret')
        db.generate_mapping(create_tables=True)
        
    except BindingError as e:
        print(f"Failed to bind to database: {e}")
        # Try fallback database
        db.bind('sqlite', filename='fallback.db')
        db.generate_mapping(create_tables=True)
        
    except TableDoesNotExist as e:
        print(f"Required table missing: {e}")
        # Create missing tables
        db.create_tables()
        
    except DBSchemaError as e:
        print(f"Schema error: {e}")
        # Handle schema migration or recreation
        
    except DatabaseError as e:
        print(f"Database operation failed: {e}")
        raise

@db_session
def handle_table_operations():
    try:
        # Operation that requires empty table
        db.execute("TRUNCATE TABLE user_sessions")
        
    except TableIsNotEmpty as e:
        print(f"Cannot truncate non-empty table: {e}")
        # Delete rows individually
        delete(s for s in UserSession)
        
    except ProgrammingError as e:
        print(f"SQL programming error: {e}")
        # Handle SQL syntax issues

Comprehensive Error Handling Pattern

from functools import wraps

def safe_db_operation(func):
    """Decorator for comprehensive database error handling."""
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
            
        except ObjectNotFound as e:
            print(f"Entity not found in {func.__name__}: {e}")
            return None
            
        except MultipleObjectsFoundError as e:
            print(f"Multiple entities found in {func.__name__}: {e}")
            raise
            
        except IntegrityError as e:
            print(f"Database constraint violation in {func.__name__}: {e}")
            rollback()
            raise
            
        except OptimisticCheckError as e:
            print(f"Concurrent modification in {func.__name__}: {e}")
            rollback()
            raise
            
        except TransactionError as e:
            print(f"Transaction error in {func.__name__}: {e}")
            rollback()
            raise
            
        except DatabaseError as e:
            print(f"Database error in {func.__name__}: {e}")
            rollback()
            raise
            
        except Exception as e:
            print(f"Unexpected error in {func.__name__}: {e}")
            rollback()
            raise
            
    return wrapper

# Usage of the decorator
@safe_db_operation
@db_session
def update_user_profile(user_id, **updates):
    user = User[user_id]  # May raise ObjectNotFound
    for key, value in updates.items():
        setattr(user, key, value)
    commit()
    return user

Warning and Runtime Error Handling

import warnings

# Handle runtime warnings
def handle_warnings():
    # Catch Pony runtime warnings
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always")
        
        with db_session:
            # Operations that might generate warnings
            problematic_data = select(u for u in User if u.data_field)
            
        for warning in w:
            if issubclass(warning.category, PonyRuntimeWarning):
                print(f"Pony warning: {warning.message}")
                # Handle data quality issues

@db_session
def handle_expression_errors():
    try:
        # Complex expression that might fail evaluation
        result = select(u.calculate_score() for u in User)
        
    except ExprEvalError as e:
        print(f"Expression evaluation failed: {e}")
        # Fall back to safer calculation
        result = select(u for u in User)
        scores = [u.calculate_score() for u in result]

Install with Tessl CLI

npx tessl i tessl/pypi-pony

docs

aggregations-helpers.md

attributes-relationships.md

data-types.md

database-entities.md

debugging-utilities.md

exception-handling.md

framework-integrations.md

index.md

query-operations.md

security-permissions.md

session-management.md

tile.json