Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Version 8.5.0

Unreleased

- Supported versions of Windows enable ANSI terminal styles by default.
Colorama is no longer a dependency and is not used. :issue:`2986` :pr:`3505`


Version 8.4.2
-------------
Expand Down
5 changes: 2 additions & 3 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ Some standalone examples of Click applications are packaged with Click. They are
performs custom validation of parameters in different ways.
- [naval](https://github.com/pallets/click/tree/main/examples/naval) : Port of the [docopt](http://docopt.org/) naval
example.
- [colors](https://github.com/pallets/click/tree/main/examples/colors) : A simple example that colorizes text. Uses
colorama on Windows.
- [colors](https://github.com/pallets/click/tree/main/examples/colors) : A simple example that colorizes text.
- [aliases](https://github.com/pallets/click/tree/main/examples/aliases) : An advanced example that implements
{ref}`aliases`.
- [imagepipe](https://github.com/pallets/click/tree/main/examples/imagepipe) : A complex example that implements some
Expand Down Expand Up @@ -81,7 +80,7 @@ What this means is that the {func}`echo` function applies some error correction
instead of dying with a {exc}`UnicodeError`.

The echo function also supports color and other styles in output. It will automatically remove styles if the output
stream is a file. On Windows, colorama is automatically installed and used. See {ref}`ansi-colors`.
stream is a file. See {ref}`ansi-colors`.

If you don't need this, you can also use the `print()` construct / function.

Expand Down
11 changes: 8 additions & 3 deletions docs/utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,21 @@ click.echo('Hello World!', err=True)
```{versionadded} 2.0
```

The {func}`echo` function supports ANSI colors and styles. On Windows this uses [colorama](https://pypi.org/project/colorama/).
The {func}`echo` function supports ANSI colors and styles.

Primarily this means that:

- Click's {func}`echo` function will automatically strip ANSI color codes if the stream is not connected to a terminal.
- the {func}`echo` function will transparently connect to the terminal on Windows and translate ANSI codes to terminal
API calls. This means that colors will work on Windows the same way they do on other operating systems.

On Windows, Click uses colorama without calling `colorama.init()`. You can still call that in your code, but it's not
required for Click.
:::{admonition} Older Windows Support
:class: note

Recent Windows 11 supports ANSI styling by default, in both Terminal and cmd.exe.
If you need to support color output on older versions of Windows, install
[colorama](https://pypi.org/project/colorama/) and call `colorama.init()`.
:::

For styling a string, the {func}`style` function can be used:

Expand Down
2 changes: 0 additions & 2 deletions examples/colors/README
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ $ colors_
colors is a simple example that shows how you can
colorize text.

Uses colorama on Windows.

Usage:

$ pip install --editable .
Expand Down
9 changes: 0 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ classifiers = [
"Typing :: Typed",
]
requires-python = ">=3.10"
dependencies = [
"colorama; platform_system == 'Windows'",
]

[project.urls]
Donate = "https://palletsprojects.com/donate"
Expand Down Expand Up @@ -114,12 +111,6 @@ show_error_codes = true
pretty = true
strict = true

[[tool.mypy.overrides]]
module = [
"colorama.*",
]
ignore_missing_imports = true

[tool.pyright]
pythonVersion = "3.10"
include = ["src", "tests/typing"]
Expand Down
42 changes: 1 addition & 41 deletions src/click/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
CYGWIN = sys.platform.startswith("cygwin")
WIN = sys.platform.startswith("win")
MAC = sys.platform == "darwin"
auto_wrap_for_ansi: t.Callable[[t.TextIO], t.TextIO] | None = None
_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]")


Expand Down Expand Up @@ -511,9 +510,7 @@ def should_strip_ansi(
return not color


# On Windows, wrap the output streams with colorama to support ANSI
# color codes.
# NOTE: double check is needed so mypy does not analyze this on Linux
# double check is needed so mypy does not analyze this on Linux
if sys.platform.startswith("win") and WIN:
from ._winconsole import _get_windows_console_stream

Expand All @@ -522,43 +519,6 @@ def _get_argv_encoding() -> str:

return locale.getpreferredencoding()

_ansi_stream_wrappers: cabc.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary()

def auto_wrap_for_ansi(stream: t.TextIO, color: bool | None = None) -> t.TextIO:
"""Support ANSI color and style codes on Windows by wrapping a
stream with colorama.
"""
try:
cached = _ansi_stream_wrappers.get(stream)
except Exception:
cached = None

if cached is not None:
return cached

import colorama

strip = should_strip_ansi(stream, color)
ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip)
rv = t.cast(t.TextIO, ansi_wrapper.stream)
_write = rv.write

def _safe_write(s: str) -> int:
try:
return _write(s)
except BaseException:
ansi_wrapper.reset_all()
raise

rv.write = _safe_write # type: ignore[method-assign]

try:
_ansi_stream_wrappers[stream] = rv
except Exception:
pass

return rv

else:

def _get_argv_encoding() -> str:
Expand Down
11 changes: 0 additions & 11 deletions src/click/termui.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

from ._compat import isatty
from ._compat import strip_ansi
from ._compat import WIN
from .exceptions import Abort
from .exceptions import UsageError
from .globals import resolve_color_default
Expand Down Expand Up @@ -84,17 +83,7 @@ def hidden_prompt_func(prompt: str) -> str:
def _readline_prompt(func: t.Callable[[str], str], text: str, err: bool) -> str:
"""Call a prompt function, passing the full prompt on non-Windows so
readline can handle line editing and cursor positioning correctly.

On Windows the prompt is written separately via :func:`echo` for
colorama support, with only the last character passed to *func*.
"""
if WIN:
# Write the prompt separately so that we get nice coloring
# through colorama on Windows.
echo(text[:-1], nl=False, err=err)
# Echo the last character to stdout to work around an issue
# where readline causes backspace to clear the whole line.
return func(text[-1:])
if err:
with redirect_stdout(sys.stderr):
return func(text)
Expand Down
16 changes: 5 additions & 11 deletions src/click/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from ._compat import _default_text_stderr
from ._compat import _default_text_stdout
from ._compat import _find_binary_writer
from ._compat import auto_wrap_for_ansi
from ._compat import binary_streams
from ._compat import open_stream
from ._compat import should_strip_ansi
Expand Down Expand Up @@ -262,6 +261,9 @@ def echo(
default Click will remove color if the output does not look like
an interactive terminal.

.. versionchanged:: 8.5
Colorama is no longer used for color on Windows.

.. versionchanged:: 6.0
Support Unicode output on the Windows console. Click does not
modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()``
Expand Down Expand Up @@ -319,16 +321,8 @@ def echo(

# ANSI style code support. For no message or bytes, nothing happens.
# When outputting to a file instead of a terminal, strip codes.
else:
color = resolve_color_default(color)

if should_strip_ansi(file, color):
out = strip_ansi(out)
elif WIN:
if auto_wrap_for_ansi is not None:
file = auto_wrap_for_ansi(file, color) # type: ignore
elif not color:
out = strip_ansi(out)
elif should_strip_ansi(file, resolve_color_default(color)):
out = strip_ansi(out)

file.write(out) # type: ignore
file.flush()
Expand Down
18 changes: 7 additions & 11 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,22 +472,18 @@ def test_echo_color_flag(monkeypatch, capfd):
out, err = capfd.readouterr()
assert out == f"{styled_text}\n"

isatty = True
click.echo(styled_text)
out, err = capfd.readouterr()
assert out == f"{styled_text}\n"

isatty = False
# Faking isatty() is not enough on Windows;
# the implementation caches the colorama wrapped stream
# so we have to use a new stream for each test
stream = StringIO()
click.echo(styled_text, file=stream)
assert stream.getvalue() == f"{text}\n"

stream = StringIO()
click.echo(styled_text, file=stream, color=True)
assert stream.getvalue() == f"{styled_text}\n"
click.echo(styled_text)
out, err = capfd.readouterr()
assert out == f"{text}\n"

click.echo(styled_text, color=True)
out, err = capfd.readouterr()
assert out == f"{styled_text}\n"


def test_prompt_cast_default(capfd, monkeypatch):
Expand Down
4 changes: 0 additions & 4 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading