~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/cleanup.py

(jelmer) Use the absolute_import feature everywhere in bzrlib,
 and add a source test to make sure it's used everywhere. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009 Canonical Ltd
 
1
# Copyright (C) 2009, 2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
31
31
If you want to be certain that the first, and only the first, error is raised,
32
32
then use::
33
33
 
34
 
    operation = OperationWithCleanups(lambda operation: do_something())
 
34
    operation = OperationWithCleanups(do_something)
35
35
    operation.add_cleanup(cleanup_something)
36
 
    operation.run()
 
36
    operation.run_simple()
37
37
 
38
38
This is more inconvenient (because you need to make every try block a
39
39
function), but will ensure that the first error encountered is the one raised,
41
41
details.
42
42
"""
43
43
 
 
44
from __future__ import absolute_import
44
45
 
45
46
from collections import deque
46
47
import sys
78
79
        _run_cleanup(func, *args, **kwargs)
79
80
 
80
81
 
81
 
class OperationWithCleanups(object):
 
82
class ObjectWithCleanups(object):
 
83
    """A mixin for objects that hold a cleanup list.
 
84
 
 
85
    Subclass or client code can call add_cleanup and then later `cleanup_now`.
 
86
    """
 
87
    def __init__(self):
 
88
        self.cleanups = deque()
 
89
 
 
90
    def add_cleanup(self, cleanup_func, *args, **kwargs):
 
91
        """Add a cleanup to run.
 
92
 
 
93
        Cleanups may be added at any time.  
 
94
        Cleanups will be executed in LIFO order.
 
95
        """
 
96
        self.cleanups.appendleft((cleanup_func, args, kwargs))
 
97
 
 
98
    def cleanup_now(self):
 
99
        _run_cleanups(self.cleanups)
 
100
        self.cleanups.clear()
 
101
 
 
102
 
 
103
class OperationWithCleanups(ObjectWithCleanups):
82
104
    """A way to run some code with a dynamic cleanup list.
83
105
 
84
106
    This provides a way to add cleanups while the function-with-cleanups is
91
113
 
92
114
    where `some_func` is::
93
115
 
94
 
        def some_func(operation, args, ...)
 
116
        def some_func(operation, args, ...):
95
117
            do_something()
96
118
            operation.add_cleanup(something)
97
119
            # etc
98
120
 
99
121
    Note that the first argument passed to `some_func` will be the
100
 
    OperationWithCleanups object.
 
122
    OperationWithCleanups object.  To invoke `some_func` without that, use
 
123
    `run_simple` instead of `run`.
101
124
    """
102
125
 
103
126
    def __init__(self, func):
 
127
        super(OperationWithCleanups, self).__init__()
104
128
        self.func = func
105
 
        self.cleanups = deque()
106
 
 
107
 
    def add_cleanup(self, cleanup_func, *args, **kwargs):
108
 
        """Add a cleanup to run.
109
 
 
110
 
        Cleanups may be added at any time before or during the execution of
111
 
        self.func.  Cleanups will be executed in LIFO order.
112
 
        """
113
 
        self.cleanups.appendleft((cleanup_func, args, kwargs))
114
129
 
115
130
    def run(self, *args, **kwargs):
116
131
        return _do_with_cleanups(
117
132
            self.cleanups, self.func, self, *args, **kwargs)
118
133
 
 
134
    def run_simple(self, *args, **kwargs):
 
135
        return _do_with_cleanups(
 
136
            self.cleanups, self.func, *args, **kwargs)
 
137
 
119
138
 
120
139
def _do_with_cleanups(cleanup_funcs, func, *args, **kwargs):
121
140
    """Run `func`, then call all the cleanup_funcs.
170
189
                # but don't propagate them.
171
190
                _run_cleanup(cleanup, *c_args, **kwargs)
172
191
        if exc_info is not None:
173
 
            raise exc_info[0], exc_info[1], exc_info[2]
 
192
            try:
 
193
                raise exc_info[0], exc_info[1], exc_info[2]
 
194
            finally:
 
195
                del exc_info
174
196
        # No error, so we can return the result
175
197
        return result
176
198