28
26
displays no output.
35
import bzrlib.progress
38
class TextUIFactory(object):
39
def progress_bar(self):
41
# this in turn is abstract, and creates either a tty or dots
42
# bar depending on what we think of the terminal
43
return bzrlib.progress.ProgressBar()
46
class SilentUIFactory(object):
47
def progress_bar(self):
48
return bzrlib.progress.DummyProgress()
33
from bzrlib.lazy_import import lazy_import
34
lazy_import(globals(), """
46
class UIFactory(object):
49
This tells the library how to display things to the user. Through this
50
layer different applications can choose the style of UI.
56
def get_password(self, prompt='', **kwargs):
57
"""Prompt the user for a password.
59
:param prompt: The prompt to present the user
60
:param kwargs: Arguments which will be expanded into the prompt.
61
This lets front ends display different things if
64
:return: The password string, return None if the user canceled the
65
request. Note that we do not touch the encoding, users may
66
have whatever they see fit and the password should be
69
raise NotImplementedError(self.get_password)
71
def nested_progress_bar(self):
72
"""Return a nested progress bar.
74
When the bar has been finished with, it should be released by calling
78
t = progress.ProgressTask(self._task_stack[-1], self)
80
t = progress.ProgressTask(None, self)
81
self._task_stack.append(t)
84
def _progress_finished(self, task):
85
"""Called by the ProgressTask when it finishes"""
86
if not self._task_stack:
87
warnings.warn("%r finished but nothing is active"
89
elif task != self._task_stack[-1]:
90
warnings.warn("%r is not the active task %r"
91
% (task, self._task_stack[-1]))
93
del self._task_stack[-1]
94
if not self._task_stack:
95
self._progress_all_finished()
97
def _progress_all_finished(self):
98
"""Called when the top-level progress task finished"""
101
def _progress_updated(self, task):
102
"""Called by the ProgressTask when it changes.
104
Should be specialized to draw the progress.
108
def clear_term(self):
109
"""Prepare the terminal for output.
111
This will, for example, clear text progress bars, and leave the
112
cursor at the leftmost position.
116
def get_boolean(self, prompt):
117
"""Get a boolean question answered from the user.
119
:param prompt: a message to prompt the user with. Should be a single
120
line without terminating \n.
121
:return: True or False for y/yes or n/no.
123
raise NotImplementedError(self.get_boolean)
125
def recommend_upgrade(self,
128
# this should perhaps be in the TextUIFactory and the default can do
130
trace.warning("%s is deprecated "
131
"and a better format is available.\n"
132
"It is recommended that you upgrade by "
133
"running the command\n"
138
def report_transport_activity(self, transport, byte_count, direction):
139
"""Called by transports as they do IO.
141
This may update a progress bar, spinner, or similar display.
142
By default it does nothing.
148
class CLIUIFactory(UIFactory):
149
"""Common behaviour for command line UI factories.
151
This is suitable for dumb terminals that can't repaint existing text."""
153
def __init__(self, stdin=None, stdout=None, stderr=None):
154
UIFactory.__init__(self)
155
self.stdin = stdin or sys.stdin
156
self.stdout = stdout or sys.stdout
157
self.stderr = stderr or sys.stderr
159
def get_boolean(self, prompt):
161
# FIXME: make a regexp and handle case variations as well.
163
self.prompt(prompt + "? [y/n]: ")
164
line = self.stdin.readline()
165
if line in ('y\n', 'yes\n'):
167
if line in ('n\n', 'no\n'):
170
def get_non_echoed_password(self, prompt):
171
if not sys.stdin.isatty():
172
raise errors.NotATerminal()
173
encoding = osutils.get_terminal_encoding()
174
return getpass.getpass(prompt.encode(encoding, 'replace'))
176
def get_password(self, prompt='', **kwargs):
177
"""Prompt the user for a password.
179
:param prompt: The prompt to present the user
180
:param kwargs: Arguments which will be expanded into the prompt.
181
This lets front ends display different things if
183
:return: The password string, return None if the user
184
canceled the request.
187
prompt = (prompt % kwargs)
188
# There's currently no way to say 'i decline to enter a password'
189
# as opposed to 'my password is empty' -- does it matter?
190
return self.get_non_echoed_password(prompt)
192
def prompt(self, prompt):
193
"""Emit prompt on the CLI."""
194
self.stdout.write(prompt)
197
"""Write an already-formatted message."""
198
self.stdout.write(msg + '\n')
201
class SilentUIFactory(CLIUIFactory):
202
"""A UI Factory which never prints anything.
204
This is the default UI, if another one is never registered.
208
CLIUIFactory.__init__(self)
210
def get_password(self, prompt='', **kwargs):
213
def prompt(self, prompt):
220
def clear_decorator(func, *args, **kwargs):
221
"""Decorator that clears the term"""
222
ui_factory.clear_term()
223
func(*args, **kwargs)
51
226
ui_factory = SilentUIFactory()
227
"""IMPORTANT: never import this symbol directly. ONLY ever access it as
231
def make_ui_for_terminal(stdin, stdout, stderr):
232
"""Construct and return a suitable UIFactory for a text mode program.
234
If stdout is a smart terminal, this gets a smart UIFactory with
235
progress indicators, etc. If it's a dumb terminal, just plain text output.
238
isatty = getattr(stdin, 'isatty', None)
243
elif os.environ.get('TERM') in (None, 'dumb', ''):
244
# e.g. emacs compile window
246
# User may know better, otherwise default to TextUIFactory
247
if ( os.environ.get('BZR_USE_TEXT_UI', None) is not None
249
from bzrlib.ui.text import TextUIFactory
251
return cls(stdin=stdin, stdout=stdout, stderr=stderr)