Coverage for tests.py: 98%

171 statements  

« prev     ^ index     » next       coverage.py v7.8.1, created at 2025-05-23 01:23 +0000

1# Copyright (c) 2017, Emergence by Design Inc. 

2 

3import argparse 

4import os 

5import sys 

6from collections import OrderedDict 

7from functools import partial 

8from io import StringIO 

9from unittest import TestCase 

10 

11from colors import bold 

12from colors import color 

13from colors import underline 

14 

15from argparse_color_formatter import ColorHelpFormatter 

16from argparse_color_formatter import ColorTextWrapper 

17 

18 

19try: 

20 from contextlib import redirect_stderr 

21 from contextlib import redirect_stdout 

22except ImportError: 

23 import contextlib 

24 

25 @contextlib.contextmanager 

26 def redirect_stdout(target): 

27 original = sys.stdout 

28 sys.stdout = target 

29 yield 

30 sys.stdout = original 

31 

32 @contextlib.contextmanager 

33 def redirect_stderr(target): 

34 original = sys.stderr 

35 sys.stderr = target 

36 yield 

37 sys.stderr = original 

38 

39 

40colors = OrderedDict( 

41 ( 

42 ("red", partial(color, fg="red", style="bold")), 

43 ("orange", partial(color, fg="orange", style="bold")), 

44 ("yellow", partial(color, fg="yellow", style="bold")), 

45 ("green", partial(color, fg="green", style="bold")), 

46 ("blue", partial(color, fg="blue", style="bold")), 

47 ("indigo", partial(color, fg="indigo", style="bold")), 

48 ("violet", partial(color, fg="violet", style="bold")), 

49 ) 

50) 

51positions = ["first", "second", "third", "forth", "fifth", "sixth", "seventh"] 

52 

53color_kwargs = { 

54 "color": bold("color"), 

55 "typically": underline("typically"), 

56} 

57color_pos = OrderedDict((p, v(p)) for v, p in zip(colors.values(), positions)) 

58color_names = OrderedDict((k, v(k)) for k, v in colors.items()) 

59 

60if sys.version_info >= (3, 10): 60 ↛ 67line 60 didn't jump to line 67 because the condition on line 60 was always true

61 color_kwargs.update( 

62 { 

63 "options_string": "options", 

64 } 

65 ) 

66else: 

67 color_kwargs.update( 

68 { 

69 "options_string": "optional arguments", 

70 } 

71 ) 

72 

73 

74def rainbow_text(text): 

75 retval = [] 

76 colors_iter = iter(colors.values()) 

77 cur_color = next(colors_iter) 

78 for char in text: 

79 retval.append(cur_color(char)) 

80 try: 

81 cur_color = next(colors_iter) 

82 except StopIteration: 

83 colors_iter = iter(colors.values()) 

84 cur_color = next(colors_iter) 

85 return "".join(retval) 

86 

87 

88color_kwargs.update(color_pos) 

89color_kwargs.update(color_names) 

90color_kwargs.update( 

91 { 

92 "colorful": rainbow_text("colorful"), 

93 "rainbow_maker": rainbow_text("rainbow_maker"), 

94 "bow": rainbow_text("bow"), 

95 "red-orange-yellow-green-blue-indigo-violet": rainbow_text("red-orange-yellow-green-blue-indigo-violet"), 

96 } 

97) 

98 

99 

100def rainbow_maker_arg_help(color_name): 

101 return "{color} used when making rainbow, {typically} this would be {color_name}.".format( 

102 color=bold("color"), typically=underline("typically"), color_name=color_kwargs[color_name] 

103 ) 

104 

105 

106def rainbow_maker(args): 

107 parser = argparse.ArgumentParser( 

108 prog="{rainbow_maker}".format(**color_kwargs), 

109 usage="%(prog)s [-h] {first} {second} {third} {forth} {fifth} {sixth} {seventh}".format(**color_kwargs), 

110 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format( 

111 **color_kwargs 

112 ), 

113 description="This script is a test for {rainbow_maker}. This description consists of 140 chars." 

114 " It should be able to fit onto two 80 char lines.".format(**color_kwargs), 

115 formatter_class=ColorHelpFormatter, 

116 add_help=False, 

117 ) 

118 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()): 

119 parser.add_argument(arg_name, default=color_name, help=rainbow_maker_arg_help(color_name)) 

120 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs)) 

121 parser.parse_args(args) 

122 

123 

124def rainbow_maker_colored_metavar(args, *, longer_help=1): 

125 parser = argparse.ArgumentParser( 

126 prog="{rainbow_maker}".format(**color_kwargs), 

127 # with recent fixes, these will be colored as well if the metavar is colored, and wrapped properly. 

128 # so we don't need to do this ourselves anymore. 

129 # usage="%(prog)s [-h] {first} {second} {third} {forth} {fifth} {sixth} {seventh}".format(**color_kwargs), 

130 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format( 

131 **color_kwargs 

132 ), 

133 description="This script is a test for {rainbow_maker}. This description consists of 140 chars." 

134 " It should be able to fit onto two 80 char lines.".format(**color_kwargs), 

135 formatter_class=ColorHelpFormatter, 

136 add_help=False, 

137 ) 

138 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()): 

139 parser.add_argument( 

140 color_name, 

141 metavar=color_kwargs[arg_name], 

142 default=color_name, 

143 help=rainbow_maker_arg_help(color_name) * longer_help, 

144 ) 

145 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs)) 

146 parser.parse_args(args) 

147 

148 

149def rainbow_maker_auto_usage(args): 

150 parser = argparse.ArgumentParser( 

151 prog="{rainbow_maker}".format(**color_kwargs), 

152 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format( 

153 **color_kwargs 

154 ), 

155 description="This script is a test for {rainbow_maker}. This description consists of 140 chars." 

156 " It should be able to fit onto two 80 char lines.".format(**color_kwargs), 

157 formatter_class=ColorHelpFormatter, 

158 add_help=False, 

159 ) 

160 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()): 

161 parser.add_argument(arg_name, default=color_name, help=rainbow_maker_arg_help(color_name)) 

162 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs)) 

163 parser.parse_args(args) 

164 

165 

166def rainbow_maker_auto_usage_short_prog(args): 

167 parser = argparse.ArgumentParser( 

168 prog="{bow}".format(**color_kwargs), 

169 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format( 

170 **color_kwargs 

171 ), 

172 description="This script is a test for {rainbow_maker}. This description consists of 140 chars." 

173 " It should be able to fit onto two 80 char lines.".format(**color_kwargs), 

174 formatter_class=ColorHelpFormatter, 

175 add_help=False, 

176 ) 

177 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()): 

178 parser.add_argument(arg_name, default=color_name, help=rainbow_maker_arg_help(color_name)) 

179 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs)) 

180 parser.parse_args(args) 

181 

182 

183def rainbow_maker_auto_usage_long_prog(args): 

184 parser = argparse.ArgumentParser( 

185 prog="{red-orange-yellow-green-blue-indigo-violet}".format(**color_kwargs), 

186 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format( 

187 **color_kwargs 

188 ), 

189 description="This script is a test for {rainbow_maker}. This description consists of 140 chars." 

190 " It should be able to fit onto two 80 char lines.".format(**color_kwargs), 

191 formatter_class=ColorHelpFormatter, 

192 add_help=False, 

193 ) 

194 for arg_name, color_name in zip(color_pos.keys(), color_names.keys()): 

195 parser.add_argument(arg_name, default=color_name, help=rainbow_maker_arg_help(color_name)) 

196 parser.add_argument("-h", "--help", action="help", help="displays this {colorful} help text".format(**color_kwargs)) 

197 parser.parse_args(args) 

198 

199 

200def rainbow_maker_no_args(args): 

201 parser = argparse.ArgumentParser( 

202 prog="{rainbow_maker}".format(**color_kwargs), 

203 epilog="This epilog has some {colorful} escapes in it as well and should not wrap on 80.".format( 

204 **color_kwargs 

205 ), 

206 description="This script is a test for {rainbow_maker}. This description consists of 140 chars." 

207 " It should be able to fit onto two 80 char lines.".format(**color_kwargs), 

208 formatter_class=ColorHelpFormatter, 

209 add_help=False, 

210 ) 

211 parser.parse_args(args) 

212 

213 

214class TestColorArgsParserOutput(TestCase): 

215 maxDiff = None 

216 

217 def test_color_output_wrapped_as_expected(self): 

218 try: 

219 os.environ["COLUMNS"] = "80" 

220 out = StringIO() 

221 with redirect_stdout(out): 

222 self.assertRaises(SystemExit, rainbow_maker, ["-h"]) 

223 out.seek(0) 

224 self.assertEqual( 

225 out.read(), 

226 "usage: {rainbow_maker} [-h] {first} {second} {third} {forth} {fifth} {sixth} {seventh}\n" 

227 "\n" 

228 "This script is a test for {rainbow_maker}. This description consists of 140\n" 

229 "chars. It should be able to fit onto two 80 char lines.\n" 

230 "\n" 

231 "positional arguments:\n" 

232 " first {color} used when making rainbow, {typically} this would be {red}.\n" 

233 " second {color} used when making rainbow, {typically} this would be {orange}.\n" 

234 " third {color} used when making rainbow, {typically} this would be {yellow}.\n" 

235 " forth {color} used when making rainbow, {typically} this would be {green}.\n" 

236 " fifth {color} used when making rainbow, {typically} this would be {blue}.\n" 

237 " sixth {color} used when making rainbow, {typically} this would be {indigo}.\n" 

238 " seventh {color} used when making rainbow, {typically} this would be {violet}.\n" 

239 "\n" 

240 "{options_string}:\n" 

241 " -h, --help displays this {colorful} help text\n" 

242 "\n" 

243 "This epilog has some {colorful} escapes in it as well and should not wrap on 80.\n".format( 

244 **color_kwargs 

245 ), 

246 ) 

247 finally: 

248 del os.environ["COLUMNS"] 

249 

250 def test_color_output_wrapped_as_expected_small_width(self): 

251 try: 

252 os.environ["COLUMNS"] = "42" 

253 out = StringIO() 

254 with redirect_stdout(out): 

255 self.assertRaises(SystemExit, rainbow_maker, ["-h"]) 

256 out.seek(0) 

257 self.assertEqual( 

258 out.read(), 

259 # usage doesnt wrap for some reason when manually specified. 

260 # seems like a bug but leaving alone because seems out of scope re: colors. 

261 "usage: {rainbow_maker} [-h] {first} {second} {third} {forth} {fifth} {sixth} {seventh}\n" 

262 "\n" 

263 "This script is a test for {rainbow_maker}.\n" 

264 "This description consists of 140 chars.\n" 

265 "It should be able to fit onto two 80\n" 

266 "char lines.\n" 

267 "\n" 

268 "positional arguments:\n" 

269 " first {color} used when making\n" 

270 " rainbow, {typically} this\n" 

271 " would be {red}.\n" 

272 " second {color} used when making\n" 

273 " rainbow, {typically} this\n" 

274 " would be {orange}.\n" 

275 " third {color} used when making\n" 

276 " rainbow, {typically} this\n" 

277 " would be {yellow}.\n" 

278 " forth {color} used when making\n" 

279 " rainbow, {typically} this\n" 

280 " would be {green}.\n" 

281 " fifth {color} used when making\n" 

282 " rainbow, {typically} this\n" 

283 " would be {blue}.\n" 

284 " sixth {color} used when making\n" 

285 " rainbow, {typically} this\n" 

286 " would be {indigo}.\n" 

287 " seventh {color} used when making\n" 

288 " rainbow, {typically} this\n" 

289 " would be {violet}.\n" 

290 "\n" 

291 "{options_string}:\n" 

292 " -h, --help displays this {colorful}\n" 

293 " help text\n" 

294 "\n" 

295 "This epilog has some {colorful} escapes in\n" 

296 "it as well and should not wrap on 80.\n".format(**color_kwargs), 

297 ) 

298 finally: 

299 del os.environ["COLUMNS"] 

300 

301 def test_color_output_wrapped_as_expected_with_auto_usage(self): 

302 try: 

303 os.environ["COLUMNS"] = "80" 

304 out = StringIO() 

305 with redirect_stdout(out): 

306 self.assertRaises(SystemExit, rainbow_maker_auto_usage, ["-h"]) 

307 out.seek(0) 

308 self.assertEqual( 

309 out.read(), 

310 "usage: {rainbow_maker} [-h] first second third forth fifth sixth seventh\n" 

311 "\n" 

312 "This script is a test for {rainbow_maker}. This description consists of 140\n" 

313 "chars. It should be able to fit onto two 80 char lines.\n" 

314 "\n" 

315 "positional arguments:\n" 

316 " first {color} used when making rainbow, {typically} this would be {red}.\n" 

317 " second {color} used when making rainbow, {typically} this would be {orange}.\n" 

318 " third {color} used when making rainbow, {typically} this would be {yellow}.\n" 

319 " forth {color} used when making rainbow, {typically} this would be {green}.\n" 

320 " fifth {color} used when making rainbow, {typically} this would be {blue}.\n" 

321 " sixth {color} used when making rainbow, {typically} this would be {indigo}.\n" 

322 " seventh {color} used when making rainbow, {typically} this would be {violet}.\n" 

323 "\n" 

324 "{options_string}:\n" 

325 " -h, --help displays this {colorful} help text\n" 

326 "\n" 

327 "This epilog has some {colorful} escapes in it as well and should not wrap on 80.\n".format( 

328 **color_kwargs 

329 ), 

330 ) 

331 finally: 

332 del os.environ["COLUMNS"] 

333 

334 def test_color_output_wrapped_as_expected_with_auto_usage_small_width(self): 

335 try: 

336 os.environ["COLUMNS"] = "42" 

337 out = StringIO() 

338 with redirect_stdout(out): 

339 self.assertRaises(SystemExit, rainbow_maker_auto_usage, ["-h"]) 

340 out.seek(0) 

341 self.assertEqual( 

342 out.read(), 

343 "usage: {rainbow_maker} [-h]\n" 

344 " first second third\n" 

345 " forth fifth sixth\n" 

346 " seventh\n" 

347 "\n" 

348 "This script is a test for {rainbow_maker}.\n" 

349 "This description consists of 140 chars.\n" 

350 "It should be able to fit onto two 80\n" 

351 "char lines.\n" 

352 "\n" 

353 "positional arguments:\n" 

354 " first {color} used when making\n" 

355 " rainbow, {typically} this\n" 

356 " would be {red}.\n" 

357 " second {color} used when making\n" 

358 " rainbow, {typically} this\n" 

359 " would be {orange}.\n" 

360 " third {color} used when making\n" 

361 " rainbow, {typically} this\n" 

362 " would be {yellow}.\n" 

363 " forth {color} used when making\n" 

364 " rainbow, {typically} this\n" 

365 " would be {green}.\n" 

366 " fifth {color} used when making\n" 

367 " rainbow, {typically} this\n" 

368 " would be {blue}.\n" 

369 " sixth {color} used when making\n" 

370 " rainbow, {typically} this\n" 

371 " would be {indigo}.\n" 

372 " seventh {color} used when making\n" 

373 " rainbow, {typically} this\n" 

374 " would be {violet}.\n" 

375 "\n" 

376 "{options_string}:\n" 

377 " -h, --help displays this {colorful}\n" 

378 " help text\n" 

379 "\n" 

380 "This epilog has some {colorful} escapes in\n" 

381 "it as well and should not wrap on 80.\n".format(**color_kwargs), 

382 ) 

383 finally: 

384 del os.environ["COLUMNS"] 

385 

386 def test_color_output_wrapped_as_expected_with_auto_usage_short_prog_small_width(self): 

387 try: 

388 os.environ["COLUMNS"] = "42" 

389 out = StringIO() 

390 with redirect_stdout(out): 

391 self.assertRaises(SystemExit, rainbow_maker_auto_usage_short_prog, ["-h"]) 

392 out.seek(0) 

393 self.assertEqual( 

394 out.read(), 

395 "usage: {bow} [-h]\n" 

396 " first second third forth\n" 

397 " fifth sixth seventh\n" 

398 "\n" 

399 "This script is a test for {rainbow_maker}.\n" 

400 "This description consists of 140 chars.\n" 

401 "It should be able to fit onto two 80\n" 

402 "char lines.\n" 

403 "\n" 

404 "positional arguments:\n" 

405 " first {color} used when making\n" 

406 " rainbow, {typically} this\n" 

407 " would be {red}.\n" 

408 " second {color} used when making\n" 

409 " rainbow, {typically} this\n" 

410 " would be {orange}.\n" 

411 " third {color} used when making\n" 

412 " rainbow, {typically} this\n" 

413 " would be {yellow}.\n" 

414 " forth {color} used when making\n" 

415 " rainbow, {typically} this\n" 

416 " would be {green}.\n" 

417 " fifth {color} used when making\n" 

418 " rainbow, {typically} this\n" 

419 " would be {blue}.\n" 

420 " sixth {color} used when making\n" 

421 " rainbow, {typically} this\n" 

422 " would be {indigo}.\n" 

423 " seventh {color} used when making\n" 

424 " rainbow, {typically} this\n" 

425 " would be {violet}.\n" 

426 "\n" 

427 "{options_string}:\n" 

428 " -h, --help displays this {colorful}\n" 

429 " help text\n" 

430 "\n" 

431 "This epilog has some {colorful} escapes in\n" 

432 "it as well and should not wrap on 80.\n".format(**color_kwargs), 

433 ) 

434 finally: 

435 del os.environ["COLUMNS"] 

436 

437 def test_color_output_wrapped_as_expected_with_auto_usage_long_prog_small_width(self): 

438 try: 

439 os.environ["COLUMNS"] = "42" 

440 out = StringIO() 

441 with redirect_stdout(out): 

442 self.assertRaises(SystemExit, rainbow_maker_auto_usage_long_prog, ["-h"]) 

443 out.seek(0) 

444 self.assertEqual( 

445 out.read(), 

446 "usage: {red-orange-yellow-green-blue-indigo-violet}\n" 

447 " [-h]\n" 

448 " first second third forth fifth\n" 

449 " sixth seventh\n" 

450 "\n" 

451 "This script is a test for {rainbow_maker}.\n" 

452 "This description consists of 140 chars.\n" 

453 "It should be able to fit onto two 80\n" 

454 "char lines.\n" 

455 "\n" 

456 "positional arguments:\n" 

457 " first {color} used when making\n" 

458 " rainbow, {typically} this\n" 

459 " would be {red}.\n" 

460 " second {color} used when making\n" 

461 " rainbow, {typically} this\n" 

462 " would be {orange}.\n" 

463 " third {color} used when making\n" 

464 " rainbow, {typically} this\n" 

465 " would be {yellow}.\n" 

466 " forth {color} used when making\n" 

467 " rainbow, {typically} this\n" 

468 " would be {green}.\n" 

469 " fifth {color} used when making\n" 

470 " rainbow, {typically} this\n" 

471 " would be {blue}.\n" 

472 " sixth {color} used when making\n" 

473 " rainbow, {typically} this\n" 

474 " would be {indigo}.\n" 

475 " seventh {color} used when making\n" 

476 " rainbow, {typically} this\n" 

477 " would be {violet}.\n" 

478 "\n" 

479 "{options_string}:\n" 

480 " -h, --help displays this {colorful}\n" 

481 " help text\n" 

482 "\n" 

483 "This epilog has some {colorful} escapes in\n" 

484 "it as well and should not wrap on 80.\n".format(**color_kwargs), 

485 ) 

486 finally: 

487 del os.environ["COLUMNS"] 

488 

489 def test_color_output_wrapped_as_expected_with_no_args(self): 

490 out = StringIO() 

491 with redirect_stderr(out): 

492 self.assertRaises(SystemExit, rainbow_maker_no_args, ["--bad"]) 

493 out.seek(0) 

494 self.assertEqual( 

495 out.read(), 

496 "usage: {rainbow_maker}\n" "{rainbow_maker}: error: unrecognized arguments: --bad\n".format(**color_kwargs), 

497 ) 

498 

499 def test_color_output_with_long_help(self): 

500 try: 

501 os.environ["COLUMNS"] = "42" 

502 out = StringIO() 

503 with redirect_stdout(out): 

504 self.assertRaises(SystemExit, partial(rainbow_maker_colored_metavar, longer_help=2), ["-h"]) 

505 out.seek(0) 

506 self.assertEqual( 

507 out.read(), 

508 "usage: {rainbow_maker} [-h]\n" 

509 " {first} {second} {third}\n" 

510 " {forth} {fifth} {sixth}\n" 

511 " {seventh}\n" 

512 "\n" 

513 "This script is a test for {rainbow_maker}.\n" 

514 "This description consists of 140 chars.\n" 

515 "It should be able to fit onto two 80\n" 

516 "char lines.\n" 

517 "\n" 

518 "positional arguments:\n" 

519 " {first} {color} used when making\n" 

520 " rainbow, {typically} this\n" 

521 " would be {red}.{color} used\n" 

522 " when making rainbow,\n" 

523 " {typically} this would be\n" 

524 " {red}.\n" 

525 " {second} {color} used when making\n" 

526 " rainbow, {typically} this\n" 

527 " would be {orange}.{color} used\n" 

528 " when making rainbow,\n" 

529 " {typically} this would be\n" 

530 " {orange}.\n" 

531 " {third} {color} used when making\n" 

532 " rainbow, {typically} this\n" 

533 " would be {yellow}.{color} used\n" 

534 " when making rainbow,\n" 

535 " {typically} this would be\n" 

536 " {yellow}.\n" 

537 " {forth} {color} used when making\n" 

538 " rainbow, {typically} this\n" 

539 " would be {green}.{color} used\n" 

540 " when making rainbow,\n" 

541 " {typically} this would be\n" 

542 " {green}.\n" 

543 " {fifth} {color} used when making\n" 

544 " rainbow, {typically} this\n" 

545 " would be {blue}.{color} used\n" 

546 " when making rainbow,\n" 

547 " {typically} this would be\n" 

548 " {blue}.\n" 

549 " {sixth} {color} used when making\n" 

550 " rainbow, {typically} this\n" 

551 " would be {indigo}.{color} used\n" 

552 " when making rainbow,\n" 

553 " {typically} this would be\n" 

554 " {indigo}.\n" 

555 " {seventh} {color} used when making\n" 

556 " rainbow, {typically} this\n" 

557 " would be {violet}.{color} used\n" 

558 " when making rainbow,\n" 

559 " {typically} this would be\n" 

560 " {violet}.\n" 

561 "\n" 

562 "{options_string}:\n" 

563 " -h, --help displays this {colorful}\n" 

564 " help text\n" 

565 "\n" 

566 "This epilog has some {colorful} escapes in\n" 

567 "it as well and should not wrap on 80.\n".format(**color_kwargs), 

568 ) 

569 finally: 

570 del os.environ["COLUMNS"] 

571 

572 

573class TestColorTextWrapper(TestCase): 

574 def test_bad_width_error(self): 

575 ctw = ColorTextWrapper(width=-1) 

576 self.assertRaisesRegex( 

577 ValueError, r"invalid width -1 \(must be > 0\)", lambda: ctw.wrap("This is some text to wrap.") 

578 ) 

579 

580 def test_starting_whitespace(self): 

581 ctw = ColorTextWrapper(width=20) 

582 self.assertEqual( 

583 ctw.wrap(" 01234 56789 01234 56789 01234 56789 01234 56789"), 

584 [" 01234 56789 01234", "56789 01234 56789", "01234 56789"], 

585 ) 

586 

587 def test_max_lines_and_placeholder(self): 

588 ctw = ColorTextWrapper(width=10, max_lines=2, placeholder="**" * 10) 

589 self.assertRaisesRegex( 

590 ValueError, 

591 r"placeholder too large for max width", 

592 lambda: ctw.wrap("01234 56789 01234 56789 01234 56789 01234 56789"), 

593 ) 

594 

595 def test_max_lines_and_indent(self): 

596 ctw = ColorTextWrapper(width=20, max_lines=2, initial_indent=" ") 

597 self.assertEqual( 

598 ctw.wrap("01234 56789 01234 56789 01234 56789 01234 56789"), [" 01234 56789 01234", "56789 01234 [...]"] 

599 ) 

600 

601 def test_max_lines_and_subsequence_indent(self): 

602 ctw = ColorTextWrapper(width=20, max_lines=0, initial_indent=" ", subsequent_indent=" ") 

603 self.assertEqual(ctw.wrap("01234 56789 01234 56789 01234 56789 01234 56789"), [" 01234 56789 [...]"]) 

604 

605 def test_too_big(self): 

606 ctw = ColorTextWrapper(width=10) 

607 self.assertEqual( 

608 ctw.wrap("0123456789 0123456789 01234567890123456789"), 

609 ["0123456789", "0123456789", "0123456789", "0123456789"], 

610 ) 

611 

612 def test_placeholder_edge_case(self): 

613 ctw = ColorTextWrapper(width=4, max_lines=1, placeholder="***") 

614 self.assertEqual(ctw.wrap("0123456789"), ["***"]) 

615 

616 def test_placeholder_edge_case_2(self): 

617 ctw = ColorTextWrapper(width=5, max_lines=2, placeholder="****") 

618 self.assertEqual(ctw.wrap("0123456789 " * 2), ["01234", "****"]) 

619 

620 

621if __name__ == "__main__": 621 ↛ 622line 621 didn't jump to line 622 because the condition on line 621 was never true

622 rainbow_maker_colored_metavar(None, longer_help=2)