+
    f0i/_                     :   ^ RI t ^ RIHt ^ RIHt ^ RIHtHtHtH	t	H
t
HtHtHtHt ^RIHt ^RIHtHtHtHtHtHt ^t^t^t^t]]]]]3,          3,          t]R]]]3,          3,          t]'       d   ^RIH t  ]]3R	 R
 llt!]3R R llt"R R lt#]3R R llt$]3R R llt%R&R R llt&R R lt'R R lt( ! R R])4      t* ! R R]*4      t+ ! R R]*4      t, ! R R ])4      t-. R'Ot.. R(Ot/ ! R! R"]04      t1]1! ^ 4      t2] ! R# R4      4       t3 ! R$ R%])4      t4R# ))    N)	dataclass)
itemgetter)	TYPE_CHECKINGAnyDictListOptionalSetTupleTypeUnion)utils)T_bboxT_numT_obj
T_obj_iter
T_obj_listT_pointTableSettings)Pagec                H    V ^8  d   QhR\         R\        R\        R\         /#    edgesx_tolerancey_tolerancereturnr   r   )formats   "V/Users/agent/.openclaw/workspace/venv/lib/python3.14/site-packages/pdfplumber/table.py__annotate__r!      s0     ! !!! ! 	!    c                    R. R. /pV  F!  pW4R,          ,          P                  V4       K#  	  \        P                  ! VR,          RV4      p\        P                  ! VR,          RV4      pWV,           # )zg
Given a list of edges, snap any within `tolerance` pixels of one another
to their positional average.
vhorientationx0top)appendr   snap_objects)r   r   r   by_orientatione	snapped_v	snapped_hs   &&&    r    
snap_edgesr/      so     .1"c2,>N'(//2  "">##6kJI"">##6{KI  r"   c                H    V ^8  d   QhR\         R\        R\        R\        /# )r   r   r&   	tolerancer   )r   strr   r   )r   s   "r    r!   r!   '   s,      $'49r"   c                   VR8X  d   RRrCMVR8X  d   RRrCM\        R4      h\        \        V \        V4      R7      4      pV^ ,          .pVR	,           Fn  pVR
,          pWs,          W,          V,           8:  d8   Wt,          W,          8  d#   \        P
                  ! WWt,          4      VR
&   K[  K]  VP                  V4       Kp  	  V# )zs
Given a list of edges along the same infinite line, join those that
are within `tolerance` pixels of one another.
r%   r'   x1r$   r(   bottomzOrientation must be 'v' or 'h'key:   NN)
ValueErrorlistsortedr   r   resize_objectr)   )	r   r&   r1   min_propmax_propsorted_edgesjoinedr,   lasts	   &&&      r    join_edge_grouprC   '   s     c!4(		"H(9::u*X*>?@L1oF"bz;4>I56{T^+"00Mr
 ,
 MM!  Mr"   c                `    V ^8  d   QhR\         R\        R\        R\        R\        R\         /# )r   r   snap_x_tolerancesnap_y_tolerancejoin_x_tolerancejoin_y_tolerancer   r   )r   s   "r    r!   r!   D   sD        	
  r"   c                   aa R R lpV^ 8  g   V^ 8  d   \        WV4      p \        WR7      p\        P                  ! WeR7      pVV3R lV 4       p\	        \        P
                  ! V!  4      p V # )zp
Using the `snap_edges` and `join_edge_group` methods above,
merge a list of edges into a more "seamless" list.
c                R    V ^8  d   QhR\         R\        \        \        3,          /# )r   edger   )r   r   r2   r   )r   s   "r    r!   !merge_edges.<locals>.__annotate__P   s#     % % %%U
"3 %r"   c                 J    V R ,          R8X  d   RV R,          3# RV R,          3# )r&   r%   r(   r$   r'    )rK   s   &r    	get_groupmerge_edges.<locals>.get_groupP   s-    #%e%%d$$r"   r6   c              3   n   <"   T F*  w  r\        Y!^ ,          V^ ,          R8X  d   SMS4      x  K,  	  R# 5i)r   r%   N)rC   ).0kitemsrG   rH   s   &  r    	<genexpr>merge_edges.<locals>.<genexpr>[   s?       $HA 	Q4adck*?O	
 	
 $s   25)r/   r<   	itertoolsgroupbyr;   chain)	r   rE   rF   rG   rH   rO   _sortededge_groupsedge_gens	   &&&ff    r    merge_edgesr]   D   sl    % !/!354DEU*G##G;K $	H (+,ELr"   c                <    V ^8  d   QhR\         R\        R\         /# r   wordsword_thresholdr   r   int)r   s   "r    r!   r!   e   s$     ( (('*((r"   c                  a \         P                  ! V \        R4      ^4      p\        V3R lV4      p\	        \        \         P                  V4      4      p\        V4      ^ 8X  d   . # \        \        \        R4      V4      4      p\        \        \        R4      V4      4      p. pV FN  pVRVRVRVR,          RVR,          RWe,
          RR/RVRVRVR,          RVR,          RWe,
          RR/.,          pKP  	  V# )	z]
Find (imaginary) horizontal lines that connect the tops
of at least `word_threshold` words.
r(   c                     < \        V 4      S8  # Nlenxra   s   &r    <lambda>"words_to_edges_h.<locals>.<lambda>m       c!f&>r"   r'   r4   r5   widthr&   r%   )
r   cluster_objectsr   filterr;   mapobjects_to_rectrh   minmax)	r`   ra   by_toplarge_clustersrectsmin_x0max_x1r   rs	   &f       r    words_to_edges_hr{   e   s    ""5*U*;Q?F>GNU**N;<E
5zQ	Z%u-.FZ%u-.FE ffqx!E(s ffq{!H+s
 	
 0 Lr"   c                <    V ^8  d   QhR\         R\        R\         /# r_   rb   )r   s   "r    r!   r!      s$     < <<'*<<r"   c                  aa \         P                  ! V \        R4      ^4      p\         P                  ! V \        R4      ^4      pR R lp\         P                  ! W^4      pW#,           V,           p\        VR R7      p\	        V3R lV4      p\        \        \         P                  V4      4      p	. p
V	 FX  o\        ;QJ d    V3R lV
 4       F  '       g   K   R	M	  R
M! V3R lV
 4       4      pV'       d   KG  V
P                  S4       KZ  	  \        V
4      ^ 8X  d   . # \        \         P                  V
4      p\        \        V\        R4      R7      4      p\        \        \        R4      V4      4      p\        \        \        R4      V4      4      p\        \        \        R4      V4      4      pV Uu. uF&  pRVR,          RVR,          RVRVRVV,
          RR/NK(  	  upRVRVRVRVRVV,
          RR/.,           # u upi )zm
Find (imaginary) vertical lines that connect the left, right, or
center of at least `word_threshold` words.
r'   r4   c                0    V ^8  d   QhR\         R\        /# )r   wordr   )r   r   )r   s   "r    r!   &words_to_edges_v.<locals>.__annotate__   s     2 2 25 2r"   c                 P    \        V R ,          V R,          ,           4      ^,          # )r'   r4   )float)r   s   &r    
get_center$words_to_edges_v.<locals>.get_center   s    T$Z$t*,-11r"   c                     \        V 4      ) # rf   rg   )rj   s   &r    rk   "words_to_edges_v.<locals>.<lambda>   s
    c!fWr"   r6   c                     < \        V 4      S8  # rf   rg   ri   s   &r    rk   r      rm   r"   c              3   R   <"   T F  p\         P                  ! SV4      x  K  	  R # 5irf   )r   get_bbox_overlap)rR   cbboxs   & r    rU   #words_to_edges_v.<locals>.<genexpr>   s#     P?O!e,,T155?Os   $'TFr(   r5   heightr&   r$   )r   ro   r   r<   rp   r;   rq   objects_to_bboxanyr)   rh   bbox_to_rectrt   rs   )r`   ra   by_x0by_x1r   	by_centerclusterssorted_clustersrv   bboxescondensed_bboxesoverlapcondensed_rectssorted_rectsry   min_top
max_bottombr   s   &f                @r    words_to_edges_vr      s    !!%D)91=E!!%D)91=E2 %%e;I}y(H X+<=O>PN #e++^<=F &(#P?OP###P?OPPw##D) 
 !	%,,.>?OJt4DEFLZ%|45F#j'67GSH-|<=J 
 A !D'!D'7jj7*3	
 
 &&7jj7*3	
		  
s   ;,Hc                H    V ^8  d   QhR\         R\        R\        R\        /# r   )r   r   T_intersections)r   s   "r    r!   r!      s,      $)<Ar"   c           	       a / pR	 Uau. uF  o\        \        V3R lV 4      4      NK  	  upw  rV\        V\        RR4      R7       F  p\        V\        RR4      R7       F  pVR,          VR,          V,           8:  g   K!  VR,          VR,          V,
          8  g   K?  VR,          VR,          V,
          8  g   K]  VR,          VR,          V,           8:  g   K{  VR,          VR,          3p	W9  d	   R. R. /W9&   W9,          R,          P	                  V4       W9,          R,          P	                  V4       K  	  K  	  V# u upi )
z]
Given a list of edges, return the points at which they intersect
within `tolerance` pixels.
r$   r%   c                    < V R ,          S8H  # )r&   rN   )rj   os   &r    rk   (edges_to_intersections.<locals>.<lambda>   s    a.!3r"   r'   r(   r6   r5   r4   )r$   r%   )r;   rp   r<   r   r)   )
r   r   r   intersectionsr   v_edgesh_edgesr$   r%   vertexs
   &&& `     r    edges_to_intersectionsr      s    &(MFPFPV3U;<jG GD%!89Zt%<=A5ah45x[QuX%;<tW4;!67tW4;!67D'1U8,.-0"c2,>M)%c*11!4%c*11!4 > : !s   "Ec                F    V ^8  d   QhR\         R\        \        ,          /# )r   r   r   )r   r   r   )r   s   "r    r!   r!      s     <( <(/ <(d6l <(r"   c                   a aaaa R V 3R llo\        \        S P                  4       4      4      o\        S4      oR VV V3R lloVV3R l\	        \        S4      4       4       p\        \        RV4      4      # )a   
Given a list of points (`intersections`), return all rectangular "cells"
that those points describe.

`intersections` should be a dictionary with (x0, top) tuples as keys,
and a list of edge objects as values. The edge objects should correspond
to the edges that touch the intersection.
c                <    V ^8  d   QhR\         R\         R\        /# )r   p1p2r   )r   bool)r   s   "r    r!   ,intersections_to_cells.<locals>.__annotate__   s!      ' w 4 r"   c                   < R  R lpV ^ ,          V^ ,          8X  dM   V! SV ,          R,          4      P                  V! SV,          R,          4      4      p\        V4      '       d   R# V ^,          V^,          8X  dM   V! SV ,          R,          4      P                  V! SV,          R,          4      4      p\        V4      '       d   R# R# )c                F    V ^8  d   QhR\         R\        \        ,          /# )r   r   r   )r   r
   r   )r   s   "r    r!   Cintersections_to_cells.<locals>.edge_connects.<locals>.__annotate__   s     	6 	6
 	6s6{ 	6r"   c                 H    \        \        \        P                  V 4      4      # rf   )setrq   r   obj_to_bbox)r   s   &r    edges_to_setCintersections_to_cells.<locals>.edge_connects.<locals>.edges_to_set   s    s5,,e455r"   r$   Tr%   F)intersectionrh   )r   r   r   commonr   s   &&  r    edge_connects-intersections_to_cells.<locals>.edge_connects   s    	6 a5BqE>!-"3C"89FF]2.s34F 6{{a5BqE>!-"3C"89FF]2.s34F 6{{r"   c                h    V ^8  d   QhR\         \        ,          R\        R\        \        ,          /# )r   pointsir   )r   r   rc   r	   r   )r   s   "r    r!   r   
  s*      4= S Xf=M r"   c                    < VS^,
          8X  d   R# W,          pW^,           R pV Uu. uF  qD^ ,          V^ ,          8X  g   K  VNK  	  ppV Uu. uF  qD^,          V^,          8X  g   K  VNK  	  ppV F  pS
! W'4      '       g   K  V Fr  pS
! W(4      '       g   K  V^ ,          V^,          3p	V	S9   g   K.  S
! W4      '       g   K>  S
! W4      '       g   KN  V^ ,          V^,          V	^ ,          V	^,          3u u # 	  K  	  R# u upi u upi r8   NrN   )r   r   ptrestrj   belowrightbelow_ptright_ptbottom_rightr   r   n_pointss   &&        r    find_smallest_cell2intersections_to_cells.<locals>.find_smallest_cell
  s    1Y!eg 2DqaDBqEMD2 2DqaDBqEMD2H ..!$R22 (Xa[9 "]2%l==%l== qE2a5,q/<?KK "	 " ' 32s   DDD+Dc              3   6   <"   T F  pS! SV4      x  K  	  R # 5irf   rN   )rR   r   r   r   s   & r    rU   )intersections_to_cells.<locals>.<genexpr>%  s     J7I!"61--7Is   N)r;   r<   keysrh   rangerp   )r   cell_genr   r   r   r   s   f @@@@r    intersections_to_cellsr      sb     & &++-./F6{H 6 KuS[7IJHtX&''r"   c                r    V ^8  d   QhR\         \        ,          R\         \         \        ,          ,          /# )r   cellsr   r   r   )r   s   "r    r!   r!   )  s'     : :4< :Df,> :r"   c                D  a R R lp\        V 4      p\        4       o. p. p\        V4      '       Ed   \        V4      p\        V4       F  pV! V4      p\        V4      ^ 8X  d7   S\        V4      ,          oVP                  V4       VP	                  V4       KQ  \        V3R lV 4       4      pV^ 8  g   Ko  S\        V4      ,          oVP                  V4       VP	                  V4       K  	  \        V4      V8X  g   K  VP                  \        V4      4       SP                  4        VP                  4        EK  \        V4      '       d   VP                  \        V4      4       \        VR R7      p	V	 U
u. uF  p
\        V
4      ^8  g   K  V
NK  	  pp
V# u up
i )zy
Given a list of bounding boxes (`cells`), return a list of tables that
hold those cells most simply (and contiguously).
c                f    V ^8  d   QhR\         R\        \        \        \        \        3,          /# )r   r   r   )r   r   r   )r   s   "r    r!   %cells_to_tables.<locals>.__annotate__/  s,     B Bf Bw'/Q)R Br"   c                      V w  rr4W3W3W23W433# rf   rN   )r   r'   r(   r4   r5   s   &    r    bbox_to_corners(cells_to_tables.<locals>.bbox_to_corners/  s#    "	B<"RLAAr"   c              3   ,   <"   T F	  qS9   x  K  	  R # 5irf   rN   )rR   r   current_cornerss   & r    rU   "cells_to_tables.<locals>.<genexpr>H  s     "NA#7s   c                 &    \        R  V  4       4      # )c              3   D   "   T F  q^,          V^ ,          3x  K  	  R# 5ir   rN   )rR   r   s   & r    rU   4cells_to_tables.<locals>.<lambda>.<locals>.<genexpr>a  s     .GQ!ad|Qs    )rs   )ts   &r    rk   !cells_to_tables.<locals>.<lambda>a  s    3.GQ.G+Gr"   r6   )r;   r   rh   r)   removesumclearr<   )r   r   remaining_cellscurrent_cellstablesinitial_cell_countcellcell_cornerscorner_countrZ   r   filteredr   s   &           @r    cells_to_tablesr   )  se   B 5kO
 %(EO"$MF
o

 /)D*40L=!Q&3|#44$$T*&&t,  #"N"NN  !##s<'88O!((.#**40# *( }!33MM$}-.!!#!
 =d=)* V!GHG"17ac!fqj7H1O 2s   <FFc                   2   a  ] tR tRt o V 3R lR ltRtV tR# )	CellGroupif  c                @   < V ^8  d   QhRS[ S[S[,          ,          /# )r   r   )r   r	   r   )r   __classdict__s   "r    r!   CellGroup.__annotate__g  s     
 
d8F#34 
r"   c                X   Wn         \        \        \        ^ 4      \	        RV4      4      4      \        \        \        ^4      \	        RV4      4      4      \        \        \        ^4      \	        RV4      4      4      \        \        \        ^4      \	        RV4      4      4      3V n        R# )r   N)r   rs   rq   r   rp   rt   r   )selfr   s   &&r    __init__CellGroup.__init__g  sx    
JqM6$#678JqM6$#678JqM6$#678JqM6$#678	
	r"   )r   r   N)__name__
__module____qualname____firstlineno__r   __static_attributes____classdictcell__r   s   @r    r   r   f  s     
 
r"   r   c                       ] tR tRtRtR# )Rowiq  rN   Nr   r   r   r   r   rN   r"   r    r   r   q      r"   r   c                       ] tR tRtRtR# )Columniu  rN   Nr  rN   r"   r    r  r  u  r  r"   r  c                      a  ] tR tRt o V 3R lR lt]V 3R lR l4       tV 3R lR lt]V 3R lR	 l4       t]V 3R
 lR l4       t	V 3R lR lt
RtV tR# )Tableiy  c                4   < V ^8  d   QhRRRS[ S[,          /# )r   pager   r   r   )r   r   s   "r    r!   Table.__annotate__z  s      V DL r"   c                    Wn         W n        R # rf   )r  r   )r   r  r   s   &&&r    r   Table.__init__z  s    	
r"   c                    < V ^8  d   QhRS[ /# r   r   )r   )r   r   s   "r    r!   r	    s     
 
f 
r"   c           
        V P                   p\        \        \        ^ 4      V4      4      \        \        \        ^4      V4      4      \	        \        \        ^4      V4      4      \	        \        \        ^4      V4      4      3# )r   )r   rs   rq   r   rt   )r   r   s   & r    r   
Table.bbox~  sa    JJJqM1%&JqM1%&JqM1%&JqM1%&	
 	
r"   c                F   < V ^8  d   QhRS[ S[,          RS[S[,          /# )r   kindr   )r   r   r   )r   r   s   "r    r!   r	    s#      d9o $y/ r"   c                   V\         J d   ^ M^p\        V'       * 4      p\        V P                  \	        W24      R7      p\        \        \        \        \	        V4      V P                  4      4      4      4      p\        P                  ! V\	        V4      4      p. pV FT  w  rV	 U
u/ uF  qV,          V
bK  	  pp
T! V Uu. uF  qP                  V4      NK  	  up4      pVP                  V4       KV  	  V# u up
i u upi )r   r6   )r   rc   r<   r   r   r;   r   rq   rW   rX   getr)   )r   r  axisantiaxisrZ   xsgroupedrowsy	row_cellsr   xdictrj   rows   &&            r    _get_rows_or_colsTable._get_rows_or_cols  s    CKqQ4x= H)CD &SD!14::>?@A ##GZ-AB#LA2;<)$$Z%)E<b1b		!b12CKK $  =1s   &C7 C<
c                0   < V ^8  d   QhRS[ S[,          /# r  r   r   )r   r   s   "r    r!   r	    s     + +d9o +r"   c                ,    V P                  \        4      # rf   )r  r   r   s   &r    r  
Table.rows  s    %%c**r"   c                0   < V ^8  d   QhRS[ S[,          /# r  r   )r   r   s   "r    r!   r	    s     . .i .r"   c                ,    V P                  \        4      # rf   )r  r  r"  s   &r    columnsTable.columns  s    %%f--r"   c                V   < V ^8  d   QhRS[ RS[S[S[S[,          ,          ,          /# )r   kwargsr   )r   r   r	   r2   )r   r   s   "r    r!   r	    s)     $ $ $T(3--@(A $r"   c           	     `   V P                   P                  p. pR  R lpV P                   F  p. pV Uu. uF  qt! WuP                  4      '       g   K  VNK   	  ppVP                   F  p	V	f   Rp
MV Uu. uF  qt! Wy4      '       g   K  VNK  	  pp\        V4      '       dX   RV9   d9   V	^,          V	^ ,          ,
          VR&   V	^,          V	^,          ,
          VR&   WR&   \        P                  ! V3/ VB p
MRp
VP                  V
4       K  	  VP                  V4       K  	  V# u upi u upi )c                <    V ^8  d   QhR\         R\        R\        /# )r   charr   r   )r   r   r   )r   s   "r    r!   #Table.extract.<locals>.__annotate__  s!     	 	u 	F 	t 	r"   c                     V R ,          V R,          ,           ^,          pV R,          V R,          ,           ^,          pVw  rErg\        W48  ;'       d    W68  ;'       d    W%8  ;'       d    W'8  4      # )r(   r5   r'   r4   )r   )r,  r   v_midh_midr'   r(   r4   r5   s   &&      r    char_in_bbox#Table.extract.<locals>.char_in_bbox  sj    %[4>1Q6E$Z$t*,1E"&BRVV5:VVELVVu~ r"   Nlayoutlayout_widthlayout_heightlayout_bbox )	r  charsr  r   r   rh   r   extract_textr)   )r   r)  r8  	table_arrr1  r  arrr,  	row_charsr   	cell_text
cell_charss   &,          r    extractTable.extract  s    				 99CC*/P%$<hh3O%IP		< $I *3")2l46N  " :#v-59!WtAw5FF>26:1gQ6GF?348=1$)$6$6z$LV$L	$&	

9%! "" S!+ . + Q"s   D&D&4D+D+)r   r  N)r   r   r   r   r   propertyr   r  r  r&  r?  r   r   r   s   @r    r  r  y  s_       
 
 * + + . .$ $r"   r  c                       ] tR tRtRtR# )
UnsetFloati  rN   Nr  rN   r"   r    rC  rC    r  r"   rC  c                      a  ] tR tRt o RtRtRtRt]t	]
t]
t]t]
t]
t^t^t]t]t^t]
t]
tRtV 3R lR lt]V 3R lR l4       tV 3R ltR	tV t R# )
r   i  linesNc                   < V ^8  d   QhRR/# )r   r   NrN   )r   r   s   "r    r!   TableSettings.__annotate__  s     1= 1=t 1=r"   c           	     ^   \          F,  p\        W4      ;'       g    ^ ^ 8  g   K  \        RV R24      h	  R	 FD  p\        WR,           4      pV\        9  g   K"  \        V RRP	                  \        4       R24      h	  V P
                  f   / V n        R
 F>  pW@P
                  9  g   K  V P
                  P                  R^4      V P
                  V&   K@  	  RV P
                  9   d   V P
                  R R F/  w  rE\        W4      \        J g   K  \        W\        W4      4       K1  	  R# )ao  Clean up user-provided table settings.

Validates that the table settings provided consists of acceptable values and
returns a cleaned up version. The cleaned up version fills out the missing
values with the default values in the provided settings.

TODO: Can be further used to validate that the values are of the correct
    type. For example, raising a value error when a non-boolean input is
    provided for the key ``keep_blank_chars``.

:param table_settings: User-provided table settings.
:returns: A cleaned up version of the user-provided table settings.
:raises ValueError: When an unrecognised key is provided.
zTable setting 'z' cannot be negative	_strategyz_strategy must be one of{,}Nr1   )
horizontalvertical)r   r   ))rE   snap_tolerance)rF   rN  )rG   join_tolerance)rH   rO  )intersection_x_toleranceintersection_tolerance)intersection_y_tolerancerQ  )	NON_NEGATIVE_SETTINGSgetattrr:   TABLE_STRATEGIESjointext_settingsr  UNSETsetattr)r   settingr&   strategyattrfallbacks   &     r    __post_init__TableSettings.__post_init__  s%     -G&++!q0 ?7);O!PQQ - 6Kt;%>?H// "m $"234B8  6 %!#D 3D---+/+=+=+A+A+q+Q""4( 3 $,,,"";/
ND t"e+GD$;<
r"   c                4   < V ^8  d   QhRS[ S[,          RR/# )r   settingsr   r   r	   T_table_settings)r   r   s   "r    r!   rG  .  s%     E Ex(89 Eo Er"   c                   Vf   V ! 4       # \        W4      '       d   V# \        V\        4      '       dI   / p/ pVP                  4        F$  w  rEVR,          R8X  d   WSVR,          &   K   WRV&   K&  	  W2R&   V ! R/ VB # \        RV 24      h)N:N   Ntext_:re  NNrW  zCannot resolve settings: rN   )
isinstancedictrT   r:   )clsra  core_settingsrW  rS   r$   s   &&    r    resolveTableSettings.resolve-  s    5L&&O$''MM (R5G#+,!B%('(!$	 )
 .;/*'''8
CDDr"   c                  < V ^8  d   Qh/ S[ ;R&   S[ ;R&   S[S[S[S[S[3,          ,          ,          ;R&   S[S[S[S[S[3,          ,          ,          ;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R	&   S[;R
&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[S[S[ S[3,          ,          ;R&   # )r   vertical_strategyhorizontal_strategyexplicit_vertical_linesexplicit_horizontal_linesrN  rE   rF   rO  rG   rH   edge_min_lengthedge_min_length_prefiltermin_words_verticalmin_words_horizontalrQ  rP  rR  rW  )	r2   r	   r   r   r   r   rc   r   r   )r   r   s   "r    r!   rG    s     $  &  &d5+>&?@G	 
  (U5%<-@(ABI  2  #  #  2  #  #     %(  8  <   "%! " $+# $ $+% & DcN+2' r"   )rW  )!r   r   r   r   rn  ro  rp  rq  DEFAULT_SNAP_TOLERANCErN  rX  rE   rF   DEFAULT_JOIN_TOLERANCErO  rG   rH   rr  rs  DEFAULT_MIN_WORDS_VERTICALrt  DEFAULT_MIN_WORDS_HORIZONTALru  rQ  rP  rR  rW  r^  classmethodrk  __annotate_func__r   r   r   s   @r    r   r     s     $&CGEI2N##2N##O'(8 <$%&+&+.2M1= 1=f E ES  r"   c                   L   a  ] tR tRt o RtR	V 3R lR lltV 3R lR ltRtV tR# )
TableFinderiA  a  
Given a PDF page, find plausible table structures.

Largely borrowed from Anssi Nurminen's master's thesis:
http://dspace.cc.tut.fi/dpub/bitstream/handle/123456789/21520/Nurminen.pdf?sequence=3

... and inspired by Tabula:
https://github.com/tabulapdf/tabula-extractor/issues/16
Nc                4   < V ^8  d   QhRRRS[ S[,          /# )r   r  r   ra  rb  )r   r   s   "r    r!   TableFinder.__annotate__L  s!     
 
V 
x8H/I 
r"   c                   Wn         \        P                  V4      V n        V P	                  4       V n        \        V P
                  V P                  P                  V P                  P                  4      V n	        \        V P                  4      V n        \        V P                  4       Uu. uF  p\        V P                   V4      NK  	  upV n        R # u upi rf   )r  r   rk  ra  	get_edgesr   r   rP  rR  r   r   r   r   r  r   )r   r  ra  
cell_groups   &&& r    r   TableFinder.__init__L  s    	%--h7^^%
3JJMM22MM22

 ,D,>,>?
;J4::;V
;VZE$))Z(;V
 
s   +Cc                    < V ^8  d   QhRS[ /# r  )r   )r   r   s   "r    r!   r  Z  s     iN iN: iNr"   c                D	   V P                   pR FZ  p\        WR,           4      pVR8X  g   K  \        VRV,           R,           4      p\        V4      ^8  g   KJ  \        RV RV R24      h	  VP                  pVP
                  pVR8X  g   VR8X  d1   V P                  P                  ! R/ VP                  ;'       g    / B p. pVP                  ;'       g    .  F  p	\        V	\        4      '       dA   \        P                  ! V	4       F$  p
V
R	,          R
8X  g   K  VP                  V
4       K&  	  KY  VP                  RV	RV	RV P                  P                  ^,          RV P                  P                  ^,          RV P                  P                  ^,          V P                  P                  ^,          ,
          R	R
/4       K  	  VR8X  d9   \        P                   ! V P                  P"                  R
VP$                  R7      pMhVR8X  d:   \        P                   ! V P                  P"                  R
RVP$                  R7      pM(VR8X  d   \'        XVP(                  R7      pM	VR8X  d   . pXV,           p. pVP*                  ;'       g    .  F  p	\        V	\        4      '       dA   \        P                  ! V	4       F$  p
V
R	,          R8X  g   K  VP                  V
4       K&  	  KY  VP                  RV P                  P                  ^ ,          RV P                  P                  ^,          RV P                  P                  ^,          V P                  P                  ^ ,          ,
          RV	RV	R	R/4       K  	  VR8X  d9   \        P                   ! V P                  P"                  RVP$                  R7      pMhVR8X  d:   \        P                   ! V P                  P"                  RRVP$                  R7      pM(VR8X  d   \-        XVP.                  R7      pM	VR8X  d   . pXV,           p\1        V4      \1        V4      ,           p\3        VVP4                  VP6                  VP8                  VP:                  R7      p\        P                   ! VVP<                  R7      # )rM  rI  explicit	explicit__lineszIf z"_strategy == 'explicit', explicit_zD_lines must be specified as a list/tuple of two or more floats/ints.textr&   r$   r'   r4   r(   r5   r   rE  )
min_lengthlines_strictline)	edge_typer  )ra   r%   rn   )rE   rF   rG   rH   )rM  rL  rN   )ra  rT  rh   r:   rn  ro  r  extract_wordsrW  rp  rg  rh  r   obj_to_edgesr)   r   filter_edgesr   rs  r   rt  rq  r{   ru  r;   r]   rE   rF   rG   rH   rr  )r   ra  r&   r[  rE  v_strath_stratr`   
v_explicitdescr,   v_baser$   
h_explicith_baser%   r   s   &                r    r  TableFinder.get_edgesZ  s   ==5Kx{)BCH:%+*Ch*NOu:>$k] +$$/= 1'(  6 ,,..f6 1II++Mx/E/E/K/KME
44:::D$%%++D1A'3."))!, 2 !!ddtyy~~a0 $)).."3 $)).."3diinnQ6G"G%s	 ;" g''		1S1SF &''		 #==	F %eH<W<WXF
"FZ
66<<"<D$%%++D1A'3."))!, 2 !!diinnQ/diinnQ/!2TYY^^A5F!Ft $%s	 =" g''		1S1SF &''		 #==	F %h&C&CF 
"FZQ$q'!%66%66%66%66
 !!%H4L4LMMr"   )r   r   r   r  ra  r   rf   )	r   r   r   r   __doc__r   r  r   r   r   s   @r    r}  r}  A  s"     
 
iN iNr"   r}  )r8   r8   )rE  r  r  r  )rN  rE   rF   rO  rG   rH   rr  rs  rt  ru  rQ  rP  rR  )5rW   dataclassesr   operatorr   typingr   r   r   r   r	   r
   r   r   r   r7  r   _typingr   r   r   r   r   r   rv  rw  rx  ry  r2   r   rc  r  r   r/   rC   r]   r{   r   r   r   r   objectr   r   r  r  rU  rS  r   rC  rX  r   r}  rN   r"   r    <module>r     s@    !  T T T  J J     wS*_ 556$sCx.89 
 0/!& =S:D .J(X .H<~6<(~:z
 
	) 		Y 	PF Pf A  "	 	 	1 XE XE XEvBN& BNr"   