B
    	\'                 @   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ddlm	Z	m
Z
 e
rXejZn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.
    N   )_bytes_or_unicodePY3_OR_LATERc               @   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	   ?lib/python3.7/site-packages/sklearn/externals/joblib/hashing.py	<genexpr>*   s    z*_ConsistentSet.__init__.<locals>.<genexpr>)sortedZ	_sequence	TypeErrordecimalZ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   0   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 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   s<   t  | _trtjntj}tj| | j|d t	
|| _d S )N)protocol)ioBytesIOstreamr   pickleZDEFAULT_PROTOCOLZHIGHEST_PROTOCOLPicklerr   hashlibnew_hash)r   	hash_namer   r	   r	   r
   r   9   s
    

zHasher.__init__Tc          
   C   sv   y|  | W n> tjk
rL } z| jd||f f7  _ W d d }~X Y nX | j }| j| |rr| j S d S )Nz"PicklingError while hashing %r: %r)	dumpr   PicklingErrorr   r   getvaluer!   updateZ	hexdigest)r   objZreturn_digestr   dumpsr	   r	   r
   r   C   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| | d S )N__func__)
isinstancetypes
MethodTypetypepophasattrr)   r   __self__r   r   	__class__r   save)r   r'   Z	func_nameZinstclsr	   r	   r
   r2   N   s    

zHasher.savec             C   s   t |trd S t| | d S )N)r*   r   r   memoize)r   r'   r	   r	   r
   r4   a   s    
zHasher.memoizeNc             C   s   t ||d}tjdkr|d= ytj| |f| W nl tjk
r   tj| |f| t|dd }|dkr|}|d krx|j}tj	| }t
||st||| Y nX d S )N)namepack)      r6   r   __main__)dictsysversion_infor   save_globalr   r$   getattrr   modulesr/   setattr)r   r'   r5   r6   kwargsmoduleZmy_namemodr	   r	   r
   r=   l   s    


zHasher.save_globalc          
   C   sP   yt | tt| W n2 tk
rJ   t | 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
   rF      s
    zHasher._batch_setitemsc             C   s   t | 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   r4   structr6   r=   r   dispatchcopyr-   lenobjectr   r#   rF   rI   setr	   r	   r	   r
   r   4   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/   rQ   
_getbuffer
memoryview)r   r"   rR   rT   r	   r	   r
   r      s    


zNumpyHasher.__init__c             C   s   t || jjr|jjs|jdkr*| }n&|jjr8|}n|jj	rH|j
}n| }| j| || jj | jrt || jjr| jj}n|j}|d|j|j|jff}n"t || jjr|j}|d|jff}t| | 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.
        r	   ZHASHEDN)r*   rT   ZndarrayZdtypeZ	hasobjectshapeZflattenflagsc_contiguousf_contiguousTr!   r&   rU   ZviewZuint8rR   Zmemmapr1   stridesZdescrr   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
   rP      s   
rP   r   Fc             C   s,   dt jkrt||d}n
t|d}|| 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
    rS   )r"   rR   )r"   )r;   r?   rP   r   r   )r'   r"   rR   Zhasherr	   r	   r
   r      s    

r   )r   F)r   r   r   r;   r+   rJ   r   r   Z_compatr   r   Z_Picklerr   rN   r   r   r   rP   r   r	   r	   r	   r
   <module>   s    mU