The terminal_color Module

This module provides tools for colorizing terminal output.

This module defines the ansi escape sequences used for colorizing the output from terminal programs in Linux. You can access the ansi escape sequences using the ansi() function:

>>> from osrf_pycommon.terminal_color import ansi
>>> print(["This is ", ansi('red'), "red", ansi('reset'), "."])
['This is ', '\x1b[31m', 'red', '\x1b[0m', '.']

You can also use format_color() to do in-line substitution of keys wrapped in @{} markers for their ansi escape sequences:

>>> from osrf_pycommon.terminal_color import format_color
>>> print(format_color("This is @{bf}blue@{reset}.").split())
['This', 'is', '\x1b[34mblue\x1b[0m.']

This is a list of all of the available substitutions:

Long Form Shorter Value
@{blackf} @{kf} \033[30m
@{redf} @{rf} \033[31m
@{greenf} @{gf} \033[32m
@{yellowf} @{yf} \033[33m
@{bluef} @{bf} \033[34m
@{purplef} @{pf} \033[35m
@{cyanf} @{cf} \033[36m
@{whitef} @{wf} \033[37m
@{blackb} @{kb} \033[40m
@{redb} @{rb} \033[41m
@{greenb} @{gb} \033[42m
@{yellowb} @{yb} \033[43m
@{blueb} @{bb} \033[44m
@{purpleb} @{pb} \033[45m
@{cyanb} @{cb} \033[46m
@{whiteb} @{wb} \033[47m
@{escape}   \033
@{reset} @| \033[0m
@{boldon} @! \033[1m
@{italicson} @/ \033[3m
@{ulon} @_ \033[4m
@{invon}   \033[7m
@{boldoff}   \033[22m
@{italicsoff}   \033[23m
@{uloff}   \033[24m
@{invoff}   \033[27m

These substitution’s values come from the ANSI color escape sequences, see: http://en.wikipedia.org/wiki/ANSI_escape_code

Also for any of the keys which have a trailing f, you can safely drop the trailing f and get the same thing.

For example, format_color("@{redf}") and format_color("@{red}") are functionally equivalent.

Also, many of the substitutions have shorten forms for convenience, such that @{redf}, @{rf}, @{red}, and @{r} are all the same.

Note that a trailing b is always required when specifying a background.

Some of the most common non-color sequences have {}‘less versions.

For example, @{boldon}‘s shorter form is @!.

By default, the substitutions (and calls to ansi()) resolve to escape sequences, but if you call disable_ansi_color_substitution_globally() then they will resolve to empty strings.

This allows you to always use the substitution strings and disable them globally when desired.

On Windows the substitutions are always resolved to empty strings as the ansi escape sequences do not work on Windows. Instead strings annotated with @{} style substitutions or raw \x1b[xxm style ansi escape sequences must be passed to print_color() in order for colors to be displayed on windows. Also the print_ansi_color_win32() function can be used on strings which only contain ansi escape sequences.

Note

There are existing Python modules like colorama which provide ansi colorization on multiple platforms, so a valid question is: “why write this module?”. The reason for writing this module is to provide the color annotation of strings and functions for removing or replacing ansi escape sequences which are not provided by modules like colorama. This module could have depended on colorama for colorization on Windows, but colorama works by replacing the built-in sys.stdout and sys.stderr, which we did not want and it has extra functionality that we do not need. So, instead of depending on colorama, the Windows color printing code was used as the inspiration for the Windows color printing in the windows.py module in this terminal_color package. The colorama license was placed in the header of that file and the colorama license is compatible with this package’s license.

osrf_pycommon.terminal_color.ansi(key)[source]

Returns the escape sequence for a given ansi color key.

osrf_pycommon.terminal_color.disable_ansi_color_substitution_globally()[source]

Causes format_color() to replace color annotations with empty strings.

It also affects ansi().

This is not the case by default, so if you want to make all substitutions given to either function mentioned above return empty strings then call this function.

The default behavior can be restored by calling enable_ansi_color_substitution_globally().

osrf_pycommon.terminal_color.enable_ansi_color_substitution_globally()[source]

Causes format_color() to replace color annotations with ansi esacpe sequences.

It also affects ansi().

This is the case by default, so there is no need to call this everytime.

If you have previously caused all substitutions to evaluate to an empty string by calling disable_ansi_color_substitution_globally(), then you can restore the escape sequences for substitutions by calling this function.

osrf_pycommon.terminal_color.format_color(msg)[source]

Replaces color annotations with ansi escape sequences.

See this module’s documentation for the list of available substitutions.

If disable_ansi_color_substitution_globally() has been called then all color annotations will be replaced by empty strings.

Also, on Windows all color annotations will be replaced with empty strings. If you want colorization on Windows, you must pass annotated strings to print_color().

Parameters:msg (str) – string message to be colorized
Returns:colorized string
Return type:str
osrf_pycommon.terminal_color.get_ansi_dict()[source]

Returns a copy of the dictionary of keys and ansi escape sequences.

osrf_pycommon.terminal_color.print_ansi_color_win32(*args, **kwargs)[source]

Prints color string containing ansi escape sequences to console in Windows.

If called on a non-Windows system, a NotImplementedError occurs.

Does not respect disable_ansi_color_substitution_globally().

Does not substitute color annotations like @{r} or @!, the string must already contain the \033[1m style ansi escape sequences.

Works by splitting each argument up by ansi escape sequence, printing the text between the sequences, and doing the corresponding win32 action for each ansi sequence encountered.

osrf_pycommon.terminal_color.print_color(*args, **kwargs)[source]

Colorizes and prints with an implicit ansi reset at the end

Calls format_color() on each positional argument and then sends all positional and keyword arguments to print.

If the end keyword argument is not present then the default end value ansi('reset') + '\n' is used and passed to print.

os.linesep is used to determine the actual value for \n.

Therefore, if you use the end keyword argument be sure to include an ansi reset escape sequence if necessary.

On Windows the substituted arguments and keyword arguments are passed to print_ansi_color_win32() instead of just print.

osrf_pycommon.terminal_color.remove_ansi_escape_senquences(string)[source]

Removes any ansi escape sequences found in the given string and returns it.

osrf_pycommon.terminal_color.sanitize(msg)[source]

Sanitizes the given string to prevent format_color() from substituting content.

For example, when the string 'Email: {user}@{org}' is passed to format_color() the @{org} will be incorrectly recognized as a colorization annotation and it will fail to substitute with a KeyError: org.

In order to prevent this, you can first “sanatize” the string, add color annotations, and then pass the whole string to format_color().

If you give this function the string 'Email: {user}@{org}', then it will return 'Email: {{user}}@@{{org}}'. Then if you pass that to format_color() it will return 'Email: {user}@{org}'. In this way format_color() is the reverse of this function and so it is safe to call this function on any incoming data if it will eventually be passed to format_color().

In addition to expanding { => {{, } => }}, and @ => @@, this function will also replace any instances of @!, @/, @_, and @| with @{atexclimation}, @{atfwdslash}, @{atunderscore}, and @{atbar} respectively. And then there are corresponding keys in the ansi dict to convert them back.

For example, if you pass the string '|@ Notice @|' to this function it will return '|@@ Notice @{atbar}'. And since ansi('atbar') always returns @|, even when disable_ansi_color_substitution_globally() has been called, the result of passing that string to format_color() will be '|@ Notice @|' again.

There are two main strategies for constructing strings which use both the Python str.format() function and the colorization annotations.

One way is to just build each piece and concatenate the result:

print_color("@{r}", "{error}".format(error=error_str))
# Or using print (remember to include an ansi reset)
print(format_color("@{r}" + "{error}".format(error=error_str) + "@|"))

Another way is to use this function on the format string, concatenate to the annotations, pass the whole string to format_color(), and then format the whole thing:

print(format_color("@{r}" + sanitize("{error}") + "@|")
      .format(error=error_str))

However, the most common use for this function is to sanitize incoming strings which may have unknown content:

def my_func(user_content):
    print_color("@{y}" + sanitize(user_content))

This function is not intended to be used on strings with color annotations.

Parameters:msg (str) – string message to be sanitized
Returns:sanitized string
Return type:str
osrf_pycommon.terminal_color.split_by_ansi_escape_sequence(string, include_delimiters=False)[source]

Splits a string into a list using any ansi escape sequence as a delimiter.

Parameters:
  • string (str) – string to be split
  • include_delimiters (bool) – If True include matched escape sequences in the list (default: False)
Returns:

list of strings, split from original string by escape sequences

Return type:

list

osrf_pycommon.terminal_color.test_colors(file=None)[source]

Prints a color testing block using print_color()