150
143
def test_progress_nested(self):
151
144
# test factory based nested and popping.
152
ui = TextUIFactory(None, None, None)
153
146
pb1 = ui.nested_progress_bar()
154
147
pb2 = ui.nested_progress_bar()
155
# You do get a warning if the outermost progress bar wasn't finished
156
# first - it's not clear if this is really useful or if it should just
157
# become orphaned -- mbp 20090120
158
warnings, _ = self.callCatchWarnings(pb1.finished)
159
if len(warnings) != 1:
160
self.fail("unexpected warnings: %r" % (warnings,))
148
self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
164
152
def test_progress_stack(self):
165
# test the progress bar stack which the default text factory
153
# test the progress bar stack which the default text factory
167
155
stderr = StringIO()
168
156
stdout = StringIO()
169
157
# make a stack, which accepts parameters like a pb.
170
stack = self.applyDeprecated(
171
deprecated_in((1, 12, 0)),
173
to_file=stderr, to_messages_file=stdout)
158
stack = ProgressBarStack(to_file=stderr, to_messages_file=stdout)
175
160
self.assertFalse(getattr(stack, 'note', False))
176
161
pb1 = stack.get_nested()
177
162
pb2 = stack.get_nested()
178
warnings, _ = self.callCatchWarnings(pb1.finished)
179
self.assertEqual(len(warnings), 1)
163
self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
182
166
# the text ui factory never actually removes the stack once its setup.
183
167
# we need to be able to nest again correctly from here.
184
168
pb1 = stack.get_nested()
185
169
pb2 = stack.get_nested()
186
warnings, _ = self.callCatchWarnings(pb1.finished)
187
self.assertEqual(len(warnings), 1)
170
self.assertRaises(errors.MissingProgressBarFinish, pb1.finished)
174
def test_text_factory_setting_progress_bar(self):
175
# we should be able to choose the progress bar type used.
176
factory = TextUIFactory(bar_type=DotsProgressBar)
177
bar = factory.nested_progress_bar()
179
self.assertIsInstance(bar, DotsProgressBar)
181
def test_cli_stdin_is_default_stdin(self):
182
factory = CLIUIFactory()
183
self.assertEqual(sys.stdin, factory.stdin)
191
185
def assert_get_bool_acceptance_of_user_input(self, factory):
192
186
factory.stdin = StringIO("y\nyes with garbage\n"
193
187
"yes\nn\nnot an answer\n"
218
212
self.assertEqual('', factory.stdin.readline())
220
214
def test_text_ui_getbool(self):
221
factory = TextUIFactory(None, None, None)
215
factory = TextUIFactory()
222
216
self.assert_get_bool_acceptance_of_user_input(factory)
224
218
def test_text_factory_prompts_and_clears(self):
225
219
# a get_boolean call should clear the pb before prompting
227
factory = TextUIFactory(stdin=StringIO("yada\ny\n"), stdout=out, stderr=out)
228
pb = factory.nested_progress_bar()
230
pb.show_spinner = False
231
pb.show_count = False
232
pb.update("foo", 0, 1)
220
factory = TextUIFactory(bar_type=DotsProgressBar)
221
factory.stdout = _TTYStringIO()
222
factory.stdin = StringIO("yada\ny\n")
223
pb = self.apply_redirected(factory.stdin, factory.stdout,
224
factory.stdout, factory.nested_progress_bar)
226
self.apply_redirected(factory.stdin, factory.stdout,
227
factory.stdout, pb.update, "foo", 0, 1)
233
228
self.assertEqual(True,
234
229
self.apply_redirected(None, factory.stdout,
236
231
factory.get_boolean,
237
232
"what do you want"))
238
output = out.getvalue()
239
self.assertContainsRe(factory.stdout.getvalue(),
241
self.assertContainsRe(factory.stdout.getvalue(),
242
r"what do you want\? \[y/n\]: what do you want\? \[y/n\]: ")
243
# stdin should have been totally consumed
244
self.assertEqual('', factory.stdin.readline())
246
def test_text_tick_after_update(self):
247
ui_factory = TextUIFactory(stdout=StringIO(), stderr=StringIO())
248
pb = ui_factory.nested_progress_bar()
250
pb.update('task', 0, 3)
251
# Reset the clock, so that it actually tries to repaint itself
252
ui_factory._progress_view._last_repaint = time.time() - 1.0
257
def test_silent_ui_getusername(self):
258
factory = SilentUIFactory()
259
factory.stdin = StringIO("someuser\n\n")
260
factory.stdout = StringIO()
261
self.assertEquals(None,
262
factory.get_username(u'Hello\u1234 %(host)s', host=u'some\u1234'))
263
self.assertEquals("", factory.stdout.getvalue())
264
self.assertEquals("someuser\n\n", factory.stdin.getvalue())
266
def test_text_ui_getusername(self):
267
factory = TextUIFactory(None, None, None)
268
factory.stdin = StringIO("someuser\n\n")
269
factory.stdout = StringIO()
270
factory.stdout.encoding = "utf8"
271
# there is no output from the base factory
272
self.assertEqual("someuser",
273
factory.get_username('Hello %(host)s', host='some'))
274
self.assertEquals("Hello some: ", factory.stdout.getvalue())
275
self.assertEqual("", factory.get_username("Gebruiker"))
233
output = factory.stdout.getvalue()
234
self.assertEqual("foo: .\n"
235
"what do you want? [y/n]: what do you want? [y/n]: ",
236
factory.stdout.getvalue())
276
237
# stdin should be empty
277
238
self.assertEqual('', factory.stdin.readline())
279
def test_text_ui_getusername_utf8(self):
280
ui = TestUIFactory(stdin=u'someuser\u1234'.encode('utf8'),
281
stdout=StringIOWrapper())
282
ui.stdin.encoding = "utf8"
283
ui.stdout.encoding = ui.stdin.encoding
284
pb = ui.nested_progress_bar()
286
# there is no output from the base factory
287
username = self.apply_redirected(ui.stdin, ui.stdout, ui.stdout,
288
ui.get_username, u'Hello\u1234 %(host)s', host=u'some\u1234')
289
self.assertEquals(u"someuser\u1234", username.decode('utf8'))
290
self.assertEquals(u"Hello\u1234 some\u1234: ",
291
ui.stdout.getvalue().decode("utf8"))
296
class TestTextProgressView(TestCase):
297
"""Tests for text display of progress bars.
299
# XXX: These might be a bit easier to write if the rendering and
300
# state-maintaining parts of TextProgressView were more separate, and if
301
# the progress task called back directly to its own view not to the ui
302
# factory. -- mbp 20090312
304
def _make_factory(self):
306
uif = TextUIFactory(stderr=out)
307
uif._progress_view._width = 80
310
def test_render_progress_easy(self):
311
"""Just one task and one quarter done"""
312
out, uif = self._make_factory()
313
task = uif.nested_progress_bar()
314
task.update('reticulating splines', 5, 20)
316
'\r[####/ ] reticulating splines 5/20 \r'
319
def test_render_progress_nested(self):
320
"""Tasks proportionally contribute to overall progress"""
321
out, uif = self._make_factory()
322
task = uif.nested_progress_bar()
323
task.update('reticulating splines', 0, 2)
324
task2 = uif.nested_progress_bar()
325
task2.update('stage2', 1, 2)
326
# so we're in the first half of the main task, and half way through
329
r'[####\ ] reticulating splines:stage2 1/2'
330
, uif._progress_view._render_line())
331
# if the nested task is complete, then we're all the way through the
332
# first half of the overall work
333
task2.update('stage2', 2, 2)
335
r'[#########| ] reticulating splines:stage2 2/2'
336
, uif._progress_view._render_line())
338
def test_render_progress_sub_nested(self):
339
"""Intermediate tasks don't mess up calculation."""
340
out, uif = self._make_factory()
341
task_a = uif.nested_progress_bar()
342
task_a.update('a', 0, 2)
343
task_b = uif.nested_progress_bar()
345
task_c = uif.nested_progress_bar()
346
task_c.update('c', 1, 2)
347
# the top-level task is in its first half; the middle one has no
348
# progress indication, just a label; and the bottom one is half done,
349
# so the overall fraction is 1/4
351
r'[####| ] a:b:c 1/2'
352
, uif._progress_view._render_line())