~barry/mailman/events-and-web

« back to all changes in this revision

Viewing changes to src/mailman/database/transaction.py

  • Committer: Barry Warsaw
  • Date: 2012-04-22 21:33:33 UTC
  • mfrom: (7150.1.11 transactions)
  • Revision ID: barry@list.org-20120422213333-3skjqsjktooesgsl
Several non-functional improvements to the code base.

Reduce the explicit use of the config.db global by introducing two new
helpers:
 - A new transaction() context manager which will commit the transaction on
   successful exit, otherwise it will abort the transaction
 - A new dbconnection decorator which calls the decorated method with the
   Storm store object as the first argument (after self).  This can be used
   instead of config.db.store.

By reducing the explicit use of this global, we have a better chance of
refactoring it away in the future.  Still TODO: runner.py and lmtp.py.

Be explicit about the `store` attribute on the IDatabase interface.

More consistent use of __future__ imports.

Remove an obsolete command line script.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
__metaclass__ = type
23
23
__all__ = [
 
24
    'dbconnection',
 
25
    'transaction',
24
26
    'transactional',
25
27
    ]
26
28
 
27
29
 
 
30
from contextlib import contextmanager
 
31
 
28
32
from mailman.config import config
29
33
 
30
34
 
31
35
 
32
 
class transactional:
 
36
@contextmanager
 
37
def transaction():
 
38
    """Context manager for ensuring the transaction is complete."""
 
39
    try:
 
40
        yield
 
41
    except:
 
42
        config.db.abort()
 
43
        raise
 
44
    else:
 
45
        config.db.commit()
 
46
 
 
47
 
 
48
 
 
49
def transactional(function):
33
50
    """Decorator for transactional support.
34
51
 
35
52
    When the function this decorator wraps exits cleanly, the current
38
55
 
39
56
    Either way, the current transaction is completed.
40
57
    """
41
 
    def __init__(self, function):
42
 
        self._function = function
43
 
 
44
 
    def __get__(self, obj, type=None):
45
 
        def wrapper(*args, **kws):
46
 
            try:
47
 
                rtn = self._function(obj, *args, **kws)
48
 
                config.db.commit()
49
 
                return rtn
50
 
            except:
51
 
                config.db.abort()
52
 
                raise
53
 
        return wrapper
 
58
    def wrapper(*args, **kws):
 
59
        try:
 
60
            rtn = function(*args, **kws)
 
61
            config.db.commit()
 
62
            return rtn
 
63
        except:
 
64
            config.db.abort()
 
65
            raise
 
66
    return wrapper
 
67
 
 
68
 
 
69
 
 
70
def dbconnection(function):
 
71
    """Decorator for getting at the database connection.
 
72
 
 
73
    Use this to avoid having to access the global `config.db.store`
 
74
    attribute.  This calls the function with `store` as the first argument.
 
75
    """
 
76
    def wrapper(*args, **kws):
 
77
        # args[0] is self.
 
78
        return function(args[0], config.db.store, *args[1:], **kws)
 
79
    return wrapper