o
    8ήc[                     @   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 d S N)r
   DEBUG_CACHEprint)msgargs r   9/tmp/pip-target-vg8gfxp4/lib/python/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      dS )zW
        The base filesystem path of this cache (for example its root folder).
        Nr   selfr   r   r   
cache_path&       z_Cache.cache_pathc                 C   r   )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,   r   z_Cache.load_overloadc                 C   r   )z<
        Save the overload for the given signature.
        Nr   r   r   datar   r   r   save_overload4   r   z_Cache.save_overloadc                 C   r   )z#
        Enable the cache.
        Nr   r   r   r   r   enable:   r   z_Cache.enablec                 C   r   )z$
        Disable the cache.
        Nr   r   r   r   r   disable@   r   z_Cache.disablec                 C   r   )z"
        Flush the cache.
        Nr   r   r   r   r   flushF   r   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      d S r   r   r   r   r   r   r   N   s   zNullCache.cache_pathc                 C   r+   r   r   r   r   r   r   r   R      zNullCache.load_overloadc                 C   r+   r   r   )r   r   cresr   r   r   r"   U   r,   zNullCache.save_overloadc                 C   r+   r   r   r   r   r   r   r#   X   r,   zNullCache.enablec                 C   r+   r   r   r   r   r   r   r$   [   r,   zNullCache.disablec                 C   r+   r   r   r   r   r   r   r%   ^   r,   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   r   )zA
        Return the directory the function is cached in.
        Nr   r   r   r   r   r2   m   r   z_CacheLocator.get_cache_pathc                 C   r   )z{
        Get a timestamp representing the source code's freshness.
        Can return any picklable Python object.
        Nr   r   r   r   r   get_source_stamps   r   z_CacheLocator.get_source_stampc                 C   r   )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   r   z_CacheLocator.get_disambiguatorc                 C   s   t )ze
        Create a locator instance for the given function located in the
        given file.
        )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).
        _)
r3   r8   abspathdirnamesplithashlibsha1encode	hexdigestjoin)r=   r?   r8   subpath	parentdirhashedr   r   r   get_suitable_cache_subpath   s
   z(_CacheLocator.get_suitable_cache_subpathN)r&   r'   r(   __doc__r9   r   r2   r:   r;   classmethodr@   rN   r   r   r   r   r/   b   s    



r/   c                   @   ,   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 r   )str_linenor   r   r   r   r;         
z/_SourceFileBackedLocatorMixin.get_disambiguatorc                 C   s>   t j|sd S | ||}z|  W |S  ty   Y d S w r   )r3   r8   existsr9   OSErrorr=   r>   r?   r   r   r   r   r@      s   

z+_SourceFileBackedLocatorMixin.from_functionN)r&   r'   r(   rO   r:   r;   rP   r@   r   r   r   r   rR      s    	rR   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   )rY   __code__co_firstlinenor^   rN   r3   r8   rJ   r
   	CACHE_DIR_cache_path)r   r>   r?   cache_subpathr   r   r   __init__   s   

z"_UserProvidedCacheLocator.__init__c                 C      | j S r   rg   r   r   r   r   r2         z(_UserProvidedCacheLocator.get_cache_pathc                    s    t jsd S tt| }|||S r   )r
   rf   superrc   r@   )r=   r>   r?   parent	__class__r   r   r@      s   
z'_UserProvidedCacheLocator.from_function)	r&   r'   r(   rO   ri   r2   rP   r@   __classcell__r   r   ro   r   rc      s    rc   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__)	rY   rd   re   r^   r3   r8   rJ   rD   rg   )r   r>   r?   r   r   r   ri      s   
z_InTreeCacheLocator.__init__c                 C   rj   r   rk   r   r   r   r   r2      rl   z"_InTreeCacheLocator.get_cache_pathN)r&   r'   r(   rO   ri   r2   r   r   r   r   rr      s    rr   c                   @   rQ   )	_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)rY   rd   re   r^   r   user_cache_dirrN   r3   r8   rJ   rg   )r   r>   r?   appdirs	cache_dirrh   r   r   r   ri      s   

z_UserWideCacheLocator.__init__c                 C   rj   r   rk   r   r   r   r   r2      rl   z$_UserWideCacheLocator.get_cache_pathc                 C   sJ   t j|sttddsd S | ||}z|  W |S  ty$   Y d S w rS   )r3   r8   r`   rU   rV   r9   ra   rb   r   r   r   r@      s   

z#_UserWideCacheLocator.from_functionN)r&   r'   r(   rO   ri   r2   rP   r@   r   r   r   r   rt      s    rt   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   s4   || _ t|}t|tr|| _d S |d| _d S )Nzutf-8)rY   inspect	getsource
isinstancebytes_bytes_sourcerH   )r   r>   r?   sourcer   r   r   ri     s
   


z_IPythonCacheLocator.__init__c                 C   s@   zddl m} W n ty   ddlm} Y nw tj| dS )Nr   )get_ipython_cache_dirnumba_cache)IPython.pathsr   ImportErrorIPython.utils.pathr3   r8   rJ   )r   r   r   r   r   r2     s   z#_IPythonCacheLocator.get_cache_pathc                 C   s   t | j S r   )rF   sha256r   rI   r   r   r   r   r:        z%_IPythonCacheLocator.get_source_stampc                 C   s0   d | jdd d }t| d d S )N    T   
   )rJ   r   
splitlinesrF   r   rI   )r   
firstlinesr   r   r   r;     s   z&_IPythonCacheLocator.get_disambiguatorc                 C   sV   | dstjtj| dsd S | ||}z|  W |S  ty*   Y d S w )Nz	<ipython-
ipykernel_)
startswithr3   r8   basenamerD   r9   ra   rb   r   r   r   r@   '  s   

z"_IPythonCacheLocator.from_functionN)
r&   r'   r(   rO   ri   r2   r:   r;   rP   r@   r   r   r   r   r{      s    
	r{   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y   |j}Y nw t|}| jD ]}|	||}|d ur- n	q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 )rd   re   r^   r(   AttributeErrorr&   r|   getfile_locator_classesr@   RuntimeError_locatorr3   r8   splitextr   rU   rV   get_filename_base_filename_base)
r   r>   qualnamesource_pathr=   locatorfilenamemodnamefullnamer   r   r   r   ri   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   r;   rV   version_info)r   r   r   fixed_fullnamefmtr   r   r   r   \  s
   zCacheImpl.get_filename_basec                 C   rj   r   )r   r   r   r   r   filename_based     zCacheImpl.filename_basec                 C   rj   r   )r   r   r   r   r   r   h  r   zCacheImpl.locatorc                 C   r   )z$Returns the serialized form the dataNr   r   r!   r   r   r   reducel     zCacheImpl.reducec                 C   r   )z4Returns the de-serialized form of the *reduced_data*Nr   )r   r   reduced_datar   r   r   rebuildq  r   zCacheImpl.rebuildc                 C   r   )zEReturns True if the given data is cachable; otherwise, returns False.Nr   r   r   r   r   check_cachablev  r   zCacheImpl.check_cachableN)r&   r'   r(   rO   rc   rr   rt   r{   r   ri   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 )z4
        Returns a serialized CompileResult
        )_reduce)r   r-   r   r   r   r        zCompileResultCacheImpl.reducec                 C   s   t jj|g|R  S )z8
        Returns the unserialized CompileResult
        )r   r	   _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}|r1d|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   )	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.rA   FT)anyliftedlibraryhas_dynamic_globalsfndescr   rE   warningswarn_explicitr   r   rY   r^   )r   r-   cannot_cacher   r   r   r   r     s   
z%CompileResultCacheImpl.check_cachableN)r&   r'   r(   rO   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   r   )z2
        Returns a serialized CodeLibrary
        )serialize_using_object_coder   codelibr   r   r   r     r   zCodeLibraryCacheImpl.reducec                 C   s   |  |S )z6
        Returns the unserialized CodeLibrary
        )codegen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     r   z#CodeLibraryCacheImpl.check_cachablec                    s&   t t| }|||}d| j|gS )N-)rm   r   r   rJ   _filename_prefix)r   r   r   rn   resro   r   r   r     s   
z&CodeLibraryCacheImpl.get_filename_base)
r&   r'   r(   rO   r   r   r   r   r   rq   r   r   ro   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)rg   _index_namer3   r8   rJ   _index_path_data_name_pattern_source_stampru   __version___version)r   r   r   source_stampr   r   r   ri     s   zIndexDataCacheFile.__init__c                 C   s   |  i  d S r   )_save_indexr   r   r   r   r%        zIndexDataCacheFile.flushc                 C   s|   |   }z|| }W n+ ty5   t| }tdD ]}| |}||vr) nq|||< | | Y nw | || 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   s@   |   }||}|du rdS z| |W S  ty   Y dS w )z0
        Load a cache entry with *key*.
        N)r   get
_load_datara   )r   r   r   r   r   r   r   load  s   
zIndexDataCacheFile.loadc                 C   s   z!t | jd}t|}| }W d   n1 sw   Y  W n ty,   i  Y S w || jkr4i S t|\}}td| j || j	krHi S |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   readFileNotFoundErrorr   loadsr   r   )r   fversionr!   stampr   r   r   r   r     s    



zIndexDataCacheFile._load_indexc                 C   sl   | j |f}| |}| | j}tj| j|dd || W d    n1 s)w   Y  td| j d S )NrA   )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   sT   |  |}t|d}| }W d    n1 sw   Y  t|}td| |S )Nr   z[cache] data loaded from %r)
_data_pathr   r   r   r   r   )r   namer8   r   r!   tupr   r   r   r     s   



zIndexDataCacheFile._load_datac                 C   sV   |  |}| |}| |}|| W d    n1 sw   Y  td| d S )Nz[cache] data saved to %r)r   r   r   r   r   )r   r   r!   r8   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     r   zIndexDataCacheFile._data_namec                 C   s   t j| j|S r   )r3   r8   rJ   rg   )r   r   r   r   r   r   "  r   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 d   n1 s$w   Y  t|| W dS  tyI   zt| W   tyH   Y  w w )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)	uuiduuid4hexr   r3   r   	Exceptionunlinkra   )r   filepathuidtmpnamer   r   r   r   r   (  s"   z"IndexDataCacheFile._open_for_writeN)r&   r'   r(   rO   ri   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   r2   rg   r:   r   r   _cache_filer#   )r   r>   r   r   r   r   r   ri   V  s   
zCache.__init__c                 C   s   d| j j| jf S )Nz<%s py_func=%r>)rp   r&   r  r   r   r   r   __repr__c  s   zCache.__repr__c                 C   rj   r   rk   r   r   r   r   r   f  r   zCache.cache_pathc                 C   
   d| _ d S )NT_enabledr   r   r   r   r#   j  r_   zCache.enablec                 C   r  )NFr  r   r   r   r   r$   m  r_   zCache.disablec                 C   s   | j   d S r   )r  r%   r   r   r   r   r%   p  r   zCache.flushc                 C   s@   |   |   | ||W  d   S 1 sw   Y  dS )zr
        Load and recreate the cached object for the given signature,
        using the *target_context*.
        N)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 u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 d   dS 1 sw   Y  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   r9   r  r   r   r  r   )r   r   r!   r   r   r   r   r    s   zCache._save_overloadc              
   c   sX    t jdkr'zd V  W d S  ty& } z|jtjkr W Y d }~d S d }~ww d V  d S )Nnt)r3   r   ra   errnoEACCES)r   er   r   r   r    s   

z'Cache._guard_against_spurious_io_errorsc                 C   s\   | j jj}| j jdurt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   )rF   r   rI   )r   r   r   r   <lambda>  s    z"Cache._index_key.<locals>.<lambda>)r  rd   co_code__closure__tupler   magic_tuple)r   r   r   	codebytescvars	cvarbyteshasherr   r   r   r    s   

zCache._index_key)r&   r'   r(   rO   r  ri   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(   rO   r   r  r   r   r   r   r)    s    r)  r   c                    sB   t vsJ 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(   rO   r  r   )r+  r   r   LibraryCache  s    r,  )_lib_cache_prefixesaddr   r
  )r*  r,  r   )r+  r*  r   make_library_cache  s
   
r/  )3rO   abcr   r   r   r  r  rF   r|   r   r3   r   rV   r5   r   r   numba.misc.appdirsr   ru   numba.core.errorsr   numba.core.baser   numba.core.codegenr   numba.core.compilerr	   
numba.corer
   r   numba.core.serializer   r   r   r*   r/   objectrR   rc   rr   rt   r{   r   r   r   r   r
  r)  r   r-  r/  r   r   r   r   <module>   sL    )9  7E$~~
