ó
    1¼„j
1  ã                  óÞ  • S r SSKJr  SSKrSSKJr  SSKJrJrJ	r	J
r
Jr  SSKJrJrJrJrJrJr  SSKJrJrJrJrJrJr   " S S	\5      r\R8                  " S
5      r\R8                  " S\R<                  5      r\R8                  " S\R<                  5      r SS jr! S         SS jjr"  S         SS jjr#SS jr$SS jr%S S jr&S!S jr'S"S jr( " S S\5      r)S#S jr*S$S jr+g)%u  Turn one page's dpt-3 response into records, and project them for the graft.

A dpt-3 response has two parts: one long markdown string holding all the text
the model read off the page, and a tree describing what sits where. Each tree
node names its kind, gives its rectangle on the page, and points at the stretch
of the long string that belongs to it â€” the node itself stores no text, so
getting a node's text means cutting its stretch out of the string.

`digest_page` walks the tree and produces the track's records: a figure node
becomes a `DigestedFigure` with its kind, description and value tables kept
separate; a table node and its cell nodes become a `DigestedTable` with a box
on every cell; everything else on the page is kept as context. A response
without the tree raises `UnrecognizedResponse` naming the stored file and the
model, so a billed page can never pass as blank because the code did not
recognize the format. A page node reporting anything but success raises too,
with the response's own reason.

`project_scan` turns a digest into the `PageScan` every downstream consumer
already reads â€” the graft, the correction sweep, the value reconciliation. A
figure is projected as its description followed by its value tables rendered
as markdown; a table is projected grid-for-grid. The rest of the digest stays
in the track models.

The figure markup is the response's own labelling â€” the model wraps each
figure's content in tags it emits itself â€” so reading it back is reading the
format, not inferring anything about the page.
é    )ÚannotationsN)Ú
HTMLParser)ÚAnyÚDictÚListÚOptionalÚTuple)ÚDigestedFigureÚDigestedTableÚDigestedTextÚFigureValueCellÚFigureValueTableÚ
PageDigest)ÚBoxÚChartContextÚFigureRecordÚPageScanÚ
PageStatusÚScannedTablec                  ó   • \ rS rSrSrSrg)ÚUnrecognizedResponseé.   z5A response in neither the dpt-2 nor the dpt-3 format.© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   ó    Ú</home/mande/repo/quber/src/quber/core/figures/dpt3/digest.pyr   r   .   s   † Ü?r    r   z$<figure\b[^>]*\btype="([^"]*)"[^>]*>z <description>(.*?)</description>z<table>(.*?)</table>c                ó˜   • [        U R                  S5      [        5      (       a  g[        U R                  S5      [        5      (       a  gg)zÕWhich format a raw response holds: `dpt2`, `dpt3`, or None for neither.

The format is visible in the response itself: a dpt-2 response carries a
flat `chunks` list, a dpt-3 response carries the `structure` tree.
ÚchunksÚdpt2Ú	structureÚdpt3N)Ú
isinstanceÚgetÚlistÚdict)Úresponses    r!   Úresponse_generationr,   <   s9   € ô �(—,‘,˜xÓ(¬$×/Ñ/ØÜ�(—,‘,˜{Ó+¬T×2Ñ2ØØr    c                óœ  • U R                  S5      n[        U[        5      (       d  [        U=(       d    S SU S35      eU R                  S5      =(       d    SnU R                  S5      =(       d    0 n[	        UUR                  S5      UUR                  S	5      =(       d    UR                  S
5      UR                  S5      =(       d    0 R                  SUR                  S5      5      S9nUR                  S5      =(       d    /  GH>  nUR                  S5      S:w  a  M  UR                  S5      n	U	S;  a0  [        U=(       d    S SU SU	< SUR                  S5       S35      eUR                  S5      =(       d    /  H¾  n
U
R                  S5      nUS:X  a'  UR                  R                  [        X¥U5      5        MA  US:X  a'  UR                  R                  [        X¥U5      5        Mn  UR                  R                  [        UU=(       d    S[        X¥5      [        U
5      U
R                  S5      S95        MÀ     GMA     U$ )a/  Digest one page's raw dpt-3 response into the track's records.

`page` is the 1-based source page the submission came from; the response
numbers its own single page from one, so the source page is carried in
rather than read back out of it. `artifact` names the stored response file
for error messages.
r%   zthe responsez (model z>) holds neither a dpt-2 chunks list nor a dpt-3 structure treeÚmarkdownÚ ÚmetadataÚjob_idÚmodel_versionÚversionÚbillingÚtotal_creditsÚcredit_usage)Úpager1   Úmodelr3   ÚcreditsÚchildrenÚtyper7   Ústatus)NÚokz) reports page status z (Úreasonz/); the page was billed and cannot pass as blankÚfigureÚtableÚid)r7   ÚkindÚtextÚboxÚnode_id)r(   r'   r*   r   r   Ú
ValueErrorÚfiguresÚappendÚ_figureÚtablesÚ_tableÚcontextr   Ú_sliceÚ_box)r+   r7   r8   Úartifactr%   r.   ÚmetaÚdigestÚ	page_noder<   ÚnoderB   s               r!   Údigest_pagerT   I   s  € ð —‘˜[Ó)€IÜ�i¤×&Ñ&Ü"Ø×)˜>Ð*¨(°5°'ð :)ð )ó
ð 	
ð �|‰|˜JÓ'×-¨2€HØ�<‰<˜
Ó#×) r€DäØØ�x‰x˜Ó!ØØ—‘˜Ó)×@¨T¯X©X°iÓ-@Ø—‘˜)Ó$×*¨×/Ñ/°ÀÇÁÈ.ÓAYÓZñ€Fð —]‘] :Ó.×4°"Ó4ˆ	Ø�=‰=˜Ó  FÓ*ÙØ—‘˜xÓ(ˆØ˜Ó%ÜØ×-˜~Ð.¨h°u°gÐ=SÐTZÑS]Ø�Y—]‘] 8Ó,Ð-Ð-\ð^óð ð —M‘M *Ó-×3°Ò3ˆDØ—8‘8˜FÓ#ˆDØ�xÓØ—‘×%Ñ%¤g¨d¸dÓ&CÖDØ˜“Ø—‘×$Ñ$¤V¨D¸DÓ%AÖBà—‘×%Ñ%Ü Ø!Ø!ŸZ RÜ# DÓ3Ü  ›JØ $§¡¨£ñöô 4ñ 5ð2 €Mr    c                ó@  • U R                    Vs/ s HA  n[        U R                  [        U5      UR                  UR
                  U R                  S9PMC     nnU R                   Vs/ s HM  n[        U R                  UR                  UR                  UR                  UR
                  U R                  S9PMO     nnU R                   Vs/ s Hc  nUR                  R                  5       (       d  M$  [        U R                  UR                  UR                  UR                  UR
                  S9PMe     n	nU(       a  SO
U(       a  SOSn
[!        U R                  U
UU R                  U R"                  U R$                  U R&                  UUUUU	S9$ s  snf s  snf s  snf )u¹   The digest as the `PageScan` every downstream consumer already reads.

The figure records carry text, id and rectangle â€” the graft's whole
contract. The digest keeps everything else.
)r7   rC   rD   Úchunk_idr1   )r7   ÚcellsÚ
cell_boxesrD   rV   r1   )r7   rB   rC   rD   rV   rG   rJ   Úempty)r7   r<   Úpicture_classesr1   r8   r3   r9   ÚreusedÚresponse_artifactrG   rJ   rL   )rG   r   r7   Úfigure_textrD   rE   r1   rJ   r   rW   rX   rL   rC   Ústripr   rB   r   r8   r3   r9   )rQ   rZ   r\   r[   r?   rG   r@   rJ   ÚitemrL   r<   s              r!   Úproject_scanr`   ‚   sn  € ð& —n’nó	ò %ˆFô 	Ø—‘Ü˜VÓ$Ø—
‘
Ø—^‘^Ø—=‘=ô	
ñ %ð ð 	ð& —]’]ó
ò #ˆEô 	Ø—‘Ø—+‘+Ø×'Ñ'Ø—	‘	Ø—]‘]Ø—=‘=ô	
ñ #ð ð 
ð —N’Nóâ"ˆDØ�9‰9�?‰?×ó 	lŒ˜&Ÿ+™+¨D¯I©I¸D¿I¹IÈ4Ï8É8Ð^b×^jÑ^jÔkÙ"ð ð ö
 '.™¾v±8È7€FÜØ�[‰[ØØ'Ø�}‰}Ø�l‰lØ—‘Ø—‘ØØ+ØØØñð ùò7	ùò
ùòs   �AFÁ'AFÃ#FÃ2AFc                ó(  • / nU R                   R                  5       (       a)  UR                  U R                   R                  5       5        U R                   H(  n[	        U5      nU(       d  M  UR                  U5        M*     SR                  U5      $ )a	  A figure's readable content: its description, then its value tables.

This is what the graft puts on the picture and what the correction agent
and the value reconciliation read, so the values are rendered as markdown
rows rather than left in the response's markup.
ú

)Údescriptionr^   rH   ÚvaluesÚ_markdown_rowsÚjoin)r?   Úpartsr@   Úrendereds       r!   r]   r]   ¸   ss   € ð €EØ×Ñ×Ñ×!Ñ!Ø�‰�V×'Ñ'×-Ñ-Ó/Ô0Ø—”ˆÜ! %Ó(ˆßˆ8Ø�L‰L˜Ö"ñ ð �;‰;�uÓÐr    c                óÎ  • / nU R                    H¾  nU Vs/ s H<  nSR                  UR                  R                  5       5      R	                  SS5      PM>     nnUR                  SSR                  U5      -   S-   5        [        U5      S:X  d  Mƒ  [        U R                   5      S:”  d  Mž  UR                  SS[        U5      -  -   5        MÀ     S	R                  U5      $ s  snf )
z7A value table as pipe-delimited rows, one line per row.Ú Ú|Ú/z| z | z |é   z --- |Ú
)Úrowsrf   rC   ÚsplitÚreplacerH   Úlen)r@   ÚlinesÚrowÚcellrW   s        r!   re   re   É   s´   € à€EØ�zŒzˆÙKNÓOÊ3À4�—‘˜$Ÿ)™)Ÿ/™/Ó+Ó,×4Ñ4°S¸#Ö>É3ˆÐOØ�‰�T˜EŸJ™J uÓ-Ñ-°Ñ4Ô5Üˆu‹:˜�?œs 5§:¡:›°Õ2Ø�L‰L˜˜x¬#¨c«(Ñ2Ñ2Ö3ñ	 ð
 �9‰9�UÓÐùò	 Ps   –AC"c           
     óJ  • [        X5      n[        R                  U5      n[        R	                  U5       Vs/ s H)  oUR                  5       (       d  M  UR                  5       PM+     nn[        R	                  U5       Vs/ s H  n[        U5      PM     nn[        UU(       a  UR                  S5      R                  5       OSSR                  U5      [        U 5      U V	s/ s H  o™R                  (       d  M  U	PM     sn	U R                  S5      S9$ s  snf s  snf s  sn	f )zHOne figure node: kind, descriptions and value tables out of its stretch.rm   r/   rb   rA   )r7   rB   rc   rD   rd   rE   )rM   Ú_FIGURE_OPEN_REÚsearchÚ_DESCRIPTION_REÚfindallr^   Ú_VALUE_TABLE_REÚ_value_tabler
   ÚgroupÚlowerrf   rN   ro   r(   )
rS   r.   r7   ÚcontentÚ
kind_matchÚdÚdescriptionsÚhtmlrJ   Úts
             r!   rI   rI   Ô   sÞ   € ä�TÓ$€GÜ ×'Ñ'¨Ó0€JÜ'6×'>Ñ'>¸wÔ'GÓUÒ'G !Ï7É7Ï9“I�A—G‘G–IÑ'G€LÐUÜ-<×-DÑ-DÀWÔ-MÓNÒ-M TŒl˜4Ö Ñ-M€FÐNÜØÞ-7ˆj×Ñ˜qÓ!×'Ñ'Ô)¸RØ—K‘K Ó-Ü�‹JÙ!Ó,š6�a§V¥V—™6Ñ,Ø—‘˜“ñð ùò VùÚNùò -s   ¸DÁDÂDÃ#D Ã;D c                ó,  • / nSnSnU R                  S5      =(       d    /  GH  nUR                  S5      S:w  a  M  [        UR                  S5      =(       d    S5      n[        UR                  S5      =(       d    S5      n[        XG[        UR                  S5      =(       d    S5      -   5      n[        XX[        UR                  S	5      =(       d    S5      -   5      nUR                  XxS
R	                  [        Xa5      R                  5       5      [        U5      45        GM     [        U5       V	s/ s H  n	[        U5       V	s/ s H  n	SPM     sn	PM!     n
n	[        U5       V	s/ s H  n	[        U5       V	s/ s H  n	SPM     sn	PM!     nn	U H:  u  pxpÍSUs=::  a  U:  d  M  O  M  SUs=::  a  U:  d  M(  O  M,  XÊU   U'   XÛU   U'   M<     U(       do  [        [        X5      5      nUR                   VVs/ s H  ow Vs/ s H  ofR                  PM     snPM      n
nnU
 VV	s/ s H  ow V	s/ s H  n	SPM     sn	PM     nnn	[        X*U[        U 5      U R                  S5      S9$ s  sn	f s  sn	f s  sn	f s  sn	f s  snf s  snnf s  sn	f s  sn	nf )zßOne table node as a dense grid, cells and boxes read off its cell nodes.

A cell that spans is written at its own row and column; the positions it
covers stay blank and carry no box, so the grid never states a value twice.
r   r:   r;   Ú
table_cellrt   ÚcolÚrowspanrm   Úcolspanrj   r/   NrA   )r7   rW   rX   rD   rE   )r(   ÚintÚmaxrH   rf   rM   rp   rN   Úranger|   ro   rC   r   )rS   r.   r7   Úplacedro   Úcolumnsru   rt   r‡   Ú_ÚgridÚboxesrC   rD   Úvalue_tables                  r!   rK   rK   ä   s"  € ð 9;€FØ€DØ€GØ—‘˜Ó$×*¨Ó*ˆØ�8‰8�FÓ˜|Ó+ÙÜ�$—(‘(˜5“/×& QÓ'ˆÜ�$—(‘(˜5“/×& QÓ'ˆÜ�4œs 4§8¡8¨IÓ#6×#;¸!Ó<Ñ<Ó=ˆÜ�g¤S¨¯©°)Ó)<×)AÀÓ%BÑBÓCˆØ�‰�s §¡¬&°Ó*@×*FÑ*FÓ*HÓ!IÌ4ÐPTË:ÐV×Wñ +ô 38¸´+Ó>²+¨Qœ˜wœÓ(š�A‹R™Ô(±+€DÐ>ÜPUÐVZÔP[Ó'\ÒP[È1´u¸W´~Ó(F²~°!«±~Ô(FÑP[€EÐ'\Û%Ñˆ�$Ø��?�d�?‰?˜q CÕ1¨'×1Ñ1Ø!�‰I�c‰NØ!�#‰J�s‹Oñ  &ö
 ä"¤6¨$Ó#9Ó:ˆØ7B×7GÒ7GÔHÒ7G° sÓ+¢s˜t—”¡sÔ+Ñ7GˆÑHÙ04Ô5²¨ Ó$¢˜1“$¡Ô$±ˆÑ5ä˜d¸5ÄdÈ4ÃjÐZ^×ZbÑZbÐcgÓZhÑiÐiùò )ùÒ>ùÚ(FùÒ'\ùò ,ùÓHùÚ$ùÓ5s`   Ä5I1ÅI,
ÅI1Å*I;Å=I6
Æ	I;Ç<	JÈJ ÈJÈ)	JÈ2JÈ>JÉ,I1É6I;Ê JÊJc                óú   • [        5       nUR                  U 5        UR                  5         [        UR                   VVs/ s H%  o"(       d  M  U Vs/ s H  n[        US9PM     snPM'     snnS9$ s  snf s  snnf )zDOne value table's rows, read out of the response's own table markup.)rC   )ro   )Ú	_GridTextÚfeedÚcloser   ro   r   )rƒ   Úparserrt   ru   s       r!   r|   r|     sb   € ä‹[€FØ
‡K�K�ÔØ
‡L�L„NÜÐZ`×ZeÒZeÔ!mÒZeÐSVÓilÓ"NÉ#Ó"NÊ#À$¤?¸Ô#=É#Ô"NÑZeÒ!mÑnÐnùÒ"NùÓ!ms   Á 
A7
ÁA7
ÁA2Á%A7
Á2A7
c                  ór   ^ • \ rS rSrSrSU 4S jjrSS jrSS jrSS jrSU 4S jjr	SS jr
SS	 jrS
rU =r$ )r”   i  z�Collects `td`/`th` text row by row. Markup inside a cell is dropped and
its text kept, so a value typeset with a line break reads as one string.c                óJ   >• [         TU ]  SS9  / U l        S U l        S U l        g )NT)Úconvert_charrefs)ÚsuperÚ__init__ro   Ú_rowÚ_parts©ÚselfÚ	__class__s    €r!   rœ   Ú_GridText.__init__  s(   ø€ Ü‰Ñ¨$ÐÑ/Ø%'ˆŒ	Ø)-ˆŒ	Ø+/ˆ�r    c                óÜ   • US:X  a  U R                  5         / U l        g US;   a  U R                  5         / U l        g US:X  a*  U R                  b  U R                  R	                  S5        g g g )NÚtr©ÚtdÚthÚbrrj   )Ú
_flush_rowr�   Ú_flush_cellrž   rH   )r    ÚtagÚattrss      r!   Úhandle_starttagÚ_GridText.handle_starttag  s^   € Ø�$‹;Ø�O‰OÔØˆD�IØ�LÓ Ø×ÑÔØˆD�KØ�D‹[˜TŸ[™[Ñ4Ø�K‰K×Ñ˜sÕ#ð 5ˆ[r    c                ó`   • US;   a  U R                  5         g US:X  a  U R                  5         g g )Nr¥   r¤   )rª   r©   )r    r«   s     r!   Úhandle_endtagÚ_GridText.handle_endtag"  s,   € Ø�,ÓØ×ÑÕØ�D‹[Ø�O‰OÕð r    c                óV   • U R                   b  U R                   R                  U5        g g ©N)rž   rH   )r    Údatas     r!   Úhandle_dataÚ_GridText.handle_data(  s#   € Ø�;‰;Ñ"Ø�K‰K×Ñ˜tÕ$ð #r    c                óB   >• [         TU ]  5         U R                  5         g r³   )r›   r–   r©   rŸ   s    €r!   r–   Ú_GridText.close,  s   ø€ Ü‰‰ŒØ�‰Õr    c                óø   • U R                   c  g U R                  c  / U l        U R                  R                  SR                  SR                  U R                   5      R	                  5       5      5        S U l         g )Nrj   r/   )rž   r�   rH   rf   rp   ©r    s    r!   rª   Ú_GridText._flush_cell0  sX   € Ø�;‰;ÑØØ�9‰9ÑØˆDŒIØ�	‰	×Ñ˜Ÿ™ "§'¡'¨$¯+©+Ó"6×"<Ñ"<Ó">Ó?Ô@Øˆ�r    c                ó˜   • U R                  5         U R                  b-  U R                  R                  U R                  5        S U l        g g r³   )rª   r�   ro   rH   rº   s    r!   r©   Ú_GridText._flush_row8  s:   € Ø×ÑÔØ�9‰9Ñ Ø�I‰I×Ñ˜TŸY™YÔ'ØˆD�Ið !r    )rž   r�   ro   )ÚreturnÚNone)r«   Ústrr¬   zList[Tuple[str, Optional[str]]]r¾   r¿   )r«   rÀ   r¾   r¿   )r´   rÀ   r¾   r¿   )r   r   r   r   r   rœ   r­   r°   rµ   r–   rª   r©   r   Ú__classcell__)r¡   s   @r!   r”   r”     s1   ø† ñP÷0ô$ôô%÷ô÷ò r    r”   c                óÂ   • U R                  S5      =(       d    0 nUR                  S5      =(       d    0 nUR                  S5      UR                  S5      pTUb  Uc  gXU $ )zJA node's text: the stretch of the response's one long string it points at.Ú	groundingrŒ   ÚstartÚendr/   )r(   )rS   r.   rÃ   ÚrngrÄ   rÅ   s         r!   rM   rM   ?  sW   € à—‘˜Ó%×+¨€IØ
�-‰-˜Ó
 ×
& B€CØ—‘˜Ó! 3§7¡7¨5£>ˆ3Ø�}˜™ØØ˜#ÐÐr    c                ó²   • U R                  S5      =(       d    0 nUR                  S5      =(       d    0 n US   US   US   US   S.$ ! [         a     gf = f)	zGA node's rectangle in the workflow's own box keys, or None without one.rÃ   rD   ÚxminÚyminÚxmaxÚymax)ÚleftÚtopÚrightÚbottomN)r(   ÚKeyError)rS   rÃ   rD   s      r!   rN   rN   I  sg   € à—‘˜Ó%×+¨€IØ
�-‰-˜Ó
×
$ "€Cðà˜‘KØ�v‘;Ø˜‘[Ø˜&‘kñ	
ð 	
øô ó Ùðús   ¶A	 Á	
AÁA)r+   úDict[str, Any]r¾   úOptional[str]r³   )
r+   rÑ   r7   rŠ   r8   rÀ   rO   rÒ   r¾   r   )NF)
rQ   r   rZ   z	List[str]r\   rÒ   r[   Úboolr¾   r   )r?   r
   r¾   rÀ   )r@   r   r¾   rÀ   )rS   rÑ   r.   rÀ   r7   rŠ   r¾   r
   )rS   rÑ   r.   rÀ   r7   rŠ   r¾   r   )rƒ   rÀ   r¾   r   )rS   rÑ   r.   rÀ   r¾   rÀ   )rS   rÑ   r¾   zOptional[Box]),r   Ú
__future__r   ÚreÚhtml.parserr   Útypingr   r   r   r   r	   Úquber.core.figures.dpt3.modelsr
   r   r   r   r   r   Úquber.core.figures.modelsr   r   r   r   r   r   rF   r   Úcompilerw   ÚDOTALLry   r{   r,   rT   r`   r]   re   rI   rK   r|   r”   rM   rN   r   r    r!   Ú<module>rÜ      s(  ðñõ8 #ã 	Ý "ß 3Õ 3÷÷ ÷ j× iô@˜:ô @ð
 —*’*ÐDÓE€ð —*’*Ð@À"Ç)Á)ÓL€ð —*’*Ð4°b·i±iÓ@€ô
ð" #ð	6Øð6à
ð6ð ð6ð ð	6ð
 õ6ðx (,Øð	3Øð3àð3ð %ð3ð ð	3ð
 õ3ôlô"ôô jôDoô.�
ô .ôbõr    