Coverage for tests.py: 87%
195 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-02 17:29 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-02 17:29 +0000
1# Copyright (c) 2017, Emergence by Design Inc.
3import argparse
4import os
5import sys
6from collections import OrderedDict
7from functools import partial
8from io import StringIO
9from unittest import TestCase
10from unittest import skipUnless
12from colors import bold
13from colors import color
14from colors import strip_color
15from colors import underline
17from argparse_color_formatter import ColorHelpFormatter
18from argparse_color_formatter import ColorTextWrapper
21try:
22 from contextlib import redirect_stderr
23 from contextlib import redirect_stdout
24except ImportError:
25 import contextlib
27 @contextlib.contextmanager
28 def redirect_stdout(target):
29 original = sys.stdout
30 sys.stdout = target
31 yield
32 sys.stdout = original
34 @contextlib.contextmanager
35 def redirect_stderr(target):
36 original = sys.stderr
37 sys.stderr = target
38 yield
39 sys.stderr = original
42colors = OrderedDict(
43 (
44 ("red", partial(color, fg="red", style="bold")),
45 ("orange", partial(color, fg="orange", style="bold")),
46 ("yellow", partial(color, fg="yellow", style="bold")),
47 ("green", partial(color, fg="green", style="bold")),
48 ("blue", partial(color, fg="blue", style="bold")),
49 ("indigo", partial(color, fg="indigo", style="bold")),
50 ("violet", partial(color, fg="violet", style="bold")),
51 )
52)
53positions = ["first", "second", "third", "forth", "fifth", "sixth", "seventh"]
55color_kwargs = {
56 "color": bold("color"),
57 "typically": underline("typically"),
58}
59color_pos = OrderedDict((p, v(p)) for v, p in zip(colors.values(), positions))
60color_names = OrderedDict((k, v(k)) for k, v in colors.items())
62if sys.version_info >= (3, 10): 62 ↛ 69line 62 didn't jump to line 69 because the condition on line 62 was always true
63 color_kwargs.update(
64 {
65 "options_string": "options",
66 }
67 )
68else:
69 color_kwargs.update(
70 {
71 "options_string": "optional arguments",
72 }
73 )
76def rainbow_text(text):
77 retval = []
78 colors_iter = iter(colors.values())
79 cur_color = next(colors_iter)
80 for char in text:
81 retval.append(cur_color(char))
82 try:
83 cur_color = next(colors_iter)
84 except StopIteration:
85 colors_iter = iter(colors.values())
86 cur_color = next(colors_iter)
87 return "".join(retval)
90color_kwargs.update(color_pos)
91color_kwargs.update(color_names)
92color_kwargs.update(
93 {
94 "colorful": rainbow_text("colorful"),
95 "rainbow_maker": rainbow_text("rainbow_maker"),
96 "bow": rainbow_text("bow"),
97 "red-orange-yellow-green-blue-indigo-violet": rainbow_text("red-orange-yellow-green-blue-indigo-violet"),
98 }
99)
102def rainbow_maker_arg_help(color_name):
103 return "{color} used when making rainbow, {typically} this would be {color_name}.".format(
104 color=bold("color"), typically=underline("typically"), color_name=color_kwargs[color_name]
105 )
108def rainbow_maker(args):
109 parser = argparse.ArgumentParser(
110 prog="{rainbow_maker}".format(**color_kwargs),
111 usage="%(prog)s [-h] {first} {second} {third} {forth} {fifth} {sixth} {seventh}".format(**color_kwargs),
112 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format(
113 **color_kwargs
114 ),
115 description="This script is a test for {rainbow_maker}. This description consists of 140 chars."
116 " It should be able to fit onto two 80 char lines.".format(**color_kwargs),
117 formatter_class=ColorHelpFormatter,
118 add_help=False,
119 )
120 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()):
121 parser.add_argument(arg_name, default=color_name, help=rainbow_maker_arg_help(color_name))
122 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs))
123 parser.parse_args(args)
126def rainbow_maker_colored_metavar(args, *, longer_help=1):
127 parser = argparse.ArgumentParser(
128 prog="{rainbow_maker}".format(**color_kwargs),
129 # with recent fixes, these will be colored as well if the metavar is colored, and wrapped properly.
130 # so we don't need to do this ourselves anymore.
131 # usage="%(prog)s [-h] {first} {second} {third} {forth} {fifth} {sixth} {seventh}".format(**color_kwargs),
132 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format(
133 **color_kwargs
134 ),
135 description="This script is a test for {rainbow_maker}. This description consists of 140 chars."
136 " It should be able to fit onto two 80 char lines.".format(**color_kwargs),
137 formatter_class=ColorHelpFormatter,
138 add_help=False,
139 )
140 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()):
141 parser.add_argument(
142 color_name,
143 metavar=color_kwargs[arg_name],
144 default=color_name,
145 help=rainbow_maker_arg_help(color_name) * longer_help,
146 )
147 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs))
148 parser.parse_args(args)
151def rainbow_maker_auto_usage(args):
152 parser = argparse.ArgumentParser(
153 prog="{rainbow_maker}".format(**color_kwargs),
154 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format(
155 **color_kwargs
156 ),
157 description="This script is a test for {rainbow_maker}. This description consists of 140 chars."
158 " It should be able to fit onto two 80 char lines.".format(**color_kwargs),
159 formatter_class=ColorHelpFormatter,
160 add_help=False,
161 )
162 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()):
163 parser.add_argument(arg_name, default=color_name, help=rainbow_maker_arg_help(color_name))
164 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs))
165 parser.parse_args(args)
168def rainbow_maker_auto_usage_short_prog(args):
169 parser = argparse.ArgumentParser(
170 prog="{bow}".format(**color_kwargs),
171 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format(
172 **color_kwargs
173 ),
174 description="This script is a test for {rainbow_maker}. This description consists of 140 chars."
175 " It should be able to fit onto two 80 char lines.".format(**color_kwargs),
176 formatter_class=ColorHelpFormatter,
177 add_help=False,
178 )
179 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()):
180 parser.add_argument(arg_name, default=color_name, help=rainbow_maker_arg_help(color_name))
181 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs))
182 parser.parse_args(args)
185def rainbow_maker_auto_usage_long_prog(args):
186 parser = argparse.ArgumentParser(
187 prog="{red-orange-yellow-green-blue-indigo-violet}".format(**color_kwargs),
188 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format(
189 **color_kwargs
190 ),
191 description="This script is a test for {rainbow_maker}. This description consists of 140 chars."
192 " It should be able to fit onto two 80 char lines.".format(**color_kwargs),
193 formatter_class=ColorHelpFormatter,
194 add_help=False,
195 )
196 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()):
197 parser.add_argument(arg_name, default=color_name, help=rainbow_maker_arg_help(color_name))
198 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs))
199 parser.parse_args(args)
202def rainbow_maker_no_args(args):
203 parser = argparse.ArgumentParser(
204 prog="{rainbow_maker}".format(**color_kwargs),
205 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format(
206 **color_kwargs
207 ),
208 description="This script is a test for {rainbow_maker}. This description consists of 140 chars."
209 " It should be able to fit onto two 80 char lines.".format(**color_kwargs),
210 formatter_class=ColorHelpFormatter,
211 add_help=False,
212 )
213 parser.parse_args(args)
216class TestColorArgsParserOutput(TestCase):
217 maxDiff = None
219 def test_color_output_wrapped_as_expected(self):
220 try:
221 os.environ["COLUMNS"] = "80"
222 out = StringIO()
223 with redirect_stdout(out):
224 self.assertRaises(SystemExit, rainbow_maker, ["-h"])
225 out.seek(0)
226 self.assertEqual(
227 out.read(),
228 "usage: {rainbow_maker} [-h] {first} {second} {third} {forth} {fifth} {sixth} {seventh}\n"
229 "\n"
230 "This script is a test for {rainbow_maker}. This description consists of 140\n"
231 "chars. It should be able to fit onto two 80 char lines.\n"
232 "\n"
233 "positional arguments:\n"
234 " first {color} used when making rainbow, {typically} this would be {red}.\n"
235 " second {color} used when making rainbow, {typically} this would be {orange}.\n"
236 " third {color} used when making rainbow, {typically} this would be {yellow}.\n"
237 " forth {color} used when making rainbow, {typically} this would be {green}.\n"
238 " fifth {color} used when making rainbow, {typically} this would be {blue}.\n"
239 " sixth {color} used when making rainbow, {typically} this would be {indigo}.\n"
240 " seventh {color} used when making rainbow, {typically} this would be {violet}.\n"
241 "\n"
242 "{options_string}:\n"
243 " -h, --help displays this {colorful} help text\n"
244 "\n"
245 "This epilog has some {colorful} escapes in it as well and should not wrap on 80.\n".format(
246 **color_kwargs
247 ),
248 )
249 finally:
250 del os.environ["COLUMNS"]
252 def test_color_output_wrapped_as_expected_small_width(self):
253 try:
254 os.environ["COLUMNS"] = "42"
255 out = StringIO()
256 with redirect_stdout(out):
257 self.assertRaises(SystemExit, rainbow_maker, ["-h"])
258 out.seek(0)
259 self.assertEqual(
260 out.read(),
261 # usage doesnt wrap for some reason when manually specified.
262 # seems like a bug but leaving alone because seems out of scope re: colors.
263 "usage: {rainbow_maker} [-h] {first} {second} {third} {forth} {fifth} {sixth} {seventh}\n"
264 "\n"
265 "This script is a test for {rainbow_maker}.\n"
266 "This description consists of 140 chars.\n"
267 "It should be able to fit onto two 80\n"
268 "char lines.\n"
269 "\n"
270 "positional arguments:\n"
271 " first {color} used when making\n"
272 " rainbow, {typically} this\n"
273 " would be {red}.\n"
274 " second {color} used when making\n"
275 " rainbow, {typically} this\n"
276 " would be {orange}.\n"
277 " third {color} used when making\n"
278 " rainbow, {typically} this\n"
279 " would be {yellow}.\n"
280 " forth {color} used when making\n"
281 " rainbow, {typically} this\n"
282 " would be {green}.\n"
283 " fifth {color} used when making\n"
284 " rainbow, {typically} this\n"
285 " would be {blue}.\n"
286 " sixth {color} used when making\n"
287 " rainbow, {typically} this\n"
288 " would be {indigo}.\n"
289 " seventh {color} used when making\n"
290 " rainbow, {typically} this\n"
291 " would be {violet}.\n"
292 "\n"
293 "{options_string}:\n"
294 " -h, --help displays this {colorful}\n"
295 " help text\n"
296 "\n"
297 "This epilog has some {colorful} escapes in\n"
298 "it as well and should not wrap on 80.\n".format(**color_kwargs),
299 )
300 finally:
301 del os.environ["COLUMNS"]
303 def test_color_output_wrapped_as_expected_with_auto_usage(self):
304 try:
305 os.environ["COLUMNS"] = "80"
306 out = StringIO()
307 with redirect_stdout(out):
308 self.assertRaises(SystemExit, rainbow_maker_auto_usage, ["-h"])
309 out.seek(0)
310 self.assertEqual(
311 out.read(),
312 "usage: {rainbow_maker} [-h] first second third forth fifth sixth seventh\n"
313 "\n"
314 "This script is a test for {rainbow_maker}. This description consists of 140\n"
315 "chars. It should be able to fit onto two 80 char lines.\n"
316 "\n"
317 "positional arguments:\n"
318 " first {color} used when making rainbow, {typically} this would be {red}.\n"
319 " second {color} used when making rainbow, {typically} this would be {orange}.\n"
320 " third {color} used when making rainbow, {typically} this would be {yellow}.\n"
321 " forth {color} used when making rainbow, {typically} this would be {green}.\n"
322 " fifth {color} used when making rainbow, {typically} this would be {blue}.\n"
323 " sixth {color} used when making rainbow, {typically} this would be {indigo}.\n"
324 " seventh {color} used when making rainbow, {typically} this would be {violet}.\n"
325 "\n"
326 "{options_string}:\n"
327 " -h, --help displays this {colorful} help text\n"
328 "\n"
329 "This epilog has some {colorful} escapes in it as well and should not wrap on 80.\n".format(
330 **color_kwargs
331 ),
332 )
333 finally:
334 del os.environ["COLUMNS"]
336 def test_color_output_wrapped_as_expected_with_auto_usage_small_width(self):
337 try:
338 os.environ["COLUMNS"] = "42"
339 out = StringIO()
340 with redirect_stdout(out):
341 self.assertRaises(SystemExit, rainbow_maker_auto_usage, ["-h"])
342 out.seek(0)
343 self.assertEqual(
344 out.read(),
345 "usage: {rainbow_maker} [-h]\n"
346 " first second third\n"
347 " forth fifth sixth\n"
348 " seventh\n"
349 "\n"
350 "This script is a test for {rainbow_maker}.\n"
351 "This description consists of 140 chars.\n"
352 "It should be able to fit onto two 80\n"
353 "char lines.\n"
354 "\n"
355 "positional arguments:\n"
356 " first {color} used when making\n"
357 " rainbow, {typically} this\n"
358 " would be {red}.\n"
359 " second {color} used when making\n"
360 " rainbow, {typically} this\n"
361 " would be {orange}.\n"
362 " third {color} used when making\n"
363 " rainbow, {typically} this\n"
364 " would be {yellow}.\n"
365 " forth {color} used when making\n"
366 " rainbow, {typically} this\n"
367 " would be {green}.\n"
368 " fifth {color} used when making\n"
369 " rainbow, {typically} this\n"
370 " would be {blue}.\n"
371 " sixth {color} used when making\n"
372 " rainbow, {typically} this\n"
373 " would be {indigo}.\n"
374 " seventh {color} used when making\n"
375 " rainbow, {typically} this\n"
376 " would be {violet}.\n"
377 "\n"
378 "{options_string}:\n"
379 " -h, --help displays this {colorful}\n"
380 " help text\n"
381 "\n"
382 "This epilog has some {colorful} escapes in\n"
383 "it as well and should not wrap on 80.\n".format(**color_kwargs),
384 )
385 finally:
386 del os.environ["COLUMNS"]
388 def test_color_output_wrapped_as_expected_with_auto_usage_short_prog_small_width(self):
389 try:
390 os.environ["COLUMNS"] = "42"
391 out = StringIO()
392 with redirect_stdout(out):
393 self.assertRaises(SystemExit, rainbow_maker_auto_usage_short_prog, ["-h"])
394 out.seek(0)
395 self.assertEqual(
396 out.read(),
397 "usage: {bow} [-h]\n"
398 " first second third forth\n"
399 " fifth sixth seventh\n"
400 "\n"
401 "This script is a test for {rainbow_maker}.\n"
402 "This description consists of 140 chars.\n"
403 "It should be able to fit onto two 80\n"
404 "char lines.\n"
405 "\n"
406 "positional arguments:\n"
407 " first {color} used when making\n"
408 " rainbow, {typically} this\n"
409 " would be {red}.\n"
410 " second {color} used when making\n"
411 " rainbow, {typically} this\n"
412 " would be {orange}.\n"
413 " third {color} used when making\n"
414 " rainbow, {typically} this\n"
415 " would be {yellow}.\n"
416 " forth {color} used when making\n"
417 " rainbow, {typically} this\n"
418 " would be {green}.\n"
419 " fifth {color} used when making\n"
420 " rainbow, {typically} this\n"
421 " would be {blue}.\n"
422 " sixth {color} used when making\n"
423 " rainbow, {typically} this\n"
424 " would be {indigo}.\n"
425 " seventh {color} used when making\n"
426 " rainbow, {typically} this\n"
427 " would be {violet}.\n"
428 "\n"
429 "{options_string}:\n"
430 " -h, --help displays this {colorful}\n"
431 " help text\n"
432 "\n"
433 "This epilog has some {colorful} escapes in\n"
434 "it as well and should not wrap on 80.\n".format(**color_kwargs),
435 )
436 finally:
437 del os.environ["COLUMNS"]
439 def test_color_output_wrapped_as_expected_with_auto_usage_long_prog_small_width(self):
440 try:
441 os.environ["COLUMNS"] = "42"
442 out = StringIO()
443 with redirect_stdout(out):
444 self.assertRaises(SystemExit, rainbow_maker_auto_usage_long_prog, ["-h"])
445 out.seek(0)
446 self.assertEqual(
447 out.read(),
448 "usage: {red-orange-yellow-green-blue-indigo-violet}\n"
449 " [-h]\n"
450 " first second third forth fifth\n"
451 " sixth seventh\n"
452 "\n"
453 "This script is a test for {rainbow_maker}.\n"
454 "This description consists of 140 chars.\n"
455 "It should be able to fit onto two 80\n"
456 "char lines.\n"
457 "\n"
458 "positional arguments:\n"
459 " first {color} used when making\n"
460 " rainbow, {typically} this\n"
461 " would be {red}.\n"
462 " second {color} used when making\n"
463 " rainbow, {typically} this\n"
464 " would be {orange}.\n"
465 " third {color} used when making\n"
466 " rainbow, {typically} this\n"
467 " would be {yellow}.\n"
468 " forth {color} used when making\n"
469 " rainbow, {typically} this\n"
470 " would be {green}.\n"
471 " fifth {color} used when making\n"
472 " rainbow, {typically} this\n"
473 " would be {blue}.\n"
474 " sixth {color} used when making\n"
475 " rainbow, {typically} this\n"
476 " would be {indigo}.\n"
477 " seventh {color} used when making\n"
478 " rainbow, {typically} this\n"
479 " would be {violet}.\n"
480 "\n"
481 "{options_string}:\n"
482 " -h, --help displays this {colorful}\n"
483 " help text\n"
484 "\n"
485 "This epilog has some {colorful} escapes in\n"
486 "it as well and should not wrap on 80.\n".format(**color_kwargs),
487 )
488 finally:
489 del os.environ["COLUMNS"]
491 def test_color_output_wrapped_as_expected_with_no_args(self):
492 out = StringIO()
493 with redirect_stderr(out):
494 self.assertRaises(SystemExit, rainbow_maker_no_args, ["--bad"])
495 out.seek(0)
496 self.assertEqual(
497 out.read(),
498 "usage: {rainbow_maker}\n{rainbow_maker}: error: unrecognized arguments: --bad\n".format(**color_kwargs),
499 )
501 def test_color_output_with_long_help(self):
502 try:
503 os.environ["COLUMNS"] = "42"
504 out = StringIO()
505 with redirect_stdout(out):
506 self.assertRaises(SystemExit, partial(rainbow_maker_colored_metavar, longer_help=2), ["-h"])
507 out.seek(0)
508 self.assertEqual(
509 out.read(),
510 "usage: {rainbow_maker} [-h]\n"
511 " {first} {second} {third}\n"
512 " {forth} {fifth} {sixth}\n"
513 " {seventh}\n"
514 "\n"
515 "This script is a test for {rainbow_maker}.\n"
516 "This description consists of 140 chars.\n"
517 "It should be able to fit onto two 80\n"
518 "char lines.\n"
519 "\n"
520 "positional arguments:\n"
521 " {first} {color} used when making\n"
522 " rainbow, {typically} this\n"
523 " would be {red}.{color} used\n"
524 " when making rainbow,\n"
525 " {typically} this would be\n"
526 " {red}.\n"
527 " {second} {color} used when making\n"
528 " rainbow, {typically} this\n"
529 " would be {orange}.{color} used\n"
530 " when making rainbow,\n"
531 " {typically} this would be\n"
532 " {orange}.\n"
533 " {third} {color} used when making\n"
534 " rainbow, {typically} this\n"
535 " would be {yellow}.{color} used\n"
536 " when making rainbow,\n"
537 " {typically} this would be\n"
538 " {yellow}.\n"
539 " {forth} {color} used when making\n"
540 " rainbow, {typically} this\n"
541 " would be {green}.{color} used\n"
542 " when making rainbow,\n"
543 " {typically} this would be\n"
544 " {green}.\n"
545 " {fifth} {color} used when making\n"
546 " rainbow, {typically} this\n"
547 " would be {blue}.{color} used\n"
548 " when making rainbow,\n"
549 " {typically} this would be\n"
550 " {blue}.\n"
551 " {sixth} {color} used when making\n"
552 " rainbow, {typically} this\n"
553 " would be {indigo}.{color} used\n"
554 " when making rainbow,\n"
555 " {typically} this would be\n"
556 " {indigo}.\n"
557 " {seventh} {color} used when making\n"
558 " rainbow, {typically} this\n"
559 " would be {violet}.{color} used\n"
560 " when making rainbow,\n"
561 " {typically} this would be\n"
562 " {violet}.\n"
563 "\n"
564 "{options_string}:\n"
565 " -h, --help displays this {colorful}\n"
566 " help text\n"
567 "\n"
568 "This epilog has some {colorful} escapes in\n"
569 "it as well and should not wrap on 80.\n".format(**color_kwargs),
570 )
571 finally:
572 del os.environ["COLUMNS"]
574 @skipUnless(sys.version_info >= (3, 14), "argparse added native colors in Python 3.14")
575 def test_python314_native_colors_and_application_colors_wrap_correctly(self):
576 old_columns = os.environ.get("COLUMNS")
577 old_python_colors = os.environ.get("PYTHON_COLORS")
578 try:
579 os.environ["COLUMNS"] = "32"
580 os.environ["PYTHON_COLORS"] = "1"
581 colored_word = color("ABCDEFGHIJ", fg="red")
582 parser = argparse.ArgumentParser(
583 prog="rainbow-tool",
584 description=f"prefix {colored_word} suffix words that should wrap cleanly",
585 formatter_class=ColorHelpFormatter,
586 )
587 parser.add_argument(
588 "--example",
589 metavar=colored_word,
590 help=f"prefix {colored_word} suffix words that should wrap cleanly",
591 )
593 output = parser.format_help()
594 self.assertIn("\x1b[", output)
595 plain_output = strip_color(output)
596 self.assertIn(
597 "usage: rainbow-tool [-h]\n [--example ABCDEFGHIJ]\n",
598 plain_output,
599 )
600 self.assertIn(
601 "prefix ABCDEFGHIJ suffix words\nthat should wrap cleanly\n",
602 plain_output,
603 )
604 self.assertIn(
605 " prefix ABCDEFGHIJ\n suffix words that\n should wrap cleanly\n",
606 plain_output,
607 )
608 finally:
609 if old_columns is None:
610 del os.environ["COLUMNS"]
611 else:
612 os.environ["COLUMNS"] = old_columns
613 if old_python_colors is None:
614 del os.environ["PYTHON_COLORS"]
615 else:
616 os.environ["PYTHON_COLORS"] = old_python_colors
619class TestColorTextWrapper(TestCase):
620 def test_bad_width_error(self):
621 ctw = ColorTextWrapper(width=-1)
622 self.assertRaisesRegex(
623 ValueError, r"invalid width -1 \(must be > 0\)", lambda: ctw.wrap("This is some text to wrap.")
624 )
626 def test_starting_whitespace(self):
627 ctw = ColorTextWrapper(width=20)
628 self.assertEqual(
629 ctw.wrap(" 01234 56789 01234 56789 01234 56789 01234 56789"),
630 [" 01234 56789 01234", "56789 01234 56789", "01234 56789"],
631 )
633 def test_max_lines_and_placeholder(self):
634 ctw = ColorTextWrapper(width=10, max_lines=2, placeholder="**" * 10)
635 self.assertRaisesRegex(
636 ValueError,
637 r"placeholder too large for max width",
638 lambda: ctw.wrap("01234 56789 01234 56789 01234 56789 01234 56789"),
639 )
641 def test_max_lines_and_indent(self):
642 ctw = ColorTextWrapper(width=20, max_lines=2, initial_indent=" ")
643 self.assertEqual(
644 ctw.wrap("01234 56789 01234 56789 01234 56789 01234 56789"), [" 01234 56789 01234", "56789 01234 [...]"]
645 )
647 def test_max_lines_and_subsequence_indent(self):
648 ctw = ColorTextWrapper(width=20, max_lines=0, initial_indent=" ", subsequent_indent=" ")
649 self.assertEqual(ctw.wrap("01234 56789 01234 56789 01234 56789 01234 56789"), [" 01234 56789 [...]"])
651 def test_too_big(self):
652 ctw = ColorTextWrapper(width=10)
653 self.assertEqual(
654 ctw.wrap("0123456789 0123456789 01234567890123456789"),
655 ["0123456789", "0123456789", "0123456789", "0123456789"],
656 )
658 def test_placeholder_edge_case(self):
659 ctw = ColorTextWrapper(width=4, max_lines=1, placeholder="***")
660 self.assertEqual(ctw.wrap("0123456789"), ["***"])
662 def test_placeholder_edge_case_2(self):
663 ctw = ColorTextWrapper(width=5, max_lines=2, placeholder="****")
664 self.assertEqual(ctw.wrap("0123456789 " * 2), ["01234", "****"])
667if __name__ == "__main__": 667 ↛ 668line 667 didn't jump to line 668 because the condition on line 667 was never true
668 rainbow_maker_colored_metavar(None, longer_help=2)