U
    ,d[                     @   s  d Z ddlmZmZmZ ddlZddlZddlZddlZddl	Z	ddl
Z
ddl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ZddlmZ ddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ dd Z G dd dedZ!G dd de!Z"G dd dedZ#G dd de$Z%G dd de%e#Z&G dd de%e#Z'G dd de%e#Z(G dd de#Z)G dd dedZ*G d d! d!e*Z+G d"d# d#e*Z,G d$d% d%e$Z-G d&d' d'e!Z.G d(d) d)e.Z/e0d*gZ1d+d, Z2dS )-z+
Caching mechanism for compiled functions.
    )ABCMetaabstractmethodabstractpropertyN)AppDirs)NumbaWarning)BaseContext)CodeLibrary)CompileResult)configcompilerdumpsc                 G   s   t jr| | } t|  d S N)r
   ZDEBUG_CACHEprint)msgargs r   6/tmp/pip-unpacked-wheel-eu7e0c37/numba/core/caching.py
_cache_log   s    r   c                   @   sT   e Zd Zedd Zedd Zedd Zedd Zed	d
 Z	edd Z
dS )_Cachec                 C   s   dS )zW
        The base filesystem path of this cache (for example its root folder).
        Nr   selfr   r   r   
cache_path&   s    z_Cache.cache_pathc                 C   s   dS )z
        Load an overload for the given signature using the target context.
        The saved object must be returned if successful, None if not found
        in the cache.
        Nr   r   sigtarget_contextr   r   r   load_overload,   s    z_Cache.load_overloadc                 C   s   dS )z<
        Save the overload for the given signature.
        Nr   r   r   datar   r   r   save_overload4   s    z_Cache.save_overloadc                 C   s   dS )z#
        Enable the cache.
        Nr   r   r   r   r   enable:   s    z_Cache.enablec                 C   s   dS )z$
        Disable the cache.
        Nr   r   r   r   r   disable@   s    z_Cache.disablec                 C   s   dS )z"
        Flush the cache.
        Nr   r   r   r   r   flushF   s    z_Cache.flushN)__name__
__module____qualname__r   r   r   r   r   r    r!   r"   r   r   r   r   r   $   s   




r   )	metaclassc                   @   s@   e Zd Zedd Zdd Zdd Zdd Zd	d
 Zdd Z	dS )	NullCachec                 C   s   d S r   r   r   r   r   r   r   N   s    zNullCache.cache_pathc                 C   s   d S r   r   r   r   r   r   r   R   s    zNullCache.load_overloadc                 C   s   d S r   r   )r   r   cresr   r   r   r   U   s    zNullCache.save_overloadc                 C   s   d S r   r   r   r   r   r   r    X   s    zNullCache.enablec                 C   s   d S r   r   r   r   r   r   r!   [   s    zNullCache.disablec                 C   s   d S r   r   r   r   r   r   r"   ^   s    zNullCache.flushN)
r#   r$   r%   propertyr   r   r   r    r!   r"   r   r   r   r   r'   M   s   
r'   c                   @   sT   e Zd ZdZdd Zedd Zedd Zedd	 Ze	d
d Z
e	dd ZdS )_CacheLocatorz<
    A filesystem locator for caching a given function.
    c                 C   s*   |   }tj|dd tj|d  d S )NT)exist_ok)dir)get_cache_pathosmakedirstempfileTemporaryFileclose)r   pathr   r   r   ensure_cache_pathg   s    z_CacheLocator.ensure_cache_pathc                 C   s   dS )zA
        Return the directory the function is cached in.
        Nr   r   r   r   r   r-   m   s    z_CacheLocator.get_cache_pathc                 C   s   dS )z{
        Get a timestamp representing the source code's freshness.
        Can return any picklable Python object.
        Nr   r   r   r   r   get_source_stamps   s    z_CacheLocator.get_source_stampc                 C   s   dS )z
        Get a string disambiguator for this locator's function.
        It should allow disambiguating different but similarly-named functions.
        Nr   r   r   r   r   get_disambiguatorz   s    z_CacheLocator.get_disambiguatorc                 C   s   t dS )ze
        Create a locator instance for the given function located in the
        given file.
        N)NotImplementedError)clspy_funcpy_filer   r   r   from_function   s    z_CacheLocator.from_functionc                 C   sH   t j|}t j|}t j|d }t|  }d	||gS )zGiven the Python file path, compute a suitable path inside the
        cache directory.

        This will reduce a file path that is too long, which can be a problem
        on some operating system (i.e. Windows 7).
        _)
r.   r3   abspathdirnamesplithashlibsha1encode	hexdigestjoin)r8   r:   r3   subpath	parentdirhashedr   r   r   get_suitable_cache_subpath   s
    z(_CacheLocator.get_suitable_cache_subpathN)r#   r$   r%   __doc__r4   r   r-   r5   r6   classmethodr;   rI   r   r   r   r   r*   b   s   



r*   c                   @   s,   e Zd ZdZdd Zdd Zedd ZdS )	_SourceFileBackedLocatorMixinzf
    A cache locator mixin for functions which are backed by a well-known
    Python source file.
    c                 C   s2   t tddrttj}nt| j}|j|jfS NfrozenF)getattrsysr.   stat
executable_py_filest_mtimest_size)r   str   r   r   r5      s    z._SourceFileBackedLocatorMixin.get_source_stampc                 C   s
   t | jS r   )str_linenor   r   r   r   r6      s    z/_SourceFileBackedLocatorMixin.get_disambiguatorc                 C   sB   t j|sd S | ||}z|  W n tk
r<   Y d S X |S r   )r.   r3   existsr4   OSErrorr8   r9   r:   r   r   r   r   r;      s    
z+_SourceFileBackedLocatorMixin.from_functionN)r#   r$   r%   rJ   r5   r6   rK   r;   r   r   r   r   rL      s
   	rL   c                       s4   e Zd ZdZdd Zdd Ze fddZ  ZS )_UserProvidedCacheLocatorzd
    A locator that always point to the user provided directory in
    `numba.config.CACHE_DIR`
    c                 C   s0   || _ |jj| _| |}tjtj	|| _
d S r   )rS   __code__co_firstlinenorX   rI   r.   r3   rE   r
   	CACHE_DIR_cache_path)r   r9   r:   cache_subpathr   r   r   __init__   s    

z"_UserProvidedCacheLocator.__init__c                 C   s   | j S r   r`   r   r   r   r   r-      s    z(_UserProvidedCacheLocator.get_cache_pathc                    s    t js
d S tt| }|||S r   )r
   r_   superr\   r;   )r8   r9   r:   parent	__class__r   r   r;      s    
z'_UserProvidedCacheLocator.from_function)	r#   r$   r%   rJ   rb   r-   rK   r;   __classcell__r   r   rf   r   r\      s
   r\   c                   @   s    e Zd ZdZdd Zdd ZdS )_InTreeCacheLocatorzn
    A locator for functions backed by a regular Python module with a
    writable __pycache__ directory.
    c                 C   s.   || _ |jj| _tjtj| j d| _d S )N__pycache__)	rS   r]   r^   rX   r.   r3   rE   r?   r`   )r   r9   r:   r   r   r   rb      s    
z_InTreeCacheLocator.__init__c                 C   s   | j S r   rc   r   r   r   r   r-      s    z"_InTreeCacheLocator.get_cache_pathN)r#   r$   r%   rJ   rb   r-   r   r   r   r   ri      s   ri   c                   @   s,   e Zd ZdZdd Zdd Zedd ZdS )	_UserWideCacheLocatorz
    A locator for functions backed by a regular Python module or a
    frozen executable, cached into a user-wide cache directory.
    c                 C   s@   || _ |jj| _tddd}|j}| |}tj	||| _
d S )NnumbaF)appname	appauthor)rS   r]   r^   rX   r   user_cache_dirrI   r.   r3   rE   r`   )r   r9   r:   appdirs	cache_dirra   r   r   r   rb      s    

z_UserWideCacheLocator.__init__c                 C   s   | j S r   rc   r   r   r   r   r-      s    z$_UserWideCacheLocator.get_cache_pathc                 C   sN   t j|sttddsd S | ||}z|  W n tk
rH   Y d S X |S rM   )r.   r3   rY   rO   rP   r4   rZ   r[   r   r   r   r;      s    
z#_UserWideCacheLocator.from_functionN)r#   r$   r%   rJ   rb   r-   rK   r;   r   r   r   r   rk      s
   rk   c                   @   s<   e Zd ZdZdd Zdd Zdd Zdd	 Zed
d Z	dS )_IPythonCacheLocatorzT
    A locator for functions entered at the IPython prompt (notebook or other).
    c                 C   s2   || _ t|}t|tr"|| _n|d| _d S )Nzutf-8)rS   inspect	getsource
isinstancebytes_bytes_sourcerC   )r   r9   r:   sourcer   r   r   rb     s
    

z_IPythonCacheLocator.__init__c                 C   sB   zddl m} W n  tk
r0   ddlm} Y nX tj| dS )Nr   )get_ipython_cache_dirZnumba_cache)ZIPython.pathsry   ImportErrorZIPython.utils.pathr.   r3   rE   )r   ry   r   r   r   r-     s
    z#_IPythonCacheLocator.get_cache_pathc                 C   s   t | j S r   )rA   sha256rw   rD   r   r   r   r   r5     s    z%_IPythonCacheLocator.get_source_stampc                 C   s0   d | jdd d }t| d d S )N    T   
   )rE   rw   
splitlinesrA   r{   rD   )r   Z
firstlinesr   r   r   r6     s    z&_IPythonCacheLocator.get_disambiguatorc                 C   sZ   | ds(tjtj| ds(d S | ||}z|  W n tk
rT   Y d S X |S )Nz	<ipython-Z
ipykernel_)
startswithr.   r3   basenamer?   r4   rZ   r[   r   r   r   r;   '  s    
z"_IPythonCacheLocator.from_functionN)
r#   r$   r%   rJ   rb   r-   r5   r6   rK   r;   r   r   r   r   rr      s   
	rr   c                   @   sh   e Zd ZdZeeeegZdd Z	dd Z
edd Zedd	 Zed
d Zedd Zedd ZdS )	CacheImplz
    Provides the core machinery for caching.
    - implement how to serialize and deserialize the data in the cache.
    - control the filename of the cache.
    - provide the cache locator
    c           
      C   s   |j j| _z
|j}W n tk
r.   |j}Y nX t|}| jD ]}|	||}|d k	r@ qnq@t
d||f || _t|}tjtj|d }d||f }ttdd}	| ||	| _d S )Nz:cannot cache function %r: no locator available for file %rr   z%s.%sabiflags )r]   r^   rX   r%   AttributeErrorr#   rs   getfile_locator_classesr;   RuntimeError_locatorr.   r3   splitextr   rO   rP   get_filename_base_filename_base)
r   r9   qualnamesource_pathr8   locatorfilenamemodnamefullnamer   r   r   r   rb   C  s&    




zCacheImpl.__init__c                 C   s<   | dd dd}d}||| j tjd tjd |f S )N<r   >z%s-%s.py%d%d%sr      )replacer   r6   rP   version_info)r   r   r   Zfixed_fullnamefmtr   r   r   r   \  s      zCacheImpl.get_filename_basec                 C   s   | j S r   )r   r   r   r   r   filename_based  s    zCacheImpl.filename_basec                 C   s   | j S r   )r   r   r   r   r   r   h  s    zCacheImpl.locatorc                 C   s   dS )z$Returns the serialized form the dataNr   r   r   r   r   r   reducel  s    zCacheImpl.reducec                 C   s   dS )z4Returns the de-serialized form of the *reduced_data*Nr   )r   r   Zreduced_datar   r   r   rebuildq  s    zCacheImpl.rebuildc                 C   s   dS )zEReturns True if the given data is cachable; otherwise, returns False.Nr   r   r   r   r   check_cachablev  s    zCacheImpl.check_cachableN)r#   r$   r%   rJ   r\   ri   rk   rr   r   rb   r   r)   r   r   r   r   r   r   r   r   r   r   r   7  s$   



r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	CompileResultCacheImplz>
    Implements the logic to cache CompileResult objects.
    c                 C   s   |  S )z4
        Returns a serialized CompileResult
        )Z_reduce)r   r(   r   r   r   r     s    zCompileResultCacheImpl.reducec                 C   s   t jj|f| S )z8
        Returns the unserialized CompileResult
        )r   r	   Z_rebuildr   r   payloadr   r   r   r     s    zCompileResultCacheImpl.rebuildc                 C   sf   d}t dd |jD rd}n|jjr*d}|rbd|jjdd |f }t|t	| j
j| j d	S d
S )z@
        Check cachability of the given compile result.
        Nc                 s   s   | ]}|j  V  qd S r   )Z	can_cache.0xr   r   r   	<genexpr>  s     z8CompileResultCacheImpl.check_cachable.<locals>.<genexpr>zas it uses lifted codezLas it uses dynamic globals (such as ctypes pointers and large global arrays)z&Cannot cache compiled function "%s" %s.r<   FT)anyZliftedZlibraryhas_dynamic_globalsZfndescr   r@   warningswarn_explicitr   r   rS   rX   )r   r(   Zcannot_cacher   r   r   r   r     s     z%CompileResultCacheImpl.check_cachableN)r#   r$   r%   rJ   r   r   r   r   r   r   r   r   |  s   r   c                       s<   e Zd ZdZdZdd Zdd Zdd Z fd	d
Z  Z	S )CodeLibraryCacheImplz<
    Implements the logic to cache CodeLibrary objects.
    Nc                 C   s   |  S )z2
        Returns a serialized CodeLibrary
        )Zserialize_using_object_coder   Zcodelibr   r   r   r     s    zCodeLibraryCacheImpl.reducec                 C   s   |  |S )z6
        Returns the unserialized CodeLibrary
        )codegenZunserialize_libraryr   r   r   r   r     s    zCodeLibraryCacheImpl.rebuildc                 C   s   |j  S )z=
        Check cachability of the given CodeLibrary.
        )r   r   r   r   r   r     s    z#CodeLibraryCacheImpl.check_cachablec                    s&   t t| }|||}d| j|gS )N-)rd   r   r   rE   _filename_prefix)r   r   r   re   resrf   r   r   r     s    
z&CodeLibraryCacheImpl.get_filename_base)
r#   r$   r%   rJ   r   r   r   r   r   rh   r   r   rf   r   r     s   r   c                   @   sv   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zejdd ZdS )IndexDataCacheFilezP
    Implements the logic for the index file and data file used by a cache.
    c                 C   sD   || _ d|f | _tj| j | j| _d|f | _|| _tj	| _
d S )Nz%s.nbiz%s.{number:d}.nbc)r`   Z_index_namer.   r3   rE   _index_path_data_name_pattern_source_stamprl   __version___version)r   r   r   source_stampr   r   r   rb     s    zIndexDataCacheFile.__init__c                 C   s   |  i  d S r   )_save_indexr   r   r   r   r"     s    zIndexDataCacheFile.flushc                 C   s~   |   }z|| }W nX tk
rl   t| }tdD ]}| |}||kr: qVq:|||< | | Y nX | || dS )z?
        Save a new cache entry with *key* and *data*.
        r   N)	_load_indexKeyErrorsetvalues	itertoolscount
_data_namer   
_save_data)r   keyr   	overloads	data_nameexistingir   r   r   save  s    
zIndexDataCacheFile.savec                 C   sF   |   }||}|dkrdS z| |W S  tk
r@   Y dS X dS )z0
        Load a cache entry with *key*.
        N)r   get
_load_datarZ   )r   r   r   r   r   r   r   load  s    
zIndexDataCacheFile.loadc              	   C   s   z.t | jd}t|}| }W 5 Q R X W n tk
rF   i  Y S X || jkrVi S t|\}}td| j || j	kr~i S |S dS )z|
        Load the cache index and return it as a dictionary (possibly
        empty if cache is empty or obsolete).
        rbz[cache] index loaded from %rN)
openr   pickler   readFileNotFoundErrorr   loadsr   r   )r   fversionr   Zstampr   r   r   r   r     s    



zIndexDataCacheFile._load_indexc              	   C   sX   | j |f}| |}| | j"}tj| j|dd || W 5 Q R X td| j d S )Nr<   )protocolz[cache] index saved to %r)	r   _dump_open_for_writer   r   dumpr   writer   )r   r   r   r   r   r   r   r     s    

zIndexDataCacheFile._save_indexc              	   C   s@   |  |}t|d}| }W 5 Q R X t|}td| |S )Nr   z[cache] data loaded from %r)
_data_pathr   r   r   r   r   )r   namer3   r   r   tupr   r   r   r     s    


zIndexDataCacheFile._load_datac              	   C   sB   |  |}| |}| |}|| W 5 Q R X td| d S )Nz[cache] data saved to %r)r   r   r   r   r   )r   r   r   r3   r   r   r   r   r     s
    

zIndexDataCacheFile._save_datac                 C   s   | j j|dS )N)number)r   format)r   r   r   r   r   r     s    zIndexDataCacheFile._data_namec                 C   s   t j| j|S r   )r.   r3   rE   r`   )r   r   r   r   r   r   "  s    zIndexDataCacheFile._data_pathc                 C   s   t |S r   r   )r   objr   r   r   r   %  s    zIndexDataCacheFile._dumpc                 c   s   t  jdd }d||f }z,t|d}|V  W 5 Q R X t|| W n: tk
r   zt| W n tk
r|   Y nX  Y nX dS )z
        Open *filepath* for writing in a race condition-free way (hopefully).
        uuid4 is used to try and avoid name collisions on a shared filesystem.
        N   z	%s.tmp.%swb)	uuidZuuid4hexr   r.   r   	ExceptionunlinkrZ   )r   filepathuidZtmpnamer   r   r   r   r   (  s    z"IndexDataCacheFile._open_for_writeN)r#   r$   r%   rJ   rb   r"   r   r   r   r   r   r   r   r   r   
contextlibcontextmanagerr   r   r   r   r   r     s   r   c                   @   s~   e Zd ZdZdZdd Zdd Zedd Zd	d
 Z	dd Z
dd Zdd Zdd Zdd Zdd Zejdd Zdd ZdS )Cachea<  
    A per-function compilation cache.  The cache saves data in separate
    data files and maintains information in an index file.

    There is one index file per function and Python version
    ("function_name-<lineno>.pyXY.nbi") which contains a mapping of
    signatures and architectures to data files.
    It is prefixed by a versioning key and a timestamp of the Python source
    file containing the function.

    There is one data file ("function_name-<lineno>.pyXY.<number>.nbc")
    per function, function signature, target architecture and Python version.

    Separate index and data files per Python version avoid pickle
    compatibility problems.

    Note:
    This contains the driver logic only.  The core logic is provided
    by a subclass of ``CacheImpl`` specified as *_impl_class* in the subclass.
    Nc                 C   s\   t || _|| _| || _| jj | _| jj }| jj	}t
| j||d| _|   d S )N)r   r   r   )repr_name_py_func_impl_class_implr   r-   r`   r5   r   r   _cache_filer    )r   r9   r   r   r   r   r   rb   V  s    
zCache.__init__c                 C   s   d| j j| jf S )Nz<%s py_func=%r>)rg   r#   r   r   r   r   r   __repr__c  s    zCache.__repr__c                 C   s   | j S r   rc   r   r   r   r   r   f  s    zCache.cache_pathc                 C   s
   d| _ d S )NT_enabledr   r   r   r   r    j  s    zCache.enablec                 C   s
   d| _ d S )NFr   r   r   r   r   r!   m  s    zCache.disablec                 C   s   | j   d S r   )r   r"   r   r   r   r   r"   p  s    zCache.flushc              
   C   s4   |   |   | ||W  5 Q R  S Q R X dS )zr
        Load and recreate the cached object for the given signature,
        using the *target_context*.
        N)Zrefresh!_guard_against_spurious_io_errors_load_overloadr   r   r   r   r   s  s    
zCache.load_overloadc                 C   s@   | j s
d S | || }| j|}|d k	r<| j||}|S r   )r   
_index_keyr   r   r   r   r   )r   r   r   r   r   r   r   r   r   ~  s    zCache._load_overloadc              	   C   s$   |    | || W 5 Q R X dS )zE
        Save the data for the given signature in the cache.
        N)r   _save_overloadr   r   r   r   r     s    
zCache.save_overloadc                 C   sR   | j s
d S | j|sd S | jj  | ||j}| j|}| j	|| d S r   )
r   r   r   r   r4   r   r   r   r   r   )r   r   r   r   r   r   r   r     s    zCache._save_overloadc              
   c   sR   t jdkrHz
d V  W qN tk
rD } z|jtjkr4 W 5 d }~X Y qNX nd V  d S )Nnt)r.   r   rZ   errnoEACCES)r   er   r   r   r     s    

z'Cache._guard_against_spurious_io_errorsc                 C   s\   | j jj}| j jdk	r6tdd | j jD }t|}nd}dd }|| ||||ffS )a
  
        Compute index key for the given signature and codegen.
        It includes a description of the OS, target architecture and hashes of
        the bytecode for the function and, if the function has a __closure__,
        a hash of the cell_contents.
        Nc                 S   s   g | ]
}|j qS r   )cell_contentsr   r   r   r   
<listcomp>  s     z$Cache._index_key.<locals>.<listcomp>r|   c                 S   s   t |  S r   )rA   r{   rD   )r   r   r   r   <lambda>  r|   z"Cache._index_key.<locals>.<lambda>)r   r]   co_code__closure__tupler   Zmagic_tuple)r   r   r   Z	codebytesZcvarsZ	cvarbytesZhasherr   r   r   r     s    

zCache._index_key)r#   r$   r%   rJ   r   rb   r   r)   r   r    r!   r"   r   r   r   r   r   r   r   r   r   r   r   r   r   =  s    
	

r   c                   @   s   e Zd ZdZeZdS )FunctionCachezF
    Implements Cache that saves and loads CompileResult objects.
    N)r#   r$   r%   rJ   r   r   r   r   r   r   r     s   r   r   c                    sB   t kstt  G fdddt G  fdddt}|S )z
    Create a Cache class for additional compilation features to cache their
    result for reuse.  The cache is saved in filename pattern like
    in ``FunctionCache`` but with additional *prefix* as specified.
    c                       s   e Zd Z ZdS )z6make_library_cache.<locals>.CustomCodeLibraryCacheImplN)r#   r$   r%   r   r   )prefixr   r   CustomCodeLibraryCacheImpl  s   r   c                       s   e Zd ZdZ ZdS )z(make_library_cache.<locals>.LibraryCachez
        Implements Cache that saves and loads CodeLibrary objects for additional
        feature for the specified python function.
        N)r#   r$   r%   rJ   r   r   )r   r   r   LibraryCache  s   r  )_lib_cache_prefixesAssertionErroraddr   r   )r   r  r   )r   r   r   make_library_cache  s
    
r  )3rJ   abcr   r   r   r   r   rA   rs   r   r.   r   rP   r0   r   r   Znumba.misc.appdirsr   rl   Znumba.core.errorsr   Znumba.core.baser   Znumba.core.codegenr   Znumba.core.compilerr	   Z
numba.corer
   r   Znumba.core.serializer   r   r   r'   r*   objectrL   r\   ri   rk   rr   r   r   r   r   r   r   r   r  r  r   r   r   r   <module>   sJ   )9  7E$~~
