~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/cleanup.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

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
102
124
    """
103
125
 
104
126
    def __init__(self, func):
 
127
        super(OperationWithCleanups, self).__init__()
105
128
        self.func = func
106
 
        self.cleanups = deque()
107
 
 
108
 
    def add_cleanup(self, cleanup_func, *args, **kwargs):
109
 
        """Add a cleanup to run.
110
 
 
111
 
        Cleanups may be added at any time before or during the execution of
112
 
        self.func.  Cleanups will be executed in LIFO order.
113
 
        """
114
 
        self.cleanups.appendleft((cleanup_func, args, kwargs))
115
129
 
116
130
    def run(self, *args, **kwargs):
117
131
        return _do_with_cleanups(
121
135
        return _do_with_cleanups(
122
136
            self.cleanups, self.func, *args, **kwargs)
123
137
 
124
 
    def cleanup_now(self):
125
 
        _run_cleanups(self.cleanups)
126
 
        self.cleanups.clear()
127
 
 
128
138
 
129
139
def _do_with_cleanups(cleanup_funcs, func, *args, **kwargs):
130
140
    """Run `func`, then call all the cleanup_funcs.
179
189
                # but don't propagate them.
180
190
                _run_cleanup(cleanup, *c_args, **kwargs)
181
191
        if exc_info is not None:
182
 
            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
183
196
        # No error, so we can return the result
184
197
        return result
185
198