""" termcolors.py """ color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white') foreground = {color_names[x]: '3%s' % x for x in range(8)} background = {color_names[x]: '4%s' % x for x in range(8)} RESET = '0' opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} def colorize(text='', opts=(), **kwargs): """ Return your text, enclosed in ANSI graphics codes. Depends on the keyword arguments 'fg' and 'bg', and the contents of the opts tuple/list. Return the RESET code if no parameters are given. Valid colors: 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' Valid options: 'bold' 'underscore' 'blink' 'reverse' 'conceal' 'noreset' - string will not be auto-terminated with the RESET code Examples: colorize('hello', fg='red', bg='blue', opts=('blink',)) colorize() colorize('goodbye', opts=('underscore',)) print(colorize('first line', fg='red', opts=('noreset',))) print('this should be red too') print(colorize('and so should this')) print('this should not be red') """ code_list = [] if text == '' and len(opts) == 1 and opts[0] == 'reset': return '\x1b[%sm' % RESET for k, v in kwargs.items(): if k == 'fg': code_list.append(foreground[v]) elif k == 'bg': code_list.append(background[v]) for o in opts: if o in opt_dict: code_list.append(opt_dict[o]) if 'noreset' not in opts: text = '%s\x1b[%sm' % (text or '', RESET) return '%s%s' % (('\x1b[%sm' % ';'.join(code_list)), text or '') def make_style(opts=(), **kwargs): """ Return a function with default parameters for colorize() Example: bold_red = make_style(opts=('bold',), fg='red') print(bold_red('hello')) KEYWORD = make_style(fg='yellow') COMMENT = make_style(fg='blue', opts=('bold',)) """ return lambda text: colorize(text, opts, **kwargs) NOCOLOR_PALETTE = 'nocolor' DARK_PALETTE = 'dark' LIGHT_PALETTE = 'light' PALETTES = { NOCOLOR_PALETTE: { 'ERROR': {}, 'SUCCESS': {}, 'WARNING': {}, 'NOTICE': {}, 'SQL_FIELD': {}, 'SQL_COLTYPE': {}, 'SQL_KEYWORD': {}, 'SQL_TABLE': {}, 'HTTP_INFO': {}, 'HTTP_SUCCESS': {}, 'HTTP_REDIRECT': {}, 'HTTP_NOT_MODIFIED': {}, 'HTTP_BAD_REQUEST': {}, 'HTTP_NOT_FOUND': {}, 'HTTP_SERVER_ERROR': {}, 'MIGRATE_HEADING': {}, 'MIGRATE_LABEL': {}, }, DARK_PALETTE: { 'ERROR': {'fg': 'red', 'opts': ('bold',)}, 'SUCCESS': {'fg': 'green', 'opts': ('bold',)}, 'WARNING': {'fg': 'yellow', 'opts': ('bold',)}, 'NOTICE': {'fg': 'red'}, 'SQL_FIELD': {'fg': 'green', 'opts': ('bold',)}, 'SQL_COLTYPE': {'fg': 'green'}, 'SQL_KEYWORD': {'fg': 'yellow'}, 'SQL_TABLE': {'opts': ('bold',)}, 'HTTP_INFO': {'opts': ('bold',)}, 'HTTP_SUCCESS': {}, 'HTTP_REDIRECT': {'fg': 'green'}, 'HTTP_NOT_MODIFIED': {'fg': 'cyan'}, 'HTTP_BAD_REQUEST': {'fg': 'red', 'opts': ('bold',)}, 'HTTP_NOT_FOUND': {'fg': 'yellow'}, 'HTTP_SERVER_ERROR': {'fg': 'magenta', 'opts': ('bold',)}, 'MIGRATE_HEADING': {'fg': 'cyan', 'opts': ('bold',)}, 'MIGRATE_LABEL': {'opts': ('bold',)}, }, LIGHT_PALETTE: { 'ERROR': {'fg': 'red', 'opts': ('bold',)}, 'SUCCESS': {'fg': 'green', 'opts': ('bold',)}, 'WARNING': {'fg': 'yellow', 'opts': ('bold',)}, 'NOTICE': {'fg': 'red'}, 'SQL_FIELD': {'fg': 'green', 'opts': ('bold',)}, 'SQL_COLTYPE': {'fg': 'green'}, 'SQL_KEYWORD': {'fg': 'blue'}, 'SQL_TABLE': {'opts': ('bold',)}, 'HTTP_INFO': {'opts': ('bold',)}, 'HTTP_SUCCESS': {}, 'HTTP_REDIRECT': {'fg': 'green', 'opts': ('bold',)}, 'HTTP_NOT_MODIFIED': {'fg': 'green'}, 'HTTP_BAD_REQUEST': {'fg': 'red', 'opts': ('bold',)}, 'HTTP_NOT_FOUND': {'fg': 'red'}, 'HTTP_SERVER_ERROR': {'fg': 'magenta', 'opts': ('bold',)}, 'MIGRATE_HEADING': {'fg': 'cyan', 'opts': ('bold',)}, 'MIGRATE_LABEL': {'opts': ('bold',)}, } } DEFAULT_PALETTE = DARK_PALETTE def parse_color_setting(config_string): """Parse a DJANGO_COLORS environment variable to produce the system palette The general form of a palette definition is: "palette;role=fg;role=fg/bg;role=fg,option,option;role=fg/bg,option,option" where: palette is a named palette; one of 'light', 'dark', or 'nocolor'. role is a named style used by Django fg is a foreground color. bg is a background color. option is a display options. Specifying a named palette is the same as manually specifying the individual definitions for each role. Any individual definitions following the palette definition will augment the base palette definition. Valid roles: 'error', 'success', 'warning', 'notice', 'sql_field', 'sql_coltype', 'sql_keyword', 'sql_table', 'http_info', 'http_success', 'http_redirect', 'http_not_modified', 'http_bad_request', 'http_not_found', 'http_server_error', 'migrate_heading', 'migrate_label' Valid colors: 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' Valid options: 'bold', 'underscore', 'blink', 'reverse', 'conceal', 'noreset' """ if not config_string: return PALETTES[DEFAULT_PALETTE] # Split the color configuration into parts parts = config_string.lower().split(';') palette = PALETTES[NOCOLOR_PALETTE].copy() for part in parts: if part in PALETTES: # A default palette has been specified palette.update(PALETTES[part]) elif '=' in part: # Process a palette defining string definition = {} # Break the definition into the role, # plus the list of specific instructions. # The role must be in upper case role, instructions = part.split('=') role = role.upper() styles = instructions.split(',') styles.reverse() # The first instruction can contain a slash # to break apart fg/bg. colors = styles.pop().split('/') colors.reverse() fg = colors.pop() if fg in color_names: definition['fg'] = fg if colors and colors[-1] in color_names: definition['bg'] = colors[-1] # All remaining instructions are options opts = tuple(s for s in styles if s in opt_dict) if opts: definition['opts'] = opts # The nocolor palette has all available roles. # Use that palette as the basis for determining # if the role is valid. if role in PALETTES[NOCOLOR_PALETTE] and definition: palette[role] = definition # If there are no colors specified, return the empty palette. if palette == PALETTES[NOCOLOR_PALETTE]: return None return palette