Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/traitlets/utils/text.py: 30%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

27 statements  

1""" 

2Utilities imported from ipython_genutils 

3""" 

4from __future__ import annotations 

5 

6import re 

7import textwrap 

8from textwrap import indent as _indent 

9 

10 

11def indent(val: str) -> str: 

12 return _indent(val, " ") 

13 

14 

15def _dedent(text: str) -> str: 

16 """Equivalent of textwrap.dedent that ignores unindented first line.""" 

17 

18 if text.startswith("\n"): 

19 # text starts with blank line, don't ignore the first line 

20 return textwrap.dedent(text) 

21 

22 # split first line 

23 splits = text.split("\n", 1) 

24 if len(splits) == 1: 

25 # only one line 

26 return textwrap.dedent(text) 

27 

28 first, rest = splits 

29 # dedent everything but the first line 

30 rest = textwrap.dedent(rest) 

31 return "\n".join([first, rest]) 

32 

33 

34def wrap_paragraphs(text: str, ncols: int = 80) -> list[str]: 

35 """Wrap multiple paragraphs to fit a specified width. 

36 

37 This is equivalent to textwrap.wrap, but with support for multiple 

38 paragraphs, as separated by empty lines. 

39 

40 Returns 

41 ------- 

42 

43 list of complete paragraphs, wrapped to fill `ncols` columns. 

44 """ 

45 paragraph_re = re.compile(r"\n(\s*\n)+", re.MULTILINE) 

46 text = _dedent(text).strip() 

47 paragraphs = paragraph_re.split(text)[::2] # every other entry is space 

48 out_ps = [] 

49 indent_re = re.compile(r"\n\s+", re.MULTILINE) 

50 for p in paragraphs: 

51 # presume indentation that survives dedent is meaningful formatting, 

52 # so don't fill unless text is flush. 

53 if indent_re.search(p) is None: 

54 # wrap paragraph 

55 p = textwrap.fill(p, ncols) 

56 out_ps.append(p) 

57 return out_ps