B
    [&                 @   s.  d Z ddlmZ dZyddlmZ W n  ek
rD   ddlmZ Y nX ddlZddl	Z	ddl
Z
yddlmZ W n ek
r   ddlZY nX yddlZW n ek
r   ddlZY nX ddlZddlZejd dkrefZneefZdd Ze ZG d	d
 d
ejZG dd dZdd Zedkr*e  dS )a   PickleShare - a small 'shelve' like datastore with concurrency support

Like shelve, a PickleShareDB object acts like a normal dictionary. Unlike
shelve, many processes can access the database simultaneously. Changing a
value in database is immediately visible to other processes accessing the
same database.

Concurrency is possible because the values are stored in separate files. Hence
the "database" is a directory where *all* files are governed by PickleShare.

Example usage::

    from pickleshare import *
    db = PickleShareDB('~/testpickleshare')
    db.clear()
    print "Should be empty:",db.items()
    db['hello'] = 15
    db['aku ankka'] = [1,2,313]
    db['paths/are/ok/key'] = [1,(5,46)]
    print db.keys()
    del db['aku ankka']

This module is certainly not ZODB, but can be used for low-load
(non-mission-critical) situations where tiny code size trumps the
advanced features of a "real" object database.

Installation guide: pip install pickleshare

Author: Ville Vainio <vivainio@gmail.com>
License: MIT open source license.

    )print_functionz0.7.5)PathN   c             C   s   dt t| d  dd  S )Nz%02x   )abshash)key r
   *lib/python3.7/site-packages/pickleshare.pygethashfile@   s    r   c               @   s   e Zd ZdZdd Zdd Zdd Zdd	 Zed
fddZ	dd Z
dd Zdd Zdd Zd%ddZdd Zdd Zdd Zd&dd Zd!d" Zd#d$ ZdS )'PickleShareDBz7 The main 'connection' object for PickleShare database c          
   C   s   t |tst|}tjtj|}t|| _| j	 s~y| jj
dd W n0 tk
r| } z|jtjkrl W dd}~X Y nX i | _dS )z: Return a db object that will manage the specied directoryT)parentsN)
isinstancestring_typesstrospathabspath
expanduserr   rootis_dirmkdirOSErrorerrnoZEEXISTcache)selfr   er
   r
   r   __init__G   s    


zPickleShareDB.__init__c          	   C   s   | j | }y| tj }W n tk
r8   t|Y nX || jkrd|| j| d krd| j| d S y(|d}t|	 }W dQ R X W n   t|Y nX ||f| j|< |S )z db['key'] reading    r   rbN)
r   statST_MTIMEr   KeyErrorr   openpickleloadsread)r   r	   filmtimefobjr
   r
   r   __getitem__Y   s    
zPickleShareDB.__getitem__c          
   C   s   | j | }|j}|r(| s(|jdd |d}tj||dd W dQ R X y|| jf| j	|< W n0 t
k
r } z|jtjkr W dd}~X Y nX dS )z db['key'] = 5 T)r   wb   )ZprotocolN)r   parentr   r   r$   r%   dumpr!   st_mtimer   r   r   ZENOENT)r   r	   valuer(   r/   r*   r   r
   r
   r   __setitem__m   s    
zPickleShareDB.__setitem__c             C   sL   | j | }| s|  |t| }| |i }|||i || |< dS )z hashed set N)r   r   r   r   getupdate)r   hashrootr	   r2   hroothfiledr
   r
   r   hset}   s    
zPickleShareDB.hsetTc             C   sX   | j | }|t| }| |t}|tkrL|rB|tkr>t||S | |}|||S )z hashed get )r   r   r4   	_sentinelr#   hdict)r   r6   r	   defaultZ	fast_onlyr7   r8   r9   r
   r
   r   hget   s    

zPickleShareDB.hgetc          	   C   s   |  |d }|  t|r&|d p(d}|drF|g|dd  }i }xP|D ]H}y|| |  W n& tk
r   td|d | |= Y nX | | qPW |S )z> Get all data contained in hashed category 'hashroot' as dict z/* xxNZCorruptz!deleted - hset is not threadsafe!)keyssortlenendswithr5   r#   printuncache)r   r6   hfilesZlastallr*   r
   r
   r   r<      s    

zPickleShareDB.hdictc             C   st   |  |d }i }x$|D ]}|| |  | | qW || |d < x*|D ]"}| j| }|jdkrdqJ|  qJW dS )z Compress category 'hashroot', so hset is fast again

        hget will fail if fast_only is True for compressed items (that were
        hset before hcompress).

        z/*z/xxrA   N)rB   r5   rG   r   nameunlink)r   r6   rH   rI   r*   pr
   r
   r   	hcompress   s    



zPickleShareDB.hcompressc             C   s>   | j | }| j|d y|  W n tk
r8   Y nX dS )z del db["key"] N)r   r   poprK   r   )r   r	   r(   r
   r
   r   __delitem__   s    
zPickleShareDB.__delitem__c             C   s   t || jddS )z% Make a key suitable for user's eyes \/)r   Zrelative_tor   replace)r   rL   r
   r
   r   _normalized   s    zPickleShareDB._normalizedNc                s4   |dkr j d}n j |} fdd|D S )z, All keys in DB, or all keys matching a globN*c                s   g | ]}|  r |qS r
   )is_filerS   ).0rL   )r   r
   r   
<listcomp>   s    z&PickleShareDB.keys.<locals>.<listcomp>)r   ZrglobZglob)r   Zglobpatfilesr
   )r   r   rB      s    zPickleShareDB.keysc             C   s   t |  S )N)iterrB   )r   r
   r
   r   __iter__   s    zPickleShareDB.__iter__c             C   s   t |  S )N)rD   rB   )r   r
   r
   r   __len__   s    zPickleShareDB.__len__c             G   s*   |s
i | _ x|D ]}| j |d qW dS )z Removes all, or specified items from cache

        Use this after reading a large amount of large objects
        to free up memory, when you won't be needing the objects
        for a while.

        N)r   rN   )r   itemsitr
   r
   r   rG      s    
zPickleShareDB.uncache<   c             C   s   dgd dgd  dg }d}d}xhy| | }|S  t k
rD   Y nX ||krVt |t||  ||| 7 }|t|d k r$|d7 }q$W dS )a   Wait (poll) for a key to get a value

        Will wait for `maxwaittime` seconds before raising a KeyError.
        The call exits normally if the `key` field in db gets a value
        within the timeout period.

        Use this for synchronizing different processes or for ensuring
        that an unfortunately timed "db['key'] = newvalue" operation
        in another process (which causes all 'get' operation to cause a
        KeyError for the duration of pickling) won't screw up your program
        logic.
        g?r   g      ?r.   r   r   N)r#   timeZsleeprD   )r   r	   ZmaxwaittimeZwtimesZtriesZwaitedvalr
   r
   r   waitget   s    zPickleShareDB.waitgetc             C   s
   t | |S )z, Get a convenient link for accessing items  )PickleShareLink)r   Zfolderr
   r
   r   getlink  s    zPickleShareDB.getlinkc             C   s
   d| j  S )NzPickleShareDB('%s'))r   )r   r
   r
   r   __repr__  s    zPickleShareDB.__repr__)N)r^   )__name__
__module____qualname____doc__r   r,   r3   r:   r;   r>   r<   rM   rO   rS   rB   rZ   r[   rG   ra   rc   rd   r
   r
   r
   r   r   E   s"   
	
 r   c               @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )rb   z A shortdand for accessing nested PickleShare data conveniently.

    Created through PickleShareDB.getlink(), example::

        lnk = db.getlink('myobjects/test')
        lnk.foo = 2
        lnk.bar = lnk.foo + 5

    c             C   s   | j t  d S )N)__dict__r5   locals)r   dbkeydirr
   r
   r   r   (  s    zPickleShareLink.__init__c             C   s   | j d | j d d |  S )Nrk   rl   rQ   )ri   )r   r	   r
   r
   r   __getattr__+  s    zPickleShareLink.__getattr__c             C   s   || j | jd | < d S )NrQ   )rk   rl   )r   r	   r`   r
   r
   r   __setattr__-  s    zPickleShareLink.__setattr__c             C   s@   | j d }|| j d d }d| j d ddd |D f S )Nrk   rl   z/*z<PickleShareLink '%s': %s>;c             S   s   g | ]}t | qS r
   )r   basename)rV   kr
   r
   r   rW   4  s    z,PickleShareLink.__repr__.<locals>.<listcomp>)ri   rB   join)r   rk   rB   r
   r
   r   rd   /  s
    
zPickleShareLink.__repr__N)re   rf   rg   rh   r   rm   rn   rd   r
   r
   r
   r   rb     s
   	rb   c              C   s  dd l } | d}t}dd l}t|jdk r8t| d S |jd }|jdd  }|dkr|sbdg}||d }dd l}||  n|dkr|j	
 }||d }t|}	|  xb| D ]\}
}|||
< qW nD|dkr||d }|  t|d	 n|d
krt  t  d S )Nr   z    pickleshare - manage PickleShare databases

    Usage:

        pickleshare dump /path/to/db > dump.txt
        pickleshare load /path/to/db < dump.txt
        pickleshare test /path/to/db
    r.   r   r0   .loadZtestwaitZ250test)textwrapdedentr   sysrD   argvrF   pprintr\   stdinr'   evalclearra   ru   Zstress)rv   ZusageZDBrx   cmdargsrk   rz   Zcontdatarq   vr
   r
   r   main6  s<    
 


r   __main__)rh   Z
__future__r   __version__Zpathlibr   ImportErrorZpathlib2r   r!   r_   Zcollections.abcabcZcollections_abccollectionsZcPickler%   r   rx   version_infor   r   Zunicoder   objectr;   MutableMappingr   rb   r   re   r
   r
   r
   r   <module>"   s8    Z'
