diff --git a/pyproject.toml b/pyproject.toml index e1961cc..2678ca5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ packages = ["rmtree", "rmtree.struct"] [project] name = "rmtree" -version = "1.0.6" +version = "1.2.0" requires-python = ">=3.10" readme = "README.md" license = { file = "LICENSE" } diff --git a/rmtree/main.py b/rmtree/main.py index 5d7aadf..cfe8c54 100644 --- a/rmtree/main.py +++ b/rmtree/main.py @@ -28,13 +28,16 @@ def main(args=None): parser.add_argument('dst', type=Path, help='The folder where the files are exported to.', nargs='?') parser.add_argument('--verbose', '-v', action='count', default=0, help='Increase verbosity.') - parser.add_argument('--dependencies-verbosity', type=int, default=0, + parser.add_argument('--dependencies-verbosity', '-dv', type=int, default=0, help='Set verbosity of the dependencies.') parser.add_argument('--test-compatibility', '-t', action='store_true', default=False, help='Test if the files from the reMarkable are compatible with this program.') - parser.add_argument('--ignore-assertion', '-i', action='store_true', default=False, + parser.add_argument('--ignore-assertion', '-ia', action='store_true', default=False, help='If the program should continue despite assertion errors.' 'There will be no guarantee the output is correct.') + parser.add_argument('--ignore-compatibility', '-ic', action='store_true', default=False, + help='If the program should continue despite compatibility errors.' + 'WARNING The output will not be correct.') args = parser.parse_args(args) @@ -55,7 +58,7 @@ def main(args=None): if ((not args.test_compatibility) and (count_assertion_errors == 0 or args.ignore_assertion) - and count_compatibility_errors == 0): + and count_compatibility_errors == 0 or args.ignore_compatibility): # export all the files files = list_files(args.src) progress = tqdm(files.items()) diff --git a/rmtree/struct/content.py b/rmtree/struct/content.py index 6151591..28b1a52 100644 --- a/rmtree/struct/content.py +++ b/rmtree/struct/content.py @@ -69,7 +69,7 @@ def iterate_pages(self, bg_pdf: tp.Optional[PdfReader]) -> tp.Iterator[tp.Tuple[ if self.get_version() == 1: if i < len(self.raw["pages"]): page_def = self.raw["pages"][i] - page = Page.from_file(self.src, self.uuid, page_def["id"], page_def) + page = Page.from_file(self.src, self.uuid, page_def, page_def) if bg_pdf is not None and i < len(bg_pdf.pages): bg = bg_pdf.pages[i] diff --git a/rmtree/struct/file.py b/rmtree/struct/file.py index 5db08e5..606a6e3 100644 --- a/rmtree/struct/file.py +++ b/rmtree/struct/file.py @@ -9,10 +9,11 @@ from pathlib import Path from pypdf import PdfReader, PdfWriter, Transformation +from pypdf.annotations import FreeText from rmtree.struct.content import Content, ContentFile from rmtree.struct.metadata import Metadata -from rmtree.struct.page import PageEmpty, PageRM +from rmtree.struct.page import PageEmpty, PageRM, PageVersion logger = logging.getLogger(__name__) @@ -83,6 +84,22 @@ def __init__(self, metadata: Metadata, content: ContentFile): super().__init__(metadata, content) self.content = content # fix type hints + @staticmethod + def __add_annotation__(doc: PdfWriter, page_number: int, content: str, + width=400, height=40) -> None: + annotation = FreeText( + text=content, + rect=(0, 0, width, height), + font="Arial", + italic=True, + font_size="20pt", + font_color="ffffff", + border_color=None, + background_color=None, + ) + annotation.flags = 4 + doc.add_annotation(page_number=page_number, annotation=annotation) + def export(self, output_path: Path): fullpath = os.path.join(output_path, replace_invalid_char(self.metadata.get_name())) background_pdf_path = os.path.join(self.metadata.src, self.get_uuid() + ".pdf") @@ -97,7 +114,7 @@ def export(self, output_path: Path): background_pdf = PdfReader(background_pdf_path) if os.path.exists(background_pdf_path) else None output_pdf = PdfWriter() for page, background_page in self.content.iterate_pages(background_pdf): - if isinstance(page, PageRM): + if isinstance(page, PageRM) and page.get_version() == PageVersion.V6: try: # get the svg as a pdf svg_pdf_p, (x_shift, y_shift, w_svg, h_svg) = page.export() @@ -125,10 +142,27 @@ def export(self, output_path: Path): new_page.merge_transformed_page(svg_pdf_p, Transformation().translate(x_svg, y_svg)) except Exception: + output_pdf.add_blank_page(400, 500) + self.__add_annotation__(output_pdf, + len(output_pdf.pages) - 1, + f"An error occurred while exporting this page.\n\n\n" + f"{traceback.format_exc()}", + 400, + 500) logger.warning(f"Failed to export {page.get_page_uuid()} of {self.get_uuid()}:") traceback.print_exc() - elif background_page is not None: - output_pdf.add_page(background_page) + else: + if background_page is not None: + output_pdf.add_page(background_page) + else: + output_pdf.add_blank_page(400, 500) + if isinstance(page, PageRM): # if there is a non v6 page + self.__add_annotation__(output_pdf, + len(output_pdf.pages) - 1, + f"This page uses a rm v{page.get_version()}." + f" It is incompatible with this software.\n" + f"Please go to this page, draw and remove a stroke in order" + f" to update to page to v6.") if len(output_pdf.pages) > 0: output_pdf.write(fullpath + ".pdf")