コード例 #1
0
 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)
コード例 #2
0
 def test_dot_notation(self):
     self.assertEqual(jsutil.get_value(DOC, 'a01'), 1)
     self.assertEqual(jsutil.get_value(DOC, 'c01.c11'), 3)
     self.assertEqual(jsutil.get_value(DOC, 'c01.c13.c22'), 6)
     self.assertEqual(jsutil.get_value(DOC, 'c01.c13'), {
         'c21': 5,
         'c22': 6
     })
     self.assertListEqual(jsutil.get_value(DOC, 'c01.c14'), [7, 8, 9])
コード例 #3
0
ファイル: test_util_json.py プロジェクト: st2sandbox/st2
 def test_dot_notation(self):
     self.assertEqual(jsutil.get_value(DOC, "a01"), 1)
     self.assertEqual(jsutil.get_value(DOC, "c01.c11"), 3)
     self.assertEqual(jsutil.get_value(DOC, "c01.c13.c22"), 6)
     self.assertEqual(jsutil.get_value(DOC, "c01.c13"), {
         "c21": 5,
         "c22": 6
     })
     self.assertListEqual(jsutil.get_value(DOC, "c01.c14"), [7, 8, 9])
コード例 #4
0
    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')
コード例 #5
0
ファイル: execution.py プロジェクト: lyandut/st2
    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')
コード例 #6
0
 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)
コード例 #7
0
ファイル: action.py プロジェクト: tomzhang/st2
 def _format_for_common_representation(self, task):
     '''
     Formats a task for common representation between mistral and action-chain.
     '''
     # This really needs to be better handled on the back-end but that would be a bigger
     # change so handling in cli.
     context = getattr(task, 'context', None)
     if context and 'chain' in context:
         task_name_key = 'context.chain.name'
     elif context and 'mistral' in context:
         task_name_key = 'context.mistral.task_name'
     # Use LiveAction as the object so that the formatter lookup does not change.
     # AKA HACK!
     return models.action.LiveAction(**{
         'id': task.id,
         'status': task.status,
         'task': jsutil.get_value(vars(task), task_name_key),
         'action': task.action.get('ref', None),
         'start_timestamp': task.start_timestamp
     })
コード例 #8
0
 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)
コード例 #9
0
 def test_ip_address_calls_complex(self, mock__get_value_complex):
     jsutil.get_value(DOC_IP_ADDRESS, 'ips."192.168.1.1"')
     mock__get_value_complex.assert_called_with(DOC_IP_ADDRESS,
                                                'ips."192.168.1.1"')
コード例 #10
0
ファイル: test_util_json.py プロジェクト: AlexeyDeyneko/st2
 def test_dot_notation_with_key_error(self):
     self.assertIsNone(jsutil.get_value(DOC, 'd01'))
     self.assertIsNone(jsutil.get_value(DOC, 'a01.a11'))
     self.assertIsNone(jsutil.get_value(DOC, 'c01.c11.c21.c31'))
     self.assertIsNone(jsutil.get_value(DOC, 'c01.c14.c31'))
コード例 #11
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_ip_address(self):
     self.assertEqual(jsutil.get_value(DOC_IP_ADDRESS, 'ips."192.168.1.1"'),
                      {"hostname": "router.domain.tld"})
コード例 #12
0
 def test_single_key_calls_simple(self, mock__get_value_simple):
     jsutil.get_value(DOC, 'a01')
     mock__get_value_simple.assert_called_with(DOC, 'a01')
コード例 #13
0
 def test_chars_nums_dashes_underscores_calls_simple(self):
     for char in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_':
         with mock.patch(
                 "st2client.utils.jsutil._get_value_simple") as mock_simple:
             jsutil.get_value(DOC, char)
             mock_simple.assert_called_with(DOC, char)
コード例 #14
0
 def test_double_dot_calls_complex(self, mock__get_value_complex):
     jsutil.get_value(DOC, 'c01..c11')
     mock__get_value_complex.assert_called_with(DOC, 'c01..c11')
コード例 #15
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_ip_address_calls_complex(self, mock__get_value_complex):
     jsutil.get_value(DOC_IP_ADDRESS, 'ips."192.168.1.1"')
     mock__get_value_complex.assert_called_with(DOC_IP_ADDRESS, 'ips."192.168.1.1"')
コード例 #16
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_dot_notation_calls_simple(self, mock__get_value_simple):
     jsutil.get_value(DOC, 'c01.c11')
     mock__get_value_simple.assert_called_with(DOC, 'c01.c11')
コード例 #17
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_single_key_calls_simple(self, mock__get_value_simple):
     jsutil.get_value(DOC, 'a01')
     mock__get_value_simple.assert_called_with(DOC, 'a01')
コード例 #18
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_symbols_calls_complex(self):
     for char in '`~!@#$%^&&*()=+{}[]|\\;:\'"<>,./?':
         with mock.patch("st2client.utils.jsutil._get_value_complex") as mock_complex:
             jsutil.get_value(DOC, char)
             mock_complex.assert_called_with(DOC, char)
コード例 #19
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_chars_nums_dashes_underscores_calls_simple(self):
     for char in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_':
         with mock.patch("st2client.utils.jsutil._get_value_simple") as mock_simple:
             jsutil.get_value(DOC, char)
             mock_simple.assert_called_with(DOC, char)
コード例 #20
0
 def test_beginning_dot_calls_complex(self, mock__get_value_complex):
     jsutil.get_value(DOC, '.c01.c11')
     mock__get_value_complex.assert_called_with(DOC, '.c01.c11')
コード例 #21
0
 def test_ending_dot_calls_complex(self, mock__get_value_complex):
     jsutil.get_value(DOC, 'c01.c11.')
     mock__get_value_complex.assert_called_with(DOC, 'c01.c11.')
コード例 #22
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_ending_dot_calls_complex(self, mock__get_value_complex):
     jsutil.get_value(DOC, 'c01.c11.')
     mock__get_value_complex.assert_called_with(DOC, 'c01.c11.')
コード例 #23
0
 def test_ip_address(self):
     self.assertEqual(jsutil.get_value(DOC_IP_ADDRESS, 'ips."192.168.1.1"'),
                      {"hostname": "router.domain.tld"})
コード例 #24
0
    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
コード例 #25
0
 def test_symbols_calls_complex(self):
     for char in '`~!@#$%^&&*()=+{}[]|\\;:\'"<>,./?':
         with mock.patch("st2client.utils.jsutil._get_value_complex"
                         ) as mock_complex:
             jsutil.get_value(DOC, char)
             mock_complex.assert_called_with(DOC, char)
コード例 #26
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_beginning_dot_calls_complex(self, mock__get_value_complex):
     jsutil.get_value(DOC, '.c01.c11')
     mock__get_value_complex.assert_called_with(DOC, '.c01.c11')
コード例 #27
0
 def test_dot_notation_calls_simple(self, mock__get_value_simple):
     jsutil.get_value(DOC, 'c01.c11')
     mock__get_value_simple.assert_called_with(DOC, 'c01.c11')
コード例 #28
0
ファイル: test_util_json.py プロジェクト: StackStorm/st2
 def test_double_dot_calls_complex(self, mock__get_value_complex):
     jsutil.get_value(DOC, 'c01..c11')
     mock__get_value_complex.assert_called_with(DOC, 'c01..c11')
コード例 #29
0
ファイル: execution.py プロジェクト: StackStorm/st2
    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
コード例 #30
0
ファイル: test_util_json.py プロジェクト: AlexeyDeyneko/st2
 def test_dot_notation(self):
     self.assertEqual(jsutil.get_value(DOC, 'a01'), 1)
     self.assertEqual(jsutil.get_value(DOC, 'c01.c11'), 3)
     self.assertEqual(jsutil.get_value(DOC, 'c01.c13.c22'), 6)
     self.assertEqual(jsutil.get_value(DOC, 'c01.c13'), {'c21': 5, 'c22': 6})
     self.assertListEqual(jsutil.get_value(DOC, 'c01.c14'), [7, 8, 9])
コード例 #31
0
 def test_dot_notation_with_key_error(self):
     self.assertIsNone(jsutil.get_value(DOC, 'd01'))
     self.assertIsNone(jsutil.get_value(DOC, 'a01.a11'))
     self.assertIsNone(jsutil.get_value(DOC, 'c01.c11.c21.c31'))
     self.assertIsNone(jsutil.get_value(DOC, 'c01.c14.c31'))
コード例 #32
0
    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