def format(cls, entry, *args, **kwargs): attrs = kwargs.get('attributes', []) attribute_transform_functions = kwargs.get( 'attribute_transform_functions', {}) key = kwargs.get('key', None) if key: output = jsutil.get_value(entry.result, key) else: # drop entry to the dict so that jsutil can operate entry = vars(entry) output = '' for attr in attrs: value = jsutil.get_value(entry, attr) value = strutil.strip_carriage_returns(strutil.unescape(value)) if (isinstance(value, six.string_types) and len(value) > 0 and value[0] in ['{', '['] and value[len(value) - 1] in ['}', ']']): new_value = ast.literal_eval(value) if type(new_value) in [dict, list]: value = new_value if type(value) in [dict, list]: # 1. To get a nice overhang indent get safe_dump to generate output with # the attribute key and then remove the attribute key from the string. # 2. Drop the trailing newline # 3. Set width to maxint so pyyaml does not split text. Anything longer # and likely we will see other issues like storage :P. formatted_value = yaml.safe_dump({attr: value}, default_flow_style=False, width=PLATFORM_MAXINT, indent=2)[len(attr) + 2:-1] value = ('\n' if isinstance(value, dict) else '') + formatted_value value = strutil.dedupe_newlines(value) # transform the value of our attribute so things like 'status' # and 'timestamp' are formatted nicely transform_function = attribute_transform_functions.get( attr, lambda value: value) value = transform_function(value=value) output += ('\n' if output else '') + '%s: %s' % \ (DisplayColors.colorize(attr, DisplayColors.BLUE), value) if six.PY3: return strutil.unescape(str(output)) else: # Assume Python 2 return strutil.unescape( str(output)).decode('unicode_escape').encode('utf-8')
def format(cls, subject, *args, **kwargs): attributes = kwargs.get('attributes', None) attribute_display_order = kwargs.get('attribute_display_order', DEFAULT_ATTRIBUTE_DISPLAY_ORDER) attribute_transform_functions = kwargs.get('attribute_transform_functions', {}) if not attributes or 'all' in attributes: attributes = sorted([attr for attr in subject.__dict__ if not attr.startswith('_')]) for attr in attribute_display_order[::-1]: if attr in attributes: attributes.remove(attr) attributes = [attr] + attributes table = PrettyTable() table.field_names = ['Property', 'Value'] table.max_width['Property'] = 20 table.max_width['Value'] = 60 table.padding_width = 1 table.align = 'l' table.valign = 't' for attribute in attributes: value = cls._get_attribute_value(subject, attribute) if type(value) is dict or type(value) is list: value = json.dumps(value, indent=4) value = strutil.unescape(value) transfor_function = attribute_transform_functions.get(attribute, lambda value: value) value = transfor_function(value=value) table.add_row([attribute, value]) return table
def format(cls, entry, *args, **kwargs): attrs = kwargs.get('attributes', []) key = kwargs.get('key', None) if key: output = jsutil.get_value(entry.result, key) else: # drop entry to the dict so that jsutil can operate entry = vars(entry) output = '' for attr in attrs: value = jsutil.get_value(entry, attr) if (isinstance(value, basestring) and len(value) > 0 and value[0] in ['{', '['] and value[len(value) - 1] in ['}', ']']): new_value = ast.literal_eval(value) if type(new_value) in [dict, list]: value = new_value if type(value) in [dict, list]: # 1. To get a nice overhang indent get safe_dump to generate output with # the attribute key and then remove the attribute key from the string. # 2. Drop the trailing newline # 3. Set width to maxint so pyyaml does not split text. Anything longer # and likely we will see other issues like storage :P. formatted_value = yaml.safe_dump({attr: value}, default_flow_style=False, width=sys.maxint, indent=2)[len(attr) + 2:-1] value = ('\n' if isinstance(value, dict) else '') + formatted_value output += ('\n' if output else '') + '%s: %s' % \ (DisplayColors.colorize(attr, DisplayColors.BLUE), value) return strutil.unescape(output)
def format(cls, entry, *args, **kwargs): attrs = kwargs.get('attributes', []) attribute_transform_functions = kwargs.get('attribute_transform_functions', {}) key = kwargs.get('key', None) if key: output = jsutil.get_value(entry.result, key) else: # drop entry to the dict so that jsutil can operate entry = vars(entry) output = '' for attr in attrs: value = jsutil.get_value(entry, attr) value = strutil.strip_carriage_returns(strutil.unescape(value)) if (isinstance(value, six.string_types) and len(value) > 0 and value[0] in ['{', '['] and value[len(value) - 1] in ['}', ']']): new_value = ast.literal_eval(value) if type(new_value) in [dict, list]: value = new_value if type(value) in [dict, list]: # 1. To get a nice overhang indent get safe_dump to generate output with # the attribute key and then remove the attribute key from the string. # 2. Drop the trailing newline # 3. Set width to maxint so pyyaml does not split text. Anything longer # and likely we will see other issues like storage :P. formatted_value = yaml.safe_dump({attr: value}, default_flow_style=False, width=PLATFORM_MAXINT, indent=2)[len(attr) + 2:-1] value = ('\n' if isinstance(value, dict) else '') + formatted_value value = strutil.dedupe_newlines(value) # transform the value of our attribute so things like 'status' # and 'timestamp' are formatted nicely transform_function = attribute_transform_functions.get(attr, lambda value: value) value = transform_function(value=value) output += ('\n' if output else '') + '%s: %s' % \ (DisplayColors.colorize(attr, DisplayColors.BLUE), value) if six.PY3: return strutil.unescape(str(output)) else: # Assume Python 2 return strutil.unescape(str(output)).decode('unicode_escape').encode('utf-8')
def format(cls, subject, *args, **kwargs): attributes = kwargs.get("attributes", None) attribute_display_order = kwargs.get( "attribute_display_order", DEFAULT_ATTRIBUTE_DISPLAY_ORDER ) attribute_transform_functions = kwargs.get("attribute_transform_functions", {}) if not attributes or "all" in attributes: attributes = sorted( [attr for attr in subject.__dict__ if not attr.startswith("_")] ) for attr in attribute_display_order[::-1]: if attr in attributes: attributes.remove(attr) attributes = [attr] + attributes table = PrettyTable() table.field_names = ["Property", "Value"] table.max_width["Property"] = 20 table.max_width["Value"] = 60 table.padding_width = 1 table.align = "l" table.valign = "t" for attribute in attributes: if "." in attribute: field_names = attribute.split(".") value = cls._get_attribute_value(subject, field_names.pop(0)) for name in field_names: value = cls._get_attribute_value(value, name) if type(value) is str: break else: value = cls._get_attribute_value(subject, attribute) transform_function = attribute_transform_functions.get( attribute, lambda value: value ) value = transform_function(value=value) if type(value) is dict or type(value) is list: value = json.dumps(value, indent=4) value = strutil.strip_carriage_returns(strutil.unescape(value)) table.add_row([attribute, value]) return table
def format(cls, subject, *args, **kwargs): attributes = kwargs.get('attributes', None) attribute_display_order = kwargs.get('attribute_display_order', DEFAULT_ATTRIBUTE_DISPLAY_ORDER) attribute_transform_functions = kwargs.get('attribute_transform_functions', {}) if not attributes or 'all' in attributes: attributes = sorted([attr for attr in subject.__dict__ if not attr.startswith('_')]) for attr in attribute_display_order[::-1]: if attr in attributes: attributes.remove(attr) attributes = [attr] + attributes table = PrettyTable() table.field_names = ['Property', 'Value'] table.max_width['Property'] = 20 table.max_width['Value'] = 60 table.padding_width = 1 table.align = 'l' table.valign = 't' for attribute in attributes: if '.' in attribute: field_names = attribute.split('.') value = cls._get_attribute_value(subject, field_names.pop(0)) for name in field_names: value = cls._get_attribute_value(value, name) if type(value) is str: break else: value = cls._get_attribute_value(subject, attribute) transform_function = attribute_transform_functions.get(attribute, lambda value: value) value = transform_function(value=value) if type(value) is dict or type(value) is list: value = json.dumps(value, indent=4) value = strutil.unescape(value) table.add_row([attribute, value]) return table
def format(cls, entry, *args, **kwargs): attrs = kwargs.get('attributes', []) key = kwargs.get('key', None) if key: output = jsutil.get_value(entry.result, key) else: output = '' for attr in attrs: value = getattr(entry, attr, None) if (isinstance(value, basestring) and len(value) > 0 and value[0] in ['{', '['] and value[len(value) - 1] in ['}', ']']): new_value = ast.literal_eval(value) if type(new_value) in [dict, list]: value = new_value if type(value) in [dict, list]: value = ('\n' if isinstance(value, dict) else '') + json.dumps(value, indent=4) output += ('\n' if output else '') + '%s: %s' % (attr.upper(), value) return strutil.unescape(output)
def format(cls, entry, *args, **kwargs): attrs = kwargs.get('attributes', []) key = kwargs.get('key', None) if key: output = jsutil.get_value(entry.result, key) else: # drop entry to the dict so that jsutil can operate entry = vars(entry) output = '' for attr in attrs: value = jsutil.get_value(entry, attr) if (isinstance(value, basestring) and len(value) > 0 and value[0] in ['{', '['] and value[len(value) - 1] in ['}', ']']): new_value = ast.literal_eval(value) if type(new_value) in [dict, list]: value = new_value if type(value) in [dict, list]: value = ('\n' if isinstance(value, dict) else '') + json.dumps(value, indent=4) output += ('\n' if output else '') + '%s: %s' % \ (DisplayColors.colorize(attr, DisplayColors.BLUE), value) return strutil.unescape(output)
def test_unicode_string(self): in_str = '\u8c03\u7528CMS\u63a5\u53e3\u5220\u9664\u865a\u62df\u76ee\u5f55' out_str = strutil.unescape(in_str) self.assertEqual(out_str, in_str)
def test_unescape(self): in_str = 'Action execution result double escape \\"stuffs\\".\\r\\n' expected = 'Action execution result double escape \"stuffs\".\r\n' out_str = strutil.unescape(in_str) self.assertEqual(out_str, expected)
def format(cls, entry, *args, **kwargs): attrs = kwargs.get('attributes', []) attribute_transform_functions = kwargs.get('attribute_transform_functions', {}) key = kwargs.get('key', None) if key: output = jsutil.get_value(entry.result, key) else: # drop entry to the dict so that jsutil can operate entry = vars(entry) output = '' for attr in attrs: value = jsutil.get_value(entry, attr) value = strutil.strip_carriage_returns(strutil.unescape(value)) # TODO: This check is inherently flawed since it will crash st2client # if the leading character is objectish start and last character is objectish # end but the string isn't supposed to be a object. Try/Except will catch # this for now, but this should be improved. if (isinstance(value, six.string_types) and len(value) > 0 and value[0] in ['{', '['] and value[len(value) - 1] in ['}', ']']): try: new_value = ast.literal_eval(value) except: new_value = value if type(new_value) in [dict, list]: value = new_value if type(value) in [dict, list]: # 1. To get a nice overhang indent get safe_dump to generate output with # the attribute key and then remove the attribute key from the string. # 2. Drop the trailing newline # 3. Set width to maxint so pyyaml does not split text. Anything longer # and likely we will see other issues like storage :P. formatted_value = yaml.safe_dump({attr: value}, default_flow_style=False, width=PLATFORM_MAXINT, indent=2)[len(attr) + 2:-1] value = ('\n' if isinstance(value, dict) else '') + formatted_value value = strutil.dedupe_newlines(value) # transform the value of our attribute so things like 'status' # and 'timestamp' are formatted nicely transform_function = attribute_transform_functions.get(attr, lambda value: value) value = transform_function(value=value) output += ('\n' if output else '') + '%s: %s' % \ (DisplayColors.colorize(attr, DisplayColors.BLUE), value) output_schema = entry.get('action', {}).get('output_schema') schema_check = get_config()['general']['silence_schema_output'] if not output_schema and kwargs.get('with_schema'): rendered_schema = { 'output_schema': schema.render_output_schema_from_output(entry['result']) } rendered_schema = yaml.safe_dump(rendered_schema, default_flow_style=False) output += '\n' output += _print_bordered( "Based on the action output the following inferred schema was built:" "\n\n" "%s" % rendered_schema ) elif not output_schema and not schema_check: output += ( "\n\n** This action does not have an output_schema. " "Run again with --with-schema to see a suggested schema." ) if six.PY3: return strutil.unescape(str(output)) else: # Assume Python 2 try: result = strutil.unescape(str(output)).decode('unicode_escape').encode('utf-8') except UnicodeDecodeError: # String contains a value which is not an unicode escape sequence, ignore the error result = strutil.unescape(str(output)) return result
def format(cls, entries, *args, **kwargs): attributes = kwargs.get('attributes', []) attribute_transform_functions = kwargs.get( 'attribute_transform_functions', {}) widths = kwargs.get('widths', []) widths = widths or [] if not widths and attributes: # Dynamically calculate column size based on the terminal size lines, cols = get_terminal_size() if attributes[0] == 'id': # consume iterator and save as entries so collection is accessible later. entries = [e for e in entries] # first column contains id, make sure it's not broken up first_col_width = cls._get_required_column_width( values=[e.id for e in entries], minimum_width=MIN_ID_COL_WIDTH) cols = (cols - first_col_width) col_width = int(math.floor((cols / len(attributes)))) else: col_width = int(math.floor((cols / len(attributes)))) first_col_width = col_width widths = [] subtract = 0 for index in range(0, len(attributes)): attribute_name = attributes[index] if index == 0: widths.append(first_col_width) continue if attribute_name in COLORIZED_ATTRIBUTES: current_col_width = COLORIZED_ATTRIBUTES[attribute_name][ 'col_width'] subtract += (current_col_width - col_width) else: # Make sure we subtract the added width from the last column so we account # for the fixed width columns and make sure table is not wider than the # terminal width. if index == (len(attributes) - 1) and subtract: current_col_width = (col_width - subtract) if current_col_width <= MIN_COL_WIDTH: # Make sure column width is always grater than MIN_COL_WIDTH current_col_width = MIN_COL_WIDTH else: current_col_width = col_width widths.append(current_col_width) if not attributes or 'all' in attributes: entries = list(entries) if entries else [] if len(entries) >= 1: attributes = entries[0].__dict__.keys() attributes = sorted( [attr for attr in attributes if not attr.startswith('_')]) else: # There are no entries so we can't infer available attributes attributes = [] # Determine table format. if len(attributes) == len(widths): # Customize width for each column. columns = zip(attributes, widths) else: # If only 1 width value is provided then # apply it to all columns else fix at 28. width = widths[0] if len(widths) == 1 else 28 columns = zip(attributes, [width for i in range(0, len(attributes))]) # Format result to table. table = PrettyTable() for column in columns: table.field_names.append(column[0]) table.max_width[column[0]] = column[1] table.padding_width = 1 table.align = 'l' table.valign = 't' for entry in entries: # TODO: Improve getting values of nested dict. values = [] for field_name in table.field_names: if '.' in field_name: field_names = field_name.split('.') value = getattr(entry, field_names.pop(0), {}) for name in field_names: value = cls._get_field_value(value, name) if type(value) is str: break value = strutil.strip_carriage_returns( strutil.unescape(value)) values.append(value) else: value = cls._get_simple_field_value(entry, field_name) transform_function = attribute_transform_functions.get( field_name, lambda value: value) value = transform_function(value=value) value = strutil.strip_carriage_returns( strutil.unescape(value)) values.append(value) table.add_row(values) # width for the note global table_width try: table_width = len(table.get_string().split("\n")[0]) except IndexError: table_width = 0 return table
def format(cls, entry, *args, **kwargs): attrs = kwargs.get('attributes', []) attribute_transform_functions = kwargs.get( 'attribute_transform_functions', {}) key = kwargs.get('key', None) if key: output = jsutil.get_value(entry.result, key) else: # drop entry to the dict so that jsutil can operate entry = vars(entry) output = '' for attr in attrs: value = jsutil.get_value(entry, attr) value = strutil.strip_carriage_returns(strutil.unescape(value)) # TODO: This check is inherently flawed since it will crash st2client # if the leading character is objectish start and last character is objectish # end but the string isn't supposed to be a object. Try/Except will catch # this for now, but this should be improved. if (isinstance(value, six.string_types) and len(value) > 0 and value[0] in ['{', '['] and value[len(value) - 1] in ['}', ']']): try: new_value = ast.literal_eval(value) except: new_value = value if type(new_value) in [dict, list]: value = new_value if type(value) in [dict, list]: # 1. To get a nice overhang indent get safe_dump to generate output with # the attribute key and then remove the attribute key from the string. # 2. Drop the trailing newline # 3. Set width to maxint so pyyaml does not split text. Anything longer # and likely we will see other issues like storage :P. formatted_value = yaml.safe_dump({attr: value}, default_flow_style=False, width=PLATFORM_MAXINT, indent=2)[len(attr) + 2:-1] value = ('\n' if isinstance(value, dict) else '') + formatted_value value = strutil.dedupe_newlines(value) # transform the value of our attribute so things like 'status' # and 'timestamp' are formatted nicely transform_function = attribute_transform_functions.get( attr, lambda value: value) value = transform_function(value=value) output += ('\n' if output else '') + '%s: %s' % \ (DisplayColors.colorize(attr, DisplayColors.BLUE), value) output_schema = entry.get('action', {}).get('output_schema') schema_check = get_config()['general']['silence_schema_output'] if not output_schema and kwargs.get('with_schema'): rendered_schema = { 'output_schema': schema.render_output_schema_from_output(entry['result']) } rendered_schema = yaml.safe_dump(rendered_schema, default_flow_style=False) output += '\n' output += _print_bordered( "Based on the action output the following inferred schema was built:" "\n\n" "%s" % rendered_schema) elif not output_schema and not schema_check: output += ( "\n\n** This action does not have an output_schema. " "Run again with --with-schema to see a suggested schema.") if six.PY3: return strutil.unescape(str(output)) else: # Assume Python 2 try: result = strutil.unescape( str(output)).decode('unicode_escape').encode('utf-8') except UnicodeDecodeError: # String contains a value which is not an unicode escape sequence, ignore the error result = strutil.unescape(str(output)) return result
def format(cls, entries, *args, **kwargs): attributes = kwargs.get('attributes', []) attribute_transform_functions = kwargs.get('attribute_transform_functions', {}) widths = kwargs.get('widths', []) widths = widths or [] if not widths and attributes: # Dynamically calculate column size based on the terminal size lines, cols = get_terminal_size() if attributes[0] == 'id': # consume iterator and save as entries so collection is accessible later. entries = [e for e in entries] # first column contains id, make sure it's not broken up first_col_width = cls._get_required_column_width(values=[e.id for e in entries], minimum_width=MIN_ID_COL_WIDTH) cols = (cols - first_col_width) col_width = int(math.floor((cols / len(attributes)))) else: col_width = int(math.floor((cols / len(attributes)))) first_col_width = col_width widths = [] for index in range(0, len(attributes)): if index == 0: widths.append(first_col_width) else: widths.append(col_width) if not attributes or 'all' in attributes: attributes = sorted([attr for attr in entries[0].__dict__ if not attr.startswith('_')]) # Determine table format. if len(attributes) == len(widths): # Customize width for each column. columns = zip(attributes, widths) else: # If only 1 width value is provided then # apply it to all columns else fix at 28. width = widths[0] if len(widths) == 1 else 28 columns = zip(attributes, [width for i in range(0, len(attributes))]) # Format result to table. table = PrettyTable() for column in columns: table.field_names.append(column[0]) table.max_width[column[0]] = column[1] table.padding_width = 1 table.align = 'l' table.valign = 't' for entry in entries: # TODO: Improve getting values of nested dict. values = [] for field_name in table.field_names: if '.' in field_name: field_names = field_name.split('.') value = getattr(entry, field_names.pop(0), {}) for name in field_names: value = cls._get_field_value(value, name) if type(value) is str: break value = strutil.unescape(value) values.append(value) else: value = cls._get_simple_field_value(entry, field_name) transform_function = attribute_transform_functions.get(field_name, lambda value: value) value = transform_function(value=value) value = strutil.unescape(value) values.append(value) table.add_row(values) return table
def format(cls, entries, *args, **kwargs): attributes = kwargs.get('attributes', []) attribute_transform_functions = kwargs.get('attribute_transform_functions', {}) widths = kwargs.get('widths', []) widths = widths or [] if not widths and attributes: # Dynamically calculate column size based on the terminal size lines, cols = get_terminal_size() if attributes[0] == 'id': # consume iterator and save as entries so collection is accessible later. entries = [e for e in entries] # first column contains id, make sure it's not broken up first_col_width = cls._get_required_column_width(values=[e.id for e in entries], minimum_width=MIN_ID_COL_WIDTH) cols = (cols - first_col_width) col_width = int(math.floor((cols / len(attributes)))) else: col_width = int(math.floor((cols / len(attributes)))) first_col_width = col_width widths = [] subtract = 0 for index in range(0, len(attributes)): attribute_name = attributes[index] if index == 0: widths.append(first_col_width) continue if attribute_name in COLORIZED_ATTRIBUTES: current_col_width = COLORIZED_ATTRIBUTES[attribute_name]['col_width'] subtract += (current_col_width - col_width) else: # Make sure we subtract the added width from the last column so we account # for the fixed width columns and make sure table is not wider than the # terminal width. if index == (len(attributes) - 1) and subtract: current_col_width = (col_width - subtract) if current_col_width <= MIN_COL_WIDTH: # Make sure column width is always grater than MIN_COL_WIDTH current_col_width = MIN_COL_WIDTH else: current_col_width = col_width widths.append(current_col_width) if not attributes or 'all' in attributes: entries = list(entries) if entries else [] if len(entries) >= 1: attributes = list(entries[0].__dict__.keys()) attributes = sorted([attr for attr in attributes if not attr.startswith('_')]) else: # There are no entries so we can't infer available attributes attributes = [] # Determine table format. if len(attributes) == len(widths): # Customize width for each column. columns = zip(attributes, widths) else: # If only 1 width value is provided then # apply it to all columns else fix at 28. width = widths[0] if len(widths) == 1 else 28 columns = zip(attributes, [width for i in range(0, len(attributes))]) # Format result to table. table = PrettyTable() for column in columns: table.field_names.append(column[0]) table.max_width[column[0]] = column[1] table.padding_width = 1 table.align = 'l' table.valign = 't' for entry in entries: # TODO: Improve getting values of nested dict. values = [] for field_name in table.field_names: if '.' in field_name: field_names = field_name.split('.') value = getattr(entry, field_names.pop(0), {}) for name in field_names: value = cls._get_field_value(value, name) if type(value) is str: break value = strutil.strip_carriage_returns(strutil.unescape(value)) values.append(value) else: value = cls._get_simple_field_value(entry, field_name) transform_function = attribute_transform_functions.get(field_name, lambda value: value) value = transform_function(value=value) value = strutil.strip_carriage_returns(strutil.unescape(value)) values.append(value) table.add_row(values) # width for the note try: cls.table_width = len(table.get_string().split("\n")[0]) except IndexError: cls.table_width = 0 return table
def format(cls, entry, *args, **kwargs): attrs = kwargs.get("attributes", []) attribute_transform_functions = kwargs.get( "attribute_transform_functions", {}) key = kwargs.get("key", None) if key: output = jsutil.get_value(entry.result, key) else: # drop entry to the dict so that jsutil can operate entry = vars(entry) output = "" for attr in attrs: value = jsutil.get_value(entry, attr) value = strutil.strip_carriage_returns(strutil.unescape(value)) # transform the value of our attribute so things like 'status' # and 'timestamp' are formatted nicely transform_function = attribute_transform_functions.get( attr, lambda value: value) value = transform_function(value=value) # TODO: This check is inherently flawed since it will crash st2client # if the leading character is objectish start and last character is objectish # end but the string isn't supposed to be a object. Try/Except will catch # this for now, but this should be improved. if (isinstance(value, six.string_types) and len(value) > 0 and value[0] in ["{", "["] and value[len(value) - 1] in ["}", "]"]): try: new_value = ast.literal_eval(value) except: new_value = value if type(new_value) in [dict, list]: value = new_value if isinstance(value, (dict, list)): # 1. To get a nice overhang indent get safe_dump to generate output with # the attribute key and then remove the attribute key from the string. # 2. Drop the trailing newline # 3. Set width to maxint so pyyaml does not split text. Anything longer # and likely we will see other issues like storage :P. # NOTE: We use C version of the safe dumper which is faster. # Keep in mind that using YamlSafeDumper is the same as using yaml.safe_dumps # (same class is used underneath when using yaml.safe_dump) so the code is safe. formatted_value = yaml.dump( {attr: value}, default_flow_style=False, width=PLATFORM_MAXINT, indent=2, Dumper=YamlSafeDumper, )[len(attr) + 2:-1] if isinstance(value, list): # Indent list values with 2 spaces for a nicer display. lines = formatted_value.split("\n") formatted_value = [] for line in lines: formatted_value.append(" %s" % (line)) formatted_value = "\n".join(formatted_value) value = ("\n" if isinstance(value, (dict, list)) else "") + formatted_value value = strutil.dedupe_newlines(value) # transform the value of our attribute so things like 'status' # and 'timestamp' are formatted nicely transform_function = attribute_transform_functions.get( attr, lambda value: value) value = transform_function(value=value) output += ("\n" if output else "") + "%s: %s" % ( DisplayColors.colorize(attr, DisplayColors.BLUE), value, ) output_schema = entry.get("action", {}).get("output_schema") schema_check = get_config()["general"]["silence_schema_output"] if not output_schema and kwargs.get("with_schema"): rendered_schema = { "output_schema": schema.render_output_schema_from_output(entry["result"]) } rendered_schema = yaml.safe_dump(rendered_schema, default_flow_style=False) output += "\n" output += _print_bordered( "Based on the action output the following inferred schema was built:" "\n\n" "%s" % rendered_schema) elif not output_schema and not schema_check: output += ( "\n\n** This action does not have an output_schema. " "Run again with --with-schema to see a suggested schema.") if six.PY3: return strutil.unescape(str(output)) else: # Assume Python 2 try: result = (strutil.unescape( str(output)).decode("unicode_escape").encode("utf-8")) except UnicodeDecodeError: # String contains a value which is not an unicode escape sequence, ignore the error result = strutil.unescape(str(output)) return result