From 370f6efe9077dfa5cd4ee22ea53b764493336bb1 Mon Sep 17 00:00:00 2001 From: Bogatenkova Anastasiya Date: Wed, 5 Jun 2024 11:46:02 +0300 Subject: [PATCH] update master (#451) Co-authored-by: Andrew Perminov --- VERSION | 2 +- dedoc/api/api_args.py | 1 - dedoc/api/api_utils.py | 23 ++- dedoc/api/dedoc_api.py | 39 +++-- dedoc/api/web/index.html | 6 +- dedoc/data_structures/document_metadata.py | 7 +- .../data_structures/docx_document.py | 39 ++--- .../pptx_reader/numbering_extractor.py | 51 +++++++ dedoc/readers/pptx_reader/paragraph.py | 55 +++++++ dedoc/readers/pptx_reader/pptx_reader.py | 107 ++++++++------ .../pptx_reader/properties_extractor.py | 124 ++++++++++++++++ dedoc/readers/pptx_reader/shape.py | 51 +++++++ dedoc/readers/pptx_reader/table.py | 64 +++++++++ .../article_structure_extractor.py | 2 +- dedoc/utils/office_utils.py | 35 +++++ docs/source/changelog.rst | 7 + docs/source/dedoc_api_usage/api.rst | 5 - docs/source/readers_output/annotations.rst | 21 ++- docs/source/readers_output/line_types.rst | 6 + requirements.txt | 2 - tests/api_tests/test_api_format_pptx.py | 136 +++++++++++++++++- tests/data/pptx/test-presentation.pptx | Bin 0 -> 111665 bytes 22 files changed, 672 insertions(+), 111 deletions(-) create mode 100644 dedoc/readers/pptx_reader/numbering_extractor.py create mode 100644 dedoc/readers/pptx_reader/paragraph.py create mode 100644 dedoc/readers/pptx_reader/properties_extractor.py create mode 100644 dedoc/readers/pptx_reader/shape.py create mode 100644 dedoc/readers/pptx_reader/table.py create mode 100644 dedoc/utils/office_utils.py create mode 100644 tests/data/pptx/test-presentation.pptx diff --git a/VERSION b/VERSION index 7e541aec..6b4d1577 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.2 \ No newline at end of file +2.2.3 \ No newline at end of file diff --git a/dedoc/api/api_args.py b/dedoc/api/api_args.py index f139733f..20d01db1 100644 --- a/dedoc/api/api_args.py +++ b/dedoc/api/api_args.py @@ -17,7 +17,6 @@ class QueryParameters: need_content_analysis: str = Form("false", enum=["true", "false"], description="Enable parsing contents of the attached files") recursion_deep_attachments: str = Form("10", description="Depth on which nested attachments will be parsed if need_content_analysis=true") return_base64: str = Form("false", enum=["true", "false"], description="Save attached images to the document metadata in base64 format") - attachments_dir: Optional[str] = Form(None, description="Path to the directory where to save files' attachments") # tables handling need_pdf_table_analysis: str = Form("true", enum=["true", "false"], description="Enable table recognition for pdf") diff --git a/dedoc/api/api_utils.py b/dedoc/api/api_utils.py index 46a6ce6d..c942fefa 100644 --- a/dedoc/api/api_utils.py +++ b/dedoc/api/api_utils.py @@ -14,6 +14,7 @@ from dedoc.data_structures.parsed_document import ParsedDocument from dedoc.data_structures.table import Table from dedoc.data_structures.tree_node import TreeNode +from dedoc.extensions import converted_mimes, recognized_mimes def __prettify_text(text: str) -> Iterator[str]: @@ -148,11 +149,22 @@ def json2html(text: str, text += table2html(table, table2id) text += "

 

" + image_mimes = recognized_mimes.image_like_format.union(converted_mimes.image_like_format) + if attachments is not None and len(attachments) > 0: text += "

Attachments:

" for attachment_id, attachment in enumerate(attachments): attachment_text = json2html(text="", paragraph=attachment.content.structure, tables=attachment.content.tables, attachments=attachment.attachments) - text += f'

attachment {attachment_id} ({attachment.metadata.file_name}):

{attachment_text}
' + attachment_base64 = f'data:{attachment.metadata.file_type};base64,{attachment.metadata.base64}"' + attachment_link = f'{attachment.metadata.file_name}' + is_image = attachment.metadata.file_type in image_mimes + attachment_image = f'' if is_image else "" + + text += f"""
+

attachment {attachment_id} ({attachment_link}):

+ {attachment_image} + {attachment_text} +
""" return text @@ -193,12 +205,9 @@ def __annotations2html(paragraph: TreeNode, table2id: Dict[str, int], attach2id: name = annotation.name value = annotation.value - bool_annotations = [BoldAnnotation.name, - ItalicAnnotation.name, - StrikeAnnotation.name, - SubscriptAnnotation.name, - SuperscriptAnnotation.name, - UnderlinedAnnotation.name] + bool_annotations = [ + BoldAnnotation.name, ItalicAnnotation.name, StrikeAnnotation.name, SubscriptAnnotation.name, SuperscriptAnnotation.name, UnderlinedAnnotation.name + ] check_annotations = bool_annotations + [TableAnnotation.name, ReferenceAnnotation.name, AttachAnnotation.name] if name not in check_annotations and not value.startswith("heading "): continue diff --git a/dedoc/api/dedoc_api.py b/dedoc/api/dedoc_api.py index 4572ab05..9e7063f7 100644 --- a/dedoc/api/dedoc_api.py +++ b/dedoc/api/dedoc_api.py @@ -1,3 +1,4 @@ +import base64 import dataclasses import importlib import json @@ -62,41 +63,57 @@ def _get_static_file_path(request: Request) -> str: return os.path.abspath(os.path.join(directory, file)) +def __add_base64_info_to_attachments(document_tree: ParsedDocument, attachments_dir: str) -> None: + for attachment in document_tree.attachments: + with open(os.path.join(attachments_dir, attachment.metadata.temporary_file_name), "rb") as attachment_file: + attachment.metadata.add_attribute("base64", base64.b64encode(attachment_file.read()).decode("utf-8")) + + @app.post("/upload", response_model=ParsedDocument) async def upload(file: UploadFile = File(...), query_params: QueryParameters = Depends()) -> Response: # noqa parameters = dataclasses.asdict(query_params) if not file or file.filename == "": raise MissingFileError("Error: Missing content in request_post file parameter", version=dedoc.__version__) + return_format = str(parameters.get("return_format", "json")).lower() + with tempfile.TemporaryDirectory() as tmpdir: file_path = save_upload_file(file, tmpdir) - document_tree = manager.parse(file_path, parameters=dict(parameters)) + document_tree = manager.parse(file_path, parameters={**dict(parameters), "attachments_dir": tmpdir}) + + if return_format == "html": + __add_base64_info_to_attachments(document_tree, tmpdir) - return_format = str(parameters.get("return_format", "json")).lower() if return_format == "html": html_content = json2html( text="", paragraph=document_tree.content.structure, tables=document_tree.content.tables, - attachments=document_tree.attachments, tabs=0 + attachments=document_tree.attachments, + tabs=0 ) return HTMLResponse(content=html_content) - elif return_format == "plain_text": + + if return_format == "plain_text": txt_content = json2txt(paragraph=document_tree.content.structure) return PlainTextResponse(content=txt_content) - elif return_format == "tree": + + if return_format == "tree": html_content = json2tree(paragraph=document_tree.content.structure) return HTMLResponse(content=html_content) - elif return_format == "ujson": + + if return_format == "ujson": return UJSONResponse(content=document_tree.to_api_schema().model_dump()) - elif return_format == "collapsed_tree": + + if return_format == "collapsed_tree": html_content = json2collapsed_tree(paragraph=document_tree.content.structure) return HTMLResponse(content=html_content) - elif return_format == "pretty_json": + + if return_format == "pretty_json": return PlainTextResponse(content=json.dumps(document_tree.to_api_schema().model_dump(), ensure_ascii=False, indent=2)) - else: - logger.info(f"Send result. File {file.filename} with parameters {parameters}") - return ORJSONResponse(content=document_tree.to_api_schema().model_dump()) + + logger.info(f"Send result. File {file.filename} with parameters {parameters}") + return ORJSONResponse(content=document_tree.to_api_schema().model_dump()) @app.get("/upload_example") diff --git a/dedoc/api/web/index.html b/dedoc/api/web/index.html index 055ef58b..e045d483 100644 --- a/dedoc/api/web/index.html +++ b/dedoc/api/web/index.html @@ -70,7 +70,7 @@

Type of document structure parsing

Attachments handling

-
with_attachments, need_content_analysis, recursion_deep_attachments, return_base64, attachments_dir +
with_attachments, need_content_analysis, recursion_deep_attachments, return_base64

@@ -87,10 +87,6 @@

Attachments handling

- -

- -

diff --git a/dedoc/data_structures/document_metadata.py b/dedoc/data_structures/document_metadata.py index beec9c56..e93b2c16 100644 --- a/dedoc/data_structures/document_metadata.py +++ b/dedoc/data_structures/document_metadata.py @@ -1,5 +1,5 @@ import uuid -from typing import Dict, Union +from typing import Any, Dict, Union from dedoc.api.schema.document_metadata import DocumentMetadata as ApiDocumentMetadata from dedoc.data_structures.serializable import Serializable @@ -38,8 +38,11 @@ def __init__(self, self.access_time = access_time self.file_type = file_type for key, value in kwargs.items(): - setattr(self, key, value) + self.add_attribute(key, value) self.uid = f"doc_uid_auto_{uuid.uuid1()}" if uid is None else uid + def add_attribute(self, key: str, value: Any) -> None: # noqa + setattr(self, key, value) + def to_api_schema(self) -> ApiDocumentMetadata: return ApiDocumentMetadata(**vars(self)) diff --git a/dedoc/readers/docx_reader/data_structures/docx_document.py b/dedoc/readers/docx_reader/data_structures/docx_document.py index 49d402e8..95901ec4 100644 --- a/dedoc/readers/docx_reader/data_structures/docx_document.py +++ b/dedoc/readers/docx_reader/data_structures/docx_document.py @@ -1,14 +1,11 @@ import hashlib import logging -import os import re -import zipfile from collections import defaultdict -from typing import List, Optional +from typing import List from bs4 import BeautifulSoup, Tag -from dedoc.common.exceptions.bad_file_error import BadFileFormatError from dedoc.data_structures.attached_file import AttachedFile from dedoc.data_structures.concrete_annotations.attach_annotation import AttachAnnotation from dedoc.data_structures.concrete_annotations.table_annotation import TableAnnotation @@ -19,6 +16,7 @@ from dedoc.readers.docx_reader.line_with_meta_converter import LineWithMetaConverter from dedoc.readers.docx_reader.numbering_extractor import NumberingExtractor from dedoc.readers.docx_reader.styles_extractor import StylesExtractor +from dedoc.utils.office_utils import get_bs_from_zip from dedoc.utils.utils import calculate_file_hash @@ -28,8 +26,8 @@ def __init__(self, path: str, attachments: List[AttachedFile], logger: logging.L self.path = path self.attachment_name2uid = {attachment.original_name: attachment.uid for attachment in attachments} - self.document_bs_tree = self.__get_bs_tree("word/document.xml") - self.document_bs_tree = self.__get_bs_tree("word/document2.xml") if self.document_bs_tree is None else self.document_bs_tree + self.document_bs_tree = get_bs_from_zip(self.path, "word/document.xml") + self.document_bs_tree = get_bs_from_zip(self.path, "word/document2.xml") if self.document_bs_tree is None else self.document_bs_tree self.body = self.document_bs_tree.body if self.document_bs_tree else None self.paragraph_maker = self.__get_paragraph_maker() @@ -39,8 +37,8 @@ def __init__(self, path: str, attachments: List[AttachedFile], logger: logging.L self.lines = self.__get_lines() def __get_paragraph_maker(self) -> ParagraphMaker: - styles_extractor = StylesExtractor(self.__get_bs_tree("word/styles.xml"), self.logger) - num_tree = self.__get_bs_tree("word/numbering.xml") + styles_extractor = StylesExtractor(get_bs_from_zip(self.path, "word/styles.xml"), self.logger) + num_tree = get_bs_from_zip(self.path, "word/numbering.xml") numbering_extractor = NumberingExtractor(num_tree, styles_extractor) if num_tree else None styles_extractor.numbering_extractor = numbering_extractor @@ -49,8 +47,8 @@ def __get_paragraph_maker(self) -> ParagraphMaker: path_hash=calculate_file_hash(path=self.path), styles_extractor=styles_extractor, numbering_extractor=numbering_extractor, - footnote_extractor=FootnoteExtractor(self.__get_bs_tree("word/footnotes.xml")), - endnote_extractor=FootnoteExtractor(self.__get_bs_tree("word/endnotes.xml"), key="endnote") + footnote_extractor=FootnoteExtractor(get_bs_from_zip(self.path, "word/footnotes.xml")), + endnote_extractor=FootnoteExtractor(get_bs_from_zip(self.path, "word/endnotes.xml"), key="endnote") ) def __get_lines(self) -> List[LineWithMeta]: @@ -120,23 +118,6 @@ def __paragraphs2lines(self, image_refs: dict, table_refs: dict, diagram_refs: d return lines_with_meta - def __get_bs_tree(self, filename: str) -> Optional[BeautifulSoup]: - """ - Gets xml bs tree from the given file inside the self.path. - :param filename: name of file to extract the tree - :return: BeautifulSoup tree or None if file wasn't found - """ - try: - with zipfile.ZipFile(self.path) as document: - content = document.read(filename) - content = re.sub(br"\n[\t ]*", b"", content) - soup = BeautifulSoup(content, "xml") - return soup - except KeyError: - return None - except zipfile.BadZipFile: - raise BadFileFormatError(f"Bad docx file:\n file_name = {os.path.basename(self.path)}. Seems docx is broken") - def __handle_table_xml(self, xml: Tag, table_refs: dict) -> None: table = DocxTable(xml, self.paragraph_maker) self.tables.append(table.to_table()) @@ -150,9 +131,9 @@ def __handle_table_xml(self, xml: Tag, table_refs: dict) -> None: table_refs[len(self.paragraph_list) - 1].append(table_uid) def __handle_images_xml(self, xmls: List[Tag], image_refs: dict) -> None: - rels = self.__get_bs_tree("word/_rels/document.xml.rels") + rels = get_bs_from_zip(self.path, "word/_rels/document.xml.rels") if rels is None: - rels = self.__get_bs_tree("word/_rels/document2.xml.rels") + rels = get_bs_from_zip(self.path, "word/_rels/document2.xml.rels") images_rels = dict() for rel in rels.find_all("Relationship"): diff --git a/dedoc/readers/pptx_reader/numbering_extractor.py b/dedoc/readers/pptx_reader/numbering_extractor.py new file mode 100644 index 00000000..42da3557 --- /dev/null +++ b/dedoc/readers/pptx_reader/numbering_extractor.py @@ -0,0 +1,51 @@ +class NumberingExtractor: + """ + This class is used to compute numbering text for list items. + For example: "1.", (i), "○" + """ + def __init__(self) -> None: + # Mapping according to the ST_TextAutonumberScheme + # NOTE we ignore chinese, japanese, hindi, thai + self.numbering_types = dict( + arabic="1", # 1, 2, 3, ..., 10, 11, 12, ... + alphaLc="a", # a, b, c, ..., y, z, aa, bb, cc, ..., yy, zz, aaa, bbb, ccc, ... + alphaUc="A", # A, B, C, ..., Y, Z, AA, BB, CC, ..., YY, ZZ, AAA, BBB, CCC, ... + romanLc="i", # i, ii, iii, iv, ..., xviii, xix, xx, xxi, ... + romanUc="I" # I, II, III, IV, ..., XVIII, XIX, XX, XXI, ... + ) + + self.numbering_formatting = dict( + ParenBoth="({}) ", + ParenR="{}) ", + Period="{}. ", + Plain="{} " + ) + + self.combined_types = { + num_type + num_formatting: (num_type, num_formatting) for num_type in self.numbering_types for num_formatting in self.numbering_formatting + } + self.roman_mapping = [(1000, "m"), (500, "d"), (100, "c"), (50, "l"), (10, "x"), (5, "v"), (1, "i")] + + def get_text(self, numbering: str, shift: int) -> str: + """ + Computes the next item of the list sequence. + :param numbering: type of the numbering, e.g. "arabicPeriod" + :param shift: shift from the beginning of list numbering + :return: string representation of the next numbering item + """ + num_type, num_formatting = self.combined_types.get(numbering, ("arabic", "Period")) + + if num_type in ("alphaLc", "alphaUc"): + shift1, shift2 = shift % 26, shift // 26 + 1 + num_char = chr(ord(self.numbering_types[num_type]) + shift1) * shift2 + elif num_type in ("romanLc", "romanUc"): + num_char = "" + for number, letter in self.roman_mapping: + cnt, shift = shift // number, shift % number + if num_type == "romanUc": + letter = chr(ord(letter) + ord("A") - ord("a")) + num_char += letter * cnt + else: + num_char = str(int(self.numbering_types["arabic"]) + shift) + + return self.numbering_formatting[num_formatting].format(num_char) diff --git a/dedoc/readers/pptx_reader/paragraph.py b/dedoc/readers/pptx_reader/paragraph.py new file mode 100644 index 00000000..2dfcb952 --- /dev/null +++ b/dedoc/readers/pptx_reader/paragraph.py @@ -0,0 +1,55 @@ +from bs4 import Tag + +from dedoc.data_structures import AlignmentAnnotation, BoldAnnotation, HierarchyLevel, ItalicAnnotation, LineMetadata, LineWithMeta, SizeAnnotation, \ + StrikeAnnotation, SubscriptAnnotation, SuperscriptAnnotation, UnderlinedAnnotation +from dedoc.readers.pptx_reader.numbering_extractor import NumberingExtractor +from dedoc.readers.pptx_reader.properties_extractor import PropertiesExtractor +from dedoc.utils.annotation_merger import AnnotationMerger + + +class PptxParagraph: + """ + This class corresponds to one textual paragraph of some entity, e.g. shape or table cell (tag ). + """ + def __init__(self, xml: Tag, numbering_extractor: NumberingExtractor, properties_extractor: PropertiesExtractor) -> None: + self.xml = xml + self.numbered_list_type = self.xml.buAutoNum.get("type", "arabicPeriod") if self.xml.buAutoNum else None + self.level = int(self.xml.pPr.get("lvl", 0)) + 1 if self.xml.pPr else 1 + self.numbering_extractor = numbering_extractor + self.properties_extractor = properties_extractor + self.annotation_merger = AnnotationMerger() + annotations = [BoldAnnotation, ItalicAnnotation, UnderlinedAnnotation, StrikeAnnotation, SuperscriptAnnotation, SubscriptAnnotation] + self.dict2annotation = {annotation.name: annotation for annotation in annotations} + + def get_line_with_meta(self, page_id: int, line_id: int, is_title: bool, shift: int = 0) -> LineWithMeta: + text = "" + paragraph_properties = self.properties_extractor.get_properties(self.xml.pPr, level=self.level) + hierarchy_level = HierarchyLevel.create_raw_text() + + if is_title or paragraph_properties.title: + hierarchy_level = HierarchyLevel(line_type=HierarchyLevel.header, level_1=1, level_2=self.level, can_be_multiline=False) + elif self.numbered_list_type: # numbered list + text += self.numbering_extractor.get_text(self.numbered_list_type, shift) + hierarchy_level = HierarchyLevel(line_type=HierarchyLevel.list_item, level_1=2, level_2=self.level, can_be_multiline=False) + elif self.xml.buChar: # bullet list + text += self.xml.buChar["char"] + " " + hierarchy_level = HierarchyLevel(line_type=HierarchyLevel.list_item, level_1=3, level_2=self.level, can_be_multiline=False) + + annotations = [] + if self.xml.r: + for run in self.xml.find_all("a:r"): + prev_text = text + for run_text in run: + if run_text.name == "t" and run.text: + text += run.text + + run_properties = self.properties_extractor.get_properties(run.rPr, level=self.level, properties=paragraph_properties) + annotations.append(SizeAnnotation(start=len(prev_text), end=len(text), value=str(run_properties.size))) + for property_name in self.dict2annotation: + if getattr(run_properties, property_name): + annotations.append(self.dict2annotation[property_name](start=len(prev_text), end=len(text), value="True")) + + text = f"{text}\n" + annotations = self.annotation_merger.merge_annotations(annotations, text) + annotations.append(AlignmentAnnotation(start=0, end=len(text), value=paragraph_properties.alignment)) + return LineWithMeta(text, metadata=LineMetadata(page_id=page_id, line_id=line_id, tag_hierarchy_level=hierarchy_level), annotations=annotations) diff --git a/dedoc/readers/pptx_reader/pptx_reader.py b/dedoc/readers/pptx_reader/pptx_reader.py index e109fae0..2d68b850 100644 --- a/dedoc/readers/pptx_reader/pptx_reader.py +++ b/dedoc/readers/pptx_reader/pptx_reader.py @@ -1,20 +1,20 @@ +import zipfile from typing import Dict, List, Optional -from bs4 import BeautifulSoup -from pptx import Presentation -from pptx.shapes.graphfrm import GraphicFrame -from pptx.shapes.picture import Picture -from pptx.slide import Slide +from bs4 import BeautifulSoup, Tag from dedoc.attachments_extractors.concrete_attachments_extractors.pptx_attachments_extractor import PptxAttachmentsExtractor from dedoc.data_structures import AttachAnnotation, Table, TableAnnotation -from dedoc.data_structures.cell_with_meta import CellWithMeta from dedoc.data_structures.line_metadata import LineMetadata from dedoc.data_structures.line_with_meta import LineWithMeta -from dedoc.data_structures.table_metadata import TableMetadata from dedoc.data_structures.unstructured_document import UnstructuredDocument from dedoc.extensions import recognized_extensions, recognized_mimes from dedoc.readers.base_reader import BaseReader +from dedoc.readers.pptx_reader.numbering_extractor import NumberingExtractor +from dedoc.readers.pptx_reader.properties_extractor import PropertiesExtractor +from dedoc.readers.pptx_reader.shape import PptxShape +from dedoc.readers.pptx_reader.table import PptxTable +from dedoc.utils.office_utils import get_bs_from_zip from dedoc.utils.parameter_utils import get_param_with_attachments @@ -27,6 +27,7 @@ class PptxReader(BaseReader): def __init__(self, *, config: Optional[dict] = None) -> None: super().__init__(config=config, recognized_extensions=recognized_extensions.pptx_like_format, recognized_mimes=recognized_mimes.pptx_like_format) self.attachments_extractor = PptxAttachmentsExtractor(config=self.config) + self.numbering_extractor = NumberingExtractor() def read(self, file_path: str, parameters: Optional[dict] = None) -> UnstructuredDocument: """ @@ -36,55 +37,73 @@ def read(self, file_path: str, parameters: Optional[dict] = None) -> Unstructure with_attachments = get_param_with_attachments(parameters) attachments = self.attachments_extractor.extract(file_path=file_path, parameters=parameters) if with_attachments else [] attachment_name2uid = {attachment.original_name: attachment.uid for attachment in attachments} - - prs = Presentation(file_path) - lines, tables = [], [] - - for page_id, slide in enumerate(prs.slides, start=1): - images_rels = self.__get_slide_images_rels(slide) - - for paragraph_id, shape in enumerate(slide.shapes, start=1): - - if shape.has_text_frame: - lines.append(LineWithMeta(line=f"{shape.text}\n", metadata=LineMetadata(page_id=page_id, line_id=paragraph_id))) - - if shape.has_table: - self.__add_table(lines, tables, page_id, paragraph_id, shape) - - if with_attachments and hasattr(shape, "image"): + images_rels = self.__get_slide_images_rels(file_path) + properties_extractor = PropertiesExtractor(file_path) + + slide_xml_list = self.__get_slides_bs(file_path, xml_prefix="ppt/slides/slide", xml_postfix=".xml") + lines = [] + tables = [] + + for slide_id, slide_xml in enumerate(slide_xml_list): + shape_tree_xml = slide_xml.spTree + + is_first_shape = True + for tag in shape_tree_xml: + if tag.name == "sp": + if not tag.txBody: + continue + + shape = PptxShape(tag, page_id=slide_id, init_line_id=len(lines), numbering_extractor=self.numbering_extractor, + properties_extractor=properties_extractor, is_title=is_first_shape) + shape_lines = shape.get_lines() + lines.extend(shape_lines) + if is_first_shape and len(shape_lines) > 0: + is_first_shape = False + + elif tag.tbl: + self.__add_table(lines=lines, tables=tables, page_id=slide_id, table_xml=tag.tbl, properties_extractor=properties_extractor) + elif tag.name == "pic" and tag.blip: if len(lines) == 0: - lines.append(LineWithMeta(line="", metadata=LineMetadata(page_id=page_id, line_id=paragraph_id))) - self.__add_attach_annotation(lines[-1], shape, attachment_name2uid, images_rels) + lines.append(LineWithMeta(line="", metadata=LineMetadata(page_id=slide_id, line_id=0))) + image_rel_id = str(slide_id) + tag.blip.get("r:embed", "") + self.__add_attach_annotation(lines[-1], image_rel_id, attachment_name2uid, images_rels) return UnstructuredDocument(lines=lines, tables=tables, attachments=attachments, warnings=[]) - def __add_table(self, lines: List[LineWithMeta], tables: List[Table], page_id: int, paragraph_id: int, shape: GraphicFrame) -> None: - cells = [ - [CellWithMeta(lines=[LineWithMeta(line=cell.text, metadata=LineMetadata(page_id=page_id, line_id=0))]) for cell in row.cells] - for row in shape.table.rows - ] - table = Table(cells=cells, metadata=TableMetadata(page_id=page_id)) + def __get_slides_bs(self, path: str, xml_prefix: str, xml_postfix: str) -> List[BeautifulSoup]: + with zipfile.ZipFile(path) as document: + xml_names = document.namelist() + filtered_names = [file_name for file_name in xml_names if file_name.startswith(xml_prefix) and file_name.endswith(xml_postfix)] + sorted_names = sorted(filtered_names, key=lambda x: int(x[len(xml_prefix):-len(xml_postfix)])) + slides_bs_list = [get_bs_from_zip(path, file_name, remove_spaces=True) for file_name in sorted_names] + return slides_bs_list - if len(lines) == 0: - lines.append(LineWithMeta(line="", metadata=LineMetadata(page_id=page_id, line_id=paragraph_id))) - lines[-1].annotations.append(TableAnnotation(start=0, end=len(lines[-1]), name=table.metadata.uid)) - tables.append(table) - - def __get_slide_images_rels(self, slide: Slide) -> Dict[str, str]: - rels = BeautifulSoup(slide.part.rels.xml, "xml") + def __get_slide_images_rels(self, path: str) -> Dict[str, str]: + """ + return mapping: {image Id -> image name} + """ + rels_xml_list = self.__get_slides_bs(path, xml_prefix="ppt/slides/_rels/slide", xml_postfix=".xml.rels") images_dir = "../media/" images_rels = dict() - for rel in rels.find_all("Relationship"): - if rel["Target"].startswith(images_dir): - images_rels[rel["Id"]] = rel["Target"][len(images_dir):] + for slide_id, rels_xml in enumerate(rels_xml_list): + for rel in rels_xml.find_all("Relationship"): + if rel["Target"].startswith(images_dir): + images_rels[str(slide_id) + rel["Id"]] = rel["Target"][len(images_dir):] return images_rels - def __add_attach_annotation(self, line: LineWithMeta, shape: Picture, attachment_name2uid: dict, images_rels: dict) -> None: + def __add_table(self, lines: List[LineWithMeta], tables: List[Table], page_id: int, table_xml: Tag, properties_extractor: PropertiesExtractor) -> None: + table = PptxTable(table_xml, page_id, self.numbering_extractor, properties_extractor).to_table() + + if len(lines) == 0: + lines.append(LineWithMeta(line="", metadata=LineMetadata(page_id=page_id, line_id=0))) + lines[-1].annotations.append(TableAnnotation(start=0, end=len(lines[-1]), name=table.metadata.uid)) + tables.append(table) + + def __add_attach_annotation(self, line: LineWithMeta, image_rel_id: str, attachment_name2uid: dict, images_rels: dict) -> None: try: - image_rels_id = shape.element.blip_rId - image_name = images_rels[image_rels_id] + image_name = images_rels[image_rel_id] image_uid = attachment_name2uid[image_name] line.annotations.append(AttachAnnotation(start=0, end=len(line), attach_uid=image_uid)) except KeyError as e: diff --git a/dedoc/readers/pptx_reader/properties_extractor.py b/dedoc/readers/pptx_reader/properties_extractor.py new file mode 100644 index 00000000..67c0c919 --- /dev/null +++ b/dedoc/readers/pptx_reader/properties_extractor.py @@ -0,0 +1,124 @@ +from copy import deepcopy +from dataclasses import dataclass +from typing import Dict, Optional + +from bs4 import Tag + +from dedoc.utils.office_utils import get_bs_from_zip + + +@dataclass +class Properties: + bold: bool = False + italic: bool = False + underlined: bool = False + superscript: bool = False + subscript: bool = False + strike: bool = False + size: int = 0 + alignment: str = "left" + title: bool = False + + +class PropertiesExtractor: + """ + This class allows to extract some text formatting properties (see class Properties) + + Properties hierarchy: + + - Run and paragraph properties (slide.xml) + - Slide layout properties (slideLayout.xml) TODO + - Master slide properties (slideMaster.xml) TODO + - Presentation default properties (presentation.xml -> defaultTextStyle) + """ + def __init__(self, file_path: str) -> None: + self.alignment_mapping = dict(l="left", r="right", ctr="center", just="both", dist="both", justLow="both", thaiDist="both") + self.lvl2default_properties = self.__get_default_properties_mapping(file_path) + + def get_properties(self, xml: Tag, level: int, properties: Optional[Properties] = None) -> Properties: + """ + xml examples: + + + + """ + properties = properties or self.lvl2default_properties.get(level, Properties()) + new_properties = deepcopy(properties) + if not xml: + return new_properties + + self.__update_properties(xml, new_properties) + return new_properties + + def __update_properties(self, xml: Tag, properties: Properties) -> None: + if int(xml.get("b", "0")): + properties.bold = True + if int(xml.get("i", "0")): + properties.italic = True + + underlined = xml.get("u", "none").lower() + if underlined != "none": + properties.underlined = True + + strike = xml.get("strike", "nostrike").lower() + if strike != "nostrike": + properties.strike = True + + size = xml.get("sz") + if size: + properties.size = float(size) / 100 + + baseline = xml.get("baseline") + if baseline: + if float(baseline) < 0: + properties.subscript = True + else: + properties.superscript = True + + self.__update_alignment(xml, properties) + + def __update_alignment(self, xml: Tag, properties: Properties) -> None: + alignment = xml.get("algn") + if alignment and alignment in self.alignment_mapping: + properties.alignment = self.alignment_mapping[alignment] + + def __get_default_properties_mapping(self, file_path: str) -> Dict[int, Properties]: + lvl2properties = {} + + presentation_xml = get_bs_from_zip(file_path, "ppt/presentation.xml", remove_spaces=True) + default_style = presentation_xml.defaultTextStyle + if not default_style: + return lvl2properties + + # lvl1pPr - lvl9pPr + for i in range(1, 10): + level_xml = getattr(default_style, f"lvl{i}pPr") + if level_xml: + self.__update_level_properties(level_xml, lvl2properties) + return lvl2properties + + def __update_level_properties(self, xml: Tag, lvl2properties: Dict[int, Properties]) -> None: + """ + Example: + + + + + + + + + + + + + + + """ + level = int(xml.get("lvl", "0")) + 1 + level_properties = lvl2properties.get(level, Properties()) + self.__update_alignment(xml, level_properties) + if xml.defRPr: + self.__update_properties(xml.defRPr, level_properties) + + lvl2properties[level] = level_properties diff --git a/dedoc/readers/pptx_reader/shape.py b/dedoc/readers/pptx_reader/shape.py new file mode 100644 index 00000000..b1c548d3 --- /dev/null +++ b/dedoc/readers/pptx_reader/shape.py @@ -0,0 +1,51 @@ +from collections import defaultdict +from typing import List + +from bs4 import Tag + +from dedoc.data_structures import LineWithMeta +from dedoc.readers.pptx_reader.numbering_extractor import NumberingExtractor +from dedoc.readers.pptx_reader.paragraph import PptxParagraph +from dedoc.readers.pptx_reader.properties_extractor import PropertiesExtractor + + +class PptxShape: + """ + This class corresponds to one textual block of the presentation (tag ). + """ + def __init__(self, xml: Tag, page_id: int, init_line_id: int, numbering_extractor: NumberingExtractor, properties_extractor: PropertiesExtractor, + is_title: bool = False) -> None: + self.xml = xml + self.page_id = page_id + self.init_line_id = init_line_id + self.numbering_extractor = numbering_extractor + self.properties_extractor = properties_extractor + self.is_title = is_title + + def get_lines(self) -> List[LineWithMeta]: + if not self.xml.get_text().strip(): + return [] + + if self.xml.ph and "title" in self.xml.ph.get("type", "").lower(): + self.is_title = True + + lines = [] + numbering2shift = defaultdict(int) + prev_list_level = None + + for line_id, paragraph_xml in enumerate(self.xml.find_all("a:p")): + paragraph = PptxParagraph(paragraph_xml, self.numbering_extractor, self.properties_extractor) + + if paragraph.numbered_list_type: + if prev_list_level and paragraph.level > prev_list_level: + numbering2shift[(paragraph.numbered_list_type, paragraph.level)] = 0 + + shift = numbering2shift[(paragraph.numbered_list_type, paragraph.level)] + numbering2shift[(paragraph.numbered_list_type, paragraph.level)] += 1 + prev_list_level = paragraph.level + else: + shift = 0 + + lines.append(paragraph.get_line_with_meta(line_id=self.init_line_id + line_id, page_id=self.page_id, is_title=self.is_title, shift=shift)) + + return lines diff --git a/dedoc/readers/pptx_reader/table.py b/dedoc/readers/pptx_reader/table.py new file mode 100644 index 00000000..cbe7febb --- /dev/null +++ b/dedoc/readers/pptx_reader/table.py @@ -0,0 +1,64 @@ +import hashlib + +from bs4 import Tag + +from dedoc.data_structures import CellWithMeta, Table, TableMetadata +from dedoc.readers.docx_reader.numbering_extractor import NumberingExtractor +from dedoc.readers.pptx_reader.properties_extractor import PropertiesExtractor +from dedoc.readers.pptx_reader.shape import PptxShape + + +class PptxTable: + """ + This class corresponds to the table (tag ) in the slides xml files. + """ + def __init__(self, xml: Tag, page_id: int, numbering_extractor: NumberingExtractor, properties_extractor: PropertiesExtractor) -> None: + """ + Contains information about table properties. + :param xml: BeautifulSoup tree with table properties + """ + self.xml = xml + self.page_id = page_id + self.numbering_extractor = numbering_extractor + self.properties_extractor = properties_extractor + self.__uid = hashlib.md5(xml.encode()).hexdigest() + + @property + def uid(self) -> str: + return self.__uid + + def to_table(self) -> Table: + """ + Converts xml file with table to Table class + """ + # tbl -- table; tr -- table row, tc -- table cell + # delete tables inside tables + for tbl in self.xml.find_all("a:tbl"): + tbl.extract() + + rows = self.xml.find_all("a:tr") + cell_list = [] + + for row in rows: + cells = row.find_all("a:tc") + col_index = 0 + cell_row_list = [] + + for cell in cells: + if int(cell.get("vMerge", 0)): # vertical merge + cell_with_meta = CellWithMeta(lines=cell_list[-1][col_index].lines, colspan=1, rowspan=1, invisible=True) + elif int(cell.get("hMerge", 0)): # horizontal merge + cell_with_meta = CellWithMeta(lines=cell_row_list[-1].lines, colspan=1, rowspan=1, invisible=True) + else: + colspan = int(cell.get("gridSpan", 1)) # gridSpan attribute describes number of horizontally merged cells + rowspan = int(cell.get("rowSpan", 1)) # rowSpan attribute for vertically merged set of cells (or horizontally split cells) + lines = PptxShape(xml=cell, page_id=self.page_id, numbering_extractor=self.numbering_extractor, init_line_id=0, + properties_extractor=self.properties_extractor).get_lines() + cell_with_meta = CellWithMeta(lines=lines, colspan=colspan, rowspan=rowspan, invisible=False) + + cell_row_list.append(cell_with_meta) + col_index += 1 + + cell_list.append(cell_row_list) + + return Table(cells=cell_list, metadata=TableMetadata(page_id=self.page_id, uid=self.uid)) diff --git a/dedoc/structure_extractors/concrete_structure_extractors/article_structure_extractor.py b/dedoc/structure_extractors/concrete_structure_extractors/article_structure_extractor.py index 4ef6d4e8..8e6e4a50 100644 --- a/dedoc/structure_extractors/concrete_structure_extractors/article_structure_extractor.py +++ b/dedoc/structure_extractors/concrete_structure_extractors/article_structure_extractor.py @@ -23,7 +23,7 @@ def extract(self, document: UnstructuredDocument, parameters: Optional[dict] = N :class:`~dedoc.structure_extractors.AbstractStructureExtractor`. """ for line in document.lines: - if line.metadata.tag_hierarchy_level is None: + if line.metadata.tag_hierarchy_level is None or line.metadata.tag_hierarchy_level.is_unknown(): line.metadata.tag_hierarchy_level = HierarchyLevel.create_raw_text() else: line.metadata.hierarchy_level = line.metadata.tag_hierarchy_level diff --git a/dedoc/utils/office_utils.py b/dedoc/utils/office_utils.py new file mode 100644 index 00000000..98693d94 --- /dev/null +++ b/dedoc/utils/office_utils.py @@ -0,0 +1,35 @@ +import os +import re +import zipfile +from typing import Optional + +from bs4 import BeautifulSoup + +from dedoc.common.exceptions.bad_file_error import BadFileFormatError + + +def get_bs_from_zip(zip_path: str, xml_path: str, remove_spaces: bool = False) -> Optional[BeautifulSoup]: + """ + Utility for extracting xml from files of office formats (docx, pptx, xlsx). + Gets xml BeautifulSoup tree from the given file inside the zip_path. + + :param zip_path: path to the file of the office format (docx, pptx, xlsx) + :param xml_path: name of file to extract the tree + :param remove_spaces: remove spaces between tags except (for pptx) + :return: BeautifulSoup tree or None if file wasn't found + """ + try: + with zipfile.ZipFile(zip_path) as document: + content = document.read(xml_path) + content = re.sub(br"\n[\t ]*", b"", content) + + if remove_spaces: + # remove spaces between tags, don't remove spaces inside pptx text fields: + content = re.sub(br"(?\s+<", b"><", content) + + soup = BeautifulSoup(content, "xml") + return soup + except KeyError: + return None + except zipfile.BadZipFile: + raise BadFileFormatError(f"Bad office file:\n file_name = {os.path.basename(zip_path)}. Seems file is broken") diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 25cf3af6..2834f209 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -1,6 +1,13 @@ Changelog ========= +v2.2.3 (2024-06-05) +------------------- +Release note: `v2.2.3 `_ + +* Show attached images and added ability to download attached files in the HTML output representation (API usage, return_format="html"). +* Added hierarchy level information and annotations to `PptxReader`. + v2.2.2 (2024-05-21) ------------------- Release note: `v2.2.2 `_ diff --git a/docs/source/dedoc_api_usage/api.rst b/docs/source/dedoc_api_usage/api.rst index ee68c29f..df6b4963 100644 --- a/docs/source/dedoc_api_usage/api.rst +++ b/docs/source/dedoc_api_usage/api.rst @@ -144,11 +144,6 @@ Api parameters description The encoded contents will be saved in the attachment's metadata in the ``base64_encode`` field. Use ``true`` value to enable this behaviour. - * - attachments_dir - - optional string with a valid path - - None - - The path to the directory where document's attached files can be saved instead of a temporary directory. - * - :cspan:`3` **Tables handling** * - need_pdf_table_analysis diff --git a/docs/source/readers_output/annotations.rst b/docs/source/readers_output/annotations.rst index ee1785c2..2a13989d 100644 --- a/docs/source/readers_output/annotations.rst +++ b/docs/source/readers_output/annotations.rst @@ -11,11 +11,12 @@ Below the readers are enlisted that can return non-empty list of annotations for .. _table_annotations: .. list-table:: Annotations returned by each reader - :widths: 20 10 10 10 10 10 10 10 + :widths: 20 10 10 10 10 10 10 10 10 :class: tight-table * - **Annotation** - :class:`~dedoc.readers.DocxReader` + - :class:`~dedoc.readers.PptxReader` - :class:`~dedoc.readers.HtmlReader`, :class:`~dedoc.readers.MhtmlReader`, :class:`~dedoc.readers.EmailReader` - :class:`~dedoc.readers.RawTextReader` - :class:`~dedoc.readers.PdfImageReader` @@ -24,6 +25,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - :class:`~dedoc.readers.ArticleReader` * - :class:`~dedoc.data_structures.AttachAnnotation` + - `+` - `+` - `-` - `-` @@ -33,6 +35,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - `+` * - :class:`~dedoc.data_structures.TableAnnotation` + - `+` - `+` - `-` - `-` @@ -43,6 +46,7 @@ Below the readers are enlisted that can return non-empty list of annotations for * - :class:`~dedoc.data_structures.LinkedTextAnnotation` - `+` + - `-` - `+` - `-` - `-` @@ -54,12 +58,14 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` - `-` - `-` + - `-` - `+` - `+` - `+` - `-` * - :class:`~dedoc.data_structures.AlignmentAnnotation` + - `+` - `+` - `+` - `-` @@ -71,6 +77,7 @@ Below the readers are enlisted that can return non-empty list of annotations for * - :class:`~dedoc.data_structures.IndentationAnnotation` - `+` - `-` + - `-` - `+` - `+` - `+` @@ -80,6 +87,7 @@ Below the readers are enlisted that can return non-empty list of annotations for * - :class:`~dedoc.data_structures.SpacingAnnotation` - `+` - `-` + - `-` - `+` - `+` - `+` @@ -87,6 +95,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` * - :class:`~dedoc.data_structures.BoldAnnotation` + - `+` - `+` - `+` - `-` @@ -96,6 +105,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` * - :class:`~dedoc.data_structures.ItalicAnnotation` + - `+` - `+` - `+` - `-` @@ -105,6 +115,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` * - :class:`~dedoc.data_structures.UnderlinedAnnotation` + - `+` - `+` - `+` - `-` @@ -114,6 +125,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` * - :class:`~dedoc.data_structures.StrikeAnnotation` + - `+` - `+` - `+` - `-` @@ -123,6 +135,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` * - :class:`~dedoc.data_structures.SubscriptAnnotation` + - `+` - `+` - `+` - `-` @@ -132,6 +145,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` * - :class:`~dedoc.data_structures.SuperscriptAnnotation` + - `+` - `+` - `+` - `-` @@ -144,12 +158,14 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` - `-` - `-` + - `-` - `+` - `-` - `+` - `-` * - :class:`~dedoc.data_structures.SizeAnnotation` + - `+` - `+` - `+` - `-` @@ -160,6 +176,7 @@ Below the readers are enlisted that can return non-empty list of annotations for * - :class:`~dedoc.data_structures.StyleAnnotation` - `+` + - `-` - `+` - `-` - `-` @@ -171,6 +188,7 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` - `-` - `-` + - `-` - `+` - `-` - `-` @@ -183,4 +201,5 @@ Below the readers are enlisted that can return non-empty list of annotations for - `-` - `-` - `-` + - `-` - `+` diff --git a/docs/source/readers_output/line_types.rst b/docs/source/readers_output/line_types.rst index d7c42425..666a8d35 100644 --- a/docs/source/readers_output/line_types.rst +++ b/docs/source/readers_output/line_types.rst @@ -28,6 +28,12 @@ Below the readers are enlisted that can return non-empty ``hierarchy_level_tag`` - `+` - `-` + * - :class:`~dedoc.readers.PptxReader` + - `+` + - `+` + - `+` + - `-` + * - :class:`~dedoc.readers.HtmlReader`, :class:`~dedoc.readers.MhtmlReader`, :class:`~dedoc.readers.EmailReader` - `+` - `+` diff --git a/requirements.txt b/requirements.txt index e6a7ac86..7d449f59 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ beautifulsoup4>=4.10.0,<=4.12.2 charset-normalizer>=2.0.12,<=3.2.0 Cython>=0.29.28,<=3.0.2 -docx==0.2.4 dedoc-utils==0.3.6 fastapi>=0.77.0,<=0.103.0 huggingface-hub>=0.14.1,<=0.16.4 @@ -26,7 +25,6 @@ python-Levenshtein==0.12.2 python-logstash-async>=2.5.0,<=2.7.0 python-magic<1.0 python-multipart==0.0.6 -python-pptx==0.6.21 rarfile==4.0 requests>=2.22.0 roman>=3.3,<4.0 diff --git a/tests/api_tests/test_api_format_pptx.py b/tests/api_tests/test_api_format_pptx.py index b2df8351..214265be 100644 --- a/tests/api_tests/test_api_format_pptx.py +++ b/tests/api_tests/test_api_format_pptx.py @@ -23,6 +23,138 @@ def test_odp(self) -> None: result = self._send_request(file_name, data=dict(structure_type="linear")) self.__check_content(result["content"]) + def test_structure_and_annotations(self) -> None: + file_name = "test-presentation.pptx" + result = self._send_request(file_name, data=dict(with_attachments="True")) + structure = result["content"]["structure"] + + # Test headers + node = self._get_by_tree_path(structure, "0.0") + self.assertEqual("Title\n", node["text"]) + self.assertEqual("header", node["metadata"]["paragraph_type"]) + annotations = [annotation for annotation in node["annotations"] if annotation["name"] == "size"] + self.assertEqual(1, len(annotations)) + self.assertEqual(50.0, float(annotations[0]["value"])) + annotations = [annotation for annotation in node["annotations"] if annotation["name"] == "alignment"] + self.assertEqual(1, len(annotations)) + self.assertEqual("center", annotations[0]["value"]) + node = self._get_by_tree_path(structure, "0.2") + self.assertEqual("Title\n", node["text"]) + self.assertEqual("header", node["metadata"]["paragraph_type"]) + + # Test lists + self.assertEqual("list", self._get_by_tree_path(structure, "0.2.1")["metadata"]["paragraph_type"]) + self.assertEqual("1. first item\n", self._get_by_tree_path(structure, "0.2.1.0")["text"]) + self.assertEqual("2. second item\n", self._get_by_tree_path(structure, "0.2.1.1")["text"]) + self.assertEqual("list", self._get_by_tree_path(structure, "0.2.1.1.0")["metadata"]["paragraph_type"]) + self.assertEqual("a. subitem\n", self._get_by_tree_path(structure, "0.2.1.1.0.0")["text"]) + self.assertEqual("3. third item\n", self._get_by_tree_path(structure, "0.2.1.2")["text"]) + self.assertEqual("list", self._get_by_tree_path(structure, "0.2.1.2.0")["metadata"]["paragraph_type"]) + self.assertEqual("a. \n", self._get_by_tree_path(structure, "0.2.1.2.0.0")["text"]) + + self.assertEqual("❏ first bullet item\n", self._get_by_tree_path(structure, "0.3.0.0")["text"]) + self.assertEqual("❏ second bullet item\n", self._get_by_tree_path(structure, "0.3.0.1")["text"]) + self.assertEqual("❏ subitem\n", self._get_by_tree_path(structure, "0.3.0.1.0.0")["text"]) + self.assertEqual("A. first letter item\n", self._get_by_tree_path(structure, "0.3.1.0")["text"]) + self.assertEqual("B. second letter item\n", self._get_by_tree_path(structure, "0.3.1.1")["text"]) + self.assertEqual("○ first subitem\n", self._get_by_tree_path(structure, "0.3.1.1.0.0")["text"]) + self.assertEqual("○ second subitem\n", self._get_by_tree_path(structure, "0.3.1.1.0.1")["text"]) + + # Test annotations + node = self._get_by_tree_path(structure, "0.5") + self.assertEqual("Custom title\n", node["text"]) + self.assertEqual("header", node["metadata"]["paragraph_type"]) + annotations = [annotation for annotation in node["annotations"] if annotation["name"] == "size"] + self.assertEqual(30.0, float(annotations[0]["value"])) + annotations = [annotation for annotation in node["annotations"] if annotation["name"] == "bold"] + self.assertEqual("True", annotations[0]["value"]) + annotations = [annotation for annotation in node["annotations"] if annotation["name"] == "alignment"] + self.assertEqual("center", annotations[0]["value"]) + + node = self._get_by_tree_path(structure, "0.5.0") + annotations = {float(annotation["value"]) for annotation in node["annotations"] if annotation["name"] == "size"} + self.assertSetEqual({18.0, 24.0, 10.0}, annotations) + self.assertIn({"start": 18, "end": 27, "name": "bold", "value": "True"}, node["annotations"]) + self.assertIn({"start": 28, "end": 39, "name": "italic", "value": "True"}, node["annotations"]) + self.assertIn({"start": 40, "end": 55, "name": "underlined", "value": "True"}, node["annotations"]) + self.assertIn({"start": 56, "end": 67, "name": "strike", "value": "True"}, node["annotations"]) + self.assertIn({"start": 68, "end": 79, "name": "superscript", "value": "True"}, node["annotations"]) + self.assertIn({"start": 81, "end": 90, "name": "subscript", "value": "True"}, node["annotations"]) + + node = self._get_by_tree_path(structure, "0.6") + self.assertIn({"start": 0, "end": 12, "name": "bold", "value": "True"}, node["annotations"]) + self.assertIn({"start": 0, "end": 12, "name": "italic", "value": "True"}, node["annotations"]) + self.assertIn({"start": 0, "end": 12, "name": "underlined", "value": "True"}, node["annotations"]) + self.assertIn({"start": 0, "end": 12, "name": "size", "value": "20.0"}, node["annotations"]) + self.assertIn({"start": 0, "end": 13, "name": "alignment", "value": "right"}, node["annotations"]) + + # Test tables + tables = result["content"]["tables"] + self.assertEqual(1, len(tables)) + table = tables[0] + node = self._get_by_tree_path(structure, "0.4") + annotations = [annotation for annotation in node["annotations"] if annotation["name"] == "table"] + self.assertEqual(table["metadata"]["uid"], annotations[0]["value"]) + column_number = len(table["cells"][0]) + for table_row in table["cells"]: + self.assertEqual(column_number, len(table_row)) + + cell = table["cells"][0][0] + self.assertEqual("Horizontally merged cells\n", cell["lines"][0]["text"]) + self.assertEqual(1, cell["rowspan"]) + self.assertEqual(2, cell["colspan"]) + self.assertEqual(False, cell["invisible"]) + cell = table["cells"][0][1] + self.assertEqual("Horizontally merged cells\n", cell["lines"][0]["text"]) + self.assertEqual(1, cell["rowspan"]) + self.assertEqual(1, cell["colspan"]) + self.assertEqual(True, cell["invisible"]) + + cell = table["cells"][1][2] + self.assertEqual("Vertically merged cells\n", cell["lines"][0]["text"]) + self.assertEqual(2, cell["rowspan"]) + self.assertEqual(1, cell["colspan"]) + self.assertEqual(False, cell["invisible"]) + cell = table["cells"][2][2] + self.assertEqual("Vertically merged cells\n", cell["lines"][0]["text"]) + self.assertEqual(1, cell["rowspan"]) + self.assertEqual(1, cell["colspan"]) + self.assertEqual(True, cell["invisible"]) + + cell = table["cells"][2][0] + self.assertEqual("Vertically merged cells 2\n", cell["lines"][0]["text"]) + self.assertEqual(2, cell["rowspan"]) + self.assertEqual(1, cell["colspan"]) + self.assertEqual(False, cell["invisible"]) + cell = table["cells"][3][0] + self.assertEqual("Vertically merged cells 2\n", cell["lines"][0]["text"]) + self.assertEqual(1, cell["rowspan"]) + self.assertEqual(1, cell["colspan"]) + self.assertEqual(True, cell["invisible"]) + + cell = table["cells"][3][2] + self.assertEqual("Horizontally merged cells 2\n", cell["lines"][0]["text"]) + self.assertEqual(1, cell["rowspan"]) + self.assertEqual(3, cell["colspan"]) + self.assertEqual(False, cell["invisible"]) + cell = table["cells"][3][3] + self.assertEqual("Horizontally merged cells 2\n", cell["lines"][0]["text"]) + self.assertEqual(1, cell["rowspan"]) + self.assertEqual(1, cell["colspan"]) + self.assertEqual(True, cell["invisible"]) + + # Test attachments + self.assertEqual(3, len(result["attachments"])) + attachment_uids = {attachment["metadata"]["uid"] for attachment in result["attachments"]} + node = self._get_by_tree_path(structure, "0.6") + annotations = [annotation["value"] for annotation in node["annotations"] if annotation["name"] == "attachment"] + self.assertIn(annotations[0], attachment_uids) + self.assertIn(annotations[1], attachment_uids) + node = self._get_by_tree_path(structure, "0.8.0") + self.assertEqual("Text text\n", node["text"]) + annotations = [annotation["value"] for annotation in node["annotations"] if annotation["name"] == "attachment"] + self.assertIn(annotations[0], attachment_uids) + def __check_content(self, content: dict) -> None: subparagraphs = content["structure"]["subparagraphs"] self.assertEqual("A long time ago in a galaxy far far away", subparagraphs[0]["text"].strip()) @@ -31,8 +163,8 @@ def __check_content(self, content: dict) -> None: self.assertEqual("This is simple table", subparagraphs[3]["text"].strip()) table = content["tables"][0] - self.assertListEqual(["", "Header1", "Header2", "Header3"], self._get_text_of_row(table["cells"][0])) - self.assertListEqual(["Some content", "A", "B", "C"], self._get_text_of_row(table["cells"][1])) + self.assertListEqual(["", "Header1\n", "Header2\n", "Header3\n"], self._get_text_of_row(table["cells"][0])) + self.assertListEqual(["Some content\n", "A\n", "B\n", "C\n"], self._get_text_of_row(table["cells"][1])) table_annotations = [ann for ann in subparagraphs[2]["annotations"] if ann["name"] == TableAnnotation.name] self.assertEqual(1, len(table_annotations)) diff --git a/tests/data/pptx/test-presentation.pptx b/tests/data/pptx/test-presentation.pptx new file mode 100644 index 0000000000000000000000000000000000000000..97eaf6a94c201b49cb0fbcfcbdb5b3bea97fce72 GIT binary patch literal 111665 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⪚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 l-dg<*V+>b?$B9s$yuo`2k6eQpvm) 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 literal 0 HcmV?d00001