
    SAi/_                        S SK r S SKJr  S SKJr  S SKJrJrJrJ	r	J
r
JrJrJrJr  SSKJr  SSKJrJrJrJrJrJr  SrSrSrSr\\\\\4   4   r\S	\\\4   4   r\(       a  SS
KJ r   \\4S\S\S\S\4S jjr!\4S\S\S\S\4S jjr"S\S\S\S\S\S\4S jr#\4S\S\$S\4S jjr%\4S\S\$S\4S jjr& S0S\S\S\S\4S jjr'S\S\	\   4S jr(S\	\   S\	\	\      4S  jr) " S! S"\*5      r+ " S# S$\+5      r, " S% S&\+5      r- " S' S(\*5      r./ S)Qr// S*Qr0 " S+ S,\15      r2\2" S 5      r3\ " S- S	5      5       r4 " S. S/\*5      r5g)1    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)Pageedgesx_tolerancey_tolerancereturnc                     / / S.nU  H  nX4S      R                  U5        M     [        R                  " US   SU5      n[        R                  " US   SU5      nXV-   $ )zg
Given a list of edges, snap any within `tolerance` pixels of one another
to their positional average.
vhorientationr   x0r    top)appendr   snap_objects)r   r   r   by_orientatione	snapped_v	snapped_hs          L/var/www/html/land-ocr/venv/lib/python3.13/site-packages/pdfplumber/table.py
snap_edgesr+      sk     352,>N'(//2  "">##6kJI"">##6{KI      r!   	tolerancec                 >   US:X  a  Su  p4OUS:X  a  Su  p4O[        S5      e[        [        U [        U5      S95      nUS   /nUSS	  HP  nUS
   nXs   X   U-   ::  a*  Xt   X   :  a  [        R
                  " XXt   5      US
'   M=  M?  UR                  U5        MR     U$ )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'keyr   r   N)
ValueErrorlistsortedr   r   resize_objectr$   )	r   r!   r-   min_propmax_propsorted_edgesjoinedr'   lasts	            r*   join_edge_groupr=   '   s     c'(		,(9::u*X*>?@L1oF!"bz;4>I56{T^+"00Mr
 ,
 MM!  Mr,   snap_x_tolerancesnap_y_tolerancejoin_x_tolerancejoin_y_tolerancec                   ^^ S[         S[        [        [        4   4S jnUS:  d  US:  a  [	        XU5      n [        XS9n[        R                  " XeS9nUU4S jU 5       n[        [        R                  " U6 5      n U $ )zp
Using the `snap_edges` and `join_edge_group` methods above,
merge a list of edges into a more "seamless" list.
edger   c                 0    U S   S:X  a  SU S   4$ SU S   4$ )Nr!   r    r#   r   r"    )rC   s    r*   	get_groupmerge_edges.<locals>.get_groupP   s-    #%e%%d$$r,   r   r1   c              3   \   >#    U  H!  u  p[        X!S    US    S:X  a  TOT5      v   M#     g7f)r   r    N)r=   ).0kitemsr@   rA   s      r*   	<genexpr>merge_edges.<locals>.<genexpr>[   s?       $HA 	Q4adck*?O	
 	
 $s   ),)
r   r   strr   r+   r6   	itertoolsgroupbyr5   chain)	r   r>   r?   r@   rA   rF   _sortededge_groupsedge_gens	      ``    r*   merge_edgesrU   D   s    % %%U
"3 % !/!354DEU*G##G;K $	H (+,ELr,   wordsword_thresholdc           
        ^ [         R                  " U [        S5      S5      n[        U4S jU5      n[	        [        [         R                  U5      5      n[        U5      S:X  a  / $ [        [        [        S5      U5      5      n[        [        [        S5      U5      5      n/ nU H(  nUUUUS   US   Xe-
  SS.UUUS	   US	   Xe-
  SS./-  nM*     U$ )
z]
Find (imaginary) horizontal lines that connect the tops
of at least `word_threshold` words.
r#   r   c                     > [        U 5      T:  $ NlenxrW   s    r*   <lambda>"words_to_edges_h.<locals>.<lambda>m       c!f&>r,   r   r"   r/   r    )r"   r/   r#   r0   widthr!   r0   )
r   cluster_objectsr   filterr5   mapobjects_to_rectr\   minmax)	rV   rW   by_toplarge_clustersrectsmin_x0max_x1r   rs	    `       r*   words_to_edges_hro   e   s     ""5*U*;Q?F>GNU**N;<E
5zQ	Z%u-.FZ%u-.FE xE(" {H+"
 	
 0 Lr,   c           
        ^^ [         R                  " U [        S5      S5      n[         R                  " U [        S5      S5      nS[        S[        4S jn[         R                  " XS5      nX#-   U-   n[        US S9n[        U4S	 jU5      n[        [        [         R                  U5      5      n	/ n
U	 H2  m[        U4S
 jU
 5       5      nU(       a  M!  U
R                  T5        M4     [        U
5      S:X  a  / $ [        [         R                  U
5      n[        [        U[        S5      S95      n[        [        [        S5      U5      5      n[        [        [        S5      U5      5      n[        [        [        S5      U5      5      nU Vs/ s H  nUS   US   UUUU-
  SS.PM     snUUUUUU-
  SS./-   $ s  snf )zm
Find (imaginary) vertical lines that connect the left, right, or
center of at least `word_threshold` words.
r"   r   r/   wordr   c                 0    [        U S   U S   -   5      S-  $ )Nr"   r/      )float)rq   s    r*   
get_center$words_to_edges_v.<locals>.get_center   s    T$Z$t*,-11r,   c                     [        U 5      * $ rZ   r[   )r^   s    r*   r_   "words_to_edges_v.<locals>.<lambda>   s
    c!fWr,   r1   c                     > [        U 5      T:  $ rZ   r[   r]   s    r*   r_   rx      ra   r,   c              3   R   >#    U  H  n[         R                  " TU5      v   M     g 7frZ   )r   get_bbox_overlap)rI   cbboxs     r*   rL   #words_to_edges_v.<locals>.<genexpr>   s#     P?O!e,,T155?Os   $'r   r#   r0   r   r"   r/   r#   r0   heightr!   )r   rc   r   r   r   r6   rd   r5   re   objects_to_bboxanyr$   r\   bbox_to_rectrh   rg   )rV   rW   by_x0by_x1ru   	by_centerclusterssorted_clustersrj   bboxescondensed_bboxesoverlapcondensed_rectssorted_rectsrm   min_top
max_bottombr}   s    `                @r*   words_to_edges_vr      s    !!%D)91=E!!%D)91=E2 25 2 %%e;I}y(H X+<=O>PN #e++^<=F &(P?OPPw##D) 
 !	%,,.>?OJt4DEFLZ%|45F#j'67GSH-|<=J 
 A D'D'  7*	
 
   7*	
		  
s   F>c           	        ^ 0 nS V^s/ s H  m[        [        U4S jU 5      5      PM     snu  pV[        U[        SS5      S9 H  n[        U[        SS5      S9 H  nUS   US   U-   ::  d  M  US   US   U-
  :  d  M%  US   US   U-
  :  d  M6  US   US   U-   ::  d  MG  US   US   4n	X;  a  / / S.X9'   X9   S   R	                  U5        X9   S	   R	                  U5        M     M     U$ s  snf )
z]
Given a list of edges, return the points at which they intersect
within `tolerance` pixels.
r   c                    > U S   T:H  $ )Nr!   rE   )r^   os    r*   r_   (edges_to_intersections.<locals>.<lambda>   s    a.!3r,   r"   r#   r1   r0   r/   r   r    )r5   rd   r6   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,.242,>M)%c*11!4%c*11!4 > : !s   #C/r   c                 V  ^ ^^^^ S[         S[         S[        4U 4S jjm[        [        T R	                  5       5      5      m[        T5      mS[        [            S[        S[        [           4UU U4S jjmUU4S j[        [        T5      5       5       n[        [        S	U5      5      $ )
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.
p1p2r   c                 N  > S[         S[        [           4S jnU S   US   :X  a:  U" TU    S   5      R                  U" TU   S   5      5      n[	        U5      (       a  gU S   US   :X  a:  U" TU    S   5      R                  U" TU   S   5      5      n[	        U5      (       a  gg	)
Nr   r   c                 H    [        [        [        R                  U 5      5      $ rZ   )setre   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   r   Tr   r    F)r   r
   r   intersectionr\   )r   r   r   commonr   s       r*   edge_connects-intersections_to_cells.<locals>.edge_connects   s    	6
 	6s6{ 	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,   pointsic                   > UTS-
  :X  a  g X   nXS-   S  nU Vs/ s H  oDS   US   :X  d  M  UPM     nnU Vs/ s H  oDS   US   :X  d  M  UPM     nnU Hn  nT
" X'5      (       d  M  U HV  nT
" X(5      (       d  M  US   US   4n	U	T;   d  M$  T
" X5      (       d  M3  T
" X5      (       d  MB  US   US   U	S   U	S   4s  s  $    Mp     g s  snf s  snf )Nr   r   rE   )r   r   ptrestr^   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   C
C
CCc              3   6   >#    U  H  nT" TU5      v   M     g 7frZ   rE   )rI   r   r   r   s     r*   rL   )intersections_to_cells.<locals>.<genexpr>%  s     J7I!"61--7Is   N)r   boolr5   r6   keysr\   r   intr	   r   rangerd   )r   cell_genr   r   r   r   s   ` @@@@r*   intersections_to_cellsr      s    ' w 4 & &++-./F6{H4= S Xf=M  6 KuS[7IJHtX&''r,   cellsc                   ^ S[         S[        [        [        [        [        4   4S jn[        U 5      n[	        5       m/ n/ n[        U5      (       Ga  [        U5      n[        U5       H  nU" U5      n[        U5      S:X  a2  T[	        U5      -  mUR                  U5        UR                  U5        ML  [        U4S jU 5       5      nUS:  d  Mi  T[	        U5      -  mUR                  U5        UR                  U5        M     [        U5      U:X  a:  UR                  [        U5      5        TR                  5         UR                  5         [        U5      (       a  GM  [        U5      (       a  UR                  [        U5      5        [        US S9n	U	 V
s/ s H  n
[        U
5      S:  d  M  U
PM     nn
U$ s  sn
f )	zy
Given a list of bounding boxes (`cells`), return a list of tables that
hold those cells most simply (and contiguously).
r}   r   c                      U u  pp4X4X4X24X444$ rZ   rE   )r}   r"   r#   r/   r0   s        r*   bbox_to_corners(cells_to_tables.<locals>.bbox_to_corners/  s#    "	B<"RLAAr,   r   c              3   ,   >#    U  H	  oT;   v   M     g 7frZ   rE   )rI   r|   current_cornerss     r*   rL   "cells_to_tables.<locals>.<genexpr>H  s     "NA#7s   c                 &    [        S U  5       5      $ )Nc              3   4   #    U  H  oS    US   4v   M     g7f)r   r   NrE   )rI   r|   s     r*   rL   4cells_to_tables.<locals>.<lambda>.<locals>.<genexpr>a  s     .GQ!ad|Qs   )rg   )ts    r*   r_   !cells_to_tables.<locals>.<lambda>a  s    3.GQ.G+Gr,   r1   r   )r   r   r   r5   r   r\   r$   removesumclearr6   )r   r   remaining_cellscurrent_cellstablesinitial_cell_countcellcell_cornerscorner_countrR   r   filteredr   s               @r*   cells_to_tablesr   )  s   Bf Bw'/Q)R 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$}-.!!#!5 o

> =d=)* V!GHG"17ac!fqj7H1O 2s   F=3F=c                   .    \ rS rSrS\\\      4S jrSrg)	CellGroupif  r   c                 V   Xl         [        [        [        S5      [	        S U5      5      5      [        [        [        S5      [	        S U5      5      5      [        [        [        S5      [	        S U5      5      5      [        [        [        S5      [	        S U5      5      5      4U l        g Nr   r   rs   r   )r   rg   re   r   rd   rh   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   r	   r   r   __static_attributes__rE   r,   r*   r   r   f  s    
d8F#34 
r,   r   c                       \ rS rSrSrg)Rowiq  rE   Nr   r   r   r   r   rE   r,   r*   r   r   q      r,   r   c                       \ rS rSrSrg)Columniu  rE   Nr   rE   r,   r*   r   r   u  r   r,   r   c                       \ rS rSrSSS\\   4S jr\S\4S j5       rS\	\
   S\\
   4S	 jr\S\\
   4S
 j5       r\S\\
   4S j5       rS\S\\\\         4S jrSrg)Tableiy  pager   r   c                     Xl         X l        g rZ   )r   r   )r   r   r   s      r*   r   Table.__init__z  s    	
r,   r   c           
         U R                   n[        [        [        S5      U5      5      [        [        [        S5      U5      5      [	        [        [        S5      U5      5      [	        [        [        S5      U5      5      4$ r   )r   rg   re   r   rh   )r   r|   s     r*   r}   
Table.bbox~  sa    JJJqM1%&JqM1%&JqM1%&JqM1%&	
 	
r,   kindc                    U[         L a  SOSn[        U(       + 5      n[        U R                  [	        X25      S9n[        [        [        [        [	        U5      U R                  5      5      5      5      n[        R                  " U[	        U5      5      n/ nU HR  u  pU	 V
s0 s H  oU   U
_M
     nn
U" U Vs/ s H  oR                  U5      PM     sn5      nUR                  U5        MT     U$ s  sn
f s  snf )Nr   r   r1   )r   r   r6   r   r   r5   r   re   rO   rP   getr$   )r   r   axisantiaxisrR   xsgroupedrowsy	row_cellsr   xdictr^   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   "C19C6
c                 ,    U R                  [        5      $ rZ   )r   r   r   s    r*   r   
Table.rows  s    %%c**r,   c                 ,    U R                  [        5      $ rZ   )r   r   r   s    r*   columnsTable.columns  s    %%f--r,   kwargsc           	      L   U R                   R                  n/ nS[        S[        S[        4S jnU R
                   H  n/ nU Vs/ s H  ot" XuR                  5      (       d  M  UPM     nnUR                   H  n	U	c  S n
OpU Vs/ s H  ot" Xy5      (       d  M  UPM     nn[        U5      (       a>  SU;   a   U	S   U	S   -
  US'   U	S	   U	S
   -
  US'   XS'   [        R                  " U40 UD6n
OSn
UR                  U
5        M     UR                  U5        M     U$ s  snf s  snf )Ncharr}   r   c                     U S   U S   -   S-  nU S   U S   -   S-  nUu  pEpg[        X4:  =(       a    X6:  =(       a    X%:  =(       a    X':  5      $ )Nr#   r0   rs   r"   r/   )r   )r  r}   v_midh_midr"   r#   r/   r0   s           r*   char_in_bbox#Table.extract.<locals>.char_in_bbox  sa    %[4>1Q6E$Z$t*,1E"&BRV5:VELVu~ r,   layoutrs   r   layout_widthr   r   layout_heightlayout_bbox )r   charsr   r   r   r   r}   r   r\   r   extract_textr$   )r   r  r  	table_arrr	  r   arrr  	row_charsr   	cell_text
cell_charss               r*   extractTable.extract  s1   				u 	F 	t 	 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D!D!)r   r   N)r   r   r   r   r   r   r   propertyr}   r   r   r   r   r  r   r	   rN   r  r   rE   r,   r*   r   r   y  s    V DL  
f 
 
d9o $y/ * +d9o + + .i . .$ $T(3--@(A $r,   r   )lineslines_stricttextexplicit)snap_tolerancer>   r?   join_tolerancer@   rA   edge_min_lengthedge_min_length_prefiltermin_words_verticalmin_words_horizontalintersection_toleranceintersection_x_toleranceintersection_y_tolerancec                       \ rS rSrSrg)
UnsetFloati  rE   Nr   rE   r,   r*   r(  r(    r   r,   r(  c                   z   \ rS rSr% Sr\\S'   Sr\\S'   Sr\	\
\\\4         \S'   Sr\	\
\\\4         \S'   \r\\S'   \r\\S	'   \r\\S
'   \r\\S'   \r\\S'   \r\\S'   Sr\\S'   Sr\\S'   \r\\S'   \r\\S'   Sr\\S'   \r \\S'   \r!\\S'   Sr"\	\#\\$4      \S'   SS jr%\&S\	\'   SS 4S j5       r(Sr)g)r   i  r  vertical_strategyhorizontal_strategyNexplicit_vertical_linesexplicit_horizontal_linesr  r>   r?   r  r@   rA   r   r   r   r!  r"  r#  r$  r%  r&  text_settingsr   c           	      F   [          H*  n[        X5      =(       d    SS:  d  M  [        SU S35      e   S H?  n[        XS-   5      nU[        ;  d  M  [        U SSR	                  [        5       S35      e   U R
                  c  0 U l        S
 H=  nX@R
                  ;  d  M  U R
                  R                  SS5      U R
                  U'   M?     SU R
                  ;   a  U R
                  S	 S H.  u  pE[        X5      [        L d  M  [        X[        X5      5        M0     g	)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.
r   zTable setting 'z' cannot be negative)
horizontalvertical	_strategyz_strategy must be one of{,}N)r   r   r-   r   ))r>   r  )r?   r  )r@   r  )rA   r  )r%  r$  )r&  r$  )	NON_NEGATIVE_SETTINGSgetattrr4   TABLE_STRATEGIESjoinr.  r   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,   settingsc                     Uc  U " 5       $ [        X5      (       a  U$ [        U[        5      (       a?  0 n0 nUR                  5        H  u  pEUS S S:X  a	  XSUSS  '   M  XRU'   M     X2S'   U " S0 UD6$ [        SU 35      e)N   text_r.  zCannot resolve settings: rE   )
isinstancedictrK   r4   )clsrA  core_settingsr.  rJ   r   s         r*   resolveTableSettings.resolve-  s    5L&&O$''MM (Ra5G#+,!AB%('(!$	 )
 .;/*'''8
CDDr,   )r.  )r   N)*r   r   r   r   r*  rN   __annotations__r+  r,  r	   r   r   r   r   r-  DEFAULT_SNAP_TOLERANCEr  r9  r>   r?   DEFAULT_JOIN_TOLERANCEr  r@   rA   r   r!  DEFAULT_MIN_WORDS_VERTICALr"  r   DEFAULT_MIN_WORDS_HORIZONTALr#  r$  r%  r&  r.  r   r   r?  classmethodT_table_settingsrI  r   rE   r,   r*   r   r     s)   $s$&&CGXd5+>&?@GEIxU5%<-@(ABI2NE2#e##e#2NE2#e##e#OU'(u(88 <#<$%E%&+e+&+e+.2M8DcN+21=f Ex(89 Eo E Er,   c                   B    \ rS rSrSrSSSS\\   4S jjrS\4S	 jr	S
r
g)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
Nr   r   rA  c                    Xl         [        R                  U5      U l        U R	                  5       U l        [        U R
                  U R                  R                  U R                  R                  5      U l	        [        U R                  5      U l        [        U R                  5       Vs/ s H  n[        U R                   U5      PM     snU l        g s  snf rZ   )r   r   rI  rA  	get_edgesr   r   r%  r&  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r   c           
      J   U R                   nS HL  n[        XS-   5      nUS:X  d  M  [        USU-   S-   5      n[        U5      S:  d  M<  [        SU SU S	35      e   UR                  nUR
                  nUS
:X  d  US
:X  a/  U R                  R                  " S0 UR                  =(       d    0 D6n/ nUR                  =(       d    /  H  n	[        U	[        5      (       a;  [        R                  " U	5       H  n
U
S   S:X  d  M  UR                  U
5        M!     MS  UR                  U	U	U R                  R                  S   U R                  R                  S   U R                  R                  S   U R                  R                  S   -
  SS.5        M     US:X  a5  [        R                   " U R                  R"                  SUR$                  S9nO_US:X  a6  [        R                   " U R                  R"                  SSUR$                  S9nO#US
:X  a  ['        WUR(                  S9nOUS:X  a  / nWU-   n/ nUR*                  =(       d    /  H  n	[        U	[        5      (       a;  [        R                  " U	5       H  n
U
S   S:X  d  M  UR                  U
5        M!     MS  UR                  U R                  R                  S   U R                  R                  S   U R                  R                  S   U R                  R                  S   -
  U	U	SS.5        M     US:X  a5  [        R                   " U R                  R"                  SUR$                  S9nO_US:X  a6  [        R                   " U R                  R"                  SSUR$                  S9nO#US
:X  a  [-        WUR.                  S9nOUS:X  a  / nWU-   n[1        U5      [1        U5      -   n[3        UUR4                  UR6                  UR8                  UR:                  S9n[        R                   " UUR<                  S9$ )N)r1  r0  r2  r  	explicit__linesrs   zIf z"_strategy == 'explicit', explicit_zD_lines must be specified as a list/tuple of two or more floats/ints.r  r!   r   r   r   r   r  )
min_lengthr  line)	edge_typer[  )rW   r    r   )r"   r/   rb   r#   r0   r!   )r>   r?   r@   rA   rE   )rA  r6  r\   r4   r*  r+  r   extract_wordsr.  r,  rE  rF  r   obj_to_edgesr$   r}   filter_edgesr   r!  r   r"  r-  ro   r#  r5   rU   r>   r?   r@   rA   r   )r   rA  r!   r<  r  v_strath_stratrV   
v_explicitdescr'   v_baser   
h_explicith_baser    r   s                    r*   rU  TableFinder.get_edgesZ  s   ==5Kx{)BCH:%+*Ch*NOu:>$k] +$$/= 1'(  6 ,,..f6 1II++Mx/E/E/KME
44::D$%%++D1A'3."))!, 2 !!""#yy~~a0"&)).."3"&)).."3diinnQ6G"G'*	 ;" g''		1S1SF &''		 #==	F %eH<W<WXF
"FZ
66<"<D$%%++D1A'3."))!, 2 !!"iinnQ/"iinnQ/!%!2TYY^^A5F!F#"&'*	 =" 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   rZ   )r   r   r   r   __doc__r	   rQ  r   r   rU  r   rE   r,   r*   rS  rS  A  s0    
V 
x8H/I 
iN: iNr,   rS  )r   r   )6rO   dataclassesr   operatorr   typingr   r   r   r   r	   r
   r   r   r   r  r   _typingr   r   r   r   r   r   rL  rM  rN  rO  rN   T_intersectionsrQ  r   r   r+   r=   rU   r   ro   r   r   r   r   objectr   r   r   r   r7  r5  rt   r(  r9  r   rS  rE   r,   r*   <module>rp     s@    !  T T T  J J     wS*_ 556$sCx.89 
 0/!!! ! 	!& =S$'49:  	
  D .J(('*((X .H<<'*<<@ EF$)<A6<(/ <(d6l <(~:4< :Df,> :z
 
	) 		Y 	PF Pf A  "	 	 	1 XE XE XEvBN& BNr,   