Source code for ftrack_api.formatter

# :coding: utf-8
# :copyright: Copyright (c) 2014 ftrack
import os
import sys

from builtins import str

import ftrack_api.entity.base
import ftrack_api.collection
import ftrack_api.symbol
import ftrack_api.inspection

#: Useful filters to pass to :func:`format`.`
    'ignore_unset': (
        lambda entity, name, value: value is not ftrack_api.symbol.NOT_SET

def _can_do_colors():
    '''check if we are ( likely ) to be able to handle colors.'''
    if "ANSI_COLORS_DISABLED" in os.environ:
        return False
    if "NO_COLOR" in os.environ:
        return False
    if "FORCE_COLOR" in os.environ:
        return True
    return (
        hasattr(sys.stdout, "isatty")
        and sys.stdout.isatty()
        and os.environ.get("TERM") != "dumb"

[docs]def format( entity, formatters=None, attribute_filter=None, recursive=False, indent=0, indent_first_line=True, _seen=None ): '''Return formatted string representing *entity*. *formatters* can be used to customise formatting of elements. It should be a mapping with one or more of the following keys: * header - Used to format entity type. * label - Used to format attribute names. Specify an *attribute_filter* to control which attributes to include. By default all attributes are included. The *attribute_filter* should be a callable that accepts `(entity, attribute_name, attribute_value)` and returns True if the attribute should be included in the output. For example, to filter out all unset values:: attribute_filter=ftrack_api.formatter.FILTER['ignore_unset'] If *recursive* is True then recurse into Collections and format each entity present. *indent* specifies the overall indentation in spaces of the formatted text, whilst *indent_first_line* determines whether to apply that indent to the first generated line. .. warning:: Iterates over all *entity* attributes which may cause multiple queries to the server. Turn off auto populating in the session to prevent this. ''' # Initialise default formatters. if formatters is None: formatters = dict() formatters.setdefault( 'header', lambda text: '\x1b[1m\x1b[44m\x1b[97m{}\x1b[0m\033[0m'.format(text) if _can_do_colors() else text ) formatters.setdefault( 'label', lambda text: '\x1b[1m\x1b[34m{}\x1b[0m\033[0m'.format(text) if _can_do_colors() else text ) # Determine indents. spacer = ' ' * indent if indent_first_line: first_line_spacer = spacer else: first_line_spacer = '' # Avoid infinite recursion on circular references. if _seen is None: _seen = set() identifier = str(ftrack_api.inspection.identity(entity)) if identifier in _seen: return ( first_line_spacer + formatters['header'](entity.entity_type) + '{...}' ) _seen.add(identifier) information = list() information.append( first_line_spacer + formatters['header'](entity.entity_type) ) for key, value in sorted(entity.items()): if attribute_filter is not None: if not attribute_filter(entity, key, value): continue child_indent = indent + len(key) + 3 if isinstance(value, ftrack_api.entity.base.Entity): value = format( value, formatters=formatters, attribute_filter=attribute_filter, recursive=recursive, indent=child_indent, indent_first_line=False, _seen=_seen.copy() ) if isinstance(value, ftrack_api.collection.Collection): if recursive: child_values = [] for index, child in enumerate(value): child_value = format( child, formatters=formatters, attribute_filter=attribute_filter, recursive=recursive, indent=child_indent, indent_first_line=index != 0, _seen=_seen.copy() ) child_values.append(child_value) value = '\n'.join(child_values) information.append( spacer + u' {0}: {1}'.format(formatters['label'](key), value) ) return '\n'.join(information)