Skip to content

Commit

Permalink
Release 14.2: Honor the $NO_COLOR environment variable (fixes #88)
Browse files Browse the repository at this point in the history
Details: #88
  • Loading branch information
xolox committed Dec 10, 2020
1 parent 5924f77 commit 857f2b2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 7 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -11,6 +11,14 @@ to `semantic versioning`_.
.. _Keep a Changelog: http://keepachangelog.com/
.. _semantic versioning: http://semver.org/

`Release 14.2`_ (2020-12-10)
----------------------------

Honor the ``$NO_COLOR`` environment variable as suggested in issue `#88`_.

.. _Release 14.2: https://github.com/xolox/python-coloredlogs/compare/14.1...14.2
.. _#88: https://github.com/xolox/python-coloredlogs/issues/88

`Release 14.1`_ (2020-12-10)
----------------------------

Expand Down
32 changes: 25 additions & 7 deletions coloredlogs/__init__.py
Expand Up @@ -45,6 +45,13 @@
``$COLOREDLOGS_FIELD_STYLES`` :data:`DEFAULT_FIELD_STYLES` see :func:`parse_encoded_styles()`
============================= ============================ ==================================
If the environment variable `$NO_COLOR`_ is set (the value doesn't matter, even
an empty string will do) then :func:`coloredlogs.install()` will take this as a
hint that colors should not be used (unless the ``isatty=True`` override was
passed by the caller).
.. _$NO_COLOR: https://no-color.org/
Examples of customization
=========================
Expand Down Expand Up @@ -207,7 +214,7 @@
from humanfriendly.text import format, split

# Semi-standard module versioning.
__version__ = '14.1'
__version__ = '14.2'

DEFAULT_LOG_LEVEL = logging.INFO
"""The default log level for :mod:`coloredlogs` (:data:`logging.INFO`)."""
Expand Down Expand Up @@ -370,6 +377,9 @@ def install(level=None, **kw):
with the `fmt` and `datefmt` keyword arguments (or their computed
defaults).
The environment variable ``$NO_COLOR`` is taken as a hint by
auto-detection that colors should not be used.
4. :func:`HostNameFilter.install()`, :func:`ProgramNameFilter.install()`
and :func:`UserNameFilter.install()` are called to enable the use of
additional fields in the log format.
Expand Down Expand Up @@ -425,16 +435,24 @@ def install(level=None, **kw):
enable_system_logging(level=syslog_enabled)
# Figure out whether we can use ANSI escape sequences.
use_colors = kw.get('isatty', None)
if use_colors or use_colors is None:
# Try to enable Windows native ANSI support or Colorama.
if on_windows() and not enable_ansi_support():
# In the following indented block the expression (use_colors is None)
# can be read as "auto detect is enabled and no reason has yet been
# found to automatically disable color support".
if use_colors or (use_colors is None):
# Respect the user's choice not to have colors.
if use_colors is None and 'NO_COLOR' in os.environ:
# For details on this see https://no-color.org/.
use_colors = False
# Try to enable Windows native ANSI support or Colorama?
if (use_colors or use_colors is None) and on_windows():
# This can fail, in which case ANSI escape sequences would end
# up being printed to the terminal in raw form. This is very
# user hostile, so to avoid this happening we disable color
# support on failure.
use_colors = False
# Disable ANSI escape sequences if 'stream' isn't connected
# to a terminal and no override (isatty=True) is used.
use_colors = enable_ansi_support()
# When auto detection is enabled, and so far we encountered no
# reason to disable color support, then we will enable color
# support if 'stream' is connected to a terminal.
if use_colors is None:
use_colors = terminal_supports_colors(stream)
# Create a stream handler.
Expand Down
14 changes: 14 additions & 0 deletions coloredlogs/tests.py
Expand Up @@ -432,6 +432,20 @@ def test_auto_disable(self):
stdout, stderr = interpreter.communicate()
assert ANSI_CSI not in stderr.decode('UTF-8')

def test_env_disable(self):
"""Make sure ANSI escape sequences can be disabled using ``$NO_COLOR``."""
with PatchedItem(os.environ, 'NO_COLOR', 'I like monochrome'):
with CaptureOutput() as capturer:
subprocess.check_call([
sys.executable, "-c", ";".join([
"import coloredlogs, logging",
"coloredlogs.install()",
"logging.info('Hello world')",
]),
])
output = capturer.get_text()
assert ANSI_CSI not in output

def test_html_conversion(self):
"""Check the conversion from ANSI escape sequences to HTML."""
# Check conversion of colored text.
Expand Down

0 comments on commit 857f2b2

Please sign in to comment.