103
def test_progress_construction(self):
104
"""TextUIFactory constructs the right progress view.
106
for (file_class, term, pb, expected_pb_class) in (
107
# on an xterm, either use them or not as the user requests,
108
# otherwise default on
109
(_TTYStringIO, 'xterm', 'none', NullProgressView),
110
(_TTYStringIO, 'xterm', 'text', TextProgressView),
111
(_TTYStringIO, 'xterm', None, TextProgressView),
112
# on a dumb terminal, again if there's explicit configuration do
113
# it, otherwise default off
114
(_TTYStringIO, 'dumb', 'none', NullProgressView),
115
(_TTYStringIO, 'dumb', 'text', TextProgressView),
116
(_TTYStringIO, 'dumb', None, NullProgressView),
117
# on a non-tty terminal, it's null regardless of $TERM
118
(StringIO, 'xterm', None, NullProgressView),
119
(StringIO, 'dumb', None, NullProgressView),
120
# however, it can still be forced on
121
(StringIO, 'dumb', 'text', TextProgressView),
123
os.environ['TERM'] = term
125
if 'BZR_PROGRESS_BAR' in os.environ:
126
del os.environ['BZR_PROGRESS_BAR']
128
os.environ['BZR_PROGRESS_BAR'] = pb
129
stdin = file_class('')
130
stderr = file_class()
131
stdout = file_class()
132
uif = make_ui_for_terminal(stdin, stdout, stderr)
133
self.assertIsInstance(uif, TextUIFactory,
134
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
135
self.assertIsInstance(uif.make_progress_view(),
137
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
139
def test_text_ui_non_terminal(self):
140
"""Even on non-ttys, make_ui_for_terminal gives a text ui."""
141
stdin = _NonTTYStringIO('')
142
stderr = _NonTTYStringIO()
143
stdout = _NonTTYStringIO()
144
for term_type in ['dumb', None, 'xterm']:
145
if term_type is None:
146
del os.environ['TERM']
148
os.environ['TERM'] = term_type
149
uif = make_ui_for_terminal(stdin, stdout, stderr)
150
self.assertIsInstance(uif, TextUIFactory,
151
'TERM=%r' % (term_type,))
153
def test_progress_note(self):
156
ui_factory = TextUIFactory(stdin=StringIO(''),
159
pb = ui_factory.nested_progress_bar()
161
result = self.applyDeprecated(deprecated_in((2, 1, 0)),
164
self.assertEqual(None, result)
165
self.assertEqual("t\n", stdout.getvalue())
166
# Since there was no update() call, there should be no clear() call
167
self.failIf(re.search(r'^\r {10,}\r$',
168
stderr.getvalue()) is not None,
169
'We cleared the stderr without anything to put there')
173
def test_progress_note_clears(self):
174
stderr = _TTYStringIO()
175
stdout = _TTYStringIO()
176
# so that we get a TextProgressBar
177
os.environ['TERM'] = 'xterm'
178
ui_factory = TextUIFactory(
180
stdout=stdout, stderr=stderr)
181
self.assertIsInstance(ui_factory._progress_view,
183
pb = ui_factory.nested_progress_bar()
185
# Create a progress update that isn't throttled
187
result = self.applyDeprecated(deprecated_in((2, 1, 0)),
189
self.assertEqual(None, result)
190
self.assertEqual("t\n", stdout.getvalue())
191
# the exact contents will depend on the terminal width and we don't
192
# care about that right now - but you're probably running it on at
193
# least a 10-character wide terminal :)
194
self.assertContainsRe(stderr.getvalue(), r'\r {10,}\r$')
198
def test_progress_nested(self):
199
# test factory based nested and popping.
200
ui = TextUIFactory(None, None, None)
201
pb1 = ui.nested_progress_bar()
202
pb2 = ui.nested_progress_bar()
203
# You do get a warning if the outermost progress bar wasn't finished
204
# first - it's not clear if this is really useful or if it should just
205
# become orphaned -- mbp 20090120
206
warnings, _ = self.callCatchWarnings(pb1.finished)
207
if len(warnings) != 1:
208
self.fail("unexpected warnings: %r" % (warnings,))
103
212
def test_text_ui_get_boolean(self):
104
stdin = tests.StringIOWrapper("y\n" # True
106
"yes with garbage\nY\n" # True
107
"not an answer\nno\n" # False
108
"I'm sure!\nyes\n" # True
111
stdout = tests.StringIOWrapper()
112
stderr = tests.StringIOWrapper()
113
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
213
stdin = StringIO("y\n" # True
215
"yes with garbage\nY\n" # True
216
"not an answer\nno\n" # False
217
"I'm sure!\nyes\n" # True
222
factory = TextUIFactory(stdin, stdout, stderr)
114
223
self.assertEqual(True, factory.get_boolean(""))
115
224
self.assertEqual(False, factory.get_boolean(""))
116
225
self.assertEqual(True, factory.get_boolean(""))
121
230
# stdin should be empty
122
231
self.assertEqual('', factory.stdin.readline())
124
def test_text_ui_get_integer(self):
125
stdin = tests.StringIOWrapper(
128
"hmmm\nwhat else ?\nCome on\nok 42\n4.24\n42\n")
129
stdout = tests.StringIOWrapper()
130
stderr = tests.StringIOWrapper()
131
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
132
self.assertEqual(1, factory.get_integer(""))
133
self.assertEqual(-2, factory.get_integer(""))
134
self.assertEqual(42, factory.get_integer(""))
136
233
def test_text_factory_prompt(self):
137
234
# see <https://launchpad.net/bugs/365891>
138
StringIO = tests.StringIOWrapper
139
factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
235
factory = TextUIFactory(StringIO(), StringIO(), StringIO())
140
236
factory.prompt('foo %2e')
141
237
self.assertEqual('', factory.stdout.getvalue())
142
238
self.assertEqual('foo %2e', factory.stderr.getvalue())
144
240
def test_text_factory_prompts_and_clears(self):
145
241
# a get_boolean call should clear the pb before prompting
146
out = test_progress._TTYStringIO()
147
243
os.environ['TERM'] = 'xterm'
148
factory = _mod_ui_text.TextUIFactory(
149
stdin=tests.StringIOWrapper("yada\ny\n"),
150
stdout=out, stderr=out)
151
factory._avail_width = lambda: 79
244
factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
152
245
pb = factory.nested_progress_bar()
153
246
pb.show_bar = False
154
247
pb.show_spinner = False
214
def test_quietness(self):
215
os.environ['BZR_PROGRESS_BAR'] = 'text'
216
ui_factory = _mod_ui_text.TextUIFactory(None,
217
test_progress._TTYStringIO(),
218
test_progress._TTYStringIO())
219
self.assertIsInstance(ui_factory._progress_view,
220
_mod_ui_text.TextProgressView)
221
ui_factory.be_quiet(True)
222
self.assertIsInstance(ui_factory._progress_view,
223
_mod_ui_text.NullProgressView)
225
def test_text_ui_show_user_warning(self):
226
from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
227
from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5
230
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
231
remote_fmt = remote.RemoteRepositoryFormat()
232
remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
233
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
234
to_format=remote_fmt)
235
self.assertEquals('', out.getvalue())
236
self.assertEquals("Doing on-the-fly conversion from RepositoryFormat2a() to "
237
"RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
238
"(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
239
"the same format for better performance.\n",
241
# and now with it suppressed please
244
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
245
ui.suppressed_warnings.add('cross_format_fetch')
246
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
247
to_format=remote_fmt)
248
self.assertEquals('', out.getvalue())
249
self.assertEquals('', err.getvalue())
252
class TestTextUIOutputStream(tests.TestCase):
253
"""Tests for output stream that synchronizes with progress bar."""
255
def test_output_clears_terminal(self):
256
stdout = tests.StringIOWrapper()
257
stderr = tests.StringIOWrapper()
260
uif = _mod_ui_text.TextUIFactory(None, stdout, stderr)
261
uif.clear_term = lambda: clear_calls.append('clear')
263
stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout)
264
stream.write("Hello world!\n")
265
stream.write("there's more...\n")
266
stream.writelines(["1\n", "2\n", "3\n"])
268
self.assertEqual(stdout.getvalue(),
272
self.assertEqual(['clear', 'clear', 'clear'],
278
class UITests(tests.TestCase):
280
def test_progress_construction(self):
281
"""TextUIFactory constructs the right progress view.
283
TTYStringIO = test_progress._TTYStringIO
284
FileStringIO = tests.StringIOWrapper
285
for (file_class, term, pb, expected_pb_class) in (
286
# on an xterm, either use them or not as the user requests,
287
# otherwise default on
288
(TTYStringIO, 'xterm', 'none', _mod_ui_text.NullProgressView),
289
(TTYStringIO, 'xterm', 'text', _mod_ui_text.TextProgressView),
290
(TTYStringIO, 'xterm', None, _mod_ui_text.TextProgressView),
291
# on a dumb terminal, again if there's explicit configuration do
292
# it, otherwise default off
293
(TTYStringIO, 'dumb', 'none', _mod_ui_text.NullProgressView),
294
(TTYStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
295
(TTYStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
296
# on a non-tty terminal, it's null regardless of $TERM
297
(FileStringIO, 'xterm', None, _mod_ui_text.NullProgressView),
298
(FileStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
299
# however, it can still be forced on
300
(FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
302
os.environ['TERM'] = term
304
if 'BZR_PROGRESS_BAR' in os.environ:
305
del os.environ['BZR_PROGRESS_BAR']
307
os.environ['BZR_PROGRESS_BAR'] = pb
308
stdin = file_class('')
309
stderr = file_class()
310
stdout = file_class()
311
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
312
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
313
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
314
self.assertIsInstance(uif.make_progress_view(),
316
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
318
def test_text_ui_non_terminal(self):
319
"""Even on non-ttys, make_ui_for_terminal gives a text ui."""
320
stdin = test_progress._NonTTYStringIO('')
321
stderr = test_progress._NonTTYStringIO()
322
stdout = test_progress._NonTTYStringIO()
323
for term_type in ['dumb', None, 'xterm']:
324
if term_type is None:
325
del os.environ['TERM']
327
os.environ['TERM'] = term_type
328
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
329
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
330
'TERM=%r' % (term_type,))
333
class SilentUITests(tests.TestCase):
307
class CLIUITests(TestCase):
309
def test_cli_factory_deprecated(self):
310
uif = self.applyDeprecated(deprecated_in((1, 18, 0)),
312
StringIO(), StringIO(), StringIO())
313
self.assertIsInstance(uif, UIFactory)
316
class SilentUITests(TestCase):
335
318
def test_silent_factory_get_password(self):
336
319
# A silent factory that can't do user interaction can't get a
337
320
# password. Possibly it should raise a more specific error but it
339
ui = _mod_ui.SilentUIFactory()
340
stdout = tests.StringIOWrapper()
322
ui = SilentUIFactory()
341
324
self.assertRaises(
342
325
NotImplementedError,
343
326
self.apply_redirected,
346
329
self.assertEqual('', stdout.getvalue())
348
331
def test_silent_ui_getbool(self):
349
factory = _mod_ui.SilentUIFactory()
350
stdout = tests.StringIOWrapper()
332
factory = SilentUIFactory()
351
334
self.assertRaises(
352
335
NotImplementedError,
353
336
self.apply_redirected,
354
337
None, stdout, stdout, factory.get_boolean, "foo")
357
class TestUIFactoryTests(tests.TestCase):
340
class TestUIFactoryTests(TestCase):
359
342
def test_test_ui_factory_progress(self):
360
343
# there's no output; we just want to make sure this doesn't crash -
361
# see https://bugs.launchpad.net/bzr/+bug/408201
362
ui = tests.TestUIFactory()
344
# see https://bugs.edge.launchpad.net/bzr/+bug/408201
363
346
pb = ui.nested_progress_bar()
364
347
pb.update('hello')
369
class CannedInputUIFactoryTests(tests.TestCase):
352
class CannedInputUIFactoryTests(TestCase):
371
354
def test_canned_input_get_input(self):
372
uif = _mod_ui.CannedInputUIFactory([True, 'mbp', 'password', 42])
373
self.assertEqual(True, uif.get_boolean('Extra cheese?'))
374
self.assertEqual('mbp', uif.get_username('Enter your user name'))
375
self.assertEqual('password',
376
uif.get_password('Password for %(host)s',
378
self.assertEqual(42, uif.get_integer('And all that jazz ?'))
355
uif = CannedInputUIFactory([True, 'mbp', 'password'])
356
self.assertEqual(uif.get_boolean('Extra cheese?'), True)
357
self.assertEqual(uif.get_username('Enter your user name'), 'mbp')
358
self.assertEqual(uif.get_password('Password for %(host)s', host='example.com'),
381
362
class TestBoolFromString(tests.TestCase):