103
class ConfirmationUserInterfacePolicy(object):
104
"""Wrapper for a UIFactory that allows or denies all confirmed actions."""
106
def __init__(self, wrapped_ui, default_answer, specific_answers):
107
"""Generate a proxy UI that does no confirmations.
109
:param wrapped_ui: Underlying UIFactory.
110
:param default_answer: Bool for whether requests for
111
confirmation from the user should be noninteractively accepted or
113
:param specific_answers: Map from confirmation_id to bool answer.
115
self.wrapped_ui = wrapped_ui
116
self.default_answer = default_answer
117
self.specific_answers = specific_answers
119
def __getattr__(self, name):
120
return getattr(self.wrapped_ui, name)
123
return '%s(%r, %r, %r)' % (
124
self.__class__.__name__,
127
self.specific_answers)
129
def confirm_action(self, prompt, confirmation_id, prompt_kwargs):
130
if confirmation_id in self.specific_answers:
131
return self.specific_answers[confirmation_id]
132
elif self.default_answer is not None:
133
return self.default_answer
135
return self.wrapped_ui.confirm_action(
136
prompt, confirmation_id, prompt_kwargs)
103
139
class UIFactory(object):
104
140
"""UI abstraction.
106
142
This tells the library how to display things to the user. Through this
107
143
layer different applications can choose the style of UI.
145
UI Factories are also context managers, for some syntactic sugar some users
148
:ivar suppressed_warnings: Identifiers for user warnings that should
152
_user_warning_templates = dict(
153
cross_format_fetch=("Doing on-the-fly conversion from "
154
"%(from_format)s to %(to_format)s.\n"
155
"This may take some time. Upgrade the repositories to the "
156
"same format for better performance."
110
160
def __init__(self):
111
161
self._task_stack = []
162
self.suppressed_warnings = set()
166
"""Context manager entry support.
168
Override in a concrete factory class if initialisation before use is
171
return self # This is bound to the 'as' clause in a with statement.
173
def __exit__(self, exc_type, exc_val, exc_tb):
174
"""Context manager exit support.
176
Override in a concrete factory class if more cleanup than a simple
177
self.clear_term() is needed when the UIFactory is finished with.
180
return False # propogate exceptions.
182
def be_quiet(self, state):
183
"""Tell the UI to be more quiet, or not.
185
Typically this suppresses progress bars; the application may also look
186
at ui_factory.is_quiet().
190
def confirm_action(self, prompt, confirmation_id, prompt_kwargs):
191
"""Seek user confirmation for an action.
193
If the UI is noninteractive, or the user does not want to be asked
194
about this action, True is returned, indicating bzr should just
197
The confirmation id allows the user to configure certain actions to
198
always be confirmed or always denied, and for UIs to specialize the
199
display of particular confirmations.
201
:param prompt: Suggested text to display to the user.
202
:param prompt_kwargs: A dictionary of arguments that can be
203
string-interpolated into the prompt.
204
:param confirmation_id: Unique string identifier for the confirmation.
206
return self.get_boolean(prompt % prompt_kwargs)
113
208
def get_password(self, prompt='', **kwargs):
114
209
"""Prompt the user for a password.
304
def format_user_warning(self, warning_id, message_args):
306
template = self._user_warning_templates[warning_id]
308
fail = "failed to format warning %r, %r" % (warning_id, message_args)
309
warnings.warn(fail) # so tests will fail etc
312
return template % message_args
313
except ValueError, e:
314
fail = "failed to format warning %r, %r: %s" % (
315
warning_id, message_args, e)
316
warnings.warn(fail) # so tests will fail etc
201
319
def get_boolean(self, prompt):
202
320
"""Get a boolean question answered from the user.
370
def log_transport_activity(self, display=False):
371
"""Write out whatever transport activity has been measured.
373
Implementations are allowed to do nothing, but it is useful if they can
374
write a line to the log file.
376
:param display: If False, only log to disk, if True also try to display
377
a message to the user.
380
# Default implementation just does nothing
383
def show_user_warning(self, warning_id, **message_args):
384
"""Show a warning to the user.
386
This is specifically for things that are under the user's control (eg
387
outdated formats), not for internal program warnings like deprecated
390
This can be overridden by UIFactory subclasses to show it in some
391
appropriate way; the default UIFactory is noninteractive and does
392
nothing. format_user_warning maps it to a string, though other
393
presentations can be used for particular UIs.
395
:param warning_id: An identifier like 'cross_format_fetch' used to
396
check if the message is suppressed and to look up the string.
397
:param message_args: Arguments to be interpolated into the message.
249
401
def show_error(self, msg):
250
402
"""Show an error message (not an exception) to the user.
252
404
The message should not have an error prefix or trailing newline. That
253
will be added by the factory if appropriate.
405
will be added by the factory if appropriate.
255
407
raise NotImplementedError(self.show_error)
262
414
"""Show a warning to the user."""
263
415
raise NotImplementedError(self.show_warning)
267
class SilentUIFactory(UIFactory):
417
def warn_cross_format_fetch(self, from_format, to_format):
418
"""Warn about a potentially slow cross-format transfer.
420
This is deprecated in favor of show_user_warning, but retained for api
421
compatibility in 2.0 and 2.1.
423
self.show_user_warning('cross_format_fetch', from_format=from_format,
426
def warn_experimental_format_fetch(self, inter):
427
"""Warn about fetching into experimental repository formats."""
428
if inter.target._format.experimental:
429
trace.warning("Fetching into experimental format %s.\n"
430
"This format may be unreliable or change in the future "
431
"without an upgrade path.\n" % (inter.target._format,))
434
class NoninteractiveUIFactory(UIFactory):
435
"""Base class for UIs with no user."""
437
def confirm_action(self, prompt, confirmation_id, prompt_kwargs):
441
return '%s()' % (self.__class__.__name__, )
444
class SilentUIFactory(NoninteractiveUIFactory):
268
445
"""A UI Factory which never prints anything.
270
447
This is the default UI, if another one is never registered by a program