14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Tests for the breezy ui."""
17
"""Tests for the brzlib ui
22
from StringIO import StringIO
21
24
from testtools.matchers import *
32
from brzlib.tests import (
35
from ..ui import text as _mod_ui_text
35
from brzlib.ui import text as _mod_ui_text
36
from brzlib.tests.testui import (
37
37
ProgressRecordingUIFactory,
41
class TestUIConfiguration(tests.TestCaseInTempDir):
41
class TTYStringIO(StringIO):
42
"""A helper class which makes a StringIO look like a terminal"""
48
class NonTTYStringIO(StringIO):
49
"""Helper that implements isatty() but returns False"""
55
class TestUIConfiguration(tests.TestCaseWithTransport):
43
57
def test_output_encoding_configuration(self):
44
enc = next(fixtures.generate_unicode_encodings())
58
enc = fixtures.generate_unicode_encodings().next()
45
59
config.GlobalStack().set('output_encoding', enc)
46
IO = ui_testing.BytesIOWithEncoding
47
ui = _mod_ui.make_ui_for_terminal(IO(), IO(), IO())
60
ui = tests.TestUIFactory(stdin=None,
61
stdout=tests.StringIOWrapper(),
62
stderr=tests.StringIOWrapper())
48
63
output = ui.make_output_stream()
49
64
self.assertEqual(output.encoding, enc)
52
67
class TestTextUIFactory(tests.TestCase):
69
def make_test_ui_factory(self, stdin_contents):
70
ui = tests.TestUIFactory(stdin=stdin_contents,
71
stdout=tests.StringIOWrapper(),
72
stderr=tests.StringIOWrapper())
54
75
def test_text_factory_confirm(self):
55
76
# turns into reading a regular boolean
56
with ui_testing.TestUIFactory('n\n') as ui:
60
u'Should %(thing)s pass?',
61
'breezy.tests.test_ui.confirmation',
77
ui = self.make_test_ui_factory('n\n')
78
self.assertEqual(ui.confirm_action(u'Should %(thing)s pass?',
79
'brzlib.tests.test_ui.confirmation',
64
83
def test_text_factory_ascii_password(self):
65
ui = ui_testing.TestUIFactory('secret\n')
66
with ui.nested_progress_bar():
84
ui = self.make_test_ui_factory('secret\n')
85
pb = ui.nested_progress_bar()
67
87
self.assertEqual('secret',
68
88
self.apply_redirected(ui.stdin, ui.stdout,
73
93
self.assertEqual('', ui.stdout.readline())
74
94
# stdin should be empty
75
95
self.assertEqual('', ui.stdin.readline())
77
def test_text_factory_unicode_password(self):
78
"""Test a unicode password."""
79
ui = ui_testing.TextUIFactory(u'baz\u1234')
80
password = ui.get_password(
81
u'Hello \u1234 %(user)s', user=u'some\u1234')
99
def test_text_factory_utf8_password(self):
100
"""Test an utf8 password."""
101
ui = _mod_ui_text.TextUIFactory(None, None, None)
102
ui.stdin = tests.StringIOWrapper(u'baz\u1234'.encode('utf8'))
103
ui.stdout = tests.StringIOWrapper()
104
ui.stderr = tests.StringIOWrapper()
105
ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = 'utf8'
106
password = ui.get_password(u'Hello \u1234 %(user)s', user=u'some\u1234')
82
107
self.assertEqual(u'baz\u1234', password)
83
self.assertEqual(u'Hello \u1234 some\u1234: ', ui.stderr.getvalue())
108
self.assertEqual(u'Hello \u1234 some\u1234: ',
109
ui.stderr.getvalue().decode('utf8'))
84
110
# stdin and stdout should be empty
85
111
self.assertEqual('', ui.stdin.readline())
86
112
self.assertEqual('', ui.stdout.getvalue())
88
114
def test_text_ui_get_boolean(self):
94
"yes with garbage\nY\n" # True
95
"not an answer\nno\n" # False
96
"I'm sure!\nyes\n" # True
99
with ui_testing.TextUIFactory(stdin_text) as factory:
100
self.assertEqual(True, factory.get_boolean(u""))
101
self.assertEqual(False, factory.get_boolean(u""))
102
self.assertEqual(True, factory.get_boolean(u""))
103
self.assertEqual(False, factory.get_boolean(u""))
104
self.assertEqual(True, factory.get_boolean(u""))
105
self.assertEqual(False, factory.get_boolean(u""))
106
self.assertEqual(True, factory.get_boolean(u""))
107
self.assertEqual(False, factory.get_boolean(u""))
108
self.assertEqual("foo\n", factory.stdin.read())
109
# stdin should be empty
110
self.assertEqual('', factory.stdin.readline())
111
# return false on EOF
112
self.assertEqual(False, factory.get_boolean(u""))
115
stdin = tests.StringIOWrapper("y\n" # True
119
"yes with garbage\nY\n" # True
120
"not an answer\nno\n" # False
121
"I'm sure!\nyes\n" # True
124
stdout = tests.StringIOWrapper()
125
stderr = tests.StringIOWrapper()
126
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
127
self.assertEqual(True, factory.get_boolean(u""))
128
self.assertEqual(False, factory.get_boolean(u""))
129
self.assertEqual(True, factory.get_boolean(u""))
130
self.assertEqual(False, factory.get_boolean(u""))
131
self.assertEqual(True, factory.get_boolean(u""))
132
self.assertEqual(False, factory.get_boolean(u""))
133
self.assertEqual(True, factory.get_boolean(u""))
134
self.assertEqual(False, factory.get_boolean(u""))
135
self.assertEqual("foo\n", factory.stdin.read())
136
# stdin should be empty
137
self.assertEqual('', factory.stdin.readline())
138
# return false on EOF
139
self.assertEqual(False, factory.get_boolean(u""))
114
141
def test_text_ui_choose_bad_parameters(self):
115
with ui_testing.TextUIFactory(u"") as factory:
116
# invalid default index
117
self.assertRaises(ValueError, factory.choose, u"", u"&Yes\n&No", 3)
120
ValueError, factory.choose, u"", u"&choice\n&ChOiCe")
121
# duplicated shortcut
123
ValueError, factory.choose, u"", u"&choice1\nchoi&ce2")
142
stdin = tests.StringIOWrapper()
143
stdout = tests.StringIOWrapper()
144
stderr = tests.StringIOWrapper()
145
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
146
# invalid default index
147
self.assertRaises(ValueError, factory.choose, u"", u"&Yes\n&No", 3)
149
self.assertRaises(ValueError, factory.choose, u"", u"&choice\n&ChOiCe")
150
# duplicated shortcut
151
self.assertRaises(ValueError, factory.choose, u"", u"&choice1\nchoi&ce2")
125
def test_text_ui_choose_prompt_explicit(self):
153
def test_text_ui_choose_prompt(self):
154
stdin = tests.StringIOWrapper()
155
stdout = tests.StringIOWrapper()
156
stderr = tests.StringIOWrapper()
157
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
126
158
# choices with explicit shortcuts
127
with ui_testing.TextUIFactory(u"") as factory:
128
factory.choose(u"prompt", u"&yes\n&No\nmore &info")
130
"prompt ([y]es, [N]o, more [i]nfo): \n",
131
factory.stderr.getvalue())
133
def test_text_ui_choose_prompt_automatic(self):
159
factory.choose(u"prompt", u"&yes\n&No\nmore &info")
160
self.assertEqual("prompt ([y]es, [N]o, more [i]nfo): \n", factory.stderr.getvalue())
134
161
# automatic shortcuts
135
with ui_testing.TextUIFactory(u"") as factory:
136
factory.choose(u"prompt", u"yes\nNo\nmore info")
138
"prompt ([y]es, [N]o, [m]ore info): \n",
139
factory.stderr.getvalue())
162
factory.stderr.truncate(0)
163
factory.choose(u"prompt", u"yes\nNo\nmore info")
164
self.assertEqual("prompt ([y]es, [N]o, [m]ore info): \n", factory.stderr.getvalue())
141
166
def test_text_ui_choose_return_values(self):
143
return factory.choose(u"", u"&Yes\n&No\nMaybe\nmore &info", 3)
149
"b\na\nd \n" # bad shortcuts, all ignored
150
"yes with garbage\nY\n" # 0
151
"not an answer\nno\n" # 1
152
"info\nmore info\n" # 3
155
with ui_testing.TextUIFactory(stdin_text) as factory:
156
self.assertEqual(0, choose())
157
self.assertEqual(1, choose())
158
self.assertEqual(3, choose())
159
self.assertEqual(1, choose())
160
self.assertEqual(0, choose())
161
self.assertEqual(1, choose())
162
self.assertEqual(3, choose())
163
self.assertEqual(2, choose())
164
self.assertEqual("foo\n", factory.stdin.read())
165
# stdin should be empty
166
self.assertEqual('', factory.stdin.readline())
168
self.assertEqual(None, choose())
167
choose = lambda: factory.choose(u"", u"&Yes\n&No\nMaybe\nmore &info", 3)
168
stdin = tests.StringIOWrapper("y\n" # 0
172
"b\na\nd \n" # bad shortcuts, all ignored
173
"yes with garbage\nY\n" # 0
174
"not an answer\nno\n" # 1
175
"info\nmore info\n" # 3
178
stdout = tests.StringIOWrapper()
179
stderr = tests.StringIOWrapper()
180
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
181
self.assertEqual(0, choose())
182
self.assertEqual(1, choose())
183
self.assertEqual(3, choose())
184
self.assertEqual(1, choose())
185
self.assertEqual(0, choose())
186
self.assertEqual(1, choose())
187
self.assertEqual(3, choose())
188
self.assertEqual(2, choose())
189
self.assertEqual("foo\n", factory.stdin.read())
190
# stdin should be empty
191
self.assertEqual('', factory.stdin.readline())
193
self.assertEqual(None, choose())
170
195
def test_text_ui_choose_no_default(self):
172
" \n" # no default, invalid!
175
with ui_testing.TextUIFactory(stdin_text) as factory:
176
self.assertEqual(0, factory.choose(u"", u"&Yes\n&No"))
177
self.assertEqual("foo\n", factory.stdin.read())
196
stdin = tests.StringIOWrapper(" \n" # no default, invalid!
199
stdout = tests.StringIOWrapper()
200
stderr = tests.StringIOWrapper()
201
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
202
self.assertEqual(0, factory.choose(u"", u"&Yes\n&No"))
203
self.assertEqual("foo\n", factory.stdin.read())
179
205
def test_text_ui_get_integer(self):
206
stdin = tests.StringIOWrapper(
183
209
"hmmm\nwhat else ?\nCome on\nok 42\n4.24\n42\n")
184
with ui_testing.TextUIFactory(stdin_text) as factory:
185
self.assertEqual(1, factory.get_integer(u""))
186
self.assertEqual(-2, factory.get_integer(u""))
187
self.assertEqual(42, factory.get_integer(u""))
210
stdout = tests.StringIOWrapper()
211
stderr = tests.StringIOWrapper()
212
factory = _mod_ui_text.TextUIFactory(stdin, stdout, stderr)
213
self.assertEqual(1, factory.get_integer(u""))
214
self.assertEqual(-2, factory.get_integer(u""))
215
self.assertEqual(42, factory.get_integer(u""))
189
217
def test_text_factory_prompt(self):
190
218
# see <https://launchpad.net/bugs/365891>
191
with ui_testing.TextUIFactory() as factory:
192
factory.prompt(u'foo %2e')
193
self.assertEqual('', factory.stdout.getvalue())
194
self.assertEqual('foo %2e', factory.stderr.getvalue())
219
StringIO = tests.StringIOWrapper
220
factory = _mod_ui_text.TextUIFactory(StringIO(), StringIO(), StringIO())
221
factory.prompt(u'foo %2e')
222
self.assertEqual('', factory.stdout.getvalue())
223
self.assertEqual('foo %2e', factory.stderr.getvalue())
196
225
def test_text_factory_prompts_and_clears(self):
197
226
# a get_boolean call should clear the pb before prompting
198
out = ui_testing.StringIOAsTTY()
199
228
self.overrideEnv('TERM', 'xterm')
200
factory = ui_testing.TextUIFactory("yada\ny\n", stdout=out, stderr=out)
202
pb = factory.nested_progress_bar()
203
pb._avail_width = lambda: 79
205
pb.show_spinner = False
206
pb.show_count = False
207
pb.update("foo", 0, 1)
210
self.apply_redirected(
211
None, factory.stdout, factory.stdout, factory.get_boolean,
212
u"what do you want"))
213
output = out.getvalue()
214
self.assertContainsRe(output,
216
self.assertContainsString(
218
r"what do you want? ([y]es, [n]o): what do you want? "
220
# stdin should have been totally consumed
221
self.assertEqual('', factory.stdin.readline())
229
factory = _mod_ui_text.TextUIFactory(
230
stdin=tests.StringIOWrapper("yada\ny\n"),
231
stdout=out, stderr=out)
232
factory._avail_width = lambda: 79
233
pb = factory.nested_progress_bar()
235
pb.show_spinner = False
236
pb.show_count = False
237
pb.update("foo", 0, 1)
238
self.assertEqual(True,
239
self.apply_redirected(None, factory.stdout,
242
u"what do you want"))
243
output = out.getvalue()
244
self.assertContainsRe(output,
246
self.assertContainsString(output,
247
r"what do you want? ([y]es, [n]o): what do you want? ([y]es, [n]o): ")
248
# stdin should have been totally consumed
249
self.assertEqual('', factory.stdin.readline())
223
251
def test_text_tick_after_update(self):
224
ui_factory = ui_testing.TextUIFactory()
225
with ui_factory.nested_progress_bar() as pb:
252
ui_factory = _mod_ui_text.TextUIFactory(stdout=tests.StringIOWrapper(),
253
stderr=tests.StringIOWrapper())
254
pb = ui_factory.nested_progress_bar()
226
256
pb.update('task', 0, 3)
227
257
# Reset the clock, so that it actually tries to repaint itself
228
258
ui_factory._progress_view._last_repaint = time.time() - 1.0
231
263
def test_text_ui_getusername(self):
232
ui = ui_testing.TextUIFactory('someuser\n\n')
264
ui = _mod_ui_text.TextUIFactory(None, None, None)
265
ui.stdin = tests.StringIOWrapper('someuser\n\n')
266
ui.stdout = tests.StringIOWrapper()
267
ui.stderr = tests.StringIOWrapper()
268
ui.stdout.encoding = 'utf8'
233
269
self.assertEqual('someuser',
234
270
ui.get_username(u'Hello %(host)s', host='some'))
235
271
self.assertEqual('Hello some: ', ui.stderr.getvalue())
238
274
# stdin should be empty
239
275
self.assertEqual('', ui.stdin.readline())
241
def test_text_ui_getusername_unicode(self):
242
ui = ui_testing.TextUIFactory(u'someuser\u1234')
277
def test_text_ui_getusername_utf8(self):
278
ui = _mod_ui_text.TextUIFactory(None, None, None)
279
ui.stdin = tests.StringIOWrapper(u'someuser\u1234'.encode('utf8'))
280
ui.stdout = tests.StringIOWrapper()
281
ui.stderr = tests.StringIOWrapper()
282
ui.stderr.encoding = ui.stdout.encoding = ui.stdin.encoding = "utf8"
243
283
username = ui.get_username(u'Hello %(host)s', host=u'some\u1234')
244
284
self.assertEqual(u"someuser\u1234", username)
245
self.assertEqual(u"Hello some\u1234: ", ui.stderr.getvalue())
285
self.assertEqual(u"Hello some\u1234: ",
286
ui.stderr.getvalue().decode("utf8"))
246
287
self.assertEqual('', ui.stdout.getvalue())
248
289
def test_quietness(self):
249
self.overrideEnv('BRZ_PROGRESS_BAR', 'text')
250
ui_factory = ui_testing.TextUIFactory(
251
stderr=ui_testing.StringIOAsTTY())
253
self.assertIsInstance(ui_factory._progress_view,
254
_mod_ui_text.TextProgressView)
255
ui_factory.be_quiet(True)
256
self.assertIsInstance(ui_factory._progress_view,
257
_mod_ui_text.NullProgressView)
290
self.overrideEnv('BZR_PROGRESS_BAR', 'text')
291
ui_factory = _mod_ui_text.TextUIFactory(None,
294
self.assertIsInstance(ui_factory._progress_view,
295
_mod_ui_text.TextProgressView)
296
ui_factory.be_quiet(True)
297
self.assertIsInstance(ui_factory._progress_view,
298
_mod_ui_text.NullProgressView)
259
300
def test_text_ui_show_user_warning(self):
260
from ..bzr.groupcompress_repo import RepositoryFormat2a
261
from ..bzr.knitpack_repo import RepositoryFormatKnitPack5
262
ui = ui_testing.TextUIFactory()
301
from brzlib.repofmt.groupcompress_repo import RepositoryFormat2a
302
from brzlib.repofmt.knitpack_repo import RepositoryFormatKnitPack5
305
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
263
306
remote_fmt = remote.RemoteRepositoryFormat()
264
307
remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
265
ui.show_user_warning(
266
'cross_format_fetch', from_format=RepositoryFormat2a(),
308
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
267
309
to_format=remote_fmt)
268
self.assertEqual('', ui.stdout.getvalue())
269
self.assertContainsRe(
270
ui.stderr.getvalue(),
271
"^Doing on-the-fly conversion from RepositoryFormat2a\\(\\) to "
272
"RemoteRepositoryFormat\\(_network_name="
273
"b?'Bazaar RepositoryFormatKnitPack5 \\(bzr 1.6\\)\\\\n'\\)\\.\n"
274
"This may take some time. Upgrade the repositories to "
275
"the same format for better performance\\.\n$")
310
self.assertEqual('', out.getvalue())
311
self.assertEqual("Doing on-the-fly conversion from RepositoryFormat2a() to "
312
"RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
313
"(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
314
"the same format for better performance.\n",
276
316
# and now with it suppressed please
277
ui = ui_testing.TextUIFactory()
319
ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
278
320
ui.suppressed_warnings.add('cross_format_fetch')
279
ui.show_user_warning(
280
'cross_format_fetch', from_format=RepositoryFormat2a(),
321
ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
281
322
to_format=remote_fmt)
282
self.assertEqual('', ui.stdout.getvalue())
283
self.assertEqual('', ui.stderr.getvalue())
323
self.assertEqual('', out.getvalue())
324
self.assertEqual('', err.getvalue())
286
327
class TestTextUIOutputStream(tests.TestCase):
287
328
"""Tests for output stream that synchronizes with progress bar."""
289
330
def test_output_clears_terminal(self):
331
stdout = tests.StringIOWrapper()
332
stderr = tests.StringIOWrapper()
292
uif = ui_testing.TextUIFactory()
335
uif = _mod_ui_text.TextUIFactory(None, stdout, stderr)
293
336
uif.clear_term = lambda: clear_calls.append('clear')
295
stream = _mod_ui_text.TextUIOutputStream(
296
uif, uif.stdout, 'utf-8', 'strict')
297
stream.write(u"Hello world!\n")
298
stream.write(u"there's more...\n")
299
stream.writelines([u"1\n", u"2\n", u"3\n"])
338
stream = _mod_ui_text.TextUIOutputStream(uif, uif.stdout)
339
stream.write("Hello world!\n")
340
stream.write("there's more...\n")
341
stream.writelines(["1\n", "2\n", "3\n"])
301
self.assertEqual(uif.stdout.getvalue(),
343
self.assertEqual(stdout.getvalue(),
305
347
self.assertEqual(['clear', 'clear', 'clear'],
313
355
def test_progress_construction(self):
314
356
"""TextUIFactory constructs the right progress view.
316
FileStringIO = ui_testing.StringIOWithEncoding
317
TTYStringIO = ui_testing.StringIOAsTTY
358
FileStringIO = tests.StringIOWrapper
318
359
for (file_class, term, pb, expected_pb_class) in (
319
# on an xterm, either use them or not as the user requests,
320
# otherwise default on
321
(TTYStringIO, 'xterm', 'none', _mod_ui_text.NullProgressView),
322
(TTYStringIO, 'xterm', 'text', _mod_ui_text.TextProgressView),
323
(TTYStringIO, 'xterm', None, _mod_ui_text.TextProgressView),
324
# on a dumb terminal, again if there's explicit configuration
325
# do it, otherwise default off
326
(TTYStringIO, 'dumb', 'none', _mod_ui_text.NullProgressView),
327
(TTYStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
328
(TTYStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
329
# on a non-tty terminal, it's null regardless of $TERM
330
(FileStringIO, 'xterm', None, _mod_ui_text.NullProgressView),
331
(FileStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
332
# however, it can still be forced on
333
(FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
360
# on an xterm, either use them or not as the user requests,
361
# otherwise default on
362
(TTYStringIO, 'xterm', 'none', _mod_ui_text.NullProgressView),
363
(TTYStringIO, 'xterm', 'text', _mod_ui_text.TextProgressView),
364
(TTYStringIO, 'xterm', None, _mod_ui_text.TextProgressView),
365
# on a dumb terminal, again if there's explicit configuration do
366
# it, otherwise default off
367
(TTYStringIO, 'dumb', 'none', _mod_ui_text.NullProgressView),
368
(TTYStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
369
(TTYStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
370
# on a non-tty terminal, it's null regardless of $TERM
371
(FileStringIO, 'xterm', None, _mod_ui_text.NullProgressView),
372
(FileStringIO, 'dumb', None, _mod_ui_text.NullProgressView),
373
# however, it can still be forced on
374
(FileStringIO, 'dumb', 'text', _mod_ui_text.TextProgressView),
335
376
self.overrideEnv('TERM', term)
336
self.overrideEnv('BRZ_PROGRESS_BAR', pb)
337
stdin = file_class(u'')
377
self.overrideEnv('BZR_PROGRESS_BAR', pb)
378
stdin = file_class('')
338
379
stderr = file_class()
339
380
stdout = file_class()
340
381
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
341
self.assertIsInstance(
342
uif, _mod_ui_text.TextUIFactory,
343
"TERM=%s BRZ_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
344
self.assertIsInstance(
345
uif.make_progress_view(),
382
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
383
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
384
self.assertIsInstance(uif.make_progress_view(),
346
385
expected_pb_class,
347
"TERM=%s BRZ_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
386
"TERM=%s BZR_PROGRESS_BAR=%s uif=%r" % (term, pb, uif,))
349
388
def test_text_ui_non_terminal(self):
350
389
"""Even on non-ttys, make_ui_for_terminal gives a text ui."""
351
stdin = stderr = stdout = ui_testing.StringIOWithEncoding()
390
stdin = NonTTYStringIO('')
391
stderr = NonTTYStringIO()
392
stdout = NonTTYStringIO()
352
393
for term_type in ['dumb', None, 'xterm']:
353
394
self.overrideEnv('TERM', term_type)
354
395
uif = _mod_ui.make_ui_for_terminal(stdin, stdout, stderr)
355
396
self.assertIsInstance(uif, _mod_ui_text.TextUIFactory,
356
'TERM=%r' % (term_type,))
397
'TERM=%r' % (term_type,))
359
400
class SilentUITests(tests.TestCase):