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""" 

4 

5from __future__ import annotations 

6 

7import re 

8import textwrap 

9from textwrap import indent as _indent 

10 

11 

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

13 return _indent(val, " ") 

14 

15 

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

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

18 

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

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

21 return textwrap.dedent(text) 

22 

23 # split first line 

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

25 if len(splits) == 1: 

26 # only one line 

27 return textwrap.dedent(text) 

28 

29 first, rest = splits 

30 # dedent everything but the first line 

31 rest = textwrap.dedent(rest) 

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

33 

34 

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

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

37 

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

39 paragraphs, as separated by empty lines. 

40 

41 Returns 

42 ------- 

43 

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

45 """ 

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

47 text = _dedent(text).strip() 

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

49 out_ps = [] 

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

51 for p in paragraphs: 

52 # presume indentation that survives dedent is meaningful formatting, 

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

54 if indent_re.search(p) is None: 

55 # wrap paragraph 

56 p = textwrap.fill(p, ncols) 

57 out_ps.append(p) 

58 return out_ps