ó
    ¢_i2  ã                   ó|   • S r SSKrSSKJr  SSKJrJrJrJr  SSKJ	r	  SSK
Jr  SSKJrJr  SS	KJr   " S
 S5      rg)zð
Enhanced Table Parser with Header Consolidation

Parses tables from Docling documents and consolidates consecutive headers
that immediately precede tables, following strict rules to avoid incorrect
consolidation across content boundaries.
é    N)Údatetime)ÚAnyÚListÚOptionalÚTuple)ÚInputFormat)ÚPdfPipelineOptions)ÚDocumentConverterÚPdfFormatOptioné   )ÚTableMetadatac            
       óú   • \ rS rSrSr    SS\S\S\S\4S jjrS\S	\	\
\\   4   4S
 jrS\\
   S\S	\	\\   \\   4   4S jrS\\   S	\4S jrSS\\
   S\S\S	\\   4S jjrS\4S jrS\\   S\4S jrSrg)ÚEnhancedTableParseré   zÉ
Enhanced table parser with intelligent header consolidation.

Consolidates consecutive headers of the same level that immediately
precede tables, with strict rules to prevent incorrect consolidation.
Ú	separatorÚmax_lookbackÚenable_consolidationÚdebugc                 ó4   • Xl         X l        X0l        X@l        g)a  
Initialize the enhanced table parser.

Args:
    separator: String to join multiple headers (e.g., " ^ " or " | ")
    max_lookback: Maximum elements to look back for headers
    enable_consolidation: Whether to consolidate consecutive headers
    debug: Enable debug output
N)r   r   r   r   )Úselfr   r   r   r   s        Ú5/home/mande/repo/quber/src/quber/core/table_parser.pyÚ__init__ÚEnhancedTableParser.__init__   s   € ð  #ŒØ(ÔØ$8Ô!Ø�
ó    Úpdf_pathÚreturnc                 ó„  • [        5       nSUl        SUl        SUR                  l        [        [        R                  [        US90S9nUR                  U5      nUR                  n/ nSn[        UR                  5       5      nU V	V
s/ s H  u  pšU	PM	     nn	n
[        U5       VVs0 s H  u  pÍ[        U5      U_M     nnnUR                   GHß  n[!        US5      (       aH  UR"                  (       a7  [!        UR"                  S   S5      (       a  UR"                  S   R$                  OSnUR'                  [        U5      S	5      n/ n/ nUS:”  a  U R)                  UU5      u  nnS
nU R*                  (       a  U(       a  U R-                  U5      nSnSnS
n[!        US5      (       aí  UR.                  (       aÜ  UR.                  R0                  nUR.                  R2                  nUS:”  aª  US:”  a¤  [!        UR.                  S5      (       a‰  UR.                  R4                  (       an  [7        UR.                  R4                  5      S:”  a  UR.                  R4                  S   O/ nU(       a)  [7        U5      S:”  a  US   (       a  [9        US   5      OS
nS
n[!        US5      (       av  UR"                  (       ae  [!        UR"                  S   S5      (       aG  UR"                  S   R:                  nUR<                  UR>                  UR@                  URB                  4nU RE                  UUSS9n[!        US5      (       a  URG                  U5      OS
n[I        UUUUU(       a  US   OS
UUUUUS9
nURK                  U5        US-  nU RL                  (       d  GMÎ  U RO                  U5        GMâ     XV4$ s  sn
n	f s  snnf )z¥
Parse document and extract all tables with enhanced metadata.

Args:
    pdf_path: Path to PDF file

Returns:
    Tuple of (document object, list of TableMetadata)
FT)Úpipeline_options)Úformat_optionsr   ÚprovÚpage_nor   éÿÿÿÿNÚdataÚgridÚbboxé   )ÚlimitÚexport_to_markdown)
Útable_indexÚpage_numberÚheadersÚconsolidated_headerÚdescriptive_textÚtable_markdownÚpreceding_textÚrowsÚcolsÚfirst_cell_content)(r	   Údo_ocrÚdo_table_structureÚtable_structure_optionsÚdo_cell_matchingr
   r   ÚPDFr   ÚconvertÚdocumentÚlistÚiterate_itemsÚ	enumerateÚidÚtablesÚhasattrr    r!   ÚgetÚ_find_preceding_headersr   Ú_consolidate_headersr#   Únum_rowsÚnum_colsr$   ÚlenÚstrr%   ÚlÚtÚrÚbÚ_get_preceding_textr(   r   Úappendr   Ú_print_debug_info)r   r   r   Ú	converterÚresultr9   Útables_metadatar)   Úelements_with_depthÚitemÚdepthÚelements_listÚiÚelemÚelement_to_indexÚtableÚpage_numÚ	table_idxr+   Údescriptive_textsr,   r0   r1   Ú
first_cellÚ	first_rowr%   rJ   r/   Útable_mdÚmetadatas                                 r   Úparse_documentÚ"EnhancedTableParser.parse_document1   sY  € ô .Ó/ÐØ"'ÐÔØ.2ÐÔ+ØDHÐ×0Ñ0ÔAô &Ü'ŸO™O¬_ÐN^Ñ-_Ð`ñ
ˆ	ð ×"Ñ" 8Ó,ˆØ—?‘?ˆð ˆØˆô # 8×#9Ñ#9Ó#;Ó<ÐÙ1DÔEÒ1D¡+ $›Ñ1DˆÑEÜ7@ÀÔ7OÔPÒ7O©G¨AœB˜t›H ašKÑ7OÐÑPà—_•_ˆEô ˜E 6×*Ñ*¨u¯z¯z¼gÀeÇjÁjÐQRÁmÐU^×>_Ñ>_ð —
‘
˜1‘×%Ò%àð ð )×,Ñ,¬R°«Y¸Ó;ˆIð ˆGØ "ÐØ˜1‹}Ø-1×-IÑ-IÈ-ÐYbÓ-cÑ*�Ð*ð #'ÐØ×(×(®WØ&*×&?Ñ&?ÀÓ&HÐ#ð ˆDØˆDØˆJä�u˜f×%Ñ%¨%¯*¯*à—z‘z×*Ñ*�Ø—z‘z×*Ñ*�ð ˜!“8  q£ä˜uŸz™z¨6×2Ñ2°u·z±z··Ü:=¸e¿j¹j¿o¹oÓ:NÐQRÓ:R E§J¡J§O¡O°AÒ$6ÐXZ˜	Þ$¬¨Y«¸!Ó);Ø>GÈ¿l¬¨Y°q©\Ô):ÐPT˜Jð ˆDÜ�u˜f×%Ñ%¨%¯*¯*¼ÀÇÁÈAÁÐPV×9WÑ9WØ—J‘J˜q‘M×&Ñ&�ØŸ™˜QŸS™S !§#¡# q§s¡sÐ+�ð "×5Ñ5°mÀYÐVWÐ5ÐXˆNô >EÀUÐL`×=aÑ=a�u×/Ñ/°Ô9ÐgkˆHô %Ø'Ø$ØØ$7Þ9JÐ!2°1Ò!5ÐPTØ'Ø-ØØØ#-ñˆHð ×"Ñ" 8Ô,Ø˜1ÑˆKà�z�zŠzØ×&Ñ& x×0ñM %ðP Ð(Ð(ùóW FùÛPs   Â	N6Â(N<ÚelementsrZ   c           	      ón  • / n/ nSnSn[        [        U R                  U5      5       GH  nX'-
  S-
  nX   n	[        U	5      R                  n
U
S;   a$  U R
                  (       a  [        SU
 S35          X44$ U
S:X  a'  U(       a   U R
                  (       a  [        S5          X44$ [        U	S	5      (       a  U	R                  (       d  MŸ  U	R                  R                  5       nU(       d  MÂ  [        U	S
5      =(       a    U	R                  SLnU(       aÀ  U	R                  nUc@  UnUR                  SU5        U R
                  (       a  [        SU SUSS  S35        GM6  GM9  XÕ:X  aE  U(       a>  UR                  SU5        U R
                  (       a  [        SU SUSS  S35        GM€  GMƒ  U R
                  (       a  [        SU SU S35          X44$ U(       dJ  [        U5      S:X  a;  UR                  SU5        U R
                  (       a  [        SUSS  S35        GMø  GMû  U(       d  GM  SnGM
     X44$ )aŸ  
Find headers that immediately precede a table.

Only consolidates headers that are:
1. Consecutive (no non-header content between them)
2. Of the same level
3. Immediately before the table
4. Not separated by boundary elements (tables, images, etc.)

Args:
    elements: List of document elements
    table_idx: Index of the table in the elements list

Returns:
    Tuple of (headers list, descriptive texts list)
NTr   )Ú	TableItemÚPictureItemz  Hit boundary element (z), stopping header searchÚListItemz/  Hit list item after finding headers, stoppingÚtextÚlevelr   z  Found first header at level z: é2   ú...z$  Found consecutive header at level z   Found different level header (z vs z), stoppingz  Found descriptive text: F)ÚrangeÚminr   ÚtypeÚ__name__r   Úprintr?   rg   Ústriprh   ÚinsertrE   )r   rb   rZ   r+   r[   Úcurrent_levelÚconsecutiverU   ÚidxrV   Ú	elem_typerg   Ú	is_headerrh   s                 r   rA   Ú+EnhancedTableParser._find_preceding_headers�   s,  € ð" ˆØÐØˆØˆô ”s˜4×,Ñ,¨iÓ8×9ˆAØ‘- !Ñ#ˆCØ‘=ˆDô ˜T›
×+Ñ+ˆIð Ð8Ó8Ø—:—:ÜÐ4°Y°KÐ?XÐYÔZØðn Ð)Ð)ði ˜JÓ&®7Ø—:—:ÜÐKÔLØðb Ð)Ð)ô] ˜4 ×(Ñ(°·	·	Ùà—9‘9—?‘?Ó$ˆDÞÙô    gÓ.×I°4·:±:ÀTÐ3IˆIæØŸ
™
�ð !Ñ(Ø$)�MØ—N‘N 1 dÔ+Ø—z—zÜÐ >¸u¸gÀRÈÈSÈbÈ	À{ÐRUÐV×Wò "ð Ó+¶Ø—N‘N 1 dÔ+Ø—z—zÜÐ DÀUÀGÈ2ÈdÐSVÐTVÈiÈ[ÐX[Ð\×]ò "ð
 —z—zÜÐ @ÀÀÀtÈMÈ?ÐZeÐfÔgØð  Ð)Ð)ö ¤3Ð'8Ó#9¸QÓ#>Ø%×,Ñ,¨Q°Ô5Ø—z—zÜÐ :¸4ÀÀ¸9¸+ÀSÐI×Jò "÷ ‘WØ"'“Kñ} :ðD Ð)Ð)r   r+   c                 óp   • U(       d  g[        U5      S:X  a  US   $ U R                  R                  U5      $ )z•
Consolidate multiple headers into a single string.

Args:
    headers: List of header texts to consolidate

Returns:
    Consolidated header string
Nr   r   )rE   r   Újoin)r   r+   s     r   rB   Ú(EnhancedTableParser._consolidate_headersø   s5   € ö ØÜˆw‹<˜1ÓØ˜1‘:ÐØ�~‰~×"Ñ" 7Ó+Ð+r   r'   c                 óÌ  • / nSn[        [        U R                  U5      5       H¤  nX&-
  S-
  nX   n[        U5      R                  n	U	S:X  a  UR                  SS5        M=  [        US5      (       d  MP  UR                  (       d  Mc  UR                  R                  5       n
U
(       d  M†  UR                  SU
5        US-  nXS:¼  d  M¤    O   U(       a  SR                  U5      $ S$ )a  
Get text content immediately preceding the table.

Args:
    elements: List of document elements
    table_idx: Index of the table
    limit: Maximum number of text elements to include

Returns:
    Preceding text context or None, with [Table] placeholders for intervening tables
r   r   rd   z[Table]rg   Ú
N)
rk   rl   r   rm   rn   rq   r?   rg   rp   ry   )r   rb   rZ   r'   ÚtextsÚcountrU   rt   rV   ru   rg   s              r   rK   Ú'EnhancedTableParser._get_preceding_text  sÈ   € ð ˆØˆä”s˜4×,Ñ,¨iÓ8Ö9ˆAØ‘- !Ñ#ˆCØ‘=ˆDÜ˜T›
×+Ñ+ˆIð ˜KÓ'Ø—‘˜Q 	Ô*Ùä�t˜V×$Ó$¨¯¯©Ø—y‘y—‘Ó(�ß�4Ø—L‘L  DÔ)Ø˜Q‘J�EØ•~Ùñ! :ö$ $)ˆt�y‰y˜ÓÐ2¨dÐ2r   r_   c                 óü  • [        SUR                  S-    SUR                   S35        UR                  (       a  [        SUR                   35        UR                  (       a  [        SUR                   35        UR
                  (       a  [        SUR
                  SS	  S
35        [        SUR                   SUR                   S35        UR                  (       a  [        SUR                  SS  S
35        gg)z$Print debug information for a table.z
=== Table r   z (Page z) ===zConsolidated Header: zIndividual Headers: zDescriptive Text: Néd   rj   zSize: u	    rows Ã— z colszFirst Cell: ri   )	ro   r)   r*   r,   r+   r-   r0   r1   r2   )r   r_   s     r   rM   Ú%EnhancedTableParser._print_debug_info+  sâ   € ä�˜X×1Ñ1°AÑ5Ð6°g¸h×>RÑ>RÐ=SÐSXÐYÔZØ×'×'ÜÐ)¨(×*FÑ*FÐ)GÐHÔIØ××ÜÐ(¨×)9Ñ)9Ð(:Ð;Ô<Ø×$×$ÜÐ& x×'@Ñ'@ÀÀ#Ð'FÐ&GÀsÐKÔLÜ��x—}‘}�o Y¨x¯}©}¨o¸UÐCÔDØ×&×&Ü�L ×!<Ñ!<¸S¸bÐ!AÐ BÀ#ÐFÕGð 'r   Úmetadata_listÚoutput_pathc           
      ó   • [         R                  " 5       R                  5       [        U5      / S.nU H  nUR                  UR
                  UR                  UR                  UR                  UR                  UR                  UR                  S.UR                  S.nUS   R                  U5        M�     [        USSS9 n[        R                   " X6SS	S
9  SSS5        [#        SU 35        g! , (       d  f       N= f)z†
Save table metadata to JSON file.

Args:
    metadata_list: List of TableMetadata objects
    output_path: Path for output JSON file
)Úextraction_dateÚtotal_tablesr>   )r0   r1   )r)   r*   r,   r+   r-   r/   Ú
dimensionsr\   r>   Úwzutf-8)Úencodingé   F)ÚindentÚensure_asciiNzMetadata saved to: )r   ÚnowÚ	isoformatrE   r)   r*   r,   r+   r-   r/   r0   r1   r2   rL   ÚopenÚjsonÚdumpro   )r   rƒ   r„   r#   ÚmetaÚ
table_dictÚfs          r   Úsave_metadataÚ!EnhancedTableParser.save_metadata8  sÜ   € ô  (Ÿ|š|›~×7Ñ7Ó9Ü Ó.Øñ
ˆó "ˆDà#×/Ñ/Ø#×/Ñ/Ø'+×'?Ñ'?ØŸ<™<Ø$(×$9Ñ$9Ø"&×"5Ñ"5Ø'+§y¡y¸$¿)¹)ÑDØ"×5Ñ5ñ	ˆJð �‰N×!Ñ! *Ö-ñ "ô �+˜s¨WÒ5¸Ü�IŠI�d a°eÒ<÷ 6ô 	Ð# K =Ð1Õ2÷ 6Õ5ús   ÃC/Ã/
C=)r   r   r   r   N)z ^ é
   TF)r&   )rn   Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rF   ÚintÚboolr   r   r   r   r   r`   rA   rB   r   rK   rM   r–   Ú__static_attributes__© r   r   r   r      s  † ñð ØØ%)Øñàðð ðð #ð	ð
 õð*j) sð j)¨u°S¸$¸}Ñ:MÐ5MÑ/Nô j)ðXY*°°S±	ð Y*Àcð Y*ÈeÐTXÐY\ÑT]Ð_cÐdgÑ_hÐThÑNiô Y*ðv,¨D°©Ið ,¸#ô ,ñ !3¨D°©Ið !3À#ð !3Ècð !3ÐZbÐcfÑZgõ !3ðFH¨-ô Hð 3¨4°Ñ+>ð  3ÈS÷  3r   r   )rœ   r‘   r   Útypingr   r   r   r   Údocling.datamodel.base_modelsr   Ú"docling.datamodel.pipeline_optionsr	   Údocling.document_converterr
   r   Úmodelsr   r   r    r   r   Ú<module>r¦      s0   ðñó Ý ß -Ó -å 5Ý Aß Iå !÷D3ò D3r   