Beispiel #1
0
    def _merge_pdfs(self, in_dir, out_file):
        """Merges PDFs in a given directory and outputs it to a single PDF file.
        If `same_page_number` is set to true in the config file, all tests will have `max_pages` number of pages.
        
        Parameters:
            in_dir (str): Path to the input directory containing the PDF files to be merged.
            out_file (str): Path to the merged PDF.
        """
        pw = PdfFileWriter()

        firstPDF = True
        for f in sorted(listdir(in_dir)):
            if isfile(join(in_dir, f)) and regex.match(
                    '^test.*\.pdf$', f, flags=regex.IGNORECASE):
                pr = PdfFileReader(join(in_dir, f), strict=False)

                form = pr.trailer["/Root"][
                    "/AcroForm"]  # see: https://stackoverflow.com/questions/47288578/pdf-form-filled-with-pypdf2-does-not-show-in-print

                pw.appendPagesFromReader(pr)
                if self.config['same_page_number'] and pr.getNumPages(
                ) < self.config['max_pages']:
                    for i in range(self.config['max_pages'] -
                                   pr.getNumPages()):  # pylint: disable=unused-variable
                        pw.addBlankPage()

                if firstPDF:
                    pw._root_object.update({NameObject("/AcroForm"): form})
                    firstPDF = False
                else:
                    pw._root_object["/AcroForm"]["/Fields"].extend(
                        form["/Fields"])

        pw._root_object["/AcroForm"].update(
            {NameObject("/NeedAppearances"): BooleanObject(True)})

        f = codecs.open(out_file, 'wb')
        pw.write(f)
        f.close()
Beispiel #2
0
    def draw_rectangles_for_solution(self, f_in, f_out, solution, points):
        """Drawing green filled rectangles near the correct answers for every problem,
        in order to indicate the correct solution.
        It calculates and writes the total score achieved too.
        
        Parameters:
            f_in (str): Path to the input PDF file.
            f_out (str): Path to the output PDF file.
            solution (dict): The solution (correct answers) corresponding to the input PDF file (f_in).
            points (float): Total points achieved.
        """
        pr = PdfFileReader(f_in)
        dest = pr.getNamedDestinations()
        fields = pr.getFields()

        # """IT IS NOT WORKING IF THIS COMES FIRST:"""
        #         a = PdfAnnotator(f_in)
        #         for p in range(pr.getNumPages()):
        #             for dk, dv in dest.items():
        #                 if pr.getDestinationPageNumber(dv) == p and dk.startswith('ht_'):
        #                     inds = [int(ind) for ind in dk[3:].split(':')]
        # #                     if inds[2] in solution[inds[1]][1]:
        #                     if inds[4] in solution[inds[1]][1]:
        #                         # using some hard-coded values:
        #                         a.add_annotation('square',
        #                                          Location(x1=float(dv['/Left']), y1=float(dv['/Top']), x2=float(dv['/Left'])+5, y2=float(dv['/Top'])+5, page=p),
        #                                          Appearance(stroke_color=(0, 1, 0), stroke_width=5),)
        #         a.write(f_out)

        pw = PdfFileWriter()
        #         pr = PdfFileReader(f_out, strict=False)
        pr = PdfFileReader(f_in, strict=False)
        pw.appendPagesFromReader(pr)
        pw._root_object.update(
            {NameObject("/AcroForm"): pr.trailer["/Root"]["/AcroForm"]})
        pw._root_object["/AcroForm"].update(
            {NameObject("/NeedAppearances"): BooleanObject(True)})
        for p in range(pr.getNumPages()):
            self._update_page_form_checkbox_values(pw.getPage(p), {
                fk: fv['/V']
                for fk, fv in fields.items() if '/V' in fv.keys()
            })  # sometimes '/V' disappears from the keys
        self._update_page_form_checkbox_values(pw.getPage(0),
                                               {'points': str(points)})
        f = codecs.open(f_out, 'wb')
        pw.write(f)
        f.close()

        a = PdfAnnotator(f_out)
        for p in range(pr.getNumPages()):
            for dk, dv in dest.items():
                if pr.getDestinationPageNumber(dv) == p and dk.startswith(
                        'ht_'):
                    inds = [int(ind) for ind in dk[3:].split(':')]
                    #                     if inds[2] in solution[inds[1]][1]:
                    if inds[4] in solution[inds[1]][1]:
                        # using some hard-coded values:
                        a.add_annotation(
                            'square',
                            Location(x1=float(dv['/Left']),
                                     y1=float(dv['/Top']),
                                     x2=float(dv['/Left']) + 5,
                                     y2=float(dv['/Top']) + 5,
                                     page=p),
                            Appearance(stroke_color=(0, 1, 0), stroke_width=5),
                        )
        a.write(f_out)