From 95c1f800876f6d8d5ae67ad63a1ff3f6d5680757 Mon Sep 17 00:00:00 2001 From: Christoph Auer Date: Fri, 11 Oct 2024 14:53:38 +0200 Subject: [PATCH] Change code to use unordered/ordered list, robustifications Signed-off-by: Christoph Auer --- docling/backend/html_backend.py | 50 ++++++++++--- docling/backend/mspowerpoint_backend.py | 9 ++- docling/backend/msword_backend.py | 20 +++--- docling/datamodel/document.py | 84 +++++++++++++--------- docling/document_converter.py | 1 - docling/models/tesseract_ocr_model.py | 1 - docling/pipeline/simple_model_pipeline.py | 5 +- examples/custom_convert.py | 9 +-- examples/run_with_formats.py | 4 +- tests/data/powerpoint_sample.pptx | Bin 39964 -> 41639 bytes tests/test_e2e_conversion.py | 2 +- tests/test_e2e_ocr_conversion.py | 1 - tests/test_interfaces.py | 2 +- tests/verify_utils.py | 1 - 14 files changed, 111 insertions(+), 78 deletions(-) diff --git a/docling/backend/html_backend.py b/docling/backend/html_backend.py index cae81085..216d156d 100644 --- a/docling/backend/html_backend.py +++ b/docling/backend/html_backend.py @@ -1,5 +1,5 @@ import logging -from io import BytesIO, TextIOWrapper +from io import BytesIO from pathlib import Path from typing import Set, Union @@ -81,9 +81,10 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): try: self.analyse_element(element, idx, doc) except Exception as exc_child: + _log.error(" -> error treating child: ", exc_child) _log.error(" => element: ", element, "\n") - pass + raise exc_child except Exception as exc: pass @@ -212,10 +213,18 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): def handle_list(self, element, idx, doc): """Handles list tags (ul, ol) and their list items.""" - # create a list group - self.parents[self.level + 1] = doc.add_group( - parent=self.parents[self.level], name="list", label=GroupLabel.LIST - ) + if element.name == "ul": + # create a list group + self.parents[self.level + 1] = doc.add_group( + parent=self.parents[self.level], name="list", label=GroupLabel.LIST + ) + elif element.name == "ol": + # create a list group + self.parents[self.level + 1] = doc.add_group( + parent=self.parents[self.level], + name="ordered list", + label=GroupLabel.ORDERED_LIST, + ) self.level += 1 self.walk(element, doc) @@ -226,13 +235,26 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): def handle_listitem(self, element, idx, doc): """Handles listitem tags (li).""" nested_lists = element.find(["ul", "ol"]) + + parent_list_label = self.parents[self.level].label + index_in_list = len(self.parents[self.level].children) + 1 + if nested_lists: name = element.name text = self.get_direct_text(element) + marker = "" + enumerated = False + if parent_list_label == GroupLabel.ORDERED_LIST: + marker = str(index_in_list) + enumerated = True + # create a list-item - self.parents[self.level + 1] = doc.add_text( - label=DocItemLabel.LIST_ITEM, text=text, parent=self.parents[self.level] + self.parents[self.level + 1] = doc.add_list_item( + text=text, + enumerated=enumerated, + marker=marker, + parent=self.parents[self.level], ) self.level += 1 @@ -244,8 +266,16 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): elif isinstance(element.text, str): text = element.text.strip() - doc.add_text( - label=DocItemLabel.LIST_ITEM, text=text, parent=self.parents[self.level] + marker = "" + enumerated = False + if parent_list_label == GroupLabel.ORDERED_LIST: + marker = f"{str(index_in_list)}." + enumerated = True + doc.add_list_item( + text=text, + enumerated=enumerated, + marker=marker, + parent=self.parents[self.level], ) else: _log.warn("list-item has no text: ", element) diff --git a/docling/backend/mspowerpoint_backend.py b/docling/backend/mspowerpoint_backend.py index 7703e3b1..b67c3ca3 100644 --- a/docling/backend/mspowerpoint_backend.py +++ b/docling/backend/mspowerpoint_backend.py @@ -43,7 +43,7 @@ class MsPowerpointDocumentBackend(DeclarativeDocumentBackend, PaginatedDocumentB try: self.pptx_obj = Presentation(self.path_or_stream) self.valid = True - except Exception: + except Exception as e: raise RuntimeError( f"MsPowerpointDocumentBackend could not load document with hash {document_hash}" ) from e @@ -134,6 +134,8 @@ class MsPowerpointDocumentBackend(DeclarativeDocumentBackend, PaginatedDocumentB prov = self.generate_prov(shape, slide_ind, shape.text.strip()) if is_a_list: + # TODO: determine if this is an unordered list or an ordered list. + # Set GroupLabel.ORDERED_LIST when it fits. new_list = doc.add_group( label=GroupLabel.LIST, name=f"list", parent=parent_slide ) @@ -157,9 +159,10 @@ class MsPowerpointDocumentBackend(DeclarativeDocumentBackend, PaginatedDocumentB e_is_a_list_item = True else: e_is_a_list_item = False + if e_is_a_list_item: - doc.add_text( - label=DocItemLabel.LIST_ITEM, + # TODO: Set marker and enumerated arguments if this is an enumeration element. + doc.add_list_item( parent=new_list, text=e.text.strip(), prov=prov, diff --git a/docling/backend/msword_backend.py b/docling/backend/msword_backend.py index 49911009..c3504b33 100644 --- a/docling/backend/msword_backend.py +++ b/docling/backend/msword_backend.py @@ -312,9 +312,8 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): label=GroupLabel.LIST, name="list", parent=self.parents[level - 1] ) - doc.add_text( - label=DocItemLabel.LIST_ITEM, parent=self.parents[level], text=text - ) + # TODO: Set marker and enumerated arguments if this is an enumeration element. + doc.add_list_item(parent=self.parents[level], text=text) elif ( self.prev_numid() == numid and self.prev_indent() < ilevel @@ -323,12 +322,14 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): self.level_at_new_list + self.prev_indent() + 1, self.level_at_new_list + ilevel + 1, ): + # TODO: determine if this is an unordered list or an ordered list. + # Set GroupLabel.ORDERED_LIST when it fits. self.parents[i] = doc.add_group( label=GroupLabel.LIST, name="list", parent=self.parents[i - 1] ) - doc.add_text( - label=DocItemLabel.LIST_ITEM, + # TODO: Set marker and enumerated arguments if this is an enumeration element. + doc.add_list_item( parent=self.parents[self.level_at_new_list + ilevel], text=text, ) @@ -338,16 +339,15 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): if k > self.level_at_new_list + ilevel: self.parents[k] = None - doc.add_text( - label=DocItemLabel.LIST_ITEM, + # TODO: Set marker and enumerated arguments if this is an enumeration element. + doc.add_list_item( parent=self.parents[self.level_at_new_list + ilevel], text=text, ) elif self.prev_numid() == numid or self.prev_indent() == ilevel: - doc.add_text( - label=DocItemLabel.LIST_ITEM, parent=self.parents[level - 1], text=text - ) + # TODO: Set marker and enumerated arguments if this is an enumeration element. + doc.add_list_item(parent=self.parents[level - 1], text=text) return def handle_tables(self, element, docx_obj, doc): diff --git a/docling/datamodel/document.py b/docling/datamodel/document.py index ede4e328..5ec8b6d1 100644 --- a/docling/datamodel/document.py +++ b/docling/datamodel/document.py @@ -3,7 +3,7 @@ import re from enum import Enum from io import BytesIO from pathlib import Path, PurePath -from typing import Dict, Iterable, List, Optional, Tuple, Type, Union +from typing import Dict, Iterable, List, Optional, Tuple, Union import filetype from docling_core.types import BaseText @@ -23,10 +23,6 @@ from pydantic import BaseModel from typing_extensions import deprecated from docling.backend.abstract_backend import AbstractDocumentBackend -from docling.backend.docling_parse_backend import DoclingParseDocumentBackend -from docling.backend.html_backend import HTMLDocumentBackend -from docling.backend.mspowerpoint_backend import MsPowerpointDocumentBackend -from docling.backend.msword_backend import MsWordDocumentBackend from docling.datamodel.base_models import ( AssembledUnit, ConversionStatus, @@ -372,14 +368,20 @@ class ConvertedDocument(BaseModel): strict_text: bool = False, image_placeholder: str = "", ) -> str: - return self.legacy_output.export_to_markdown( - delim=delim, - main_text_start=main_text_start, - main_text_stop=main_text_stop, - main_text_labels=main_text_labels, - strict_text=strict_text, - image_placeholder=image_placeholder, - ) + if self.legacy_output is None: + raise RuntimeError( + "No legacy output was produced, can not export as markdown. " + "Please use output.export_to_markdown() instead." + ) + else: + return self.legacy_output.export_to_markdown( + delim=delim, + main_text_start=main_text_start, + main_text_stop=main_text_stop, + main_text_labels=main_text_labels, + strict_text=strict_text, + image_placeholder=image_placeholder, + ) @deprecated("Use output.export_to_text() instead.") def render_as_text( @@ -394,13 +396,19 @@ class ConvertedDocument(BaseModel): "caption", ], ) -> str: - return self.legacy_output.export_to_markdown( - delim=delim, - main_text_start=main_text_start, - main_text_stop=main_text_stop, - main_text_labels=main_text_labels, - strict_text=True, - ) + if self.legacy_output is None: + raise RuntimeError( + "No legacy output was produced, can not export as text. " + "Please use output.export_to_markdown() instead." + ) + else: + return self.legacy_output.export_to_markdown( + delim=delim, + main_text_start=main_text_start, + main_text_stop=main_text_stop, + main_text_labels=main_text_labels, + strict_text=True, + ) @deprecated("Use output.export_to_document_tokens() instead.") def render_as_doctags( @@ -426,21 +434,27 @@ class ConvertedDocument(BaseModel): add_table_cell_label: bool = True, add_table_cell_text: bool = True, ) -> str: - return self.legacy_output.export_to_document_tokens( - delim=delim, - main_text_start=main_text_start, - main_text_stop=main_text_stop, - main_text_labels=main_text_labels, - xsize=xsize, - ysize=ysize, - add_location=add_location, - add_content=add_content, - add_page_index=add_page_index, - # table specific flags - add_table_cell_location=add_table_cell_location, - add_table_cell_label=add_table_cell_label, - add_table_cell_text=add_table_cell_text, - ) + if self.legacy_output is None: + raise RuntimeError( + "No legacy output was produced, can not export as doctags. " + "Please use output.export_to_markdown() instead." + ) + else: + return self.legacy_output.export_to_document_tokens( + delim=delim, + main_text_start=main_text_start, + main_text_stop=main_text_stop, + main_text_labels=main_text_labels, + xsize=xsize, + ysize=ysize, + add_location=add_location, + add_content=add_content, + add_page_index=add_page_index, + # table specific flags + add_table_cell_location=add_table_cell_location, + add_table_cell_label=add_table_cell_label, + add_table_cell_text=add_table_cell_text, + ) def render_element_images( self, element_types: Tuple[PageElement] = (FigureElement,) diff --git a/docling/document_converter.py b/docling/document_converter.py index dc919883..44424dba 100644 --- a/docling/document_converter.py +++ b/docling/document_converter.py @@ -11,7 +11,6 @@ from pydantic import ( ConfigDict, TypeAdapter, ValidationError, - field_validator, model_validator, ) from typing_extensions import deprecated diff --git a/docling/models/tesseract_ocr_model.py b/docling/models/tesseract_ocr_model.py index 5173c1bf..56202ca9 100644 --- a/docling/models/tesseract_ocr_model.py +++ b/docling/models/tesseract_ocr_model.py @@ -1,7 +1,6 @@ import logging from typing import Iterable -import numpy from docling_core.types.experimental import BoundingBox, CoordOrigin from docling.datamodel.base_models import OcrCell, Page diff --git a/docling/pipeline/simple_model_pipeline.py b/docling/pipeline/simple_model_pipeline.py index ceef4d06..98708a53 100644 --- a/docling/pipeline/simple_model_pipeline.py +++ b/docling/pipeline/simple_model_pipeline.py @@ -1,7 +1,4 @@ import logging -from typing import Iterable - -from docling_core.types.experimental import NodeItem from docling.backend.abstract_backend import ( AbstractDocumentBackend, @@ -9,7 +6,7 @@ from docling.backend.abstract_backend import ( ) from docling.datamodel.base_models import ConversionStatus from docling.datamodel.document import ConversionResult, InputDocument -from docling.datamodel.pipeline_options import PdfPipelineOptions, PipelineOptions +from docling.datamodel.pipeline_options import PipelineOptions from docling.pipeline.base_model_pipeline import AbstractModelPipeline _log = logging.getLogger(__name__) diff --git a/examples/custom_convert.py b/examples/custom_convert.py index 0805837b..07b4f171 100644 --- a/examples/custom_convert.py +++ b/examples/custom_convert.py @@ -6,13 +6,8 @@ from typing import Iterable from docling.datamodel.base_models import ConversionStatus, InputFormat from docling.datamodel.document import ConversionResult, DocumentConversionInput -from docling.datamodel.pipeline_options import ( - PdfPipelineOptions, - TesseractCliOcrOptions, - TesseractOcrOptions, -) -from docling.document_converter import DocumentConverter, FormatOption, PdfFormatOption -from docling.pipeline.standard_pdf_model_pipeline import StandardPdfModelPipeline +from docling.datamodel.pipeline_options import PdfPipelineOptions +from docling.document_converter import DocumentConverter, PdfFormatOption _log = logging.getLogger(__name__) diff --git a/examples/run_with_formats.py b/examples/run_with_formats.py index f086bae2..cf5cd1cf 100644 --- a/examples/run_with_formats.py +++ b/examples/run_with_formats.py @@ -2,14 +2,11 @@ import json import logging from pathlib import Path -from docling.backend.docling_parse_backend import DoclingParseDocumentBackend -from docling.backend.msword_backend import MsWordDocumentBackend from docling.backend.pypdfium2_backend import PyPdfiumDocumentBackend from docling.datamodel.base_models import InputFormat from docling.datamodel.document import DocumentConversionInput from docling.document_converter import ( DocumentConverter, - FormatOption, PdfFormatOption, WordFormatOption, ) @@ -40,6 +37,7 @@ doc_converter = DocumentConverter( # all of the below is optional, has internal # InputFormat.IMAGE, InputFormat.DOCX, InputFormat.HTML, + InputFormat.PPTX, ], # whitelist formats, other files are ignored. format_options={ InputFormat.PDF: PdfFormatOption( diff --git a/tests/data/powerpoint_sample.pptx b/tests/data/powerpoint_sample.pptx index f54963e28e0f4638e60e2506f4b1b6db835dfe4b..9779aa6c2fcf8c951063a8acd713c93dacf41e5a 100644 GIT binary patch delta 18838 zcmZ6yV{~O*(5@YJY}A&!2l!nz0AmAm#Hs^ ziM1Fk(`mC&Jq2Usa4N^(Eh8ZI1gi}Qq0N_OpvwI^5yKQo{I{RC+}CLuKTzQu;0K*4 zz*TN5`@wN4BF2P;1iTefDX*(cznh3iLl2|VAOD`3(&;S!c3Pmb5&)k&=aI7F2+h*i zHA~Dgt4V2rm~A1%4hQI72C?kav71(shMHB^+Yw%=hB|6Ybllj5XlG4gLIB@c{}Cx& z9dO0PA_eYRJQz?Xi(AsPMdE^8YKp^ zI(DUg1hd1#WYj8Zdnx>oo^hcssP&R9~sEbz>9h zEBe(%30R!K3FK+6#U^WZMdH|@(E_yvgW1NXIjw~o{-CS2NJ%B?cm4E)a%GW{Y}D`U zvcs;rA|*OaF-i=jD^X2x6{Cfu2OYRio?>J@nTH zi{D#Yo`&6mnnWAB#0Du#khR7PbjW-1b(0>r7tM3lP(iHT(V|zsj7h^p8}u;p>1zu1Hd~NuVtrIn6_6>XDXK z6uQ))8<4uLyS}^Gut8L%;dIc703Gg5yu;Fhi}lArLao82cN9=;IIb}iP45Yjv})UK z=mKleup(H0U^j7NE?aR%gp#g%6v@XPo+~jpHV40eIoL`XxZ`Rc74^;2g zW>z#IomP}jEyfd>)_FPBi~q@ei|J$;)8x$IsoP=#g#)2?Zwfmp^Z+bhdbWK+a?>`x zO)xR)IQBVNIwMKLK^o9Ir7xFQY-;Ht7TZ4D#@N4m-2m=yQvwqd%bKVTzQY?!R3^o0 zR^(&q%RAcu;C5Z-&O2mj+J0N;hUk8A&d01&$&@p@&%V*iLj<^7r6A=q2fBe3eo|KD zqSyyh>UhB;4g;Gr6Hix88BZwI>?knrrbSuF<8G7DT5mXL-x~G9o{e3kym;R$%1OBiNDeU};8fh_nP#|`lmV8@PaFM$wkpj& zYa-1)v)>E3R2=`;z#$9h)-78WbqC7^%M}bXx8C)EVk9=yPqrG&=FSjE)%d<|qG)jTkAJO)k!d zUxvg+*~o`0E{Qnmrj~a(OQ5|*2=`t~56AjQ3jhawT0Z0B372C(5&w~=8LBDv{`x40 zI!^OvH9U+s#*%72QpZ=>?Q^CaLC58z$X$ls|F0ORzPs6OdsGB8%R-38Yrv;>=0{oh z-*2!60+*j-AQV-dgJ7G!r%PnFhjbk=7CVs^_EO-Nkv=Vkh50FZN!|xo<^-*OoH1L+ zr~x$V+D$R~f^=Y4V}=V(S76RwH<(X|(!Yc+hOErANux{!S@0c=BA2FSnF+N?M;mQ1 z%_ZqUub|5}kT=NqwYk8Y?UQ1gxAr5psGY@VRg%L=P~Alr(hklDjJ`|L(oSQ}g$8GT zgPrO^-uu>PX9f)Je=J2^w#i6kDJxziC+_7JY#bxD@mzrN`KFJ`bVOnIR!;5kM#6 zZE#^Cc3m)Csb8+2E3xT~;|wQkP70?G zunn}gg;5%9py9;+D*<(02H=QqWGLX5<1PYMLxgP9Lcu@kFQAaC=>Vr1`$tchm$<$CEu(YfKOK4w_P937r3XuU6(2=4n z+sBL^x(WFy+H%QZH&4^x%0zl5jGQY-3~aVzmKU+ldDz6`U|7c<2;bS|9^rrHg3+$& z;+X&*No$i4%c>Yz%IMO}L3^(A>8*hk5zA9Fu~Yw)3{rRU2l`4dh~gJ&aGS6UBm{6k zcnoo;GPoz9o=*3tuDmFOQTz1)a_KkCgZUKaARl+(sS&>~x1nw=&QsLMUtTdS18dYH zAAxU2(;;Y*jugjM%WQ8}z1Wx_9@_s{1bB2SVL2*WQh zK?pv+hvCfKo*bmAf~5D;60t!x+G+_^D^x9G8Q|*C-ucQnL~5sI^L%2Iw&_<%UD_ zcdzj?2yGQ(4Wm&U>6t(&*UqOGbAu^sVRB_AqoMLpwj60`FNJ7z=Ti*-rtN6X+I2^{(Q6T!a9O0N{g{sX#>tc? zo`n-(Qa^8leIB_o&JP(d0<&$2Yh42?vQ}D``5t0%wBI0vNtoUBYGQA+7sYK_^`oTX zd3gQ8JCdM67_6OOs94<5t+zzCfZOXCX>5clemg(LI4F~D4*}OE|Hd1B^1W77DeOr; z!C%xey<&TVWNF4VpG?Kh0Q%yzQD$&yS2L=%eoSNyoe1 ztqO4}rU~3^rpxPE7V#P6^0x_9%mOFL{B^qBctupAa4~`|msL74Zl_Bp0V^~Sz&Z@Q zYV|(n;{9N1a!+Tp^TSYRzj+cTvh4Au zf&v1@FsXdSJP~7fYjO1#qUF_=w3kfvMQQ}3cJ18uB71iou|Y6JP%1x^&B(Ja|!K$ z8FSAWl*oTSo-LheTz9w8$z1Cmt<)yio5608g z`HFG#wS#OO4r_>G^HiD$fL8iCbCH{e@ToU9NQ|~0c2e63v95ZB%t~73f`f6u(olkz zzXpaz@;vjE##G&8MMJ{D!gS|(@!w91*M`fV|0m^qh7tGRubf_-LZ2B+4UT}2~q zaC;_V?i>zW!KvvE7tUY&nG&Y-hgY`Zg5+QL#nYnr;rO92kIFKc=}Mfj)M!L^)}(Pa z2Dmc*bQV@9PQjCaw((bYOU)DQjfG@J3op>*5JkBY>do7PhJa8|*w$Ur6O$OegYSD! zfsV|dOG@6|>b8K!M z4m|B5o1@>IsE0iF;*nvCO~PYdL*micl9iM-xA1)9mevyiZSbo*GPMHXn4aTVzU#en z9s(vB!91#(sci3d;ynDtZI*IxVVfc~{^5VNFN+!OYIY^&*6O>%XO4-I)sdnr=YgEbR69hM zUogaC&W7{_0J(`Ce<`ZbJhIxn7_e-)cf%sS>M(`({nBVsPy+Rd+{oa6~yOdq29m7VXl~0 ztq#3nx0C7aPf^h|r6n+!(8kHZa_3ysrUNGH@+XXoW~6(hkLhKVIap3zF28NOH%~~o zu}u$*?pYnpeatZ*ye_!H(gh)KY`Iy-N!dcCUklUsOA(j{KDsYL+i1mLl7D)0A! zvptDMp+~MPWsI~pP!R4*^@keJ-!D$OXN>J_d_pPMV-!{qkhMPg?3w4Im;VQ%-3lz+ zBxg{-*_5!b2Zq@hO%NIt1(uU?QGnG_1~1~G=HcdeSFqdn<>`{FCEDsB9>Qf_-eFb& z`z1)iAVLHzY-AfpT$mO=g(v2g`YuRHu%<5TDtjgHPrFsA&1aI|V%h;W8EnQOb-ta( zA3O}!gQu%cEjhMW+-32~NWr;hQQiC6hKq@Xh+iB`pTqEOIvKlv*U@ud-{y~=1pkF! z1T&S~MfEQo6pr*iC?jf&$Ke16K$aY3Zz+NMIh8t2`3@I!``Njz<>{Ur zqq)<<9=Xkg#LE+A-$|M{jj){4) zo=#0zu0h6;LUJL0Y@Ey9VQ;afvO$0zlm4F2fWk6r>m>!eXoFkho; zNI_d6v70Hn7m9>1riAjrkbgqbD$g99ly2R{^v%ur>1Ma@>&p~MMKoavpqS>wo5PtZ zPIObjf+Y$DU5*n0{Ak=4X+LkbO`0znl}dH(IN~*hx6TXOgXbeNGEVaafEslul+U1k zE^=fl7lC!s^=B3+zso=@nKlZ*wzJ@nnh$9=j_&F*ZX=z|`Np3rPpo3i04)@FCvj8E%^KZV54!qg}1!j+y{)mp4- z=9q)vEb$w2zV~AoJL)~gxaTjt5$7QBq$4!;jU^xqER8sR&Dusv0rn39Q+HZp7x8n@ zTnVihr>pF9)lrr-e&Zl|F0!Jlbqditvy7vNO2SWSFzqB%q58|9fMPb{JlV#K4Fwpb zjKdkRZMkcOz$r2KcWuoMqAH-On3aL#29Q_c`~6ZarMz@*k=3T>oSeJ1e}c)0@JamI zpB?}Lc>IPrUYo#OB=1Z_Sv(k1i{imiyI|s?ljeryt%tQ5`GH;i$=_!mPM&HgFA@i9 z`-5y;g#?+dH+eh4551)m=|(jm-ktAM-J;;20(BA3B4lXumN}n*Xdb1TdPlR_kL!k{ zg;U=IJuOP!iXCdIm2Ih@>)zEHKCD)WIyXRCN0!hXWfwOi+DS9TsU1ZntEa&sq@i0A zPY))K%6(ggF~uCbQHBNaJs4I3@h!-pu~cUI3%X#ScasqtF+=MonaSB4GTNmsX;{~( zh<9B?cZpu*$Ur8Iqq=T|Np0z%^}9spOw4><9g6$Vs;H(WMditgo@KA63Y<;y;t2rS zFrGp|qZ(h6dW9h3{NUR9a40k1^>HnOW`$(HKfo0cF{qO0Rn3uo5T>R%7*C|i#T{8s zDj&IKkn7I?Z_6~?&%`BR&-=;J-b!Hw&v*U~bmiQp-M)W+Mi7}q{&wKUA=Q54-bQ%1 z`nJUT)WT0=fZ*IK>*2}1)Hk)N3fP$^rs~)xG}wU}^4ee<4sXYdHLzO(j%;oY9C2n@ znS}A`j{}a?uGY$bweETFU|dS^VxUSgDik0!1cVV=NPpXbrXcP!Kuw~T6*=JdFIACQ zwX{xM9BVbj5x<#F8}Rk>Ypi9)k|2}42emA`2TLl;`4)gOE|j!`uEZ%u3<#oE&<}yW zTU&h&ZcxJ?t=O(=(}DYNXFv$`_*Lw!V`FKia@(;^tCT0Q7&tBLSxObUHS{>}QN^*~ zrZe*D-6vVmOg~u&FDYY9t{^N#3JtA-EG1?P20p5SB-pi)rVKnYmW)^Wp?CC+UX;dB8#jn}fF7&1^sA|){cf@WMMk7+(EPzZG^s1PT%JW*=9iRf=ckg0uqCb^3~ObhuUN zrGVp%N9uF362_FWK#9H*#;U40j>_%xF}Ce(%lvR?oMCK}XYQi|rv!PdS38wO`C>1A z^9Ar|=@1~U`1wC+HWfzlc+*#G`h)g=_?lcyh7OQ|2F+W-K~8WVjO1^61;PGpfGebC zxp->9m%M0AM5U-A9q@@(%j-Uf)v66cLXhjyb;(P2eQ;i4SH+GdI?>LLchLeIXiL&` z^8o(%bV>@I27c3aRiC+vJ731Kt=qi#e4ESm_pq!8-U+JxRc!0pXJ7w=srbx;;0JYj z6$2oQV53o?Q`d0@Q-wc@wG?%rwPBqD(OG}zxA^+*3R$mKYi%k?vLNxANTyuEGrVi}u+qEM! znrYD%ET%L9^p6ZBIN^U)%`57ka)x)F2VatBmimq#i0@?_7L-F8uXi$^aF!N?Bj;afVJ{4D zMw$XLLJ~cRT%>g5MzGw<3d3AO6hGXkN+{=`a)L)H(nMILfuOb$M!-mDqwe866phh< zjvltMD|4xKsBW<$ivoJa;)Ca%AX5h2`p>Ngp-b#v_s6Nec)Ia4>sr&uS1)9bYM_54 zub^)8EqdJ|Vd$pN_@Lm6hzJD%mH=1=&4oaZ5$Kw=Qh9y<-{j3&>awSPEK-#8joq`2 z4Ta$NeQX+9ngkeyPwyoxFQ+L98&BN4`{S-pJTx7d=*i!!ib|-LlQ>hI!8%ok7k0q0nIz1$z<9uj*U`>d$H@4=zVdU{C!HO`cVF1Q0@xz9x zhP(AKe6d9esVtjJr^55FHs;?fy=}fdWHFr{RFv`MCa!Rc4sT$8#zI6^E9Qab~Iom{g!bRWj2nSD9+q^O8`_!r}8sJVtCqnlu ziTB9EfT5FOwS@G0MfG8qJ^^@7R+ulO+bEfZ1Vi3Mmzbz+0hsPOQtqB;mi$?1aA>a$&s-TZk)`TGIQN{cb|VUQseIp2t>PP9Z+ zbAqO0kt2-reldzbcwg-M+LWV*HP~w#K#Xq5QNc`Xo=EU^#P(TWOkj2+7Lq! zdl&Uo3Hbz9hsS|AF8Xx#HxqzjU$PVvq(hXS0^-EM((nyjq9EQWVXcaDF$w91t0GZ} zj(}>|0u@e|i^RSiRj$VlB`DUvL-P78r+pRto#0$v#R1{k*d|AZ0cKp^xP)+e`iqHS zm4uk@XVC#rJ>exP+yEcsTS-LJ&&tV`X>||d6fjOjGUQ(;r0B2pa6$A@yD{YCQrqge zIBdUiZ|qlZZuW1#^6TffOI9_kxp5+$gR1O}egZ#zQ8qatuzv_c58$E_81_Rl%?e?; z|2~mRxbwQE9K7mOdUz;z*TG>}sCJEi+{k$M9GuYOqA!?1{fQ_Mr{_}{D7bK42}HS! z{&2LDn$5aJV;AkDJm9+bj*9d9xC4F?{g+;6t07u&8>(LPdL#q!siWvW?eNH8VT)EIK>C6{&LF{hPxQ zf%14f)~&vqmih)YaCmU4x$WNRi8qGy5|&PuH(%R9pY+C(X~`zMh5Zk)ME7Dq=}S(> zS=BGW%&JMs+ad%BeYVu@qXivVNO+Qeq2FPK@7IMWm;S8g`o!vLOL;2@X z5LMSSm}R*wytbU1nP#TaG%HbiZ}@{FMA6UfCV$dmgXSb-)5*{^5;~_8S~0nlg=veg z;p3){j;e73?QsJJpxku77pZX1y;y&$_=~wx=ENq)(ygFSeJ>yVJG!rOz)PH^-$iuo z+UQ9S3JSOtCyU3-EpQYymZ8zmb@gZ5z2O;Z2e(ut$sui+&5GJOo~M*(5?3$oG|_i> z3q4^#547`10GBBQfruLe-94e%h>aLh-|V?Rx;?d9U|*H-dy3VpLYi5dQ#p@O%iq(c ztwxI8Is3M~Q|#YUKvK{Z8)zyDWkib|@%KxThykEuiQ)Ml-a?waDjsa<4mUl+Z>jU^ z3nq$?A%*xmcmkmM!5Q7`dPIlZL=RX9du;Np*o%v!>@|I!U-mEayZoOIVb%ul2QTw> zYqA%95=^;Z--JT(mBA-NAZligQb+tf4|>XT^uxD4|C_M35XaM+?S671!r_*h8Q(X` z=fnC;Z>rBoJ+HLq$hF|pDWNfAy`y;dGSA|$F?2sO8}WxCCa{Idy&96VTUXC?xY{u741Q+8S*j~xWc)NZTv90@G3^cEN9AYLtPls ze?6x9GeU=vgAQ?+m{0NqyC2bJAGJd&tE4qOe&0vlkK*O^XS)```l0OL2@>!UbJ|Km z=NPA#Hbgxx4Xe-YL~_g}4VyK~{Am9=UPf_F+*S%qzuf$IK7VZn=1l=7`hC@LOh($BU*g;}T;&g_v2TnE4kh5+s(snch`4*+U!jX! zROYwpD&*VNm(nhu8F!q_DM~cx6adD$AUjvR+VAhMZn}wSKB%v+SFH(du%fq5mU(Jk zmt6Lb@<-12`F-3f)`smbsbRhS1ze_rbGJE-XkI9k8y|a_wxTf*O}z-aUfHgWrO~yd zavD%POAfDd5MIAe+jyG|OaHQL33?gQ=a1o7y~?o-Mko8l zGV{qOo%>D5XZ`9T_!OJd3k2MK3e>CBiner@0sH%ILG1380c?TC`nD#wEg+1}%6F5n z=9j7_k9(X`=kuR43;XuqWlyADhqE-Mc-`d_44o}}O-5$7Sxv>&er4``Gy2Qw{firz zP3LC+-ql7Z&rSRaW%&XAFj4xPAi8Zm_73#+uJRC9*JL?qtfGd2bMsDTK^BRIfh^^I zqwunP<&SPy*lBoVYjdBbYU?Qh0k}`jAjdVQ{;UNiarX z5&TEiPGm1{e57V4V!O6#Y7plMlTdGVH6y%d4;uKwvh4*-24rEJHo!3Vu3)ham&}l( zXr)Y*Y<%J;lWszZFrJt(BL6%#ji{F}9QrGaFpY)wHX7QHzDmBFQKch+2?_1-wl4mi2hJSo}?KS6X)& z8cUx7eE!P zckg-PJBNRlBnj{0_KWe?+)ypX3H2$2l2txg;-YfC-+|3v3-6hih!IJG+z~q= z2XF3YD0eH&M!V(NgTwh7-G4x%6B|Kp{i+eUWBqReK%5E*7}q-eDiLA73mRP#dvLsV^X3&2e53zFT<6eg`R|*j^Tg{&WpX~idztXw z+&{~J6V6x~5Z5Ls6HnzrvQqTrkvZs)dBu_+vw2>wI<8O~ZeE{fyPSt*{CDd& zRgF=4%CYFl$4`Ht=NwLp8B28gYUMHst1a}4Yn;Wa=C8$IJ*o{#PY4ZR=o!uz#{XK z6U#*akg$6Vf~cdB-32RWruj#CYMQ)~@#2La<7(6s-Q+jN`=hJMC4#Z@rKL%5DAXI@ z_MV61nO#9C4IuC_(S+8J!FqEdln=t(#|7fyh!1UR+MCiU`l1bFP!eA4s`&ds_d>;>P@sZqAw+mi8p@@dwl+H5X166~Oe0*L-dB2er`5ab;$ zWg&tg(<7R5-MvcP;q6JcpW)k<`kO@%+}R6mB;uorD{cKnO9aT_T8~g~6|$~a(H(A8 zpu?z_JxTwbNoPGPr&{0%#f?ZdAbV-ytg!NCYdB{6GO)TQXu`Z^7&$f6Pn4rQZm2>C zo6_)3e%?&z5ta|mO&a^+d3B_&ljS2tiVzGo*E`tmzYasO%-i8hcy3Y}LG$mG^B;kR z=<*IoMI;>3E`dWg1JOjKA^{u9L_#f1hcO{h=Z?x3s~PYGr_)eTH{It3o9WeYBMV#@ zzGS*1tP=}Mk%bVg9MGotLDUT}j;Kta*xSS+1rB|s{9TC4S<$>Buu%8iIMpwl&z+!U zo0jq8qrOL&s+#VyG)9cZ#8J}le5;bg0rW9;A$k$#QwOzSde+oYQGmuB>zV6ExB`l` zy0o>>>Mm5}k-3+_z#WJcRp`=)wHN8ht!oeG#g z(SxvG;rj`%O-)`Ej$RZmn=_BT^}V-B@wU1Sy7>4@`o$j-YFbw+T~NIeyc~D#6=g zz6K1ELjlD8P;AUk+!7dzIP=-0;`f!M;D%!%zJY7*l)K zxl7;^Y+HJi%={L=HmLyvsCh|WZ1BkjUZ$^*r*5p1`Bkb9;{R+$o^OBde%mwrkL$je z)z;x(T&MWITzB~Yaow_8I}$5W?ThP8bP2#eN&Eq{GxbXAlruGrg+hilJ~;v-QZfzI zlveA1ac+hRkK!dahg>|VPoAUY)p2b$?!{H}v#v7ja62ZmI?8GlCj@Izd*q6+ta3}u zRc}>q!yXT!8w~+o8+mu;{&^d0bjDIKfHpyC#ff6%^GNgiE`x-ttfaIqvWc1?0u>GXQAgbNRBfAU7aUfn$_O# z4K_@x(F#a@ja^4Eq?$@(Ay%<~7~>b9!D-n2{MBiBW}YqPKdMW_OqA0^wkvn1o$TTn zn~DAao=&7WTt-Z!T@%bK+=19!7F1M_w65;|EYGPFNm)}uE57Br97vg|pi`KLmkt7> zQh=5+gG1&eCXR@NLIs3q$5^70p82a375F5%>ABp}=CgfU*X_^{UtsrZM4oCW!G-*O zET;lHB2_+mV|w;nFB$2}Qv&K3c?jCO1C5L%&X(d868UJA1Cn{`IW$4aj8YQDR4Y6i)0{@ zi!1_%BK&Bf_8!D+gDAU|i#A6pe=%1#nv-d6wSzXE4HUP~wA$Coa#5z-4iJ5B`P3D# z3-3ZuI`0guewo?j;VzR)Exy9-fDii-(O5^{@EB$ZpNG}!nfnmr5tfH{%#A7riimEB zZg7ZYm0kf4Gy-g2nxa@3220`pVK72(*^OJV?D|HC!&ZvFWr)T6E?{^R$jga0v^UYAE4(rv8&nLr*+(ldYomP zqlJZ_!`JVIB(tQatxFC#;UE0N07>Q{?k$vYCqz$(ucZx#I9P*kwo^QUAKxo9^8B&R ze=rpxU2FWfS)j(aZI-_g>tu&5hbzDfoQ47DZ!Oz{_%1pH5=pW|i8483`};af3^4o% z1%G|isT2?a%z@m;E)0w0?YlK)v=!v2!lI^=6URtFWSo<1^^r%|{=>B5Tza6M^B1P6 z2AcSIJM>}Xx8-!4u{d62LMRkZtHB0veltKbh`D+f0VfQ9 zB1otbRQf;z{IS6|BmKO%;{7(MfTn1N*Y`l=b>fz84J)cr``I;*Nglz%)?F2OstTqt z(!;@Q_4^CD-gPROme~Dv5oj_Yzj2ToX^^^0)~!%!AR5P`b$(UerW_0fK7AlOX3~$z z4%klH*sZCc`LIIiK|oW&q)Fq!1f2*HxH1x$jr=1_i*qrPR#y^pzZwX30$2Yi-K3dy zNSyCR>)|FxaAXou&pFFxX_j71`k^w;z3gJaD4l) z4ERTB*pqf$Sl6!(LKjjpp(I&y_di5yuEwqYUu9flk4}Me{jDv-Dp1~C+2M6k>P{!Z zzSwfezD~%$@;%2_Iy~j~Bb&lD!^6O@qwVeS99FWE`BQy;99_nj2D^h27nAI74*x7W zm95XK6ygO|cS-D!l`COW6a1GGi=~1eR~6a!>P~|X=MuO9Gk2^24$egtch<3!TlQLQ zz^r>m;HO4)S!Rf&lQ~9^AH-Q(gWf8o#>D6#{$sT0Lvy8i=55skC%eNQ2&v})`O{|Y zSWW(Po9HypAD@7k_RDtiM*=ap$i#HsxoLM3IJ!75*n-2c3T9l5zFu=0I(wm@n9V;e zXcof@^@=p%TXY*4nP)8chxf4Xx%% ze4~K^p`92vr=ao)-a{^3z0sP17n#qn_i$6w|;j)^NTZ zAfwC7!?{e}o*jRb*(~n#$yTDq{(dPvEZ8Cm1jSN3N|S2P_qMA9*_~k|e3@Mk!+02w z{8D8}0)d}y^4e;kptzE z=|!Eyn03gzVo6tBl(Rye_AG?)e{J8wiO<;MR#O8CR1p}YTbtY0-}q0II|-GzRBhp3 zJgbToSh}n2SNa}pWWOx2^P6)EKl8&&kGMYGQz)i%E$cBhZ%#nO9#{kNofw zfOsT}P-Hvc$Yb-#0Yf!PeCn2ibumI}_!N`7CONvvtZdx$(l|Trxcwd7>OiO=&1}K)SYY)D zhR1!F;Yl>eP#ggdXcV6<8Ez5?cP0W>1UUe@@Gm0x)GLuaJRQxqKkxO%U@Dwe7u_9D zUH{>TvLanw+i`cj#Q!tE@v|5;k8ze>8f~xCAVNTbSKo{V2}+6z+(0S>^@%0_D~PMWBKUp%)&%$-Z*La^h-NJQ-K@>n`LvG)YTb4-N1Sk9>lOiQ+_hjaYB->Htz#&9cVW_jWrh!>*09B3a3M}yq#?ec14YT z##0Xm!hco~EV$dLTlnV^mf;SD+cul$-j2QC=ZB+3!;QOeQGLS0^mQHFts(-%+fYDj zQiI^{ssgQRN+QHBtB9k+awKKCBMoDf%AR45hpKKrFmrxS-A3VcK;X4~zk$|s7UMLm z+1ZuUGgr1pu&Tm8qx1gN^AwV(Cw9XRFR9~U>&=5DkTiFPR!8!D$YXU4!=fh3TSFLxTy=wz#?=IrARgKk(Z#cYIs*eZF zN|;t-^R#$ZnGUS{TlAwOViO2V+nEFVW$$gu*+GoacTJo+b*dCD>KQbS`4<-6Ku!lm z)xS(5?b`|5Ik~^eepv|(1?Lo0i#IWMTi`^lu@zAV;}p7!DW}YWnD<|+?f}eLoR&D7 z@EZF>9Oai@oiPb5JcjKnL|jFiQ=r5b{5JYg>rLXKpA&l}Q2}0Q+1jI{ zp zN`e!WL}2*VL5*(e+=R7}R@yrJ*>X((;U}_cQ^qP5`(iB5(ihjNI?a`5a7m%M2ix>cum@HpbTU_MOIH-5r%Fqe8?JyT8hhPf0JPelNe;5TCK!Q2S_dfnSs!q3%JCd{!Oio zD-AWOojWBPM|AVLXW#tK+Hrc7@kvhl;SE^F#kIGd+WM($Pc8NW=g1dbD!r_m3Q{Rg!?JbpYXKCFXQ8n0LQwRwVAop0PaPHmLC_a9KcR`3YZ2Gk%$}#YFAM_FDv9QnrLkD-HIvrs9DVE^Hl?X z-_OTpqRmgAu#3X*=V+(NwmkWj$ijfcrFf-~0^?coE2Xlrc{l1R zC&BZ(bu7l0n%Vs2X+FtkTW2@Do(%7<^V8t$;)01?(p0fYwI}9<9np<^+ustne!fxn zDz&cMSq9l<(}&#{aUW1$Za3oOEj`L)I=QXnGlSRUEd$nn$y6i10w`#5R~l?Gul&M) z2Lu%VHexFqf_|NV|8HR;9X44(X%q&TE9MIMYy8hTIY5OIP{yG0w@-o>TsF-cclZt> z`3%(TtLB+V!65!4iI8pjN2cx>VX0z+xXSN+a(Al6ksg>B5EOO#)TsM;P2b^5K!gU~&&CiD}oF?-Rmlfwx z_&VjLB3D~R0GESAuy8iR(RaJed4%ep4hD_pquXivh|Xyr-+<}+Age%5trBr__o>Dq zKEtU)afwnlpw4U*9a&5o4bISFqi&$uT{>AL%EbwXXK) z&j?~8KorYgWLB9H6s$FK&bE_`iQHUXf=4OsX`U^107mTMLUnzB(S(=F;2xfUem+Yb z45fULOggfmv5>o~^$oBsE%s0D5R)4#!TR{JiXI8yH&1Blji^s>k|NHv;S}aosm1{& zq$7*yC(!di|35z;Raj{E*WR~{_;aFz(*JVN&BZXDd=J-CP6W?a(5>mztv9j#$Rp=+ z-3`%#q5n;965bDM`u#WR83fBiGBoc7)-~IW1Wpm^@Ay^)fxUHbUv0B0`%`W}`h2pH z8a3-IB)IQ_CU=xD=K~`&ZVHgQy0LPh%o;@AsES$7hT3SLNgMkO80hJQQmdfoHabYT zgOuE^MgW*o?$h}QT#yxI8>B44Nf#Q5>VO5Uvy&nlEOas1LyD;IK4sETS{{ey4QW6IEA@oTg!! znqN%+-sC|4QVwTC)>qI+OxBo>H<^V8mM_456{rF(P6%5^q@7G%#~`u;Vt~(`Ch91M z>R}@J$503X6zC{Le)rjjj2(4)UJC7`x5xEoTXk=w%2Eu`aO_9%)iFH^N;0`svsPh- z<0F6pwd~#DtL?47FCkrP^$Z>T^oq%Z3F*@ztPTB$CwGFe8!f3z9$%+5PQ>=K))aQ6 z!z%y$z;=djS)Cc?9wCyV#pQ%Xhp1%9J$KyS>xAEm#yQyk3TG`pX*~amBaxJLTXQhn z|JukteLcSp#&7)|cPv7T8YG!<%J zYQkUhL@IG@fx4&zPV30w=qS2K=puvgn$-FA!AYTRX%1dVwf4iGW+xrv>J8joSi&-| z8as*oQ6*;9kPpbZXelA8c&13)4_K;)5K0kPvRUZqbP@n<8fqXkq8R%MMZ8Rw#wh@G zOfi99$TDCg?8K$M(bK-6J?l(bKU!tIl$TqnO;X4TU}-uA7hKNnMuw*Y5^+dQK3IR+ zU+{S2nlH*Y2J!w#YmVF&cVivsUXbHc$7+i&XD3+qm3-5$A_7FOI$ksd^vI^Om}ZII#a)^f2u()UoXKt ztS)}OU7eo-@{RpdvHUbj8x4Rw7h&7eeJGBUVs&Q3a|I6as8da-izMW*!2s#K{-AaQ z(#KY~-XW*vazIg4Ih>|>xoo66$vxM@$Stg>s1GdZke1Cgbe<({ z`)&U5j3>vVkbemE*XB~M&Su=a+Zu4sXDImfFL~SS6&F9_Y8K~GO9^~j-}5f6c-w@D z;6`ToM|FFS%XbB?-Xzk}G=Kxj>yz@~p!3J1xw(L^@y&{ghF`OHzX7nzseBGtoA4DE zm~EI!#71p=y6QMs@3YQs8)nu)W0MUv5{T#Wv1fE4JN*D%H+`AK&c^xDHkCt`PV4HN zjzT%#ATQhf3%SRpy#zCq+&&&N+Yi%crpmo_y^M|HpH?1wn;XZ&E0Yhw>i)bhu{n1u9w~(?vW_Yi^0=)L(-+ftu=Yn+Gh(^ z@(~*%ITL&W>2d*(3GLw_Pth0wKg9HU)<`aFk;4(H$xQr1-T;vaV?PPF_P`Dioo9pb zw^CQj$@Ub3@H@lW7#%N&J$zJK&tFgn$@UzOoC95;S{H-Y#P^!$H{%inQT|)l4E8;u zyNplh<{yTfB-s1&%{kl%P+rKML;I_Ep?X_Y{+?~z=~fc#hDtzz;y|iN zH4|6!qILjRm-4c}tXCqrmmQ1$(~+ou5BK1YL*YQgUKRmf_xU&`j)ftR^OfL25UAN# z(*XCgr9C!(`00!H*bjmp79n1D@U4q_sY_j6pBe!D>?+;F$BxQJp$MQ%ebZ?kX-M(^ zNe`woV3T3>-Wv4I!2S#Va%g`W4-GXb0Q+9PCiY)*kdXhZ9baO|(b1L3-OAiU$=Sit z<)2?6My1`pj~RXq?v4oJJocQ}O@+)otx*3vdc>-Jf|XfJ!&;d6Rwba?mw_S7L$XhuKIcrE7yPg^KhqvEsBL;w;?J-nx zB}QYKb#I3xVn<&%b{8}|ArcL1UDo)5>Y&~RaMZ=`8DYlwf90ro?p7sV+_Yg4FS9PK zmAa_vi8Cdy?df9hmdD9#2ZKbjYF=ej!Vc7QsR2CEb}>x`y3`9w-aGzI>a|YjGh3)* zO~*f*mwj=Yl^n-*e^GDY-^2pwUm~~$N&5fVIQMX<(m0OK%p%PUjoinH$$duU z8n)3$TjUWXN;NdDyNHOkh?>?VMKm+7aT^J7~N<4cc}@B zuN7hDHGL$r#MM={$K9`5Qj&JrvChRS+%?XVT(?glw_Kw=?ow=FV*peAeKFmqsrIA* zU0`o=kBCXP3hkEm=~8RmL*6X7Mt8e`AseOUR!f|1IMIhwyBokX%}aJ??~Uij^Zb>E z-o?7DztuakWY#O`$)x<;^^7|=i|ZQA%9fwltt%-*Nxf?lz2}L+ixUZrS0%0WS2Ul^ z3E7)Z4UwXUX(&yq6)D``m#)QAa+=xRp?S0?rfHOsZy#3T(ri%b>@d+aWW{+bL*iE` z9u2Haik2-9G^u(AaA-9RmQHp}zFQl#boe8G++xfq=h2i$&$G3SS2}RoR_56s^&65X zD*iZq#9Q>)mx8LoQgt}i)v_!;Sp&_?c6AIP8WXDA-ZM+4)RnfxQGB7zq?$alEvp(j z_Oz7lN)C>6Cw>~F4$3ejujji*n2wBDSuscJr<1+t(ihLI@T+pN@bPpgxaM)Tbfw?)fkClJ<>v~WrMqLkKU<4_aPd^vR!-J7CpZnA@^`lP&& z;&HErYi;i7(=&2-$&ZzGCD`_J)+#?2zY10R^3=7wG;$FW+OTTrVpp-(%IUh)t+mJ=t`PeKs z;xB9o9+lSb<}YN~T#21no0vd@RR}tathYB~Dl|?p!`Z?Ls}S`0fD3nzm$cIgXQFB5 zoqFEOW=d0~>J;D~%Z4=gQ*6rybDog3juobsK-cHv@RNp}Q#N%y+8gEj^}8B#FC_0V z*q;=aT(45o-f=1@J~!gHzi!0k^|haDy7kb%-NDiYF%L1_ea~-KQ)}z7%oQ?yG7b|0 zLv~`S){F7DE}a~M&hd|eyN~g~-NTmKa#CKti|EJm{3mQbTru!B59dZYS)BH$iNdQJ zm2MQOdXftY^L0`mQcjZZKbvbxf~HT;v8$g2S6-uP$_^CX=soxbXTg@6DwwKlNWYHH z9Y9-VzlUE!|Bff|^R2YQRGC0Qxpr34mo{2lzQw?ycVNv&;nVKE&p4gqa6kFgVT8u4 zM*YvuDWHwD13L&)j4;2Ta6@32si-E}jRWpnE#Njyg3k-40rs&~(I%iZLlx*s6L1Sx zh@gnAZ@91-1_}koGA%L}*{_{-cu;_^U$~*@WCB)l72xo80<6*dW)GJG2HON$h<8V! zV8!bqdms-+*~ZX9v^NTVt;MFT1cU@7pu;6Vi16CQ3~ELN98^^Y(;P(z5x9ncsOm7J z1snhYLPTgGpcYM0NnD@^A;Jt0kdwX$dJRJeAuj^jxLO36rYb@R^&$cSrXnZ?h7gK9 z1SGH!L9H-^kPRWAFscY5aTOuN8Z-h5v;odsQ)prN1BKE=07iDAQiNP3NbHOxd=I^L z5J4O4q~@yyuri34`t5L*JRmvB!M*@2IFJSrRwD{-b`}G&X;Ofer3l}L{|;*3A%=up zDWINii0N|qFG~${W>7FMT*U-!8x|Z(Cjb@a#XnsCPN3_&M#S2>iP`3KA|&=Sn8S)I z#ItSP4LmX&F+5K(|0u%@ljrp<$#KVu3M}ycmILB4%`nA2;$%;zE-*@y#gzGqv$o1( zK{1B_`WcHKuiOuWWNpAm1cR$tWQqCd59rBK!Vr?cRMvWY@tLo!Dm2V5oWoNEyLm)R zKngg-(}Bc;GCWMo&y*Id7T)EBr?p8uhQQ(jxW*P41E5g8AwHrxm7!N?=={8DyMrXG SK1ZSS;G+j__ho7Gseb{5wL&BS delta 17084 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 SDL^Pd6uy9fw8sDa?*9Q3Lk!{o diff --git a/tests/test_e2e_conversion.py b/tests/test_e2e_conversion.py index d7432a10..8c952123 100644 --- a/tests/test_e2e_conversion.py +++ b/tests/test_e2e_conversion.py @@ -3,7 +3,7 @@ from pathlib import Path from docling.backend.docling_parse_backend import DoclingParseDocumentBackend from docling.datamodel.base_models import InputFormat from docling.datamodel.document import ConversionResult -from docling.datamodel.pipeline_options import PdfPipelineOptions, PipelineOptions +from docling.datamodel.pipeline_options import PdfPipelineOptions from docling.document_converter import DocumentConverter, PdfFormatOption from .verify_utils import verify_conversion_result_v1, verify_conversion_result_v2 diff --git a/tests/test_e2e_ocr_conversion.py b/tests/test_e2e_ocr_conversion.py index ee7f3931..ffc62b43 100644 --- a/tests/test_e2e_ocr_conversion.py +++ b/tests/test_e2e_ocr_conversion.py @@ -8,7 +8,6 @@ from docling.datamodel.pipeline_options import ( EasyOcrOptions, OcrOptions, PdfPipelineOptions, - PipelineOptions, TesseractCliOcrOptions, TesseractOcrOptions, ) diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py index 80f5ea4e..4d3f96bc 100644 --- a/tests/test_interfaces.py +++ b/tests/test_interfaces.py @@ -6,7 +6,7 @@ import pytest from docling.backend.docling_parse_backend import DoclingParseDocumentBackend from docling.datamodel.base_models import DocumentStream, InputFormat from docling.datamodel.document import ConversionResult, DocumentConversionInput -from docling.datamodel.pipeline_options import PdfPipelineOptions, PipelineOptions +from docling.datamodel.pipeline_options import PdfPipelineOptions from docling.document_converter import DocumentConverter, PdfFormatOption from .verify_utils import verify_conversion_result_v1, verify_conversion_result_v2 diff --git a/tests/verify_utils.py b/tests/verify_utils.py index fb888bf8..23f21103 100644 --- a/tests/verify_utils.py +++ b/tests/verify_utils.py @@ -2,7 +2,6 @@ import json from pathlib import Path from typing import List -from docling_core.types import BaseText from docling_core.types import Document as DsDocument from docling_core.types.experimental import DoclingDocument from pydantic import TypeAdapter