comparison mercurial/ui.py @ 34882:e9f320a40b44

ui: move request exit handlers to global state Since the ui objects can be created with the 'load' class method, it is possible to lose the exit handlers information from the old ui instance. For example, running 'test-bad-extension.t' leads to this situation where chg creates a new ui instance which does not copy the exit handlers from the earlier ui instance. For exit handlers, which are special cases anyways, it probably makes sense to have a global state of the handlers. This would ensure that the exit handlers registered once are definitely executed at the end of the request. Test Plan: Ran all the tests without '--chg' option. This also fixes the 'test-bad-extension.t' with the '--chg' option. Differential Revision: https://phab.mercurial-scm.org/D1166
author Saurabh Singh <singhsrb@fb.com>
date Tue, 17 Oct 2017 13:20:25 -0700
parents 85a2db47ad50
children ff2110eadbfa
comparison
equal deleted inserted replaced
34881:8c9b08a0c48c 34882:e9f320a40b44
181 181
182 # unique object used to detect no default value has been provided when 182 # unique object used to detect no default value has been provided when
183 # retrieving configuration value. 183 # retrieving configuration value.
184 _unset = object() 184 _unset = object()
185 185
186 # _reqexithandlers: callbacks run at the end of a request
187 _reqexithandlers = []
188
186 class ui(object): 189 class ui(object):
187 def __init__(self, src=None): 190 def __init__(self, src=None):
188 """Create a fresh new ui object if no src given 191 """Create a fresh new ui object if no src given
189 192
190 Use uimod.ui.load() to create a ui which knows global and user configs. 193 Use uimod.ui.load() to create a ui which knows global and user configs.
191 In most cases, you should use ui.copy() to create a copy of an existing 194 In most cases, you should use ui.copy() to create a copy of an existing
192 ui object. 195 ui object.
193 """ 196 """
194 # _buffers: used for temporary capture of output 197 # _buffers: used for temporary capture of output
195 self._buffers = [] 198 self._buffers = []
196 # _exithandlers: callbacks run at the end of a request
197 self._exithandlers = []
198 # 3-tuple describing how each buffer in the stack behaves. 199 # 3-tuple describing how each buffer in the stack behaves.
199 # Values are (capture stderr, capture subprocesses, apply labels). 200 # Values are (capture stderr, capture subprocesses, apply labels).
200 self._bufferstates = [] 201 self._bufferstates = []
201 # When a buffer is active, defines whether we are expanding labels. 202 # When a buffer is active, defines whether we are expanding labels.
202 # This exists to prevent an extra list lookup. 203 # This exists to prevent an extra list lookup.
218 self._colormode = None 219 self._colormode = None
219 self._terminfoparams = {} 220 self._terminfoparams = {}
220 self._styles = {} 221 self._styles = {}
221 222
222 if src: 223 if src:
223 self._exithandlers = src._exithandlers
224 self.fout = src.fout 224 self.fout = src.fout
225 self.ferr = src.ferr 225 self.ferr = src.ferr
226 self.fin = src.fin 226 self.fin = src.fin
227 self.pageractive = src.pageractive 227 self.pageractive = src.pageractive
228 self._disablepager = src._disablepager 228 self._disablepager = src._disablepager
1096 pager.stdin.close() 1096 pager.stdin.close()
1097 pager.wait() 1097 pager.wait()
1098 1098
1099 return True 1099 return True
1100 1100
1101 @property
1102 def _exithandlers(self):
1103 return _reqexithandlers
1104
1101 def atexit(self, func, *args, **kwargs): 1105 def atexit(self, func, *args, **kwargs):
1102 '''register a function to run after dispatching a request 1106 '''register a function to run after dispatching a request
1103 1107
1104 Handlers do not stay registered across request boundaries.''' 1108 Handlers do not stay registered across request boundaries.'''
1105 self._exithandlers.append((func, args, kwargs)) 1109 self._exithandlers.append((func, args, kwargs))