def get_console_output(self, build_id, subjob_id, atom_id, result_root, max_lines=50, offset_line=None):
        """
        Return the console output if it exists, raises an ItemNotFound error if not.

        On success, the response contains keys: offset_line, num_lines, total_num_lines, and content.

        e.g.:
        {
            'offset_line': 0,
            'num_lines': 50,
            'total_num_lines': 167,
            'content': 'Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit,\n...',
        }

        :type build_id: int
        :type subjob_id: int
        :type atom_id: int
        :param result_root: the sys path to either the results or artifacts directory where results are stored.
        :type result_root: str
        :param max_lines: The maximum total number of lines to return. If this max_lines + offset_line lines do not
            exist in the output file, just return what there is.
        :type max_lines: int
        :param offset_line: The line number (0-indexed) to start reading content for. If none is specified, we will
            return the console output starting from the end of the file.
        :type offset_line: int | None
        """
        if offset_line is not None and offset_line < 0:
            raise BadRequestError('\'offset_line\' must be greater than or equal to zero.')
        if max_lines <= 0:
            raise BadRequestError('\'max_lines\' must be greater than zero.')

        artifact_dir = BuildArtifact.atom_artifact_directory(build_id, subjob_id, atom_id, result_root=result_root)
        output_file = os.path.join(artifact_dir, BuildArtifact.OUTPUT_FILE)

        if not os.path.isfile(output_file):
            raise ItemNotFoundError('Output file doesn\'t exist for build_id: {} subjob_id: {} atom_id: {}'.format(
                build_id, subjob_id, atom_id))

        try:
            console_output = ConsoleOutput(output_file)
            segment = console_output.segment(max_lines, offset_line)
        except ValueError as e:
            raise BadRequestError(e)

        return {
            'offset_line': segment.offset_line,
            'num_lines': segment.num_lines,
            'total_num_lines': segment.total_num_lines,
            'content': segment.content,
        }
Esempio n. 2
0
 def test_segment_raises_value_error_if_offset_greater_than_total_length(
         self):
     complete_output_path = self.create_temp_plaintext_file(
         _COMPLETE_OUTPUT)
     console_output = ConsoleOutput.from_plaintext(complete_output_path)
     with self.assertRaises(BadRequestError):
         console_output.segment(max_lines=5, offset_line=155)
    def get_console_output(
        cls,
        build_id: int,
        subjob_id: int,
        atom_id: int,
        result_root: str,
        max_lines: int = 50,
        offset_line: Optional[int] = None,
    ) -> Optional[ConsoleOutputSegment]:
        """
        Return the console output if it exists in the specified result_root. Return None if it does not exist.
        :param build_id: build id
        :param subjob_id: subjob id
        :param atom_id: atom id
        :param result_root: the sys path to either the results or artifacts directory where results are stored.
        :param max_lines: The maximum total number of lines to return. If this max_lines + offset_line lines do not
            exist in the output file, just return what there is.
        :param offset_line: The line number (0-indexed) to start reading content for. If none is specified, we will
            return the console output starting from the end of the file.
        :return: The console output if it exists in the specified result_root, None if it does not exist
        """
        console_output = None

        artifact_dir = cls.atom_artifact_directory(build_id,
                                                   subjob_id,
                                                   atom_id,
                                                   result_root=result_root)
        output_file_path = os.path.join(artifact_dir, cls.OUTPUT_FILE)
        if os.path.isfile(output_file_path):
            # Read directly from output file if it exists (while build is in progress).
            console_output = ConsoleOutput.from_plaintext(output_file_path)
        else:
            # Read from build artifact archive if it exists (after build is finished).
            build_dir = cls.build_artifact_directory(build_id,
                                                     result_root=result_root)
            archive_file_path = os.path.join(build_dir,
                                             cls.ARTIFACT_ZIPFILE_NAME)
            if os.path.isfile(archive_file_path):
                path_in_archive = os.path.join(
                    os.path.relpath(artifact_dir, build_dir), cls.OUTPUT_FILE)
                console_output = ConsoleOutput.from_zipfile(
                    archive_file_path, path_in_archive)

        if console_output:
            return console_output.segment(max_lines, offset_line)
        return None
Esempio n. 4
0
    def test_console_output_segment_with_no_offset_from_zipfile_returns_expected(self):
        complete_output_path = self.create_temp_zip_file(_COMPLETE_OUTPUT, _PATH_IN_ARCHIVE)

        console_output = ConsoleOutput.from_zipfile(complete_output_path, _PATH_IN_ARCHIVE)
        segment = console_output.segment(max_lines=3)

        self.assertEquals(segment.num_lines, 3)
        self.assertEquals(segment.offset_line, 7)
        self.assertEquals(segment.total_num_lines, 10)
        self.assertEquals(segment.content, 'line_7\nline_8\nline_9\n')
Esempio n. 5
0
    def test_console_output_segment_with_offset_from_zipfile_returns_expected(
            self):
        complete_output_path = self.create_temp_zip_file(
            _COMPLETE_OUTPUT, _PATH_IN_ARCHIVE)

        console_output = ConsoleOutput.from_zipfile(complete_output_path,
                                                    _PATH_IN_ARCHIVE)
        segment = console_output.segment(max_lines=3, offset_line=2)

        self.assertEquals(segment.num_lines, 3)
        self.assertEquals(segment.offset_line, 2)
        self.assertEquals(segment.total_num_lines, 10)
        self.assertEquals(segment.content, 'line_2\nline_3\nline_4\n')
Esempio n. 6
0
    def get_console_output(
            cls,
            build_id: int,
            subjob_id: int,
            atom_id: int,
            result_root: str,
            max_lines: int=50,
            offset_line: Optional[int]=None,
    ) -> Optional[ConsoleOutputSegment]:
        """
        Return the console output if it exists in the specified result_root. Return None if it does not exist.
        :param build_id: build id
        :param subjob_id: subjob id
        :param atom_id: atom id
        :param result_root: the sys path to either the results or artifacts directory where results are stored.
        :param max_lines: The maximum total number of lines to return. If this max_lines + offset_line lines do not
            exist in the output file, just return what there is.
        :param offset_line: The line number (0-indexed) to start reading content for. If none is specified, we will
            return the console output starting from the end of the file.
        :return: The console output if it exists in the specified result_root, None if it does not exist
        """
        console_output = None

        artifact_dir = cls.atom_artifact_directory(build_id, subjob_id, atom_id, result_root=result_root)
        output_file_path = os.path.join(artifact_dir, cls.OUTPUT_FILE)
        if os.path.isfile(output_file_path):
            # Read directly from output file if it exists (while build is in progress).
            console_output = ConsoleOutput.from_plaintext(output_file_path)
        else:
            # Read from build artifact archive if it exists (after build is finished).
            build_dir = cls.build_artifact_directory(build_id, result_root=result_root)
            archive_file_path = os.path.join(build_dir, cls.ARTIFACT_ZIPFILE_NAME)
            if os.path.isfile(archive_file_path):
                path_in_archive = os.path.join(os.path.relpath(artifact_dir, build_dir), cls.OUTPUT_FILE)
                console_output = ConsoleOutput.from_zipfile(archive_file_path, path_in_archive)

        if console_output:
            return console_output.segment(max_lines, offset_line)
        return None
Esempio n. 7
0
    def test_segment_for_incomplete_console_output(
            self,
            input_max_lines,
            input_offset_line,
            expected_num_lines,
            expected_offset_line,
            expected_total_num_lines,
            expected_content
    ):
        """
        :type input_max_lines: int
        :type input_offset_line: int | None
        :type expected_num_lines: int
        :type expected_offset_line: int
        :type expected_total_num_lines: int
        :type expected_content: str
        """
        console_output = ConsoleOutput(self._incomplete_console_output_file_path)
        segment = console_output.segment(max_lines=input_max_lines, offset_line=input_offset_line)

        self.assertEquals(segment.num_lines, expected_num_lines)
        self.assertEquals(segment.offset_line, expected_offset_line)
        self.assertEquals(segment.total_num_lines, expected_total_num_lines)
        self.assertEquals(segment.content, expected_content)
Esempio n. 8
0
    def test_segment_for_incomplete_console_output(
            self,
            input_max_lines: int,
            input_offset_line: Optional[int],
            expected_num_lines: int,
            expected_offset_line: int,
            expected_total_num_lines: int,
            expected_content: str,
    ):
        incomplete_output_path = self.create_temp_plaintext_file(_INCOMPLETE_OUTPUT)

        console_output = ConsoleOutput.from_plaintext(incomplete_output_path)
        segment = console_output.segment(max_lines=input_max_lines, offset_line=input_offset_line)

        self.assertEquals(segment.num_lines, expected_num_lines)
        self.assertEquals(segment.offset_line, expected_offset_line)
        self.assertEquals(segment.total_num_lines, expected_total_num_lines)
        self.assertEquals(segment.content, expected_content)
Esempio n. 9
0
    def test_segment_for_incomplete_console_output(
        self,
        input_max_lines: int,
        input_offset_line: Optional[int],
        expected_num_lines: int,
        expected_offset_line: int,
        expected_total_num_lines: int,
        expected_content: str,
    ):
        incomplete_output_path = self.create_temp_plaintext_file(
            _INCOMPLETE_OUTPUT)

        console_output = ConsoleOutput.from_plaintext(incomplete_output_path)
        segment = console_output.segment(max_lines=input_max_lines,
                                         offset_line=input_offset_line)

        self.assertEquals(segment.num_lines, expected_num_lines)
        self.assertEquals(segment.offset_line, expected_offset_line)
        self.assertEquals(segment.total_num_lines, expected_total_num_lines)
        self.assertEquals(segment.content, expected_content)
Esempio n. 10
0
 def test_segment_raises_value_error_if_offset_greater_than_total_length(self):
     with self.assertRaises(ValueError):
         console_output = ConsoleOutput(self._completed_console_output_file_path)
         console_output.segment(max_lines=5, offset_line=155)
Esempio n. 11
0
 def test_segment_raises_value_error_if_offset_greater_than_total_length(self):
     complete_output_path = self.create_temp_plaintext_file(_COMPLETE_OUTPUT)
     console_output = ConsoleOutput.from_plaintext(complete_output_path)
     with self.assertRaises(BadRequestError):
         console_output.segment(max_lines=5, offset_line=155)