U
    1e$                     @   s   d Z ddlZddlmZ ddlZddlZddlmZ ddl	m
Z
 ddlZejZedd Zdd	 Zd
d Zi add Zdd Zdd ZdddZi add ZejZejd fddZdS )!a  
Provides a reload() function that acts recursively.

Python's normal :func:`python:reload` function only reloads the module that it's
passed. The :func:`reload` function in this module also reloads everything
imported from that module, which is useful when you're changing files deep
inside a package.

To use this as your default reload function, type this::

    import builtins
    from IPython.lib import deepreload
    builtins.reload = deepreload.reload

A reference to the original :func:`python:reload` is stored in this module as
:data:`original_reload`, so you can restore it later.

This code is almost entirely based on knee.py, which is a Python
re-implementation of hierarchical module import.
    N)contextmanager)
ModuleType)warnc                 c   s$   t j}| t _z
d V  W 5 |t _X d S )N)builtin_mod
__import__)Z
new_importZsaved_import r   :/tmp/pip-unpacked-wheel-3hxk2k58/IPython/lib/deepreload.pyreplace_import_hook(   s
    
r	   c                 C   s  |}|rt | tsdS | dd}|dk	rbt|ds<tdt|dkr\|dkrXtddS |}n|d| krndS | d }d	| kr| | d< }nR|d
}|d  k r|k rn ntd|dk rd| d< dS |d|  | d< }t|}t|ddD ]F}z|d
d|}W q tk
r6 }	 ztd|	W 5 d}	~	X Y qX q|d| }zt	j
| }
W nN tk
r }	 z.|dk rtd|  d}
ntd| |	W 5 d}	~	X Y nX |
|fS )a  
    parent, name = get_parent(globals, level)

    Return the package that an import is being performed in.  If globals comes
    from the module foo.bar.bat (not itself a package), this returns the
    sys.modules entry for foo.bar.  If globals is from a package's __init__.py,
    the package's entry in sys.modules is returned.

    If globals doesn't come from a package or a module in a package, or a
    corresponding entry is not found in sys.modules, None is returned.
    )N __package__Nrindexz__package__ set to non-stringr   z(Attempted relative import in non-package__name____path__.   z2attempted relative import beyond top-level packagez?Parent module '%.200s' not found while handling absolute importzAParent module '%.200s' not loaded, cannot perform relative import)
isinstancedictgethasattr
ValueErrorlenrfindranger   sysmodulesBaseExceptionr   SystemError)globalslevelZ
orig_levelpkgnamenamemodnameZlastdotdotxeparentr   r   r   
get_parent1   s^    


r'   c                 C   s   t |dkr| d|fS |d}|dkr0td|dk rB|}d}n|d| }||d d }|dkrn|d7 }||7 }t| ||}|dkr| |krt|||}|dk	r|}|dkrtd| |||fS )zf
    mod, name, buf = load_next(mod, altmod, name, buf)

    altmod is either None or same as mod
    r   Nr   Empty module namer   r
   zNo module named %.200s)r   findr   import_submoduleImportError)modZaltmodr!   bufr#   subnamenextresultr   r   r   	load_nextz   s*    

r1   c                 C   s   |t kr|tjkrtj| }nptd| dt |< tj|d}z$|dk	rTt|}nt|| }W n   |rx|tj|<  Y nX t| ||| |S )z,m = import_submodule(mod, subname, fullname)Z	Reloadingr   N)		found_nowr   r   printr   	importlibreloadimport_moduleadd_submodule)r,   r.   fullnamemZoldmr   r   r   r*      s    

r*   c                 C   s.   | dkrdS |dkrt j| }t| || dS )zmod.{subname} = submodN)r   r   setattr)r,   Zsubmodr8   r.   r   r   r   r7      s    
r7   c              	   C   s   t | dsdS |D ]|}t |ds(td|dkrp|r6qz
| j}W n tk
rT   Y qX t| ||d}|s dS qt | |st| ||d |  qdS )	z,Handle 'from module import a, b, c' imports.r   Nr   z"Item in ``from list'' not a string*r   r   r   )r   	TypeError__all__AttributeErrorensure_fromlistr*   )r,   fromlistr-   	recursiveitemallretr   r   r   r?      s"    



r?   r   c           	      C   sv   t ||\}}t||dk rdn|| |\}} }|}| rLt||| |\}} }q2|dkr\td|sd|S t|||d |S )zReplacement for __import__()r   Nr(   )r'   r1   r   r?   )	r!   r   localsr@   r   r&   r-   headtailr   r   r   deep_import_hook   s     rH   c                 C   s   | t kr| S t| tstd| j}|tjkr:td| z
t| W S    | t|< Y nX z,zt
| }W n   | tj|<  Y nX W 5 t	  X |S )zReplacement for reload().z reload() argument must be modulez*reload(): module %.200s not in sys.modules)typesr   r   r<   r   r   r   r+   modules_reloadingclearr4   r5   )r9   r!   Znewmr   r   r   deep_reload_hook   s$    




rL   r   os.pathbuiltins__main__numpynumpy._globalsc              
   C   sJ   |D ]}dt |< qz,tt t| W  5 Q R  W S Q R X W 5 i a X dS )aM  Recursively reload all modules used in the given module.  Optionally
    takes a list of modules to exclude from reloading.  The default exclude
    list contains modules listed in sys.builtin_module_names with additional
    sys, os.path, builtins and __main__, to prevent, e.g., resetting
    display, exception, and io hooks.
    r   N)r2   r	   rH   rL   )moduleexcludeir   r   r   r5     s    

"r5   )NNNr   )r   rM   rN   rO   rP   rQ   )__doc__rN   r   
contextlibr   r4   r   rI   r   warningsr   r   Zoriginal_importr	   r'   r1   r2   r*   r7   r?   rH   rJ   rL   r5   Zoriginal_reloadbuiltin_module_namesr   r   r   r   <module>   s:   
I(
       