# Source code for stestr.commands.failing

    # Licensed under the Apache License, Version 2.0 (the "License"); you may
    # not use this file except in compliance with the License. You may obtain
    # a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    # License for the specific language governing permissions and limitations
    # under the License.

    """Show the current failures in the repository."""

    import sys

    from cliff import command
    import testtools

    from stestr import output
    from stestr.repository import util
    from stestr import results
    from stestr import user_config

    class Failing(command.Command):
        """Show the current failures known by the repository.

        Without --subunit, the process exit code will be non-zero if the
        previous test run was not successful and test failures are shown. But,
        with --subunit, the process exit code is non-zero only if the subunit
        stream could not be generated successfully from any failures. The test
        results and run status are included in the subunit stream emitted for
        the failed tests, so the stream should be used for interpretting the
        failing tests. If no subunit stream is emitted with --subunit and a
        zero exit code then there were no failures in the most recent run in
        the repository.
        """

        def get_parser(self, prog_name):
            parser = super().get_parser(prog_name)
            parser.add_argument(
                "--subunit", action="store_true",
                default=False, help="Show output as a subunit stream.")
            parser.add_argument(
                "--list", action="store_true",
                default=False, help="Show only a list of failing tests.")
            return parser

        def take_action(self, parsed_args):
            user_conf = user_config.get_user_config(self.app_args.user_config)
            args = parsed_args
            if getattr(user_conf, 'failing', False):
                list_opt = args.list or user_conf.failing.get('list', False)
            else:
                list_opt = args.list
            return failing(repo_type=self.app_args.repo_type,
                           repo_url=self.app_args.repo_url,
                           list_tests=list_opt, subunit=args.subunit)

    def _show_subunit(run):
        stream = run.get_subunit_stream()
        if getattr(sys.stdout, 'buffer', False):
            sys.stdout.buffer.write(stream.read())
        else:
            sys.stdout.write(stream.read())
        return 0

    def _make_result(repo, list_tests=False, stdout=sys.stdout):
        if list_tests:
            list_result = testtools.StreamSummary()
            return list_result, list_result
        else:
            def _get_id():
                return repo.get_latest_run().get_id()

            output_result = results.CLITestResult(_get_id,
                                                  stdout, None)
            summary_result = output_result.get_summary()
            return output_result, summary_result

    def failing(repo_type='file', repo_url=None, list_tests=False, subunit=False,
                stdout=sys.stdout):
        """Print the failing tests from the most recent run in the repository

        This function will print to STDOUT whether there are any tests that failed
        in the last run. It optionally will print the test_ids for the failing
        tests if ``list_tests`` is true. If ``subunit`` is true a subunit stream
        with just the failed tests will be printed to STDOUT.

        Note this function depends on the cwd for the repository if `repo_type` is
        set to file and `repo_url` is not specified it will use the repository
        located at CWD/.stestr

        :param str repo_type: This is the type of repository to use. Valid choices
            are 'file' and 'sql'.
        :param str repo_url: The url of the repository to use.
        :param bool list_test: Show only a list of failing tests.
        :param bool subunit: Show output as a subunit stream.
        :param file stdout: The output file to write all output to. By default
            this is sys.stdout

        :return return_code: The exit code for the command. 0 for success and > 0
            for failures.
        :rtype: int
        """
        if repo_type not in ['file', 'sql']:
            stdout.write('Repository type %s is not a type' % repo_type)
            return 1

        repo = util.get_repo_open(repo_type, repo_url)
        run = repo.get_failing()
        if subunit:
            return _show_subunit(run)
        case = run.get_test()
        failed = False
        result, summary = _make_result(repo, list_tests=list_tests)
        result.startTestRun()
        try:
            case.run(result)
        finally:
            result.stopTestRun()
        failed = not results.wasSuccessful(summary)
        if failed:
            result = 1
        else:
            result = 0
        if list_tests:
            failing_tests = [
                test for test, _ in summary.errors + summary.failures]
            output.output_tests(failing_tests, output=stdout)
        return result