3
d()                 @   s   d 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ej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dddZdS )zb
Fast cryptographic hash of Python objects, with a special case for fast
hashing of numpy arrays.
    Nc               @   s   e Zd ZdZdd ZdS )_ConsistentSetza Class used to ensure the hash of Sets is preserved
        whatever the order of its items.
    c             C   sB   yt || _W n. ttjfk
r<   t dd |D | _Y nX d S )Nc             s   s   | ]}t |V  qd S )N)hash).0e r   0/tmp/pip-build-v9q4h5k9/joblib/joblib/hashing.py	<genexpr>%   s    z*_ConsistentSet.__init__.<locals>.<genexpr>)sortedZ	_sequence	TypeErrordecimalInvalidOperation)selfZset_sequencer   r   r   __init__   s    z_ConsistentSet.__init__N)__name__
__module____qualname____doc__r   r   r   r   r   r      s   r   c               @   s   e Zd ZdZdd ZdS )_MyHashz7 Class used to hash objects that won't normally pickle c             G   s
   || _ d S )N)args)r   r   r   r   r   r   +   s    z_MyHash.__init__N)r   r   r   r   r   r   r   r   r   r   (   s   r   c               @   s   e Zd ZdZdddZdddZdd	 Zd
d Zdej	fddZ
ejj Ze
eee< e
eee< e
eee< e
eeej< dd Zdd Zeeee < dS )HasherzW A subclass of pickler, to do cryptographic hashing, rather than
        pickling.
    md5c             C   s0   t j | _d}tj| | j|d tj|| _d S )N   )protocol)ioBytesIOstreamPicklerr   hashlibnew_hash)r   	hash_namer   r   r   r   r   4   s    
zHasher.__init__Tc             C   sv   y| j | W n> tjk
rL } z | jd||f f7  _ W Y d d }~X nX | jj }| jj| |rr| jj S d S )Nz"PicklingError while hashing %r: %r)	dumppicklePicklingErrorr   r   getvaluer   update	hexdigest)r   objZreturn_digestr   dumpsr   r   r   r   =   s    
zHasher.hashc             C   s   t |tjti jfr|t|dr*|jj}n|j}|j}t|tt	krTt
||j}n(|d krht
||}n|jj}t
|||}tj| | d S )N__func__)
isinstancetypes
MethodTypetypepophasattrr)   r   __self__r"   r   	__class__r   save)r   r'   	func_nameinstclsr   r   r   r2   H   s    

zHasher.savec             C   s"   t |ttfrd S tj| | d S )N)r*   bytesstrr   memoize)r   r'   r   r   r   r8   [   s    zHasher.memoizeNc             C   s   t ||d}|d= ytj| |f| W nl tjk
r   tj| |f| t|dd }|dkr|}|d krn|j}tj| }t	||st
||| Y nX d S )N)namepackr:   r   __main__)dictr   save_globalr"   r#   getattrr   sysmodulesr/   setattr)r   r'   r9   r:   kwargsmoduleZmy_namemodr   r   r   r=   f   s    

zHasher.save_globalc             C   sP   yt j| tt| W n2 tk
rJ   t j| ttdd |D  Y nX d S )Nc             s   s   | ]\}}t ||fV  qd S )N)r   )r   kvr   r   r   r      s   z)Hasher._batch_setitems.<locals>.<genexpr>)r   _batch_setitemsiterr	   r
   )r   itemsr   r   r   rG      s
    zHasher._batch_setitemsc             C   s   t j| t| d S )N)r   r2   r   )r   Z	set_itemsr   r   r   save_set   s    zHasher.save_set)r   )T)r   r   r   r   r   r   r2   r8   structr:   r=   r   dispatchcopyr-   lenobjectr"   r!   rG   rJ   setr   r   r   r   r   /   s   
	

r   c               @   s"   e Zd ZdZd	ddZdd ZdS )
NumpyHasherz7 Special case the hasher for when numpy is loaded.
    r   Fc             C   s@   || _ tj| |d ddl}|| _t|dr6|j| _nt| _dS )a  
            Parameters
            ----------
            hash_name: string
                The hash algorithm to be used
            coerce_mmap: boolean
                Make no difference between np.memmap and np.ndarray
                objects.
        )r    r   N	getbuffer)	coerce_mmapr   r   numpynpr/   rR   
_getbuffer
memoryview)r   r    rS   rU   r   r   r   r      s    


zNumpyHasher.__init__c             C   s   t || jjr|jj r|jf kr,|j }n&|jjr:|}n|jj	rJ|j
}n|j }| jj| j|j| jj | jrt || jjr| jj}n|j}|d|j|j|jff}n6t || jjr| jjdjd | jjtj| dS tj| | dS )z Subclass the save method, to hash ndarray subclass, rather
            than pickling them. Off course, this is a total abuse of
            the Pickler class.
        ZHASHEDZ_HASHED_DTYPEzutf-8N)r*   rU   ZndarrayZdtypeZ	hasobjectshapeflattenflagsc_contiguousf_contiguousTr   r%   rV   viewZuint8rS   Zmemmapr1   stridesencoder"   r(   r   r2   )r   r'   Zobj_c_contiguousklassr   r   r   r2      s&    


zNumpyHasher.saveN)r   F)r   r   r   r   r   r2   r   r   r   r   rQ      s   
rQ   r   Fc             C   sH   d}||krt dj||dtjkr4t||d}n
t|d}|j| S )al   Quick calculation of a hash to identify uniquely Python objects
        containing numpy arrays.


        Parameters
        -----------
        hash_name: 'md5' or 'sha1'
            Hashing algorithm used. sha1 is supposedly safer, but md5 is
            faster.
        coerce_mmap: boolean
            Make no difference between np.memmap and np.ndarray
    r   sha1zAValid options for 'hash_name' are {}. Got hash_name={!r} instead.rT   )r    rS   )r    )r   rb   )
ValueErrorformatr?   r@   rQ   r   r   )r'   r    rS   Zvalid_hash_namesZhasherr   r   r   r      s    


r   )r   F)r   r"   r   r?   r+   rK   r   r   _Picklerr   rO   r   r   r   rQ   r   r   r   r   r   <module>   s   kZ