Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/black/output.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
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
1"""Nice output for Black.
3The double calls are for patching purposes in tests.
4"""
6import json
7import re
8import tempfile
9from typing import Any, Optional
11from click import echo, style
12from mypy_extensions import mypyc_attr
15@mypyc_attr(patchable=True)
16def _out(message: Optional[str] = None, nl: bool = True, **styles: Any) -> None:
17 if message is not None:
18 if "bold" not in styles:
19 styles["bold"] = True
20 message = style(message, **styles)
21 echo(message, nl=nl, err=True)
24@mypyc_attr(patchable=True)
25def _err(message: Optional[str] = None, nl: bool = True, **styles: Any) -> None:
26 if message is not None:
27 if "fg" not in styles:
28 styles["fg"] = "red"
29 message = style(message, **styles)
30 echo(message, nl=nl, err=True)
33@mypyc_attr(patchable=True)
34def out(message: Optional[str] = None, nl: bool = True, **styles: Any) -> None:
35 _out(message, nl=nl, **styles)
38def err(message: Optional[str] = None, nl: bool = True, **styles: Any) -> None:
39 _err(message, nl=nl, **styles)
42def ipynb_diff(a: str, b: str, a_name: str, b_name: str) -> str:
43 """Return a unified diff string between each cell in notebooks `a` and `b`."""
44 a_nb = json.loads(a)
45 b_nb = json.loads(b)
46 diff_lines = [
47 diff(
48 "".join(a_nb["cells"][cell_number]["source"]) + "\n",
49 "".join(b_nb["cells"][cell_number]["source"]) + "\n",
50 f"{a_name}:cell_{cell_number}",
51 f"{b_name}:cell_{cell_number}",
52 )
53 for cell_number, cell in enumerate(a_nb["cells"])
54 if cell["cell_type"] == "code"
55 ]
56 return "".join(diff_lines)
59_line_pattern = re.compile(r"(.*?(?:\r\n|\n|\r|$))")
62def _splitlines_no_ff(source: str) -> list[str]:
63 """Split a string into lines ignoring form feed and other chars.
65 This mimics how the Python parser splits source code.
67 A simplified version of the function with the same name in Lib/ast.py
68 """
69 result = [match[0] for match in _line_pattern.finditer(source)]
70 if result[-1] == "":
71 result.pop(-1)
72 return result
75def diff(a: str, b: str, a_name: str, b_name: str) -> str:
76 """Return a unified diff string between strings `a` and `b`."""
77 import difflib
79 a_lines = _splitlines_no_ff(a)
80 b_lines = _splitlines_no_ff(b)
81 diff_lines = []
82 for line in difflib.unified_diff(
83 a_lines, b_lines, fromfile=a_name, tofile=b_name, n=5
84 ):
85 # Work around https://bugs.python.org/issue2142
86 # See:
87 # https://www.gnu.org/software/diffutils/manual/html_node/Incomplete-Lines.html
88 if line[-1] == "\n":
89 diff_lines.append(line)
90 else:
91 diff_lines.append(line + "\n")
92 diff_lines.append("\\ No newline at end of file\n")
93 return "".join(diff_lines)
96def color_diff(contents: str) -> str:
97 """Inject the ANSI color codes to the diff."""
98 lines = contents.split("\n")
99 for i, line in enumerate(lines):
100 if line.startswith("+++") or line.startswith("---"):
101 line = "\033[1m" + line + "\033[0m" # bold, reset
102 elif line.startswith("@@"):
103 line = "\033[36m" + line + "\033[0m" # cyan, reset
104 elif line.startswith("+"):
105 line = "\033[32m" + line + "\033[0m" # green, reset
106 elif line.startswith("-"):
107 line = "\033[31m" + line + "\033[0m" # red, reset
108 lines[i] = line
109 return "\n".join(lines)
112@mypyc_attr(patchable=True)
113def dump_to_file(*output: str, ensure_final_newline: bool = True) -> str:
114 """Dump `output` to a temporary file. Return path to the file."""
115 with tempfile.NamedTemporaryFile(
116 mode="w", prefix="blk_", suffix=".log", delete=False, encoding="utf8"
117 ) as f:
118 for lines in output:
119 f.write(lines)
120 if ensure_final_newline and lines and lines[-1] != "\n":
121 f.write("\n")
122 return f.name