o
    3g                     @  sB  d Z ddlmZ dZdZddlZddlZddlZddlZddl	m
Z
mZ ddlmZ ddlmZmZmZmZ 	 eee  ZG d	d
 d
eZd>ddZd?ddZd@ddZd?ddZdAddZdAddZdBd!d"ZdCd$d%ZdDd'd(ZdEd*d+ZdFd-d.Z dGd0d1Z!dGd2d3Z"dGd4d5Z#dGd6d7Z$dGd8d9Z%dGd:d;Z&dGd<d=Z'dS )Ha  
The idea of this module is to avoid imports of external HPI modules and code evaluation via ast module etc.

This potentially allows it to be:

- robust: can discover modules that can't be imported, generally makes it foolproof
- faster: importing is slow and with tens of modules can be noteiceable
- secure: can be executed in a sandbox & used during setup

It should be free of external modules, importlib, exec, etc. etc.
    )annotationsREQUIRES__NOT_HPI_MODULE__N)IterableSequence)Path)Any
NamedTupleOptionalcastc                   @  sN   e Zd ZU ded< ded< dZded< dZded< dZd	ed
< dZded< dS )	HPIModulestrnamez
str | Noneskip_reasonNdoczPath | NonefileRequiresrequireslegacy)__name__
__module____qualname____annotations__r   r   r   r    r   r   0/home/garg/my-data/HPI/my/core/discovery_pure.pyr   "   s   
 r   mr   returnboolc                 C  s*   ddg}d |}td| d| d uS )Nzcore.*zconfig.*|z^my.(z)$)joinrematch)r   excludedexsr   r   r   ignored+   s
   
r$   srcr   c                 C  s   t |  S N)
_has_stats	read_textr%   r   r   r   	has_stats5   s   r*   codec                 C  sr   t | }|jD ].}ztt|j\}|jdkrW  dS W n   Y ztt|j}|dkr0W  dS W q   Y qdS )NstatsTF)astparsebodyr   r   targetsidr   )r+   axtgr   r   r   r   r'   :   s"   


r'   c                 C  s   t |  }t|S r&   )r-   r.   r(   _is_not_module_ast)r%   r2   r   r   r   _is_not_module_srcL   s   r6   r2   
ast.Modulec                   s   t  t fdd| jD S )Nc                 3  >    | ]}t |d d kpt fddt |dg D V  qdS )r   Nc                 3       | ]}t |d d kV  qdS r   Ngetattr.0nmarkerr   r   	<genexpr>U       z/_is_not_module_ast.<locals>.<genexpr>.<genexpr>namesr<   anyr>   noder@   r   r   rB   S       
z%_is_not_module_ast.<locals>.<genexpr>)NOT_HPI_MODULE_VARrF   r/   r2   r   r@   r   r5   Q      r5   c                   s   d t  fdd| jD S )Nhandle_legacy_importc                 3  r8   )r   Nc                 3  r9   r:   r;   r=   r@   r   r   rB   ^   rC   z._is_legacy_module.<locals>.<genexpr>.<genexpr>rD   rE   rG   r@   r   r   rB   \   rI   z$_is_legacy_module.<locals>.<genexpr>)rF   r/   rK   r   r@   r   _is_legacy_moduleZ   rL   rN   r   c           	      C  s   | j D ]]}t|tjsq|j}t|dkrq|d }t|dd }|tkr%q|j}t|dd }|d u r3qg }|D ]#}t|tj	rF|
|j q7t|tjrS|
|j q7tdt dt|  S d S )N   r   r1   eltsz#Expecting string constants only in z declaration)r/   
isinstancer-   Assignr0   lenr<   r   valueConstantappendStrsRuntimeErrortuple)	r2   r3   r4   tid_valsrP   depscr   r   r   _extract_requirementsd   s.   
r`   Iterable[HPIModule]c                  c  s     t  D ]	} t| E dH  qdS )a  
    Return all importable modules under all items in the 'my' namespace package

    Note: This returns all modules under all roots - if you have
    several overlays (multiple items in my.__path__ and you've overridden
    modules), this can return multiple HPIModule objects with the same
    name. It should respect import order, as we're traversing
    in my.__path__ order, so module_by_name should still work
    and return the correctly resolved module, but all_modules
    can have duplicates
    N)_iter_my_roots_modules_under_root)my_rootr   r   r   all_modules   s   
re   Iterable[Path]c                  c  s<    dd l } t| j}t|dkrtdtt|E d H  d S )Nr   z-my.__path__ was empty, try re-installing HPI?)mylist__path__rS   rY   mapr   )rg   pathsr   r   r   rb      s   
rb   rd   c           
      c  s   t | dD ]w}| rq|| j}|jdkr|j}t|dt	j
d}t|r.qt| }t|}t|r@|s@qtj|dd}d}zt|}W n tyf } zt| W Y d}~nd}~ww |rn| dnd}	t|d||| j||	d	V  qdS )
zb
    Experimental version, which isn't importing the modules, making it more robust and safe.
    z*.pyz__init__.py .F)cleanNz9 is DEPRECATED. Please refer to the module documentation.)r   r   r   r   r   r   )sortedrglob
is_symlinkrelative_toparentr   r   with_suffixreplaceossepr$   r-   r.   r(   rN   r5   get_docstringr`   	Exceptionlogging	exceptionr   )
rd   fmpr   r2   legacy_moduler   r   er   r   r   r   rc      s@   


rc   r   c                 C  s,   t  D ]}|j| kr|  S qtd|  )NzNo such module: )re   r   rY   )r   r   r   r   r   module_by_name   s
   

r   Nonec                   C  s   t tt dksJ d S )N
   )rS   rh   re   r   r   r   r   test   s   r   c                  C  s<   t d} | jd usJ | jtddksJ | jd u sJ d S )Nzmy.demorg   zdemo.py)r   r   r   r   r   )demor   r   r   	test_demo   s   r   c                  C  s   t  D ]	} d| jvsJ qd S )Nzmy.core.)re   r   )r   r   r   r   test_excluded   s   
r   c                  C  s.   t d} | j}|d usJ t|dksJ d S )Nzmy.photos.main   )r   r   rS   )photosrr   r   r   test_requires   s   r   c                   C  s   t d t d d S )Nz	my.redditzmy.fbmessenger)r   r   r   r   r   test_legacy_modules   s   r   c                  C  s4   t t } td| tjg ksJ d| vsJ dS )z@
    We want to keep this module clean of other HPI imports
    zimport my\.\S+zfrom myN)r   __file__r(   r    findall	MULTILINEr)   r   r   r   	test_pure   s   r   c                   C  s@   t drJ t drJ t dsJ t dsJ t dsJ d S )Nrl   zx = lambda : whateverz
def stats():
    pass
z
stats = lambda: "something"
z
stats = other_function
    )r'   r   r   r   r   test_has_stats   s
   r   )r   r   r   r   )r%   r   r   r   )r+   r   r   r   )r2   r7   r   r   )r2   r7   r   r   )r   ra   )r   rf   )rd   r   r   ra   )r   r   r   r   )r   r   )(__doc__
__future__r   r   rJ   r-   rz   rv   r    collections.abcr   r   pathlibr   typingr   r	   r
   r   r   r   r   r$   r*   r'   r6   r5   rN   r`   re   rb   rc   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s@    
	





	





(






