
    Vh4                        d Z ddlmZ ddlZddlZddlZddlZddlm	Z	 ddl
mZmZmZ ddlmZ ddlmZ d	hZdd
ZddZddZddZdddZddZddZ G d dej4                        Zy)z!Analyze python import statements.    )annotationsN   )read_binary_file)displayApplicationError	is_subdir)data_context)
TestTargetzansible.module_utils.sixc           
        t               }t        d |D              |z  }i | D ]%  }t        |j                  |      |j                  <   ' ddfd|D ]}  } |      }|j	                  |       j                         D ]O  \  }}||v st        |      D ]7  }||vst        j                  |d|d|d       |j                  |       9 Q  |z  D ci c]  }|t                }}j                         D ]   \  }}|D ]  }||   j                  |        " D ]I  }	dj                  |	j                  d      dd	       }
||
   ||	<   t        j                  |	d
|
d       K t        |      D ]l  }||   r	t        |d      }t        j                  j                  |      r t        j                  j                  |      sUt        j                   d|z         n |S c c}w )zNReturn a dictionary of module_utils names mapped to sets of python file paths.c              3  T   K   | ]  t        fd t        D              s ! yw)c              3  F   K   | ]  }j                  d |z          yw)%s.N)
startswith).0vms     \/home/dcms/DCMS/lib/python3.12/site-packages/ansible_test/_internal/classification/python.py	<genexpr>z<get_python_module_utils_imports.<locals>.<genexpr>.<genexpr>$   s     6iSTq||EAI7N6is   !N)anyVIRTUAL_PACKAGES)r   r   s    @r   r   z2get_python_module_utils_imports.<locals>.<genexpr>$   s     ja36iXh6i3ijs   ((Nc                P   t        j                  dd|z  | d       || h}| h}| t        v rit              D ][  }|j	                  d| z        s||v r|j                  |       t         
||dz   |            }|D ]  }|j                  |        ] t        |       }|	vrt        | d      }|	vrt        d	| z        t        	|   d
      D ]K  }|v r||v r|j                  |       t         
||dz   |            }|D ]  }|j                  |        M |S )z@Recursively expand module_utils imports from module_utils files.zmodule_utils import: z     	verbosityr      Tpackagez1Cannot determine path for module_utils import: %s)reverse)r   infor   sortedr   addget_import_pathr   )import_namedepthseenresults
sub_importmatchesresultimport_pathnameimports_by_target_pathrecurse_importvirtual_utilss            r   r-   z7get_python_module_utils_imports.<locals>.recurse_import,   s\   D5L+NZ[\<=D- **$]3 
,
(()<=!T) HHZ($^J	4%PQG") ,F+,
, &k244)+tDK"88&'Z]h'hii 1+>M 	$D}$t|HHTN^D%!)TBCG! $F#$	$     z inherits import z via    r   .z% reports imports from parent package Tr   z0No imports found which use the "%s" module_util.)r   N)r#   strr$   intr%   zt.Optional[set[str]]returnset[str])enumerate_module_utilsset#extract_python_module_utils_importspathremoveitemsr    r   r   r!   joinsplitr"   osexistsgetsizewarning)compile_targetsmodule_utilstargetmodule_utilmodule_util_importstarget_pathmodulesmodule_util_importimportsvirtual_utilparent_packagepackage_pathr,   r-   r.   s               @@@r   get_python_module_utils_importsrO       s'   )+Lj<jjMM!L! m.QRXR]R]_k.lv{{+m. .` $ 8,[9"";/ %;$@$@$B 	8 Kg%*01D*E 8&)8{Tfhs%t  AB  C$678	88 KWYfJf#g;K$6#gG#g 6 < < > 2W" 	2KK $$[1	22
 & p,"4"4S"9#2">? ' 7LR`amnop
 g ^{#*;ELww~~l+BGGOOL4QOONQ\\]^ N+ $hs   #G4c                .   t               j                  j                  }t               j                  j                  r/dt               j                  j                  j                  z   dz   }nd}| j                  d      rt        j                  j                  |       } | |k(  r|}|S |dz   t        j                  j                  t        j                  j                  | |            d   j                  t        j                  j                  d      z   }|S )z=Return a namespace and name from the given module_utils path.zansible_collections.zplugins.module_utilsansible.module_utils/__init__.pyr1   r   )r	   contentmodule_utils_path
collectionprefixendswithr?   r:   dirnamesplitextrelpathreplacesep)r:   	base_pathrV   r+   s       r   get_python_module_utils_namer^      s    &&88I~((',.*@*@*K*K*R*RRUkk'}}^$wwt$y K |bgg..rwwtY/OPQRS[[\^\c\c\g\gilmmKr/   c                 (   g } t               j                  j                  t               j                  j                        D ]D  }t        j
                  j                  |      d   }|dk7  r+| j                  t        |             F t        |       S )z0Return a list of available module_utils imports.r   z.py)
r	   rS   
walk_filesrT   r?   r:   rY   appendr^   r8   )rD   r:   exts      r   r7   r7      s}    L&&11,.2H2H2Z2Z[ @ggt$Q'%<8>?@ |r/   c                8   t        |       }	 t        j                  |      }t        | |      }|j                  |       |j                  S # t        $ rE}t	        j
                  | d|j                  d|j                         t               cY d}~S d}~ww xY w)zIReturn a list of module_utils imports found in the specified source file.:z/ Syntax error extracting module_utils imports: N)r   astparseSyntaxErrorr   rB   linenomsgr8   ModuleUtilFindervisitrK   )r:   rD   codetreeexfinders         r   r9   r9      s    
 D!Dyy dL1F
LL>>   	TXZ\ZcZcegekeklmu	s   A 	B:BBBc                t   |r1t         j                  j                  | j                  dd      d      }nd| j                  dd      z  }| j	                  d      s| dk(  r"t         j                  j                  d|      }|S t               j                  j                  r| j	                  dt               j                  j                  j                  z        s.| d	t               j                  j                  j                  z  k(  r%dj                  |j                  d      d
d       }|S t        d| z        )z"Return a path from an import name.r1   /z__init__.pyz%s.pyansible.module_utils.rQ   lib,ansible_collections.%s.plugins.module_utils.z+ansible_collections.%s.plugins.module_utils   NzUnexpected import name: %s)r?   r:   r=   r[   r   r	   rS   rU   	full_namer>   	Exception)r+   r   filenamer:   s       r   r"   r"      s    77<<S# 6FT\\#s33./4;Q3Qww||E8, K 
			*	*OOJ\^McMcMnMnMxMxxyALNDZDZDeDeDoDoooxxs+AB/0 K 4t;<<r/   c                    t         j                  j                  |       d   j                  t         j                  j                  d      }|j                  d      r|dd }|S )z(Convert the given path to a module name.r   r1   z	.__init__Ni)r?   r:   rY   r[   r\   rW   )r:   modules     r   path_to_moduler{      sL    WWd#A&..rww{{C@F{#Mr/   c                   |dk  r| }|S |s#t        j                  dd|z  | ||fz         d}|S |j                  d      }|t        |      k\  r$t        j                  dd|z  | |||fz         d}|S dj	                  |d|  | gz         }|S )z0Convert a relative import to an absolute import.r   z@Cannot resolve relative import "%s%s" in unknown module at %s:%dr1   zrelative.nomodulez@Cannot resolve relative import "%s%s" above module "%s" at %s:%dzrelative.abovelevelN)r   rB   r>   lenr=   )r+   levelrz   r:   rh   absolute_namepartss          r   relative_to_absoluter      s    z  Z^adi^ikoquw}]~~+  S!CJOO^behmbmosu{  ~B  DJ  bK  K  L1M   HHU7UF^tf%<=Mr/   c                  J    e Zd ZdZd	dZd
dZddZddZddZe	dd       Z
y)rj   z/AST visitor to find valid module_utils imports.c                4   || _         || _        t               | _        |j	                  d      r"t
        j                   j                  |      d   }|j                  d      rTt
        j                   j                  |      d   j                  dd      dd  }|dk7  r|t        vr| j                  |d       d | _        t               j                  j                  r`d}|D ]X  \  }}t        j                   || j                         s't        j"                  ||| j                         }t%        |      | _         y  y t%        t
        j                   j'                  t               j                  j(                  j*                  | j                               | _        y )	NrR   r   zlib/ansible/module_utils/rq   r1   r   rQ   ))z^lib/ansible/zansible/)z@^test/lib/ansible_test/_util/controller/sanity/validate-modules/zvalidate_modules/)z^test/units/ztest/units/)z!^test/lib/ansible_test/_internal/zansible_test/_internal/)zN^test/integration/targets/.*/ansible_collections/(?P<ns>[^/]*)/(?P<col>[^/]*)/z#ansible_collections/\g<ns>/\g<col>/)z%^test/integration/targets/.*/library/zansible/modules/)r:   rD   r8   rK   rW   r?   r>   r   r[   r   
add_importrz   r	   rS   
is_ansibleresearchsubr{   r=   rU   	directory)selfr:   rD   r   path_mappatternreplacementrevised_paths           r   __init__zModuleUtilFinder.__init__   s:   	(!$ ==(77==&q)D??67ggmmD)!,44S#>qrBG00WDT5T+>!!,,
H )1 $99Wdii0#%66';		#JL"0">DK	 )ln6L6L6W6W6a6acgclcl)mnDKr/   c                    | j                  |       | j                  |j                  D cg c]  }|j                   c}|j                         yc c}w )zVisit an import node.N)generic_visitadd_importsnamesr+   rh   )r   nodealiass      r   visit_ImportzModuleUtilFinder.visit_Import  s<    4  	$**=%**=t{{K=s   Ac                v   | j                  |       |j                  syt        |j                  |j                  | j                  | j                  |j
                        }|j                  d      sy| j                  |j                  D cg c]  }|d|j                   c}|j
                         yc c}w )zVisit an import from node.Nansibler1   )
r   rz   r   r~   r:   rh   r   r   r   r+   )r   r   rz   r   s       r   visit_ImportFromz!ModuleUtilFinder.visit_ImportFrom  s    4 {{%dkk4::t{{DIIW[WbWbc  + 	djjQUVUZZ8QSWS^S^_Qs   B6c                   |}| j                  |      r|| j                  v rQ|| j                  vrBt        j                  d| j
                  ||fz  d       | j                  j                  |       ydj                  |j                  d      dd       }| j                  |      rt        | j
                  t               j                  j                        ryt        j                  d| j
                  ||fz         y)zRecord the specified import.z%s:%d imports module_utils: %s   r   Nr1   r2   z%%s:%d Invalid module_utils import: %s)is_module_util_namerD   rK   r   r   r:   r!   r=   r>   r   r	   rS   	test_pathrB   )r   r+   line_numberr#   s       r   r   zModuleUtilFinder.add_import1  s    &&t,t(((t||+LL!ATYYP[]aDb!bnopLL$$T*88DJJsOCR01D &&t, TYY 6 6 @ @A 	?499k[fBgghr/   c                Z    |D ]&  }| j                  |      s| j                  ||       ( y)z<Add the given import names if they are module_utils imports.N)r   r   )r   r   line_nor+   s       r   r   zModuleUtilFinder.add_importsF  s-     	/D''-g.	/r/   c                   t               j                  j                  r| j                  d      ryt               j                  j                  r;| j                  dt               j                  j                  j
                  z        ryy)zrReturn True if the given name is a module_util name for the content under test. External module_utils are ignored.rr   Trt   F)r	   rS   r   r   rU   rv   )r+   s    r   r   z$ModuleUtilFinder.is_module_util_nameL  s     >!!,,AX1Y>!!,,Aor~  sA  sI  sI  sT  sT  s^  s^  B^  2_r/   N)r:   r3   rD   r6   r5   None)r   z
ast.Importr5   r   )r   zast.ImportFromr5   r   )r+   r3   r   r4   r5   r   )r   z	list[str]r   r4   r5   r   )r+   r3   r5   bool)__name__
__module____qualname____doc__r   r   r   r   r   staticmethodr    r/   r   rj   rj      s7    9(oVL`$i*/  r/   rj   )rC   zlist[TestTarget]r5   zdict[str, set[str]])r:   r3   r5   r3   )r5   r6   )r:   r3   rD   r6   r5   r6   )F)r+   r3   r   r   r5   r3   )r+   r3   r~   r4   rz   r3   r:   r3   rh   r4   r5   r3   )r   
__future__r   re   r?   r   typingtior   utilr   r   r   datar	   rE   r
   r   rO   r^   r7   r9   r"   r{   r   NodeVisitorrj   r   r/   r   <module>r      st    ' " 
 	 	  
  
^B((&&ms mr/   