B
     \Z                 @   s  d Z ddlmZmZm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mZ ddlZddlZddlZddlmZ ddlmZ ddlZdd	lmZmZmZ dd
lmZ ddl m!Z! ddl"m#Z# ddl$m%Z% dd Z&dd Z'eeG dd de(Z)G dd de)Z*eeG dd de(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+Z0eeG d"d# d#e(Z1G d$d% d%e1Z2G d&d' d'e1Z3G d(d) d)e(Z4G d*d+ d+e)Z5G d,d- d-e5Z6e7d.gZ8d/d0 Z9dS )1z+
Caching mechanism for compiled functions.
    )print_functiondivisionabsolute_import)ABCMetaabstractmethodabstractpropertyN   )cPickle)AppDirs)add_metaclass)compilerconfigutils)NumbaWarning)BaseContext)CodeLibrary)CompileResultc             C   sF   t | tr|  S t | tr"| jS t | tr6| j S tt| dS )z?
    Returns the Codegen associated with the given object.
    N)
isinstancer   codegenr   r   target_context	TypeErrortype)obj r   ,lib/python3.7/site-packages/numba/caching.py_get_codegen   s    



r   c             G   s   t jr| | } t|  d S )N)r   ZDEBUG_CACHEprint)msgargsr   r   r   
_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_path5   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!   sigr   r   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_overloadC   s    z_Cache.save_overloadc             C   s   dS )z#
        Enable the cache.
        Nr   )r!   r   r   r   enableI   s    z_Cache.enablec             C   s   dS )z$
        Disable the cache.
        Nr   )r!   r   r   r   disableO   s    z_Cache.disablec             C   s   dS )z"
        Flush the cache.
        Nr   )r!   r   r   r   flushU   s    z_Cache.flushN)__name__
__module____qualname__r   r"   r   r$   r&   r'   r(   r)   r   r   r   r   r    2   s   r    c               @   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 )Nr   )r!   r   r   r   r"   ]   s    zNullCache.cache_pathc             C   s   d S )Nr   )r!   r#   r   r   r   r   r$   a   s    zNullCache.load_overloadc             C   s   d S )Nr   )r!   r#   cresr   r   r   r&   d   s    zNullCache.save_overloadc             C   s   d S )Nr   )r!   r   r   r   r'   g   s    zNullCache.enablec             C   s   d S )Nr   )r!   r   r   r   r(   j   s    zNullCache.disablec             C   s   d S )Nr   )r!   r   r   r   r)   m   s    zNullCache.flushN)
r*   r+   r,   propertyr"   r$   r&   r'   r(   r)   r   r   r   r   r-   \   s   r-   c               @   sH   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
dS )_CacheLocatorz<
    A filesystem locator for caching a given function.
    c          
   C   s\   |   }yt| W n0 tk
rF } z|jtjkr6 W d d }~X Y nX tj|d  d S )N)dir)	get_cache_pathosmakedirsOSErrorerrnoZEEXISTtempfileZTemporaryFileclose)r!   pather   r   r   ensure_cache_pathw   s    z_CacheLocator.ensure_cache_pathc             C   s   dS )zA
        Return the directory the function is cached in.
        Nr   )r!   r   r   r   r2      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_stamp   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_disambiguator   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_functionN)r*   r+   r,   __doc__r;   r   r2   r<   r=   classmethodrB   r   r   r   r   r0   q   s   
r0   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sysr3   stat
executable_py_filest_mtimest_size)r!   str   r   r   r<      s    z._SourceFileBackedLocatorMixin.get_source_stampc             C   s
   t | jS )N)str_lineno)r!   r   r   r   r=      s    z/_SourceFileBackedLocatorMixin.get_disambiguatorc             C   s@   t j|sd S | ||}y|  W n tk
r:   d S X |S )N)r3   r9   existsr;   r5   )r?   r@   rA   r!   r   r   r   rB      s    
z+_SourceFileBackedLocatorMixin.from_functionN)r*   r+   r,   rC   r<   r=   rD   rB   r   r   r   r   rE      s   	rE   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   sV   || _ |jj| _tjtj| j \}}tj|	tjj
}tjtj|| _d S )N)rK   __code__co_firstlinenorP   r3   r9   
splitdriveabspathdirnamelstripsepjoinr   	CACHE_DIR_cache_path)r!   r@   rA   Zdriver9   Zsubpathr   r   r   __init__   s
    
z"_UserProvidedCacheLocator.__init__c             C   s   | j S )N)r\   )r!   r   r   r   r2      s    z(_UserProvidedCacheLocator.get_cache_pathc                s    t js
d S tt| }|||S )N)r   r[   superrR   rB   )r?   r@   rA   parent)	__class__r   r   rB      s    
z'_UserProvidedCacheLocator.from_function)	r*   r+   r,   rC   r]   r2   rD   rB   __classcell__r   r   )r`   r   rR      s   rR   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__)	rK   rS   rT   rP   r3   r9   rZ   rW   r\   )r!   r@   rA   r   r   r   r]      s    
z_InTreeCacheLocator.__init__c             C   s   | j S )N)r\   )r!   r   r   r   r2      s    z"_InTreeCacheLocator.get_cache_pathN)r*   r+   r,   rC   r]   r2   r   r   r   r   rb      s   rb   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   sn   || _ |jj| _tddd}|j}tj|}tj	dksZt
tddsZtj|tjj}tj||| _d S )NnumbaF)ZappnameZ	appauthorntrF   )rK   rS   rT   rP   r
   Zuser_cache_dirr3   r9   rW   namerG   rH   rV   rX   rY   rZ   r\   )r!   r@   rA   appdirsZ	cache_dirZcache_subpathr   r   r   r]      s    
z_UserWideCacheLocator.__init__c             C   s   | j S )N)r\   )r!   r   r   r   r2      s    z$_UserWideCacheLocator.get_cache_pathc             C   sL   t j|sttddsd S | ||}y|  W n tk
rF   d S X |S )NrF   F)r3   r9   rQ   rG   rH   r;   r5   )r?   r@   rA   r!   r   r   r   rB      s    
z#_UserWideCacheLocator.from_functionN)r*   r+   r,   rC   r]   r2   rD   rB   r   r   r   r   rd      s   rd   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)rK   inspectZ	getsourcer   bytes_bytes_sourceencode)r!   r@   rA   sourcer   r   r   r]     s
    

z_IPythonCacheLocator.__init__c             C   sB   yddl m} W n  tk
r0   ddlm} Y nX tj| dS )Nr   )get_ipython_cache_dirre   )ZIPython.pathsro   ImportErrorZIPython.utils.pathr3   r9   rZ   )r!   ro   r   r   r   r2     s
    z#_IPythonCacheLocator.get_cache_pathc             C   s   t | j S )N)hashlibsha256rl   	hexdigest)r!   r   r   r   r<   '  s    z%_IPythonCacheLocator.get_source_stampc             C   s0   d | jdd d }t| d d S )N    T   
   )rZ   rl   
splitlinesrq   rr   rs   )r!   Z
firstlinesr   r   r   r=   *  s    z&_IPythonCacheLocator.get_disambiguatorc             C   s>   | dsd S | ||}y|  W n tk
r8   d S X |S )Nz	<ipython-)
startswithr;   r5   )r?   r@   rA   r!   r   r   r   rB   3  s    

z"_IPythonCacheLocator.from_functionN)
r*   r+   r,   rC   r]   r2   r<   r=   rD   rB   r   r   r   r   ri     s   
	ri   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   t |j| _|jj| _y
|j}W n tk
r:   |j}Y nX t	
|}x4| jD ]}|||}|d k	rNP qNW 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 )bool__closure___is_closurerS   rT   rP   r,   AttributeErrorr*   rj   Zgetfile_locator_classesrB   RuntimeError_locatorr3   r9   splitextbasenamerG   rH   get_filename_base_filename_base)
r!   r@   qualnamesource_pathr?   locatorfilenamemodnamefullnamerz   r   r   r   r]   M  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   r   )replacer   r=   rH   version_info)r!   r   rz   Zfixed_fullnameZfmtr   r   r   r   g  s    z_CacheImpl.get_filename_basec             C   s   | j S )N)r   )r!   r   r   r   filename_baseo  s    z_CacheImpl.filename_basec             C   s   | j S )N)r   )r!   r   r   r   r   s  s    z_CacheImpl.locatorc             C   s   dS )z$Returns the serialized form the dataNr   )r!   r%   r   r   r   reducew  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   rebuild|  s    z_CacheImpl.rebuildc             C   s   dS )zEReturns True if the given data is cachable; otherwise, returns False.Nr   )r!   r%   r   r   r   check_cachable  s    z_CacheImpl.check_cachableN)r*   r+   r,   rC   rR   rb   rd   ri   r   r]   r   r/   r   r   r   r   r   r   r   r   r   r   ry   @  s   ry   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   sd   d}| j rd}n|jrd}n|jjr(d}|r`d|jjdd |f }t|t	| j
j| j dS d	S )
z@
        Check cachability of the given compile result.
        Nz'as it uses outer variables in a closurezas it uses lifted loopszLas it uses dynamic globals (such as ctypes pointers and large global arrays)z&Cannot cache compiled function "%s" %s.FT)r~   ZliftedZlibraryZhas_dynamic_globalsZfndescr   splitwarningswarn_explicitr   r   rK   rP   )r!   r.   Zcannot_cacher   r   r   r   r     s    z%CompileResultCacheImpl.check_cachableN)r*   r+   r,   rC   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!   codelibr   r   r   r     s    zCodeLibraryCacheImpl.reducec             C   s   |  |S )z6
        Returns the unserialized CodeLibrary
        )r   Zunserialize_library)r!   r   r   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   r     s    z#CodeLibraryCacheImpl.check_cachablec                s&   t t| }|||}d| j|gS )N-)r^   r   r   rZ   _filename_prefix)r!   r   rz   r_   Zres)r`   r   r   r     s    
z&CodeLibraryCacheImpl.get_filename_base)
r*   r+   r,   rC   r   r   r   r   r   ra   r   r   )r`   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_namer3   r9   rZ   _index_path_data_name_pattern_source_stampre   __version___version)r!   r"   r   source_stampr   r   r   r]     s    zIndexDataCacheFile.__init__c             C   s   |  i  d S )N)_save_index)r!   r   r   r   r)     s    zIndexDataCacheFile.flushc             C   s   |   }y|| }W nZ tk
rn   t| }x&tdD ]}| |}||kr<P q<W |||< | | 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   sB   |   }||}|dkrdS y
| |S  tk
r<   dS X dS )z0
        Load a cache entry with *key*.
        N)r   get
_load_dataEnvironmentError)r!   r   r   r   r   r   r   load  s    

zIndexDataCacheFile.loadc          
   C   s   y.t | jd}t|}| }W dQ R X W n6 tk
rd } z|jtjfkrRi S  W dd}~X Y nX || jkrti S t	|\}}t
d| j || jkri S |S dS )z|
        Load the cache index and return it as a dictionary (possibly
        empty if cache is empty or obsolete).
        rbNz[cache] index loaded from %r)openr   pickler   readr   r6   ZENOENTr   loadsr   r   )r!   fversionr%   r:   Zstampr   r   r   r   r     s    


zIndexDataCacheFile._load_indexc          	   C   sX   | j |f}| |}| | j"}tj| j|dd || W d 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 d Q R X t|}td| |S )Nr   z[cache] data loaded from %r)
_data_pathr   r   r   r   r   )r!   rg   r9   r   r%   tupr   r   r   r     s    


zIndexDataCacheFile._load_datac          	   C   sB   |  |}| |}| |}|| W d Q R X td| d S )Nz[cache] data saved to %r)r   r   r   r   r   )r!   rg   r%   r9   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 )N)r3   r9   rZ   r\   )r!   rg   r   r   r   r   1  s    zIndexDataCacheFile._data_pathc             C   s   t j|ddS )Nr   )r   )r   dumps)r!   r   r   r   r   r   4  s    zIndexDataCacheFile._dumpc             c   s|   d|t  f }y,t|d}|V  W dQ R X t|| W n: tk
rv   yt | W n tk
rn   Y nX  Y nX dS )z_
        Open *filepath* for writing in a race condition-free way
        (hopefully).
        z	%s.tmp.%dwbN)r3   getpidr   r   Zfile_replace	Exceptionunlinkr5   )r!   filepathZtmpnamer   r   r   r   r   7  s    z"IndexDataCacheFile._open_for_writeN)r*   r+   r,   rC   r]   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   sV   t || _| || _| jj | _| jj }| jj}t	| j||d| _
|   d S )N)r"   r   r   )repr_name_impl_class_implr   r2   r\   r<   r   r   _cache_filer'   )r!   r@   r   r   r   r   r   r]   d  s    

zCache.__init__c             C   s   d| j j| jf S )Nz<%s py_func=%r>)r`   r*   r   )r!   r   r   r   __repr__p  s    zCache.__repr__c             C   s   | j S )N)r\   )r!   r   r   r   r"   s  s    zCache.cache_pathc             C   s
   d| _ d S )NT)_enabled)r!   r   r   r   r'   w  s    zCache.enablec             C   s
   d| _ d S )NF)r   )r!   r   r   r   r(   z  s    zCache.disablec             C   s   | j   d S )N)r   r)   )r!   r   r   r   r)   }  s    zCache.flushc          	   C   s(   |   |   | ||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_overload)r!   r#   r   r   r   r   r$     s    
zCache.load_overloadc             C   s@   | j s
d S | |t|}| j|}|d k	r<| j||}|S )N)r   
_index_keyr   r   r   r   r   )r!   r#   r   r   r%   r   r   r   r     s    zCache._load_overloadc          	   C   s$   |    | || W dQ R X dS )zE
        Save the data for the given signature in the cache.
        N)r   _save_overload)r!   r#   r%   r   r   r   r&     s    
zCache.save_overloadc             C   sT   | j s
d S | j|sd S | jj  | |t|}| j|}| j	|| d S )N)
r   r   r   r   r;   r   r   r   r   r   )r!   r#   r%   r   r   r   r   r     s    zCache._save_overloadc          
   c   sR   t jdkrHy
d V  W qN tk
rD } z|jtjkr4 W d d }~X Y qNX nd V  d S )Nrf   )r3   rg   r   r6   ZEACCES)r!   r:   r   r   r   r     s    

z'Cache._guard_against_spurious_io_errorsc             C   s   ||  fS )z
        Compute index key for the given signature and codegen.
        It includes a description of the OS and target architecture.
        )Zmagic_tuple)r!   r#   r   r   r   r   r     s    zCache._index_key)r*   r+   r,   rC   r   r]   r   r/   r"   r'   r(   r)   r$   r   r&   r   r   r   r   r   r   r   r   r   r   K  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,   rC   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,   rC   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   ):rC   Z
__future__r   r   r   abcr   r   r   r   r6   rq   rj   r   r3   Z	six.movesr	   r   rH   r7   r   rh   r
   Zsixr   re   r{   r   r   r   errorsr   Znumba.targets.baser   Znumba.targets.codegenr   Znumba.compilerr   r   r   objectr    r-   r0   rE   rR   rb   rd   ri   ry   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sR   ), (4F&p
