Plain is headed towards 1.0! Subscribe for development updates →

 1class Error(Exception):
 2    pass
 3
 4
 5class InterfaceError(Error):
 6    pass
 7
 8
 9class DatabaseError(Error):
10    pass
11
12
13class DataError(DatabaseError):
14    pass
15
16
17class OperationalError(DatabaseError):
18    pass
19
20
21class IntegrityError(DatabaseError):
22    pass
23
24
25class InternalError(DatabaseError):
26    pass
27
28
29class ProgrammingError(DatabaseError):
30    pass
31
32
33class NotSupportedError(DatabaseError):
34    pass
35
36
37class ConnectionDoesNotExist(Exception):
38    pass
39
40
41class DatabaseErrorWrapper:
42    """
43    Context manager and decorator that reraises backend-specific database
44    exceptions using Plain's common wrappers.
45    """
46
47    def __init__(self, wrapper):
48        """
49        wrapper is a database wrapper.
50
51        It must have a Database attribute defining PEP-249 exceptions.
52        """
53        self.wrapper = wrapper
54
55    def __enter__(self):
56        pass
57
58    def __exit__(self, exc_type, exc_value, traceback):
59        if exc_type is None:
60            return
61        for plain_exc_type in (
62            DataError,
63            OperationalError,
64            IntegrityError,
65            InternalError,
66            ProgrammingError,
67            NotSupportedError,
68            DatabaseError,
69            InterfaceError,
70            Error,
71        ):
72            db_exc_type = getattr(self.wrapper.Database, plain_exc_type.__name__)
73            if issubclass(exc_type, db_exc_type):
74                plain_exc_value = plain_exc_type(*exc_value.args)
75                # Only set the 'errors_occurred' flag for errors that may make
76                # the connection unusable.
77                if plain_exc_type not in (DataError, IntegrityError):
78                    self.wrapper.errors_occurred = True
79                raise plain_exc_value.with_traceback(traceback) from exc_value
80
81    def __call__(self, func):
82        # Note that we are intentionally not using @wraps here for performance
83        # reasons. Refs #21109.
84        def inner(*args, **kwargs):
85            with self:
86                return func(*args, **kwargs)
87
88        return inner