o
    ȷe&                     @   s*  d Z ddlmZ dZzddlmZ W n ey!   ddlmZ Y nw ddlZddl	Z	ddl
Z
zddlmZ W n eyC   ddlZY nw zddlZW n eyW   ddlZY nw ddlZddlZejd dkrke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re  dS 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
   B/var/www/ideatree/venv/lib/python3.10/site-packages/pickleshare.pygethashfile@      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@z	| jj
dd W n ty? } z|jtjkr5 W Y d}~nd}~ww 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errnoEEXISTcache)selfr   er
   r
   r   __init__G   s   



zPickleShareDB.__init__c                 C   s   | j | }z	| tj }W n ty   t|w || jv r/|| j| d kr/| j| d S z|d}t|	 }W d   n1 sGw   Y  W n   t|||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   n1 s,w   Y  z|| jf| j	|< W dS  t
yX } z|jtjkrM W Y d}~dS d}~ww )z db['key'] = 5 Tr   wb   )protocolN)r   parentr   r   r'   r(   dumpr$   st_mtimer   r   r   ENOENT)r   r	   valuer+   r3   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	   r7   hroothfiledr
   r
   r   hset}   s   
zPickleShareDB.hsetTc                 C   sX   | j | }|t| }| |t}|tu r&|r!|tu rt||S | |}|||S )z hashed get )r   r   r9   	_sentinelr&   hdict)r   r;   r	   default	fast_onlyr<   r=   r>   r
   r
   r   hget   s   

zPickleShareDB.hgetc              	   C   s   |  |d }|  t|r|d pd}|dr#|g|dd  }i }|D ]#}z	|| |  W n tyD   td|d | |= Y nw | | q'|S )z> Get all data contained in hashed category 'hashroot' as dict /* xxNCorruptz!deleted - hset is not threadsafe!)keyssortlenendswithr:   r&   printuncache)r   r;   hfileslastallr-   r
   r
   r   rA      s   

zPickleShareDB.hdictc                 C   sl   |  |d }i }|D ]}|| |  | | q|| |d < |D ]}| j| }|jdkr/q"|  q"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).

        rE   z/xxrH   N)rJ   r:   rO   r   nameunlink)r   r;   rP   rR   r-   pr
   r
   r   	hcompress   s   


zPickleShareDB.hcompressc                 C   s<   | j | }| j|d z|  W dS  ty   Y dS w )z del db["key"] N)r   r   poprT   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   relative_tor   replace)r   rU   r
   r
   r   _normalized   s   zPickleShareDB._normalizedNc                    s4   |du 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_filer]   ).0rU   r   r
   r   
<listcomp>   s    z&PickleShareDB.keys.<locals>.<listcomp>)r   rglobglob)r   globpatfilesr
   ra   r   rJ      s   zPickleShareDB.keysc                 C      t |  S N)iterrJ   ra   r
   r
   r   __iter__      zPickleShareDB.__iter__c                 C   rg   rh   )rL   rJ   ra   r
   r
   r   __len__   rk   zPickleShareDB.__len__c                 G   s&   |si | _ |D ]	}| j |d q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   rW   )r   itemsitr
   r
   r   rO      s
   zPickleShareDB.uncache<   c                 C   s   dgd dgd  dg }d}d}	 z| | }|W S  t y"   Y nw ||kr+t |t||  ||| 7 }|t|d k rD|d7 }q)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      ?r1   r"   r   )r&   timesleeprL   )r   r	   maxwaittimewtimestrieswaitedvalr
   r
   r   waitget   s"   zPickleShareDB.waitgetc                 C   s
   t | |S )z, Get a convenient link for accessing items  )PickleShareLink)r   folderr
   r
   r   getlink  s   
zPickleShareDB.getlinkc                 C   s
   d| j  S )NzPickleShareDB('%s'))r   ra   r
   r
   r   __repr__  s   
zPickleShareDB.__repr__rh   )ro   )__name__
__module____qualname____doc__r!   r/   r8   r?   r@   rD   rA   rV   rX   r]   rJ   rj   rl   rO   rw   rz   r{   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 )rx   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 rh   )__dict__r:   locals)r   dbkeydirr
   r
   r   r!   (  s   zPickleShareLink.__init__c                 C   s   | j d | j d d |  S )Nr   r   rZ   )r   )r   r	   r
   r
   r   __getattr__+  r   zPickleShareLink.__getattr__c                 C   s   || j | jd | < d S )NrZ   )r   r   )r   r	   rv   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 )Nr   r   rE   z<PickleShareLink '%s': %s>;c                 S   s   g | ]}t | qS r
   )r   basename)r`   kr
   r
   r   rb   4  s    z,PickleShareLink.__repr__.<locals>.<listcomp>)r   rJ   join)r   r   rJ   r
   r
   r   r{   /  s   
zPickleShareLink.__repr__N)r|   r}   r~   r   r!   r   r   r{   r
   r
   r
   r   rx     s    	rx   c                  C   s  dd l } | d}t}dd l}t|jdk rt| d S |jd }|jdd  }|dkrD|s1dg}||d }dd l}||  d S |dkrj|j	
 }||d }t|}	|  | D ]\}
}|||
< q_d S |dkr||d }|  t|d	 d S |d
krt  t  d S 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
    r1   r"   r4   .loadtestwait250test)textwrapdedentr   sysrL   argvrN   pprintrm   stdinr*   evalclearrw   r   stress)r   usageDBr   cmdargsr   r   contdatar   vr
   r
   r   main6  s<   
	




r   __main__)r   
__future__r   __version__pathlibr   ImportErrorpathlib2r   r$   rp   collections.abcabccollections_abccollectionscPickler(   r   r   version_infor   r   unicoder   objectr@   MutableMappingr   rx   r   r|   r
   r
   r
   r   <module>   sB   ! Z'
