~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/cleanup.py

  • Committer: Andrew Bennetts
  • Date: 2009-09-24 00:30:58 UTC
  • mto: (4744.3.1 robust-cleanup-in-commit)
  • mto: This revision was merged to the branch mainline in revision 4775.
  • Revision ID: andrew.bennetts@canonical.com-20090924003058-2mjsi9onarg2u0in
Docstring and comment elaboration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
 
42
42
Note the tradeoff that run_cleanup/run_cleanups makes: errors from
43
43
`do_something` will not be obscured by errors from `cleanup_something`, but
44
 
errors from `cleanup_something` will never reach the user, even if there is not
45
 
error from `do_something`.
 
44
errors from `cleanup_something` will never reach the user, even if there is no
 
45
error from `do_something`.  So run_cleanup is good to use when a failure of
 
46
internal housekeeping (e.g. failure to finish a progress bar) is unimportant to
 
47
a user.
46
48
 
47
49
If you want to be certain that the first, and only the first, error is raised,
48
50
then use::
111
113
 
112
114
 
113
115
def do_with_cleanups(func, cleanup_funcs):
 
116
    """Run `func`, then call all the cleanup_funcs.
 
117
 
 
118
    All the cleanup_funcs are guaranteed to be run.  The first exception raised
 
119
    by func or any of the cleanup_funcs is the one that will be propagted by
 
120
    this function (subsequent errors are caught and logged).
 
121
 
 
122
    Conceptually similar to::
 
123
 
 
124
        try:
 
125
            return func()
 
126
        finally:
 
127
            for cleanup in cleanup_funcs:
 
128
                cleanup()
 
129
 
 
130
    It avoids several problems with using try/finally directly:
 
131
     * an exception from func will not be obscured by a subsequent exception
 
132
       from a cleanup.
 
133
     * an exception from a cleanup will not prevent other cleanups from
 
134
       running (but the first exception encountered is still the one
 
135
       propagated).
 
136
 
 
137
    Unike `run_cleanup`, `do_with_cleanups` can propagate an exception from a
 
138
    cleanup, but only if there is no exception from func.
 
139
    """
114
140
    # As correct as Python 2.4 allows.
115
141
    try:
116
142
        result = func()
125
151
        exc_info = None
126
152
        for cleanup in cleanup_funcs:
127
153
            # XXX: Hmm, if KeyboardInterrupt arrives at exactly this line, we
128
 
            # won't run all cleanups...
 
154
            # won't run all cleanups... perhaps we should temporarily install a
 
155
            # SIGINT handler?
129
156
            if exc_info is None:
130
157
                try:
131
158
                    cleanup()
132
159
                except:
133
 
                    # XXX: should this never swallow KeyboardInterrupt, etc?
134
160
                    # This is the first cleanup to fail, so remember its
135
161
                    # details.
136
162
                    exc_info = sys.exc_info()