
    NgO]                        d dl Z d dlmZ d dlmZ d dlmZmZmZm	Z	m
Z
mZmZmZmZ ddlmZ ddlmZmZmZmZmZmZ dZdZdZdZeeeeef         f         Zed	eeef         f         Zerdd
lm Z  eefdedededefdZ!efdedededefdZ"dedededededefdZ#efdede$defdZ%efdede$defdZ&	 d0dedededefdZ'dede	e         fdZ(de	e         de	e	e                  fd Z) G d! d"e*          Z+ G d# d$e+          Z, G d% d&e+          Z- G d' d(e*          Z.g d)Z/g d*Z0 G d+ d,e1          Z2 e2d           Z3e G d- d	                      Z4 G d. d/e*          Z5dS )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                     g g d}| D ]#}||d                                       |           $t          j        |d         d|          }t          j        |d         d|          }||z   S )zs
    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/ai-engine/env/lib/python3.11/site-packages/pdfplumber/table.py
snap_edgesr+      s~     352,>,>N 3 3q'(//2222">##6kJJI">##6{KKIy      r!   	tolerancec                    |dk    rd\  }}n|dk    rd\  }}nt          d          t          t          | t          |                              }|d         g}|dd	         D ]f}|d
         }||         ||         |z   k    r2||         ||         k    rt	          j        ||||                   |d
<   Q|                    |           g|S )z
    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X;4>I566{T(^++"0x8MMr
 MM!Mr,   snap_x_tolerancesnap_y_tolerancejoin_x_tolerancejoin_y_tolerancec                 .   dt           dt          t          t          f         fd}|dk    s|dk    rt	          | ||          } t          | |          }t          j        ||          }fd|D             }t          t          j	        |           } | S )z|
    Using the `snap_edges` and `join_edge_group` methods above,
    merge a list of edges into a more "seamless" list.
    edger   c                 B    | d         dk    r
d| d         fS d| d         fS )Nr!   r    r#   r   r"    )rC   s    r*   	get_groupzmerge_edges.<locals>.get_groupP   s0    #%%e%%d$$r,   r   r1   c              3   h   K   | ],\  }}t          ||d          |d          dk    rn          V  -dS )r   r    N)r=   ).0kitemsr@   rA   s      r*   	<genexpr>zmerge_edges.<locals>.<genexpr>[   se         Au 	1Q4adckk**?O	
 	
     r,   )
r   r   strr   r+   r6   	itertoolsgroupbyr5   chain)	r   r>   r?   r@   rA   rF   _sortededge_groupsedge_gens	      ``    r*   merge_edgesrS   D   s    % %%U
"3 % % % % !/!335"24DEEU	***G#G;;;K     $	  H (+,,ELr,   wordsword_thresholdc           
         t          j        | t          d          d          }t          fd|          }t	          t          t           j        |                    }t          |          dk    rg S t          t          t          d          |                    }t          t          t          d          |                    }g }|D ]5}||||d         |d         ||z
  dd|||d	         |d	         ||z
  ddgz  }6|S )
zi
    Find (imaginary) horizontal lines that connect the tops
    of at least `word_threshold` words.
    r#   r   c                 *    t          |           k    S NlenxrU   s    r*   <lambda>z"words_to_edges_h.<locals>.<lambda>m       c!ff&> r,   r   r"   r/   r    )r"   r/   r#   r0   widthr!   r0   )
r   cluster_objectsr   filterr5   mapobjects_to_rectrZ   minmax)	rT   rU   by_toplarge_clustersrectsmin_x0max_x1r   rs	    `       r*   words_to_edges_hrl   e   s&    "5*U*;*;Q??F>>>>GGNU*N;;<<E
5zzQ	Z%%u--..FZ%%u--..FE 
 
 xE(&"  {H+&" 
 	
. Lr,   c                    t          j        | t          d          d          }t          j        | t          d          d          }dt          dt          fd}t          j        | |d          }||z   |z   }t          |d           }t          fd	|          }t          t          t           j	        |                    }	g }
|	D ]4t          fd
|
D                       }|s|
                               5t          |
          dk    rg S t          t           j        |
          }t          t          |t          d                              }t          t          t          d          |                    }t          t          t          d          |                    t          t          t          d          |                    fd|D             ||z
  ddgz   S )zy
    Find (imaginary) vertical lines that connect the left, right, or
    center of at least `word_threshold` words.
    r"   r   r/   wordr   c                 D    t          | d         | d         z             dz  S )Nr"   r/      )float)rn   s    r*   
get_centerz$words_to_edges_v.<locals>.get_center   s"    T$Z$t*,--11r,   c                 "    t          |            S rX   rY   )r\   s    r*   r]   z"words_to_edges_v.<locals>.<lambda>   s    c!ffW r,   r1   c                 *    t          |           k    S rX   rY   r[   s    r*   r]   z"words_to_edges_v.<locals>.<lambda>   r^   r,   c              3   B   K   | ]}t          j        |          V  d S rX   )r   get_bbox_overlap)rH   cbboxs     r*   rK   z#words_to_edges_v.<locals>.<genexpr>   s0      PP!e,T155PPPPPPr,   r   r#   r0   c           	      @    g | ]}|d          |d          z
  ddS )r"   r   r"   r/   r#   r0   heightr!   rE   )rH   b
max_bottommin_tops     r*   
<listcomp>z$words_to_edges_v.<locals>.<listcomp>   sQ     
 
 
  D'D'  7*	
 	

 
 
r,   r   rz   )r   r`   r   r   r   r6   ra   r5   rb   objects_to_bboxanyr$   rZ   bbox_to_rectre   rd   )rT   rU   by_x0by_x1rr   	by_centerclusterssorted_clustersrg   bboxescondensed_bboxesoverlapcondensed_rectssorted_rectsrj   rx   r}   r~   s    `             @@@r*   words_to_edges_vr      s4    !%D)9)91==E!%D)9)91==E2 25 2 2 2 2 %eZ;;Iu}y(H X+<+<===O>>>>PPN #e+^<<==F &( * *PPPP?OPPPPP 	*##D)))
!!	%,.>??OJt4D4DEEEFFLZ%%|4455F#j''6677GSH--|<<==J
 
 
 
 
 
 
 
   7*	
 	
		 r,   c                     i } fddD             \  }}t          |t          dd                    D ]}t          |t          dd                    D ]}|d         |d         |z   k    r|d         |d         |z
  k    r|d         |d         |z
  k    rs|d         |d         |z   k    r^|d         |d         f}||vrg g d||<   ||         d                             |           ||         d	                             |           |S )
zi
    Given a list of edges, return the points at which they intersect
    within `tolerance` pixels.
    c                 R    g | ]"t          t          fd                     #S )c                     | d         k    S )Nr!   rE   )r\   os    r*   r]   z3edges_to_intersections.<locals>.<listcomp>.<lambda>   s    a.!3 r,   )r5   ra   )rH   r   r   s    @r*   r   z*edges_to_intersections.<locals>.<listcomp>   sC       ABV3333U;;<<  r,   r   r"   r#   r1   r0   r/   r   r    )r6   r   r$   )	r   r   r   intersectionsv_edgesh_edgesr   r    vertexs	   `        r*   edges_to_intersectionsr      s^    &(M   FP  GW GD%!8!8999 5 5Zt%<%<=== 	5 	5A5ah455x[QuX%;<<tW4;!677tW4;!677D'1U8,..242,>,>M&)f%c*11!444f%c*11!444	5 r,   r   c                     dt           dt           dt          f fdt          t                                                               t                    dt          t                    dt          dt          t                   f fdfdt          t                              D             }t          t          d	|                    S )
a8  
    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                    dt           dt          t                   fd}| d         |d         k    rP ||          d                                        ||         d                             }t	          |          rdS | d         |d         k    rP ||          d                                        ||         d                             }t	          |          rdS d	S )
Nr   r   c                 P    t          t          t          j        |                     S rX   )setrb   r   obj_to_bbox)r   s    r*   edges_to_setzCintersections_to_cells.<locals>.edge_connects.<locals>.edges_to_set   s    s5,e44555r,   r   r   Tr   r    F)r   r
   r   intersectionrZ   )r   r   r   commonr   s       r*   edge_connectsz-intersections_to_cells.<locals>.edge_connects   s    	6
 	6s6{ 	6 	6 	6 	6 a5BqE>>!\-"3C"899FF]2.s344 F 6{{ ta5BqE>>!\-"3C"899FF]2.s344 F 6{{ tur,   pointsic                 f   |dz
  k    rd S | |         | |dz   d          }fd|D             }fd|D             }|D ]o} 	|          s|D ]]} 	|          s|d         |d         f}|
v r: 	||          r. 	||          r"d         d         |d         |d         fc c S ^pd S )Nr   c                 8    g | ]}|d          d          k    |S )r   rE   rH   r\   pts     r*   r   zFintersections_to_cells.<locals>.find_smallest_cell.<locals>.<listcomp>  &    222qAaDBqEMMMMMr,   c                 8    g | ]}|d          d          k    |S r   rE   r   s     r*   r   zFintersections_to_cells.<locals>.find_smallest_cell.<locals>.<listcomp>  r   r,   r   rE   )r   r   restbelowrightbelow_ptright_ptbottom_rightr   r   r   n_pointss           @r*   find_smallest_cellz2intersections_to_cells.<locals>.find_smallest_cell
  s6   14AYa!egg2222D2222222D222 	L 	LH =X.. ! L L$}R22  (Xa[9 "]22%lH== 3%lH== 3
 qE2a5,q/<?KKKKKKL tr,   c              3   0   K   | ]} |          V  d S rX   rE   )rH   r   r   r   s     r*   rK   z)intersections_to_cells.<locals>.<genexpr>%  s1      JJ!""61--JJJJJJr,   N)r   boolr5   r6   keysrZ   r   intr	   r   rangera   )r   cell_genr   r   r   r   s   ` @@@@r*   intersections_to_cellsr      s    ' w 4      & &++--..//F6{{H4= S Xf=M        6 KJJJJuS[[7I7IJJJHtX&&'''r,   cellsc                    dt           dt          t          t          t          t          f         fd}t          |           }t	                      g }g }t          |          rFt          |          }t          |          D ]} ||          }t          |          dk    r=t	          |          z  |                    |           |                    |           ]t          fd|D                       }|dk    r<t	          |          z  |                    |           |                    |           t          |          |k    rJ|                    t          |                     	                                 |	                                 t          |          Ft          |          r"|                    t          |                     t          |d           }	d |	D             }
|
S )	z
    Given a list of bounding boxes (`cells`), return a list of tables that
    hold those cells most simply (and contiguously).
    rx   r   c                 ,    | \  }}}}||f||f||f||ffS rX   rE   )rx   r"   r#   r/   r0   s        r*   bbox_to_cornersz(cells_to_tables.<locals>.bbox_to_corners/  s/    "CVS	B<"cRLAAr,   r   c              3       K   | ]}|v V  	d S rX   rE   )rH   rw   current_cornerss     r*   rK   z"cells_to_tables.<locals>.<genexpr>H  s(      "N"NA1#7"N"N"N"N"N"Nr,   c                 4    t          d | D                       S )Nc              3   6   K   | ]}|d          |d         fV  dS )r   r   NrE   )rH   rw   s     r*   rK   z4cells_to_tables.<locals>.<lambda>.<locals>.<genexpr>a  s.      .G.G!ad|.G.G.G.G.G.Gr,   )rd   )ts    r*   r]   z!cells_to_tables.<locals>.<lambda>a  s    3.G.GQ.G.G.G+G+G r,   r1   c                 8    g | ]}t          |          d k    |S r   rY   )rH   r   s     r*   r   z#cells_to_tables.<locals>.<listcomp>b  s#    111ac!ffqjjjjjr,   )r   r   r   r5   r   rZ   r$   removesumclearr6   )r   r   remaining_cellscurrent_cellstablesinitial_cell_countcellcell_cornerscorner_countrP   filteredr   s              @r*   cells_to_tablesr   )  s   Bf Bw'/Q)R B B B B 5kkO
 %(EEO"$MF
o

 " //)) 	1 	1D*?400L=!!Q&&3|#4#44$$T***&&t,,,,  #"N"N"N"N"N"N"NNN  !###s<'8'88O!((...#**4000 }!333MM$}--...!!###!!!5 o

 "> = +d=))*** V!G!GHHHG117111HOr,   c                   2    e Zd Zdeee                  fdZdS )	CellGroupr   c                    || _         t          t          t          d          t	          d |                              t          t          t          d          t	          d |                              t          t          t          d          t	          d |                              t          t          t          d          t	          d |                              f| _        d S Nr   r   rp   r   )r   rd   rb   r   ra   re   rx   )selfr   s     r*   __init__zCellGroup.__init__g  s    
JqMM6$#6#67788JqMM6$#6#67788JqMM6$#6#67788JqMM6$#6#67788	
			r,   N)__name__
__module____qualname__r   r	   r   r   rE   r,   r*   r   r   f  s9        
d8F#34 
 
 
 
 
 
r,   r   c                       e Zd ZdS )RowNr   r   r   rE   r,   r*   r   r   q          Dr,   r   c                       e Zd ZdS )ColumnNr   rE   r,   r*   r   r   u  r   r,   r   c                       e Zd Zdddee         fdZedefd            Zdee	         dee	         fdZ
edee	         fd	            Zedee	         fd
            Zdedeeee                           fdZdS )Tablepager   r   c                 "    || _         || _        d S rX   )r   r   )r   r   r   s      r*   r   zTable.__init__z  s    	


r,   r   c           
      \   | j         }t          t          t          d          |                    t          t          t          d          |                    t	          t          t          d          |                    t	          t          t          d          |                    fS r   )r   rd   rb   r   re   )r   rw   s     r*   rx   z
Table.bbox~  s    JJqMM1%%&&JqMM1%%&&JqMM1%%&&JqMM1%%&&	
 	
r,   kindc                   
 |t           u rdnd
t          
           }t          | j        t	          |
                    }t          t          t          t          t	          
          | j                                                }t          j	        |t	          |                    }g }|D ]?\  }}
fd|D              |fd|D                       }	|
                    |	           @|S )Nr   r   r1   c                 "    i | ]}|         |S rE   rE   )rH   r   axiss     r*   
<dictcomp>z+Table._get_rows_or_cols.<locals>.<dictcomp>  s    <<<$T$Z<<<r,   c                 :    g | ]}                     |          S rE   )get)rH   r\   xdicts     r*   r   z+Table._get_rows_or_cols.<locals>.<listcomp>  s#    111		!111r,   )r   r   r6   r   r   r5   r   rb   rM   rN   r$   )r   r   antiaxisrP   xsgroupedrowsy	row_cellsrowr   r   s             @@r*   _get_rows_or_colszTable._get_rows_or_cols  s    CKKqqQ4x== Hd)C)CDDD &SD!1!14:>>??@@AA #GZ-A-ABB# 	 	LAy<<<<)<<<E$1111b11122CKKr,   c                 6    |                      t                    S rX   )r   r   r   s    r*   r   z
Table.rows  s    %%c***r,   c                 6    |                      t                    S rX   )r   r   r   s    r*   columnszTable.columns  s    %%f---r,   kwargsc                   	
 | j         j        }g }dt          dt          dt          fd	| j        D ]
g }	
fd|D             }
j        D ]d }nd	fd|D             }t          |          rDd|v r-d         d	         z
  |d
<   d         d         z
  |d<   |d<   t          j	        |fi |}nd}|
                    |           |
                    |           |S )Ncharrx   r   c                     | d         | d         z   dz  }| d         | d         z   dz  }|\  }}}}t          ||k    o||k     o||k    o||k               S )Nr#   r0   rp   r"   r/   )r   )r   rx   v_midh_midr"   r#   r/   r0   s           r*   char_in_bboxz#Table.extract.<locals>.char_in_bbox  sr    %[4>1Q6E$Z$t*,1E"&BR"V52:VESLVuv~  r,   c                 6    g | ]} |j                   |S rE   )rx   )rH   r   r   r   s     r*   r   z!Table.extract.<locals>.<listcomp>  s,    PPP$<<ch3O3OPPPPr,   c                 ,    g | ]} |          |S rE   rE   )rH   r   r   r   s     r*   r   z!Table.extract.<locals>.<listcomp>  s:     " " "!%ll46N6N"" " "r,   layoutrp   r   layout_widthr   r   layout_heightlayout_bbox )r   charsr   r   r   r   r   rZ   r   extract_textr$   )r   r   r  	table_arrarr	row_chars	cell_text
cell_charsr   r   r   s           @@@r*   extractzTable.extract  s^   			u 	F 	t 	 	 	 	 9 	" 	"CCPPPPP%PPPI	 & &< $II" " " " ")2" " "J : '#v--59!WtAw5FF>26:1gQ6GF?348F=1$)$6z$L$LV$L$L		$&	

9%%%%S!!!!r,   N)r   r   r   r   r   r   propertyrx   r   r   r   r   r   r   r	   rL   r  rE   r,   r*   r   r   y  s       V DL     
f 
 
 
 X
d9o $y/    * +d9o + + + X+ .i . . . X.$ $T(3--@(A $ $ $ $ $ $r,   r   )lineslines_stricttextexplicit)snap_tolerancer>   r?   join_tolerancer@   rA   edge_min_lengthmin_words_verticalmin_words_horizontalintersection_toleranceintersection_x_toleranceintersection_y_tolerancec                       e Zd ZdS )
UnsetFloatNr   rE   r,   r*   r  r    r   r,   r  c                      e Zd ZU dZeed<   dZeed<   dZee	e
eef                           ed<   dZee	e
eef                           ed<   eZeed<   eZeed<   eZeed	<   eZeed
<   eZeed<   eZeed<   dZeed<   eZeed<   eZeed<   dZeed<   eZeed<   eZeed<   dZ ee!ee"f                  ed<   ddZ#e$dee%         dd fd            Z&dS )r   r  vertical_strategyhorizontal_strategyNexplicit_vertical_linesexplicit_horizontal_linesr  r>   r?   r  r@   rA   r   r  r  r  r  r  r  text_settingsr   c           	      $   t           D ]+}t          | |          pddk     rt          d| d          ,dD ]K}t          | |dz             }|t          vr-t          | dd                    t                     d          L| j        i | _        d
D ].}|| j        vr#| j                            dd          | j        |<   /d| j        v r| j        d= dD ];\  }}t          | |          t          u rt          | |t          | |                     <d	S )a  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__zTableSettings.__post_init__  s     - 	R 	RGg&&+!q00 !P7!P!P!PQQQ 1 6 	 	Kt[;%>??H/// " 8 8"2338 8 8   0 %!#D 3 	R 	RD4---+/+=+A+A+q+Q+Q"4($,,,";/
 		= 		=ND( tT""e++dGD($;$;<<<		= 		=r,   settingsc                 $   |
 |             S t          ||           r|S t          |t                    rLi }i }|                                D ]&\  }}|d d         dk    r|||dd          <   !|||<   '||d<    | di |S t          d|           )N   text_r"  zCannot resolve settings: rE   )
isinstancedictrJ   r4   )clsr4  core_settingsr"  rI   r   s         r*   resolvezTableSettings.resolve+  s    355L#&& 	EO$'' 	EMM (( ) )1RaR5G##+,M!ABB%(('(M!$$-:M/*3'''''CCCDDDr,   )r   N)'r   r   r   r  rL   __annotations__r  r   r	   r   r   r   r   r!  DEFAULT_SNAP_TOLERANCEr  r-  r>   r?   DEFAULT_JOIN_TOLERANCEr  r@   rA   r  DEFAULT_MIN_WORDS_VERTICALr  r   DEFAULT_MIN_WORDS_HORIZONTALr  r  r  r  r"  r   r   r3  classmethodT_table_settingsr<  rE   r,   r*   r   r     s        $s$$$&&&&CGXd5+>&?@GGGEIxU5%<-@(ABIII2NE222#e####e###2NE222#e####e###OU8888 <#<<<$%E%%%&+e+++&+e+++.2M8DcN+2221= 1= 1= 1=f Ex(89 Eo E E E [E E Er,   c                   <    e Zd ZdZd	dddee         fdZdefdZdS )
TableFindera0  
    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   r4  c                 `    | _         t                              |           _                                          _        t           j         j        j         j        j                   _	        t           j	                   _         fdt           j                  D              _        d S )Nc                 :    g | ]}t          j        |          S rE   )r   r   )rH   
cell_groupr   s     r*   r   z(TableFinder.__init__.<locals>.<listcomp>T  s2     
 
 
-7E$)Z((
 
 
r,   )r   r   r<  r4  	get_edgesr   r   r  r  r   r   r   r   r   )r   r   r4  s   `  r*   r   zTableFinder.__init__J  s    	%--h77^^%%
3JM2M2
 

 ,D,>??

 
 
 
;J4:;V;V
 
 
r,   r   c           
         | j         }dD ]Z}t          ||dz             }|dk    r?t          |d|z   dz             }t          |          dk     rt          d| d| d	          [|j        }|j        }|d
k    s|d
k    r | j        j        di |j        pi }g }|j	        pg D ]}	t          |	t                    r9t          j        |	          D ]#}
|
d         dk    r|                    |
           $P|                    |	|	| j        j        d         | j        j        d         | j        j        d         | j        j        d         z
  dd           |dk    r t          j        | j        j        d          }nM|dk    r"t          j        | j        j        dd          }n%|d
k    rt%          ||j                  }n|dk    rg }||z   }g }|j        pg D ]}	t          |	t                    r9t          j        |	          D ]#}
|
d         dk    r|                    |
           $P|                    | j        j        d         | j        j        d         | j        j        d         | j        j        d         z
  |	|	dd           |dk    r t          j        | j        j        d          }nM|dk    r"t          j        | j        j        dd          }n%|d
k    rt+          ||j                  }n|dk    rg }||z   }t/          |          t/          |          z   }t1          ||j        |j        |j        |j                  }t          j        ||j                  S )N)r%  r$  r&  r  	explicit__linesrp   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   rz   r  r  line)	edge_type)rU   r    r   )r"   r/   r_   r#   r0   r!   )r>   r?   r@   rA   )
min_lengthrE   )r4  r*  rZ   r4   r  r  r   extract_wordsr"  r   r8  r9  r   obj_to_edgesr$   rx   filter_edgesr   r   r  r!  rl   r  r5   rS   r>   r?   r@   rA   r  )r   r4  r!   r0  r  v_strath_stratrT   
v_explicitdescr'   v_baser   
h_explicith_baser    r   s                    r*   rI  zTableFinder.get_edgesX  s   =5 
	 
	Kx{)BCCH:%%+*Ch*NOOu::>>$(k ( ($/( ( (   ,.f6 1 1+DI+MMx/E/KMME
4: 	 	D$%% +D11 - -A'3.."))!,,,- !!""#y~a0"&)."3"&)."3dinQ6G"G'* 	 	 	 	 g'	==FF&&'	OOOFF%eH<WXXXFF
""FZ
6<" 	 	D$%% +D11 - -A'3.."))!,,,- !!"inQ/"inQ/!%!2TY^A5F!F#"&'* 	 	 	 	 g'	==FF&&'	OOOFF%h&C  FF 
""FZQ$q''!%6%6%6%6
 
 
 !%H4LMMMMr,   rX   )	r   r   r   __doc__r	   rC  r   r   rI  rE   r,   r*   rE  rE  ?  st         
 
V 
x8H/I 
 
 
 
[N: [N [N [N [N [N [Nr,   rE  )r   r   )6rM   dataclassesr   operatorr   typingr   r   r   r   r	   r
   r   r   r   r  r   _typingr   r   r   r   r   r   r>  r?  r@  rA  rL   T_intersectionsrC  r   r   r+   r=   rS   r   rl   r   r   r   r   objectr   r   r   r   r+  r)  rq   r  r-  r   rE  rE   r,   r*   <module>ra     s       ! ! ! ! ! !       T T T T T T T T T T T T T T T T T T T T T T       J J J J J J J J J J J J J J 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 P P P PF P P Pf A@@     	 	 	 	 	 	 	 	 	
1 WE WE WE WE WE WE WE WEttN tN tN tN tN& tN tN tN tN tNr,   