Skip to content

Commit

Permalink
Repair colorama wrapping on non-Windows platforms (psf#1670)
Browse files Browse the repository at this point in the history
* Repair colorama wrapping on non-Windows platforms

The wrap_stream_for_windows() function calls
colorama.initialise.wrap_stream() function to apply colorama's magic to
wrapper to the output stream. Except this wrapper is only applied on
Windows platforms that need it, otherwise the original stream is
returned as-is.

The colorama wrapped stream lacks a detach() method, so a no-op lambda
was being assigned to the wrapped stream.

The problem is that the no-op lambda was being assigned unconditionally
whether or not colorama actually returns a wrapped stream, thus
replacing the original TextIOWrapper's detach() method. Replacing the
detach() method with a no-op lambda is the root cause of the problem
observed in psf#1664.

The solution is to only assign the no-op detach() method if the stream
lacks its own detach() method.

Repairs psf#1664
  • Loading branch information
jpgrayson authored and noxan committed Jun 6, 2021
1 parent aa6d978 commit d332cad
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -15,6 +15,8 @@

- fixed a crash when PWD=/ on POSIX (#1631)

- fixed "I/O operation on closed file" when using --diff (#1664)

- Prevent coloured diff output being interleaved with multiple files (#1673)

- Added support for PEP 614 relaxed decorator syntax on python 3.9 (#1711)
Expand Down
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -636,6 +636,7 @@ Multiple contributions by:
- [Paul Ganssle](mailto:p.ganssle@gmail.com)
- [Paul Meinhardt](mailto:mnhrdt@gmail.com)
- [Peter Bengtsson](mailto:mail@peterbe.com)
- [Peter Grayson](mailto:pete@jpgrayson.net)
- [Peter Stensmyr](mailto:peter.stensmyr@gmail.com)
- pmacosta
- [Quentin Pradet](mailto:quentin@pradet.me)
Expand Down
30 changes: 11 additions & 19 deletions src/black/__init__.py
Expand Up @@ -871,30 +871,22 @@ def color_diff(contents: str) -> str:

def wrap_stream_for_windows(
f: io.TextIOWrapper,
) -> Union[io.TextIOWrapper, "colorama.AnsiToWin32.AnsiToWin32"]:
) -> Union[io.TextIOWrapper, "colorama.AnsiToWin32"]:
"""
Wrap the stream in colorama's wrap_stream so colors are shown on Windows.
Wrap stream with colorama's wrap_stream so colors are shown on Windows.
If `colorama` is not found, then no change is made. If `colorama` does
exist, then it handles the logic to determine whether or not to change
things.
If `colorama` is unavailable, the original stream is returned unmodified.
Otherwise, the `wrap_stream()` function determines whether the stream needs
to be wrapped for a Windows environment and will accordingly either return
an `AnsiToWin32` wrapper or the original stream.
"""
try:
from colorama import initialise

# We set `strip=False` so that we can don't have to modify
# test_express_diff_with_color.
f = initialise.wrap_stream(
f, convert=None, strip=False, autoreset=False, wrap=True
)

# wrap_stream returns a `colorama.AnsiToWin32.AnsiToWin32` object
# which does not have a `detach()` method. So we fake one.
f.detach = lambda *args, **kwargs: None # type: ignore
from colorama.initialise import wrap_stream
except ImportError:
pass

return f
return f
else:
# Set `strip=False` to avoid needing to modify test_express_diff_with_color.
return wrap_stream(f, convert=None, strip=False, autoreset=False, wrap=True)


def format_stdin_to_stdout(
Expand Down

0 comments on commit d332cad

Please sign in to comment.