Coverage for pymend\output.py: 24%
44 statements
« prev ^ index » next coverage.py v7.3.2, created at 2024-04-20 19:09 +0200
« prev ^ index » next coverage.py v7.3.2, created at 2024-04-20 19:09 +0200
1"""Nice output for pymend.
3The double calls are for patching purposes in tests.
4"""
6import difflib
7import tempfile
8from typing import Any, Optional
10from click import echo, style
13def out(
14 message: Optional[str] = None,
15 *,
16 nl: bool = True,
17 **styles: Any, # noqa: ANN401
18) -> None:
19 """Output normal message.
21 Parameters
22 ----------
23 message : Optional[str]
24 Message to output (Default value = None)
25 nl : bool
26 Whether to print a newline after the message. (Default value = True)
27 **styles : Any
28 Style options for click.
29 """
30 if message is not None:
31 if "bold" not in styles:
32 styles["bold"] = True
33 message = style(message, **styles)
34 echo(message, nl=nl, err=True)
37def err(
38 message: Optional[str] = None,
39 *,
40 nl: bool = True,
41 **styles: Any, # noqa: ANN401
42) -> None:
43 """Output error message.
45 Parameters
46 ----------
47 message : Optional[str]
48 Message to output (Default value = None)
49 nl : bool
50 Whether to print a newline after the message. (Default value = True)
51 **styles : Any
52 Style options for click.
53 """
54 if message is not None:
55 if "fg" not in styles:
56 styles["fg"] = "red"
57 message = style(message, **styles)
58 echo(message, nl=nl, err=True)
61def diff(a: list[str], b: list[str], a_name: str, b_name: str) -> list[str]:
62 """Return a unified diff list between lists`a` and `b`.
64 Parameters
65 ----------
66 a : list[str]
67 Source for the diff
68 b : list[str]
69 Target for the diff.
70 a_name : str
71 Path to the source file of the diff. (Default value = '')
72 b_name : str
73 Path to the target file of the diff. (Default value = '')
75 Returns
76 -------
77 list[str]
78 The resulting diff
79 """
80 diff_lines: list[str] = []
81 for line in difflib.unified_diff(a, b, fromfile=a_name, tofile=b_name):
82 # Work around https://bugs.python.org/issue2142
83 # See:
84 # https://www.gnu.org/software/diffutils/manual/html_node/Incomplete-Lines.html
85 if line[-1] == "\n": 85 ↛ 88line 85 didn't jump to line 88, because the condition on line 85 was never false
86 diff_lines.append(line)
87 else:
88 diff_lines.append(line + "\n")
89 diff_lines.append("\\ No newline at end of file\n")
90 return diff_lines
93def color_diff(contents: str) -> str:
94 """Inject the ANSI color codes to the diff.
96 Parameters
97 ----------
98 contents : str
99 Diff content to color.
101 Returns
102 -------
103 str
104 Colored diff.
105 """
106 lines = contents.split("\n")
107 for i, line in enumerate(lines):
108 if line.startswith(("+++", "---")):
109 line = "\033[1m" + line + "\033[0m" # bold, reset # noqa: PLW2901
110 elif line.startswith("@@"):
111 line = "\033[36m" + line + "\033[0m" # cyan, reset # noqa: PLW2901
112 elif line.startswith("+"):
113 line = "\033[32m" + line + "\033[0m" # green, reset # noqa: PLW2901
114 elif line.startswith("-"):
115 line = "\033[31m" + line + "\033[0m" # red, reset # noqa: PLW2901
116 lines[i] = line
117 return "\n".join(lines)
120def dump_to_file(*output: str, ensure_final_newline: bool = True) -> str:
121 """Dump `output` to a temporary file. Return path to the file.
123 Parameters
124 ----------
125 *output : str
126 List of strings to dump into the output.
127 ensure_final_newline : bool
128 Whether to make sure that every dumped string
129 ends in a new line. (Default value = True)
131 Returns
132 -------
133 str
134 Path to the produced temp file.
135 """
136 with tempfile.NamedTemporaryFile(
137 mode="w", prefix="blk_", suffix=".log", delete=False, encoding="utf8"
138 ) as f:
139 for lines in output:
140 f.write(lines)
141 if ensure_final_newline and lines and lines[-1] != "\n":
142 f.write("\n")
143 return f.name