
    *i?                       S r SSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
Jr  SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrS r " S S\5      rSr\" S5      r\" S5      rSrS	rS
rSrSr SSSSSS	SSSS	S\RB                  S.r"SSSSS.r#SSSS.SSSS.SSSS.SSSS.S.r$ " S  S!5      r% " S" S#\%5      r& " S$ S%\'5      r( " S& S'\)5      r* " S( S)\)5      r+S* r, " S+ S,5      r-g)-z%Core disk and file backed cache API.
    Nc                 :    U R                   S-   U R                  -   $ )zBReturn full name of `func` by adding the module and function name..)
__module____qualname__)funcs    L/var/www/html/ai-backend/venv/lib/python3.13/site-packages/diskcache/core.py	full_namer	      s    ??S 4#4#444    c                   $    \ rS rSrSrS rS rSrg)Constant   z%Pretty display of immutable constant.c                 .    [         R                  X45      $ N)tuple__new__)clsnames     r   r   Constant.__new__   s    }}S'**r
   c                     SU S   -  $ )Nz%sr    selfs    r   __repr__Constant.__repr__"   s    d1g~r
   r   N)__name__r   r   __firstlineno____doc__r   r   __static_attributes__r   r
   r   r   r      s    /+r
   r   zcache.dbENOVALUNKNOWN            least-recently-storedi   @
   i    wali   i   )
statistics	tag_indexeviction_policy
size_limit
cull_limitsqlite_auto_vacuumsqlite_cache_sizesqlite_journal_modesqlite_mmap_sizesqlite_synchronousdisk_min_file_sizedisk_pickle_protocol)countsizehitsmisses)initgetcullzACREATE INDEX IF NOT EXISTS Cache_store_time ON Cache (store_time)z6SELECT {fields} FROM Cache ORDER BY store_time LIMIT ?zCCREATE INDEX IF NOT EXISTS Cache_access_time ON Cache (access_time)zaccess_time = {now}z7SELECT {fields} FROM Cache ORDER BY access_time LIMIT ?zECREATE INDEX IF NOT EXISTS Cache_access_count ON Cache (access_count)zaccess_count = access_count + 1z8SELECT {fields} FROM Cache ORDER BY access_count LIMIT ?)noner%   zleast-recently-usedzleast-frequently-usedc                   d    \ rS rSrSrSS jrS rS rS r\	4S jr
SS	 jrS
 r\	\	4S jrS rSrg)Diskg   z@Cache key and value serialization for SQLite database and files.c                 (    Xl         X l        X0l        g)zInitialize disk instance.

:param str directory: directory path
:param int min_file_size: minimum size for file use
:param int pickle_protocol: pickle protocol for serialization

N
_directorymin_file_sizepickle_protocol)r   	directoryrB   rC   s       r   __init__Disk.__init__j   s     $*.r
   c                    SnU R                  U5      u  p4[        U5      nU[        R                  L a  [        R
                  " U5      U-  $ U[        L a(  [        R
                  " UR                  S5      5      U-  $ U[        L a  X2-  $ U[        L d   e[        R
                  " [        R                  " SU5      5      U-  $ )zOCompute portable hash for `key`.

:param key: key to hash
:return: hash value

l    utf-8z!d)puttypesqlite3Binaryzlibadler32strencodeintfloatstructpack)r   keymaskdisk_key_type_disk_keys         r   hash	Disk.hashv   s     hhsmXGNN*<<)D00c!<< 89D@@c!?" E)))<<D( ;<tCCr
   c                 N   [        U5      nU[        L a  [        R                  " U5      S4$ U[        L d!  U[
        L a  SUs=::  a  S::  d  O  U[        L a  US4$ [        R                  " XR                  S9n[        R                  " U5      n[        R                  " U5      S4$ )z|Convert `key` to fields key and raw for Cache table.

:param key: key to convert
:return: (database key, raw boolean) pair

T             protocolF)rJ   bytesrK   rL   rO   rQ   rR   pickledumpsrC   pickletoolsoptimize)r   rU   type_keydataresults        r   rI   Disk.put   s     9u>>#&,,_C(CF3FFE!9<<.B.BCD ))$/F>>&)500r
   c                     U(       a)  [        U5      [        R                  L a  [        U5      $ U$ [        R
                  " [        R                  " U5      5      $ )zConvert fields `key` and `raw` from Cache table to key.

:param key: database key to convert
:param bool raw: flag indicating raw database storage
:return: corresponding Python key

)rJ   rK   rL   ra   rb   loadioBytesIO)r   rU   raws      r   r9   Disk.get   s<     !%cgnn!<5:E#E;;rzz#//r
   c                 z   [        U5      nU R                  nU[        L a  [        U5      U:  d!  U[        L a  SUs=::  a  S::  d  O  U[
        L a
  S[        SU4$ U[        L az  [        U5      U:  a  S[        S[        R                  " U5      4$ U R                  X15      u  pgU R                  U[        R                  " U5      S5        [        U5      [        US4$ U[        L a[  U R                  X15      u  pgU R                  U[        R                  " U5      SS5        [         R"                  " U5      nU[$        US4$ U(       a\  [&        R(                  " UR*                  S5      n	U R                  X15      u  pg[-        U	S	5      n
U R                  XzS5      nU[        US4$ [.        R0                  " XR2                  S
9n[        U5      U:  a  S[4        S[        R                  " U5      4$ U R                  X15      u  pgU R                  U[        R                  " U5      S5        [        U5      [4        US4$ )a
  Convert `value` to fields size, mode, filename, and value for Cache
table.

:param value: value to convert
:param bool read: True when value is file-like object
:param key: key for item (default UNKNOWN)
:return: (size, mode, filename, value) tuple for Cache table

r]   r^   r   NxbxUTF-8i  @ r
   r_   )rJ   rB   rO   lenrQ   rR   MODE_RAWra   rK   rL   filename_writerl   rm   MODE_BINARYStringIOopgetsize	MODE_TEXTftpartialreaditerrb   rc   rC   MODE_PICKLE)r   valuer   rU   
type_valuerB   rv   	full_pathr5   readeriteratorrh   s               r   store
Disk.store   s    %[
** 33u:#=c!(EH5HHe#he++5 5zM)(D'..*???&*mmC&?#Irzz%'8$?5z;$>>3"&--";HKK	2;;u#5sGD::i(DHd22ZZ

E2F"&--";HFC(H;;yD9Dh44\\%2F2FGF6{]*+tW^^F-CCC&*mmC&?#Irzz&'94@6{K4??r
   Nc                    [         R                  " U5      u  pV[        SS5       H  n[        R                  " [
        5         [        R                  " U5        S S S 5         [        XUS9nU   Sn	U H"  n
U	[        U
5      -  n	UR                  U
5        M$     U	sS S S 5        s  $    g ! , (       d  f       NV= f! [
         a    US:X  a  e  M  f = f! , (       d  f       M  = f)Nr!      encodingr&   r   )rz   splitrangeclsuppressOSErrorosmakedirsopenrt   write)r   r   r   moder   full_dirrX   r4   writerr5   chunks              r   rw   Disk._write   s    hhy)1b\EW%H% & iA %ECJ&DLL' &   "%%  B;	 s*   B)"
B:.,C)
B7	:CC
C!	c                 v   U[         :X  a)  [        U5      [        R                  L a  [	        U5      $ U$ U[
        :X  aw  U(       a+  [        [        R                  " U R                  U5      S5      $ [        [        R                  " U R                  U5      S5       nUR                  5       sSSS5        $ U[        :X  aF  [        R                  " U R                  U5      n[        USSS9 nUR                  5       sSSS5        $ U[        :X  ax  UcK  [        [        R                  " U R                  U5      S5       n[        R                  " U5      sSSS5        $ [        R                  " [        R                   " U5      5      $ g! , (       d  f       g= f! , (       d  f       g= f! , (       d  f       g= f)a`  Convert fields `mode`, `filename`, and `value` from Cache table to
value.

:param int mode: value mode raw, binary, text, or pickle
:param str filename: filename of corresponding value
:param value: database value
:param bool read: when True, return an open file handle
:return: corresponding Python value
:raises: IOError if the value cannot be read

rbNrrs   r   )ru   rJ   rK   rL   ra   rx   r   rz   joinrA   r   r|   r   rb   rk   rl   rm   )r   r   rv   r   r   r   r   s          r   fetch
Disk.fetch   s2    8#';'..#@5<KeK[ BGGDOOX>EE"''$//8<dCv!;;= DCY:Iiw76{{} 87[ }"''$//8<dCv!;;v. DC {{2::e#455 ! DC 87 DCs$   F+F=F*
F
F'*
F8c                 4   [         R                  " [        R                  " S5      S5      R	                  S5      n[
        R                  " USS USS 5      nUSS S-   n[
        R                  " XE5      n[
        R                  " U R                  U5      nXg4$ )ad  Return filename and full-path tuple for file storage.

Filename will be a randomly generated 28 character hexadecimal string
with ".val" suffixed. Two levels of sub-directories will be used to
reduce the size of directories. On older filesystems, lookups in
directories with many files may be slow.

The default implementation ignores the `key` and `value` parameters.

In some scenarios, for example :meth:`Cache.push
<diskcache.Cache.push>`, the `key` or `value` may not be known when the
item is stored in the cache.

:param key: key for item (default UNKNOWN)
:param value: value for item (default UNKNOWN)

   hexrH   Nr"   r$   z.val)codecsrP   r   urandomdecoderz   r   rA   )r   rU   r   hex_namesub_dirr   rv   r   s           r   rv   Disk.filename  s~    & ==B7>>wG''(2A,16|f$777)GGDOOX6	""r
   c                    [         R                  " U R                  U5      n[         R                  " U5      u  p4[        R
                  " [        5         [        R                  " U5        SSS5        [        R
                  " [        5         [        R                  " U5        SSS5        g! , (       d  f       NH= f! , (       d  f       g= f)zRemove a file given by `file_path`.

This method is cross-thread and cross-process safe. If an OSError
occurs, it is suppressed.

:param str file_path: relative path to file

N)
rz   r   rA   r   r   r   r   r   remove
removedirs)r   	file_pathr   r   rX   s        r   r   Disk.remove8  s{     GGDOOY7	hhy)
 [[!IIi  " [[!MM(# "! "! "!s   B-B>-
B;>
Cr@   )r   r   r   )r   r   r   r   r   rE   rZ   rI   r9   r    r   rw   r   rv   r   r   r   r
   r   r=   r=   g   sB    J
/D*140 &- 1@f06@ #' #4$r
   r=   c                   f   ^  \ rS rSrSrS	U 4S jjrU 4S jrU 4S jr\4U 4S jjr	U 4S jr
SrU =r$ )
JSONDiskiN  zCCache key and value using JSON serialization with zlib compression.c                 4   > X l         [        TU ]  " U40 UD6  g)a  Initialize JSON disk instance.

Keys and values are compressed using the zlib library. The
`compress_level` is an integer from 0 to 9 controlling the level of
compression; 1 is fastest and produces the least compression, 9 is
slowest and produces the most compression, and 0 is no compression.

:param str directory: directory path
:param int compress_level: zlib compression level (default 1)
:param kwargs: super class arguments

N)compress_levelsuperrE   )r   rD   r   kwargs	__class__s       r   rE   JSONDisk.__init__Q  s     --f-r
   c                    > [         R                  " U5      R                  S5      n[        R                  " X R
                  5      n[        TU ]  U5      $ NrH   )jsonrc   rP   rM   compressr   r   rI   )r   rU   
json_bytesrg   r   s       r   rI   JSONDisk.puta  s>    ZZ_++G4
}}Z)<)<=w{4  r
   c                    > [         TU ]  X5      n[        R                  " [        R
                  " U5      R                  S5      5      $ r   )r   r9   r   loadsrM   
decompressr   )r   rU   rn   rg   r   s       r   r9   JSONDisk.getf  s4    w{3$zz$//$/66w?@@r
   c                    > U(       dE  [         R                  " U5      R                  S5      n[        R                  " X@R
                  5      n[        TU ]  XUS9$ )NrH   rU   )r   rc   rP   rM   r   r   r   r   )r   r   r   rU   r   r   s        r   r   JSONDisk.storej  sF    E*11':JMM*.A.ABEw}Uc}22r
   c                    > [         TU ]  XX45      nU(       d9  [        R                  " [        R
                  " U5      R                  S5      5      nU$ r   )r   r   r   r   rM   r   r   )r   r   rv   r   r   rg   r   s         r   r   JSONDisk.fetchp  s=    w}TU9::dood3::7CDDr
   )r   )r!   )r   r   r   r   r   rE   rI   r9   r    r   r   r   __classcell__)r   s   @r   r   r   N  s*    M. !
A &- 3 r
   r   c                       \ rS rSrSrSrg)Timeoutiw  zDatabase timeout expired.r   Nr   r   r   r   r   r   r   r
   r   r   r   w  s    #r
   r   c                       \ rS rSrSrSrg)UnknownFileWarningi{  z.Warning used by Cache.check for unknown files.r   Nr   r   r
   r   r   r   {  s    8r
   r   c                       \ rS rSrSrSrg)EmptyDirWarningi  z2Warning used by Cache.check for empty directories.r   Nr   r   r
   r   r   r     s    <r
   r   c                   ^ [        U4S j[        U5       5       5      nX-   S-   nU(       aS  UR                  5        VVs0 s H  u  pVUT;  d  M  XV_M     nnn[        UR                  5       5      nU H  nWU-  nM
     U(       a1  W[        S U 5       5      -  nU(       a  U[        S W 5       5      -  nW$ s  snnf )a!  Create cache key out of function arguments.

:param tuple base: base of key
:param tuple args: function arguments
:param dict kwargs: function keyword arguments
:param bool typed: include types in cache key
:param set ignore: positional or keyword args to ignore
:return: cache key tuple

c              3   <   >#    U  H  u  pUT;  d  M  Uv   M     g 7fr   r   ).0indexargignores      r   	<genexpr>args_to_key.<locals>.<genexpr>  s     N%v:Ms   	r   c              3   8   #    U  H  n[        U5      v   M     g 7fr   rJ   )r   r   s     r   r   r     s     /$3T#YY$s   c              3   <   #    U  H  u  p[        U5      v   M     g 7fr   r   )r   rX   r   s      r   r   r     s     B\e\s   )r   	enumerateitemssorted)	baseargsr   typedr   rU   valsorted_itemsitems	       `    r   args_to_keyr     s     NyNND
+
C+1<<>O>xsS=N(#(>Oflln- D4KC ! u/$///5B\BBBCJ Ps   B;B;c                   t   \ rS rSrSrSS\4S jr\S 5       r\S 5       r	\S 5       r
\S	 5       r\S
 5       r\S 5       r\R                  S:S j5       r\R                  S;S j5       rS<S jrS rS rS rS=S jrS>S jrS<S jrS?S jrS?S jr     S@S jrS rS:S jrS r SAS jrSBS jr S:S jr!      SCS jr"      SDS  jr#      SDS! jr$SES" jr% SFS# jr&SGS$ jr'S% r(S& r)S:S' jr*S>S( jr+S:S) jr,S:S* jr- SHS+ jr.S:S, jr/SBS- jr0S. r1S/ r2SIS0 jr3S1 r4S2 r5S3 r6S4 r7S5 r8S6 r9S7 r:\;S4S8 jr<S9r=g)JCachei  zDisk and file backed cache.N<   c                     [        U[        5      (       d   e Uc  [
        R                  " SS9n[        U5      n[        R                  " U5      n[        R                  " U5      nXl        SU l        [        R                  " 5       U l        SU l        [        R"                  " U5      (       d   [$        R&                  " US5        U R0                  n [3        U" S5      R5                  5       5      n[:        R=                  5       nUR?                  U5        UR?                  U5        [@         H  n	URC                  U	S5        M     [E        URG                  5       5       H-  u  pU	RI                  S	5      (       d  M  U RK                  XS
S9  M/     U" S5        URG                  5        V	V
s0 s H#  u  pU	RI                  S5      (       d  M  U	SS U
_M%     nn	n
U" U40 UD6U l&        URG                  5        H"  u  pSnU" XU
45        U RK                  X5        M$     [@        RG                  5        H"  u  pSnU" XU
45        U RK                  U	5        M$     U" S5      R5                  5       u  u  U l'        U" S5        U" S5        U" S5        [P        U RR                     S   nUb  U" U5        U" S5        U" S5        U" S5        U" S5        U" S5        U RT                  (       a  U RW                  5         OU RY                  5         U R[                  5         X l        U R\                    g! [        [        4 a    [	        S5      Sef = f! [(         aM  nUR*                  [*        R,                  :w  a$  [/        UR*                  SU R                  -  5      Se SnAGNSnAff = f! [6        R8                   a    0 n GNf = fs  sn
n	f )zInitialize cache instance.

:param str directory: cache directory
:param float timeout: SQLite connection timeout
:param disk: Disk type or subclass for serialization
:param settings: any of DEFAULT_SETTINGS

z!disk must subclass diskcache.DiskNz
diskcache-)prefixr   i  z<Cache directory "%s" does not exist and could not be createdSELECT key, value FROM Settingssqlite_FupdatezFCREATE TABLE IF NOT EXISTS Settings ( key TEXT NOT NULL UNIQUE, value)disk_   z-INSERT OR REPLACE INTO Settings VALUES (?, ?)z,INSERT OR IGNORE INTO Settings VALUES (?, ?)zPRAGMA page_sizezCREATE TABLE IF NOT EXISTS Cache ( rowid INTEGER PRIMARY KEY, key BLOB, raw INTEGER, store_time REAL, expire_time REAL, access_time REAL, access_count INTEGER DEFAULT 0, tag BLOB, size INTEGER DEFAULT 0, mode INTEGER DEFAULT 0, filename TEXT, value BLOB)zBCREATE UNIQUE INDEX IF NOT EXISTS Cache_key_raw ON Cache(key, raw)zCCREATE INDEX IF NOT EXISTS Cache_expire_time ON Cache (expire_time)r8   zCREATE TRIGGER IF NOT EXISTS Settings_count_insert AFTER INSERT ON Cache FOR EACH ROW BEGIN UPDATE Settings SET value = value + 1 WHERE key = "count"; ENDzCREATE TRIGGER IF NOT EXISTS Settings_count_delete AFTER DELETE ON Cache FOR EACH ROW BEGIN UPDATE Settings SET value = value - 1 WHERE key = "count"; ENDzCREATE TRIGGER IF NOT EXISTS Settings_size_insert AFTER INSERT ON Cache FOR EACH ROW BEGIN UPDATE Settings SET value = value + NEW.size WHERE key = "size"; ENDzCREATE TRIGGER IF NOT EXISTS Settings_size_update AFTER UPDATE ON Cache FOR EACH ROW BEGIN UPDATE Settings SET value = value + NEW.size - OLD.size WHERE key = "size"; ENDzCREATE TRIGGER IF NOT EXISTS Settings_size_delete AFTER DELETE ON Cache FOR EACH ROW BEGIN UPDATE Settings SET value = value - OLD.size WHERE key = "size"; END)/
issubclassr=   	TypeErrorAssertionError
ValueErrortempfilemkdtemprO   rz   
expanduser
expandvarsrA   _timeout	threadinglocal_local_txn_idisdirr   r   r   errnoEEXISTEnvironmentError
_sql_retrydictfetchallrK   OperationalErrorDEFAULT_SETTINGScopyr   METADATApopr   r   
startswithreset_disk
_page_sizeEVICTION_POLICYr*   r)   create_tag_indexdrop_tag_indexclose_sql)r   rD   timeoutdisksettingserrorsqlcurrent_settingssetsrU   r   r   querys                r   rE   Cache.__init__  s   	LdD))))  ((=I	N	MM),	MM),	#oo'xx	"" Iu- oo	"#56??A   $$&$%HCHHS$ 
 !.JC~~i((

3e
4 / 		
 #jjl
*
~~g& CGUN* 	 

 ).v.
 **,JCCEU|$JJs" '
 #..*JCBEU|$JJsO +
 !$$6 7 @ @ B	$/ 		
  		

 	#	

   4 45f=J 	(	
 	(	
 	'	
 	'	
 	'	
 >>!!#! 	

		A >* 	L@AtK	L"   ;;%,,.*46:ooF  	  /   '' 	"!	"0
sB   L/ 2M N) /O
O/M
N&AN!!N&)OOc                     U R                   $ )zCache directory.)rA   r   s    r   rD   Cache.directoryQ  s     r
   c                     U R                   $ )z+SQLite connection timeout value in seconds.)r   r   s    r   r  Cache.timeoutV  s     }}r
   c                     U R                   $ )zDisk used for serialization.)r	  r   s    r   r  
Cache.disk[  s     zzr
   c                 f   [        U R                  SS 5      n[        R                  " 5       nX:w  a   U R	                  5         X R                  l        [        U R                  SS 5      nUc  [        R                  " [        R                  " U R                  [        5      U R                  S S9=o0R                  l         SnUR                  U5      R                  5       nU H-  u  pgUR!                  S5      (       d  M  U R#                  XgSS9  M/     U$ U$ ! [        R$                   a     U$ f = f)Npidcon)r  isolation_levelr   r   Fr   )getattrr   r   getpidr  r   rK   connectrz   r   rA   DBNAMEr   r!  executer  r  r  r  )r   	local_pidr   r!  selectr  rU   r   s           r   _con
Cache._con`  s    
 DKK5	iikJJL!KKOdkk5$/;$+OO0 $% C++/=:;;v.779 #+JC~~i00

3e
< #+ 
s
 ++  
s    !D D0/D0c                 .    U R                   R                  $ r   )r*  r'  r   s    r   r  
Cache._sql  s    yy   r
   c                 ,   ^ U R                   mU4S jnU$ )Nc                   > [         R                   " 5       n  T" U /UQ70 UD6$ ! [        R                   aO  n[        U5      S:w  a  e [         R                   " 5       U-
  nUS:  a  e [         R                  " S5         S nAOS nAff = fMu  )Ndatabase is lockedr   MbP?)timerK   r  rO   sleep)	statementr   r   startexcdiffr  s         r   _execute_with_retry-Cache._sql_retry.<locals>._execute_with_retry  s    IIKE&y:4:6::// &3x#7799;.DbyJJu%%& s   % BABBr  )r   r8  r  s     @r   r   Cache._sql_retry  s    ii	& #"r
   c              #   f   #    U R                  US9   Sv   SSS5        g! , (       d  f       g= f7f)a  Context manager to perform a transaction by locking the cache.

While the cache is locked, no other write operation is permitted.
Transactions should therefore be as short as possible. Read and write
operations performed in a transaction are atomic. Read operations may
occur concurrent to a transaction.

Transactions may be nested and may not be shared between threads.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

>>> cache = Cache()
>>> with cache.transact():  # Atomically increment two keys.
...     _ = cache.incr('total', 123.4)
...     _ = cache.incr('count', 1)
>>> with cache.transact():  # Atomically calculate average.
...     average = cache['total'] / cache['count']
>>> average
123.4

:param bool retry: retry if database timeout occurs (default False)
:return: context manager for use in `with` statement
:raises Timeout: if database timeout occurs

retryN)	_transact)r   r>  s     r   transactCache.transact  s#     8 ^^%^( )((s   1 	1
.1c              #   >  #    U R                   n/ nU R                  R                  n[        R                  " 5       nU R
                  nXg:X  a  SnO  U" S5        SnX`l          X4R                  4v   U(       a!  U R
                  U:X  d   eS U l        U" S5        U H  n	U	c  M  U" U	5        M     g ! [        R                   a    U(       a   M  Ub  U" U5        [        S ef = f! [         a*    U(       a!  U R
                  U:X  d   eS U l        U" S5        e f = f7f)NFTzBEGIN IMMEDIATECOMMITROLLBACK)r  r	  r   r   	get_identr   rK   r  r   appendBaseException)
r   r>  rv   r  	filenames_disk_removetidtxn_idbeginr   s
             r   r?  Cache._transact  s    ii	zz((!!#=E
,)* E#&L	''''' ||s***#H!# & ") // , +$X.!t+,  	||s***#J	sH   ADB2 "D$C& 3.D%D2C#DC##D&4DDc                    [         R                   " 5       nU R                  R                  U5      u  pUc  SOXs-   n
U R                  R                  X$US9u  ppXXX4nU R	                  Xm5       u  nnU" SX45      R                  5       nU(       a"  Uu  u  nnU" U5        U R                  UX5        OU R                  XX5        U R                  UUU5         SSS5        g! , (       d  f       g= f)ao  Set `key` and `value` item in cache.

When `read` is `True`, `value` should be a file-like object opened
for reading in binary mode.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key for item
:param value: value for item
:param float expire: seconds until item expires
    (default None, no expiry)
:param bool read: read value as bytes from file (default False)
:param str tag: text to associate with key (default None)
:param bool retry: retry if database timeout occurs (default False)
:return: True if item was set
:raises Timeout: if database timeout occurs

Nr   z;SELECT rowid, filename FROM Cache WHERE key = ? AND raw = ?T	r2  r	  rI   r   r?  r  _row_update_row_insert_cull)r   rU   r   expirer   tagr>  nowdb_keyrn   expire_timer5   r   rv   db_valuecolumnsr  cleanuprowsrowidold_filenames                        r   set	Cache.set  s    ( iikjjnnS)$nd#,)-)9)9%3)9)O&HTD. ^^E,g- hj	  +/(&%%  5  c;JJsC)! -,,s   /A+C##
C1c                 $    U R                  XSS9  g)zSet corresponding `value` for `key` in cache.

:param key: key for item
:param value: value for item
:return: corresponding value
:raises KeyError: if key is not found

Tr=  N)r^  r   rU   r   s      r   __setitem__Cache.__setitem__.  s     	4(r
   c                 N    U R                   nUu  pVpxpU" SUUUSUUUU	U
U4
5        g )NzUPDATE Cache SET store_time = ?, expire_time = ?, access_time = ?, access_count = ?, tag = ?, size = ?, mode = ?, filename = ?, value = ? WHERE rowid = ?r   r:  )r   r\  rU  rY  r  rW  rT  r5   r   rv   r   s              r   rP  Cache._row_update9  sI    ii8?5$h
 	
r
   c                 P    U R                   nUu  pgppU" SUUUUUSUUU	U
U45        g )NzINSERT INTO Cache( key, raw, store_time, expire_time, access_time, access_count, tag, size, mode, filename, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)r   r:  )r   rU   rn   rU  rY  r  rW  rT  r5   r   rv   r   s               r   rQ  Cache._row_insertV  sL    ii8?5$h9
 	
r
   c                     Uc  U R                   OUnUS:X  a  g SnUS-  nU" XqU45      R                  5       nU(       a:  SUS-  -  n	U" XU45        U H  u  n
U" U
5        M     U[        U5      -  nUS:X  a  g [        U R                     S   nUb  U R                  5       U R                  :  a  g UR                  SUS9nU" X45      R                  5       nU(       a0  SUR                  SUS9-  nU" X45        U H  u  n
U" U
5        M     g g )Nr   zcSELECT %s FROM Cache WHERE expire_time IS NOT NULL AND expire_time < ? ORDER BY expire_time LIMIT ?rv   %DELETE FROM Cache WHERE rowid IN (%s)r\  r:   fieldsrU  )r,   r  rt   r  r*   volumer+   format)r   rU  r  rZ  limitr,   select_expired_templateselect_expiredr[  delete_expiredrv   select_policyselect_filenamedeletes                 r   rR  Cache._cullm  s;   (-T__5
?
, 	  1:=>#45>>@D''1N j 12#!  $ #d)#JQ ((<(<=fE DKKMDOO$C'..jc.J?M2;;=<$$G$=F &#!  $ r
   c                 V   [         R                   " 5       nU R                  R                  U5      u  pVUc  SOXB-   nU R                  U5       u  pU" SXV45      R	                  5       n
U
(       a"  U
u  u  pUb  X:  a  U" SX{45         SSS5        gSSS5        g! , (       d  f       g= f)a  Touch `key` in cache and update `expire` time.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key for item
:param float expire: seconds until item expires
    (default None, no expiry)
:param bool retry: retry if database timeout occurs (default False)
:return: True if key was touched
:raises Timeout: if database timeout occurs

Nz>SELECT rowid, expire_time FROM Cache WHERE key = ? AND raw = ?z0UPDATE Cache SET expire_time = ? WHERE rowid = ?TF)r2  r	  rI   r?  r  )r   rU   rS  r>  rU  rV  rn   rW  r  rX   r[  r\  old_expire_times                r   touchCache.touch  s     iikjjnnS)$nd#,^^E"hs- hj	  .2+)%"*o.CJ$,   #""" # #"" s   ;B
B(c                     [         R                   " 5       nU R                  R                  U5      u  pUc  SOXs-   n
U R                  R                  X$US9u  ppXXX4nU R	                  Xm5       u  nnU" SX45      R                  5       nU(       a>  Uu  u  nnnUb  UU:  a  U" U5         SSS5        gU" U5        U R                  UX5        OU R                  XX5        U R                  UUU5         SSS5        g! , (       d  f       g= f)a  Add `key` and `value` item to cache.

Similar to `set`, but only add to cache if key not present.

Operation is atomic. Only one concurrent add operation for a given key
will succeed.

When `read` is `True`, `value` should be a file-like object opened
for reading in binary mode.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key for item
:param value: value for item
:param float expire: seconds until the key expires
    (default None, no expiry)
:param bool read: read value as bytes from file (default False)
:param str tag: text to associate with key (default None)
:param bool retry: retry if database timeout occurs (default False)
:return: True if item was added
:raises Timeout: if database timeout occurs

Nr   zHSELECT rowid, filename, expire_time FROM Cache WHERE key = ? AND raw = ?FTrO  )r   rU   r   rS  r   rT  r>  rU  rV  rn   rW  r5   r   rv   rX  rY  r  rZ  r[  r\  r]  rw  s                         r   add	Cache.add  s	   2 iikjjnnS)$nd#,)-)9)9%3)9)O&HTD^^E,g- hj	  <@97%"*o.CH%  -, %  5  c;JJsC)+ -,,s   /=C?5AC??
Dc                 <   [         R                   " 5       nU R                  R                  U5      u  pgSnU R                  U5       u  pU	" XU45      R	                  5       nU(       d_  Uc  [        U5      eX2-   nSU R                  R                  USUS9-   nU R                  XgX]5        U R                  XYU
5        UsSSS5        $ Uu  u  pnnUbl  X:  ag  Uc  [        U5      eX2-   nSU R                  R                  USUS9-   nU R                  XU5        U R                  XYU
5        U
" U5        UsSSS5        $ X-  nSn[        U R                     S   nUb  USUR                  US	9-   -  nS
U-  nU	" UX\U45        UsSSS5        $ ! , (       d  f       g= f)aD  Increment value by delta for item with key.

If key is missing and default is None then raise KeyError. Else if key
is missing and default is not None then use default for value.

Operation is atomic. All concurrent increment operations will be
counted individually.

Assumes value may be stored in a SQLite column. Most builds that target
machines with 64-bit pointer widths will support 64-bit signed
integers.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key for item
:param int delta: amount to increment (default 1)
:param int default: value if key is missing (default 0)
:param bool retry: retry if database timeout occurs (default False)
:return: new value for item
:raises KeyError: if key is not found and default is None
:raises Timeout: if database timeout occurs

zOSELECT rowid, expire_time, filename, value FROM Cache WHERE key = ? AND raw = ?NNNFr   zstore_time = ?, value = ?r9   z, rU  #UPDATE Cache SET %s WHERE rowid = ?)r2  r	  rI   r?  r  KeyErrorr   rQ  rR  rP  r  r*   rm  )r   rU   deltadefaultr>  rU  rV  rn   r)  r  rZ  r[  r   rY  r\  rW  rv   update_columnr   s                      r   incr
Cache.incr  s   2 iikjjnnS)) 	
 ^^E"nsv}-668D?"3-'&)9)95c *: *    c;

3W- #" 8<42e(E&;+<?"3-'&)9)95c *: *    W5

3W-!9 #"< NE1G+D,@,@A%HM(4-"6"63"6"???:WDFU+,S #""s   A7FA-F>AF
Fc                 (    U R                  X* X45      $ )a  Decrement value by delta for item with key.

If key is missing and default is None then raise KeyError. Else if key
is missing and default is not None then use default for value.

Operation is atomic. All concurrent decrement operations will be
counted individually.

Unlike Memcached, negative values are supported. Value may be
decremented below zero.

Assumes value may be stored in a SQLite column. Most builds that target
machines with 64-bit pointer widths will support 64-bit signed
integers.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key for item
:param int delta: amount to decrement (default 1)
:param int default: value if key is missing (default 0)
:param bool retry: retry if database timeout occurs (default False)
:return: new value for item
:raises KeyError: if key is not found and default is None
:raises Timeout: if database timeout occurs

)r  )r   rU   r  r  r>  s        r   decr
Cache.decrE  s    8 yyfg55r
   c                    U R                   R                  U5      u  px[        U R                     S   n	Sn
U(       a  U(       a  USS4nOU(       d  U(       a  US4nU R                  (       dj  U	cg  U R                  XU[        R                  " 5       45      R                  5       nU(       d  U$ Uu  u  ppnn U R                   R                  UUUU5      nOSnSnU R                  U5       u  nnU" XU[        R                  " 5       45      R                  5       nU(       d$  U R                  (       a  U" U5        UsSSS5        $ Uu  u  ppnn U R                   R                  UUUU5      nU R                  (       a  U" U5        [        R                  " 5       nSnU	b  U" UU	R                  US9-  U45        SSS5        U(       a  U(       a  WWW4$ U(       a  WW4$ U(       a  WW4$ W$ ! [         a    Us $ f = f! [         a'    U R                  (       a  U" U5        Us sSSS5        $ f = f! , (       d  f       N= f)ay  Retrieve value from cache. If `key` is missing, return `default`.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key for item
:param default: value to return if key is missing (default None)
:param bool read: if True, return file handle to value
    (default False)
:param bool expire_time: if True, return expire_time in tuple
    (default False)
:param bool tag: if True, return tag in tuple (default False)
:param bool retry: retry if database timeout occurs (default False)
:return: value for item or default if key not found
:raises Timeout: if database timeout occurs

r9   SELECT rowid, expire_time, tag, mode, filename, value FROM Cache WHERE key = ? AND raw = ? AND (expire_time IS NULL OR expire_time > ?)Nz8UPDATE Settings SET value = value + 1 WHERE key = "hits"z:UPDATE Settings SET value = value + 1 WHERE key = "misses"r  r  )r	  rI   r  r*   r(   r  r2  r  r   IOErrorr?  rm  )r   rU   r  r   rW  rT  r>  rV  rn   r  r)  r[  r\  db_expire_timedb_tagr   rv   rX  r   	cache_hit
cache_missr  rX   rU  r   s                            r   r9   	Cache.getc  s%   4 jjnnS)'(<(<=eD< 	 3d+GCoG=#8 99Vc499;%?@IIKDKOHFeV8X

((x4H K  M  &(36C#=>GGIJ" '& MUF(H# JJ,,T8XtLE ??	Niik> ,!5!5#!5!>>I7 ': 3>622>**6?"La  4  #J"N% '&# '&sJ   8G/ ,AH5	H5H/AH5/G>=G>%H2&H51H22H55
Ic                 X    U R                  U[        SS9nU[        L a  [        U5      eU$ )zReturn corresponding value for `key` from cache.

:param key: key matching item
:return: corresponding value
:raises KeyError: if key is not found

Tr  r>  r9   r   r  ra  s      r   __getitem__Cache.__getitem__  s.     fD9F?3-r
   c                 Z    U R                  U[        SUS9nU[        L a  [        U5      eU$ )a|  Return file handle value corresponding to `key` from cache.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key matching item
:param bool retry: retry if database timeout occurs (default False)
:return: file open for reading in binary mode
:raises KeyError: if key is not found
:raises Timeout: if database timeout occurs

T)r  r   r>  r  )r   rU   r>  handles       r   r   
Cache.read  s1     #vDFV3-r
   c                     U R                   nU R                  R                  U5      u  p4SnU" XSU[        R                  " 5       45      R	                  5       n[        U5      $ )z{Return `True` if `key` matching item is found in cache.

:param key: key matching item
:return: True if key matching item

z^SELECT rowid FROM Cache WHERE key = ? AND raw = ? AND (expire_time IS NULL OR expire_time > ?))r  r	  rI   r2  r  bool)r   rU   r  rV  rn   r)  r[  s          r   __contains__Cache.__contains__  sW     iijjnnS)< 	 6C56??ADzr
   c                    U R                   R                  U5      u  pgSnU(       a  U(       a  USS4nOU(       d  U(       a  US4nU R                  U5       u  pU	" XU[        R                  " 5       45      R	                  5       nU(       d  UsSSS5        $ Uu  u  ppnnU	" SU45        SSS5         U R                   R                  WWWS5      n Ub  U R                   R                  U5        U(       a  U(       a  UWW4$ U(       a  UW4$ U(       a  UW4$ U$ ! , (       d  f       Nw= f! [         a$    Us Wb  U R                   R                  U5        $ $ f = f! Wb  U R                   R                  U5        f f = f)a  Remove corresponding item for `key` from cache and return value.

If `key` is missing, return `default`.

Operation is atomic. Concurrent operations will be serialized.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key for item
:param default: value to return if key is missing (default None)
:param bool expire_time: if True, return expire_time in tuple
    (default False)
:param bool tag: if True, return tag in tuple (default False)
:param bool retry: retry if database timeout occurs (default False)
:return: value for item or default if key not found
:raises Timeout: if database timeout occurs

r  N!DELETE FROM Cache WHERE rowid = ?F)r	  rI   r?  r2  r  r   r  r   )r   rU   r  rW  rT  r>  rV  rn   r)  r  rX   r[  r\  r  r  r   rv   rX  r   s                      r   r  	Cache.pop  sn   , jjnnS)< 	 3tT)GCtmG^^E"hsvTYY[9:CCED	 #" LPHFeV8X3eX> #	,JJ$$T8XuEE
 #

!!(+3.&00.((&= L5 #"  	N#

!!(+ $		 #

!!(+ $s6   7DD4D- 
D*-E9E EE !E?Tc                 F   U R                   R                  U5      u  p4U R                  U5       u  pVU" SX4[        R                  " 5       45      R	                  5       nU(       d  [        U5      eUu  u  pU" SU45        U" U	5         SSS5        g! , (       d  f       g= f)aH  Delete corresponding item for `key` from cache.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default `True`).

:param key: key matching item
:param bool retry: retry if database timeout occurs (default True)
:raises KeyError: if key is not found
:raises Timeout: if database timeout occurs

zhSELECT rowid, filename FROM Cache WHERE key = ? AND raw = ? AND (expire_time IS NULL OR expire_time > ?)r  NT)r	  rI   r?  r2  r  r  )
r   rU   r>  rV  rn   r  rZ  r[  r\  rv   s
             r   __delitem__Cache.__delitem__8  s     jjnnS)^^E"ns@ diik*	
 hj  sm##' e3eX>H #""s   AB
B c                 B     U R                  XS9$ ! [         a     gf = f)aY  Delete corresponding item for `key` from cache.

Missing keys are ignored.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param key: key matching item
:param bool retry: retry if database timeout occurs (default False)
:return: True if item was deleted
:raises Timeout: if database timeout occurs

r=  F)r  r  )r   rU   r>  s      r   rt  Cache.deleteW  s-    	##C#55 		s    
c                 x   Uc  SnSn	O
US-   nUS-   n	[         R                   " 5       n
SnUc  SOX-   nU R                  R                  X5      u  pnnXXUU4nSSS	.nS
UU   -  nU R                  X5       u  nnU" UXU45      R	                  5       nU(       aF  Uu  u  nUb!  [        UUR                  S5      S-   S 5      nOUnUS:X  a  US-  nOUS:X  d   eUS-  nOSnUb  SR                  UU5      nOUnU R                  UXU5        U R                  U
UU5        UsSSS5        $ ! , (       d  f       g= f)a  Push `value` onto `side` of queue identified by `prefix` in cache.

When prefix is None, integer keys are used. Otherwise, string keys are
used in the format "prefix-integer". Integer starts at 500 trillion.

Defaults to pushing value on back of queue. Set side to 'front' to push
value on front of queue. Side must be one of 'back' or 'front'.

Operation is atomic. Concurrent operations will be serialized.

When `read` is `True`, `value` should be a file-like object opened
for reading in binary mode.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

See also `Cache.pull`.

>>> cache = Cache()
>>> print(cache.push('first value'))
500000000000000
>>> cache.get(500000000000000)
'first value'
>>> print(cache.push('second value'))
500000000000001
>>> print(cache.push('third value', side='front'))
499999999999999
>>> cache.push(1234, prefix='userids')
'userids-500000000000000'

:param value: value for item
:param str prefix: key prefix (default None, key is integer)
:param str side: either 'back' or 'front' (default 'back')
:param float expire: seconds until the key expires
    (default None, no expiry)
:param bool read: read value as bytes from file (default False)
:param str tag: text to associate with key (default None)
:param bool retry: retry if database timeout occurs (default False)
:return: key for item in cache
:raises Timeout: if database timeout occurs

Nr      I5 -000000000000000-999999999999999TDESCASC)backfrontzSSELECT key FROM Cache WHERE ? < key AND key < ? AND raw = ? ORDER BY key %s LIMIT 1-r!   r  r  l    @$ z{0}-{1:015d})
r2  r	  r   r?  r  rQ   rfindrm  rQ  rR  )r   r   r   siderS  r   rT  r>  min_keymax_keyrU  rn   rW  r5   r   rv   rX  rY  orderr)  r  rZ  r[  rU   numrV  s                             r   push
Cache.pushk  sk   h >G%G11G11Giik$nd#,)-)9)9%)F&HhT8D%0' $K	 ^^E,gv#67@@BD 	#%c399S>A#5"89:CC6>1HC7?*?1HC%!'..vs;VSw7JJsC)7 -,,s   6B+D++
D9c                 \   Uc  SnSnO
US-   nUS-   nSSS.n	S	X   -  n
U(       a  U(       a  USS4nOU(       d  U(       a  US4n  U R                  U5       u  pU" XU45      R                  5       nU(       d  UsSSS5        $ Uu  u  pnnnnnU" S
U45        Ub"  U[        R                  " 5       :  a	  U" U5        O
 SSS5        O SSS5        M   U R                  R	                  UUUS5      n Ub  U R                  R                  U5         U(       a  U(       a  UU4UU4$ U(       a  UU4U4$ U(       a  UU4U4$ UU4$ ! , (       d  f       N= f! [
         a&     Uc  GM#  U R                  R                  U5        GMA  f = f! Ub  U R                  R                  U5        f f = f)a  Pull key and value item pair from `side` of queue in cache.

When prefix is None, integer keys are used. Otherwise, string keys are
used in the format "prefix-integer". Integer starts at 500 trillion.

If queue is empty, return default.

Defaults to pulling key and value item pairs from front of queue. Set
side to 'back' to pull from back of queue. Side must be one of 'front'
or 'back'.

Operation is atomic. Concurrent operations will be serialized.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

See also `Cache.push` and `Cache.get`.

>>> cache = Cache()
>>> cache.pull()
(None, None)
>>> for letter in 'abc':
...     print(cache.push(letter))
500000000000000
500000000000001
500000000000002
>>> key, value = cache.pull()
>>> print(key)
500000000000000
>>> value
'a'
>>> _, value = cache.pull(side='back')
>>> value
'c'
>>> cache.push(1234, 'userids')
'userids-500000000000000'
>>> _, value = cache.pull('userids')
>>> value
1234

:param str prefix: key prefix (default None, key is integer)
:param default: value to return if key is missing
    (default (None, None))
:param str side: either 'front' or 'back' (default 'front')
:param bool expire_time: if True, return expire_time in tuple
    (default False)
:param bool tag: if True, return tag in tuple (default False)
:param bool retry: retry if database timeout occurs (default False)
:return: key and value item pair or default if queue is empty
:raises Timeout: if database timeout occurs

Nr   r  r  r  r  r  r  r  SELECT rowid, key, expire_time, tag, mode, filename, value FROM Cache WHERE ? < key AND key < ? AND raw = 1 ORDER BY key %s LIMIT 1r  F)r?  r  r2  r	  r   r  r   r   r   r  r  rW  rT  r>  r  r  r  r)  r  rZ  r[  r\  rU   	db_expirer  r   r   rX  r   s                         r   pull
Cache.pull  s   | >G%G11G11G0' K	 3tT)GCtmG^^E*nsv'9:CCED&	 +* MYdH ;eXF ,TYY[1H +* & + $,

((tXuE
 #JJ%%d+3<F22<**<'':E +*&  #JJ%%d+ #JJ%%d+ $s6   #E;EE 
E
F!F
 FF
 
!F+c                    Uc  SnSnO
US-   nUS-   nSSS.n	S	X   -  n
U(       a  U(       a  USS4nOU(       d  U(       a  US4n  U R                  U5       u  pU" XU45      R                  5       nU(       d  UsSSS5        $ Uu  u  pnnnnnUb,  U[        R                  " 5       :  a  U" S
U45        U" U5        O
 SSS5        O SSS5        M   U R                  R	                  UUUS5      n U(       a  U(       a  UU4UU4$ U(       a  UU4U4$ U(       a  UU4U4$ UU4$ ! , (       d  f       Nc= f! [
         a     GM  f = f)a  Peek at key and value item pair from `side` of queue in cache.

When prefix is None, integer keys are used. Otherwise, string keys are
used in the format "prefix-integer". Integer starts at 500 trillion.

If queue is empty, return default.

Defaults to peeking at key and value item pairs from front of queue.
Set side to 'back' to pull from back of queue. Side must be one of
'front' or 'back'.

Expired items are deleted from cache. Operation is atomic. Concurrent
operations will be serialized.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

See also `Cache.pull` and `Cache.push`.

>>> cache = Cache()
>>> for letter in 'abc':
...     print(cache.push(letter))
500000000000000
500000000000001
500000000000002
>>> key, value = cache.peek()
>>> print(key)
500000000000000
>>> value
'a'
>>> key, value = cache.peek(side='back')
>>> print(key)
500000000000002
>>> value
'c'

:param str prefix: key prefix (default None, key is integer)
:param default: value to return if key is missing
    (default (None, None))
:param str side: either 'front' or 'back' (default 'front')
:param bool expire_time: if True, return expire_time in tuple
    (default False)
:param bool tag: if True, return tag in tuple (default False)
:param bool retry: retry if database timeout occurs (default False)
:return: key and value item pair or default if queue is empty
:raises Timeout: if database timeout occurs

Nr   r  r  r  r  r  r  r  r  F)r?  r  r2  r	  r   r  r  s                         r   peek
Cache.peekF  s   t >G%G11G11G0' K	 3tT)GCtmG^^E*nsv'9:CCED&	 +* MYdH !,TYY[1H?%J +* & + "

((tXuE 3<F22<**<'':= +*$  s$   #D';D'D8 '
D58
EEc           	      R   SnSXQ   -  n  U R                  U5       u  pxU" U5      R                  5       n	U	(       d  [        S5      eU	u  u  n
nnnnnnnUb,  U[        R                  " 5       :  a  U" SU
45        U" U5        O
 SSS5        O SSS5        M  U R                  R                  X5      n U R                  R                  UUUS5      n U(       a  U(       a  UU4X4$ U(       a  UU4U4$ U(       a  UU4U4$ UU4$ ! , (       d  f       N}= f! [         a     GM  f = f)a*  Peek at key and value item pair in cache based on iteration order.

Expired items are deleted from cache. Operation is atomic. Concurrent
operations will be serialized.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

>>> cache = Cache()
>>> for num, letter in enumerate('abc'):
...     cache[letter] = num
>>> cache.peekitem()
('c', 2)
>>> cache.peekitem(last=False)
('a', 0)

:param bool last: last item in iteration order (default True)
:param bool expire_time: if True, return expire_time in tuple
    (default False)
:param bool tag: if True, return tag in tuple (default False)
:param bool retry: retry if database timeout occurs (default False)
:return: key and value item pair
:raises KeyError: if cache is empty
:raises Timeout: if database timeout occurs

)r  r  zdSELECT rowid, key, raw, expire_time, tag, mode, filename, value FROM Cache ORDER BY rowid %s LIMIT 1zdictionary is emptyNr  F)r?  r  r  r2  r	  r9   r   r  )r   lastrW  rT  r>  r  r)  r  rZ  r[  r\  rV  rn   r  r  r   r   rX  rU   r   s                       r   peekitemCache.peekitem  sT   6  4K
 ^^E*nsv;//1D&'<== 	!"%"  $ !,TYY[1H?%J/ +** &+ + 4 **..-C

((tXuE 3<22<**<'':S +*:  s   A(D5D 
D
D&%D&c                 ^   ^ ^^^^^ [        T5      (       a  [        S5      eUUUU UU4S jnU$ )a   Memoizing cache decorator.

Decorator to wrap callable with memoizing function using cache.
Repeated calls with the same arguments will lookup result in cache and
avoid function evaluation.

If name is set to None (default), the callable name will be determined
automatically.

When expire is set to zero, function results will not be set in the
cache. Cache lookups still occur, however. Read
:doc:`case-study-landing-page-caching` for example usage.

If typed is set to True, function arguments of different types will be
cached separately. For example, f(3) and f(3.0) will be treated as
distinct calls with distinct results.

The original underlying function is accessible through the __wrapped__
attribute. This is useful for introspection, for bypassing the cache,
or for rewrapping the function with a different cache.

>>> from diskcache import Cache
>>> cache = Cache()
>>> @cache.memoize(expire=1, tag='fib')
... def fibonacci(number):
...     if number == 0:
...         return 0
...     elif number == 1:
...         return 1
...     else:
...         return fibonacci(number - 1) + fibonacci(number - 2)
>>> print(fibonacci(100))
354224848179261915075

An additional `__cache_key__` attribute can be used to generate the
cache key used for the given arguments.

>>> key = fibonacci.__cache_key__(100)
>>> print(cache[key])
354224848179261915075

Remember to call memoize when decorating a callable. If you forget,
then a TypeError will occur. Note the lack of parenthenses after
memoize below:

>>> @cache.memoize
... def test():
...     pass
Traceback (most recent call last):
    ...
TypeError: name cannot be callable

:param cache: cache to store callable arguments and return values
:param str name: name given for callable (default None, automatic)
:param bool typed: cache different types separately (default False)
:param float expire: seconds until arguments expire
    (default None, no expiry)
:param str tag: text to associate with arguments (default None)
:param set ignore: positional or keyword args to ignore (default ())
:return: callable decorator

zname cannot be callablec                    >^ ^^ Tc  [        T 5      4OT4m[        R                  " T 5      UU UUU4S j5       mUUU	4S jnUTl        T$ )z3Decorator created by memoize() for callable `func`.c                     > TR                   " U 0 UD6nTR                  U[        SS9nU[        L a#  T" U 0 UD6nTb  TS:  a  TR                  X#TTSS9  U$ )z:Wrapper for callable to cache arguments and return values.Tr  r   )rT  r>  )__cache_key__r9   r   r^  )	r   r   rU   rh   rS  r   r   rT  wrappers	       r   r  1Cache.memoize.<locals>.decorator.<locals>.wrapperL  si     ++T<V<#vTBV#!4262F~!f#TJr
   c                      > [        TXTT5      $ )z,Make key for cache given function arguments.)r   )r   r   r   r   r   s     r   r  7Cache.memoize.<locals>.decorator.<locals>.__cache_key__Y  s    "4ufEEr
   )r	   r}   wrapsr  )
r   r  r   r  rS  r   r   r   rT  r   s
   ` @@r   	decorator Cache.memoize.<locals>.decoratorH  sK    )-IdO%D7DXXd^
 
 
F %2G!Nr
   )callabler   )r   r   r   rS  rT  r   r  s   `````` r   memoizeCache.memoize  s-    D D>>566	 	0 r
   c           
         [         R                  " SS9 nU R                  nU" S5      R                  5       n[	        U5      S:w  d  US   S   S:w  a!  U H  u  n[         R
                  " U5        M     U(       a  U" S5        U R                  U5       u  pG[        5       nSn	U" U	5      R                  5       nU H  u  pn[        R                  " U R                  U5      nUR                  U5        [        R                  " U5      (       aL  [        R                  " U5      nX:w  a/  S	nXU4n[         R
                  " Xo-  5        U(       a
  U" S
X45        M  [         R
                  " SU-  5        U(       d  M  U" SU
45        M     [        R                  " U R                  5       H  u  nnnU Vs/ s H  n[        R                  " UU5      PM     nn[        U5      U-
  nU HN  n[         U;   a  M  SU-  n[         R
                  " U["        5        U(       d  M8  [        R$                  " U5        MP     M     [        R                  " U R                  5       HX  u  nnnU(       a  M  U(       a  M  SU-  n[         R
                  " U[&        5        U(       d  MB  [        R(                  " U5        MZ     U R+                  S5        U" S5      R                  5       u  u  nU R,                  U:w  a8  Sn[         R
                  " X`R,                  U4-  5        U(       a  U" SUS45        U R+                  S5        SnU" U5      R                  5       u  u  nU R.                  U:w  a8  Sn[         R
                  " X`R.                  U4-  5        U(       a  U" SUS45        SSS5        UsSSS5        $ s  snf ! , (       d  f       N= f! , (       d  f       g= f)a  Check database and file system consistency.

Intended for use in testing and post-mortem error analysis.

While checking the Cache table for consistency, a writer lock is held
on the database. The lock blocks other cache clients from writing to
the database. For caches with many file references, the lock may be
held for a long time. For example, local benchmarking shows that a
cache with 1,000 file references takes ~60ms to check.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param bool fix: correct inconsistencies
:param bool retry: retry if database timeout occurs (default False)
:return: list of warnings
:raises Timeout: if database timeout occurs

T)recordzPRAGMA integrity_checkr!   r   okVACUUMzBSELECT rowid, size, filename FROM Cache WHERE filename IS NOT NULLzwrong file size: %s, %d != %dz)UPDATE Cache SET size = ? WHERE rowid = ?zfile not found: %sr  zunknown file: %szempty directory: %sr4   zSELECT COUNT(key) FROM Cachez,Settings.count != COUNT(Cache.key); %d != %d+UPDATE Settings SET value = ? WHERE key = ?r5   z(SELECT COALESCE(SUM(size), 0) FROM Cachez*Settings.size != SUM(Cache.size); %d != %dz*UPDATE Settings SET value = ? WHERE key =?N)warningscatch_warningsr  r  rt   warnr?  r^  rz   r   rA   r{  existsr{   r   walkr&  r   r   r   rmdirr  r4   r5   )r   fixr>  warnsr  r[  messagerX   rH  r)  r\  r5   rv   r   	real_sizer   dirpathfilespathsr  dirsr4   select_sizes                          r   checkCache.checkb  s2   * $$D1U))C /099;D4yA~at!3"&JWMM'* #' H&(3  E	2 
 6{++--1)E " BIMM),yy++$&JJy$9	,&EG#,#=D$MM'.9" #%7%.$6!" !MM"6"BCs?%J1 .28 *,)A%GQHMNHRWWWh7ENJ2E%*	!Y.$"4y"@ g/AB3IIi0 &+	 *B  -/GGDOO,D(GT5 DEE"7'"A g?3HHW- -E 

7#!"@AJJL%::&LGMM'ZZ,?"?@I"G, 

6"H -668
$99$JGMM'YY,="=>H!6Nu '~ [ 21n OS '& 21sX   A?OC$N:<9N:5!N5
AN: A
N:.N:7%N: DN:"	O5N::
O	O
Oc                 P    U R                   nU" S5        U R                  SS5        g)zCreate tag index on cache database.

It is better to initialize cache with `tag_index=True` than use this.

:raises Timeout: if database timeout occurs

z?CREATE INDEX IF NOT EXISTS Cache_tag_rowid ON Cache(tag, rowid)r)   r!   Nr  r  r   r  s     r   r  Cache.create_tag_index  s$     iiMN

;"r
   c                 P    U R                   nU" S5        U R                  SS5        g)zPDrop tag index on cache database.

:raises Timeout: if database timeout occurs

z$DROP INDEX IF EXISTS Cache_tag_rowidr)   r   Nr  r  s     r   r  Cache.drop_tag_index  s$     ii23

;"r
   c                 2    SnUSS/nU R                  X4SUS9$ )a`  Remove items with matching `tag` from cache.

Removing items is an iterative process. In each iteration, a subset of
items is removed. Concurrent writes may occur between iterations.

If a :exc:`Timeout` occurs, the first element of the exception's
`args` attribute will be the number of items removed before the
exception occurred.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param str tag: tag identifying items
:param bool retry: retry if database timeout occurs (default False)
:return: count of rows removed
:raises Timeout: if database timeout occurs

zTSELECT rowid, filename FROM Cache WHERE tag = ? AND rowid > ? ORDER BY rowid LIMIT ?r   d   r!   )	arg_indexr>  _select_delete)r   rT  r>  r)  r   s        r   evictCache.evict  s1    (& 	
 Q}""61E"JJr
   c                 j    SnSU=(       d    [         R                   " 5       S/nU R                  X4SUS9$ )as  Remove expired items from cache.

Removing items is an iterative process. In each iteration, a subset of
items is removed. Concurrent writes may occur between iterations.

If a :exc:`Timeout` occurs, the first element of the exception's
`args` attribute will be the number of items removed before the
exception occurred.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param float now: current time (default None, ``time.time()`` used)
:param bool retry: retry if database timeout occurs (default False)
:return: count of items removed
:raises Timeout: if database timeout occurs

zuSELECT rowid, expire_time, filename FROM Cache WHERE ? < expire_time AND expire_time < ? ORDER BY expire_time LIMIT ?r   r  r!   )	row_indexr>  )r2  r  )r   rU  r>  r)  r   s        r   rS  Cache.expire  s=    (, 	
 3%$))+s+""61E"JJr
   c                 ~   [         R                   " 5       nU R                  U5      n[        U R                     S   nUc  gUR	                  SUS9n U R                  5       U R                  :  a  U R                  U5       u  pgU" US5      R                  5       nU(       d   SSS5        U$ U[        U5      -  nSUR	                  SUS9-  n	U" U	S5        U H  u  n
U" U
5        M     SSS5        U R                  5       U R                  :  a  M  U$ ! , (       d  f       N0= f! [         a    [        U5      Sef = f)	aJ  Cull items from cache until volume is less than size limit.

Removing items is an iterative process. In each iteration, a subset of
items is removed. Concurrent writes may occur between iterations.

If a :exc:`Timeout` occurs, the first element of the exception's
`args` attribute will be the number of items removed before the
exception occurred.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param bool retry: retry if database timeout occurs (default False)
:return: count of items removed
:raises Timeout: if database timeout occurs

r:   Nr   rv   rj  )r&   ri  r\  )r2  rS  r  r*   rm  rl  r+   r?  r  rt   r   )r   r>  rU  r4   rr  rs  r  rZ  r[  rt  rv   s              r   r:   
Cache.cull2  s8   $ iik C  ((<(<=fE '..jc.J	+++-$//1^^E*ns6??AD	 +$  SY&E?'..g3.GH  &'+) (, + ++-$//1& % +*  	+%.d*	+s0   /D% "D#D% -=D*&D% 
D"D% %D<c                 .    SnSS/nU R                  X#US9$ )a*  Remove all items from cache.

Removing items is an iterative process. In each iteration, a subset of
items is removed. Concurrent writes may occur between iterations.

If a :exc:`Timeout` occurs, the first element of the exception's
`args` attribute will be the number of items removed before the
exception occurred.

Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).

:param bool retry: retry if database timeout occurs (default False)
:return: count of rows removed
:raises Timeout: if database timeout occurs

zHSELECT rowid, filename FROM Cache WHERE rowid > ? ORDER BY rowid LIMIT ?r   r  r=  r  )r   r>  r)  r   s       r   clearCache.cleari  s-    && 	
 3x""6u"==r
   c                    SnSn  U R                  U5       u  pU" X5      R                  5       n
U
(       d   S S S 5        U$ U[        U
5      -  nU" USR                  S U
 5       5      -  5        U
 H  nX   X$'   U	" US   5        M     S S S 5        M  ! , (       d  f       N= f! [         a    [	        U5      S ef = f)Nr   ri  ,c              3   >   #    U  H  n[        US    5      v   M     g7f)r   N)rO   )r   rows     r   r   'Cache._select_delete.<locals>.<genexpr>  s     )F##c!f++s   )r?  r  rt   r   r   )r   r)  r   r  r  r>  r4   rt  r  rZ  r[  r  s               r   r  Cache._select_delete  s     8	+^^E*nsv,557D	 +   SY&E)F)F!FFG#*-.B(  $ + **  	+%.d*	+s.   B' !BB' A	B
B' 
B$ B' 'B>c              #   B  #    U R                   nSnU R                  R                  nU(       a  SnSnOSnSnU" U5      R                  5       nU(       a  Uu  u  pOgU" X5      v    U" XhXU45      R                  5       n
U
(       d  gU
 H  u  pU" X5      v   M     M8  7f)a5  Iterate Cache keys in database sort order.

>>> cache = Cache()
>>> for key in [4, 1, 3, 0, 2]:
...     cache[key] = key
>>> list(cache.iterkeys())
[0, 1, 2, 3, 4]
>>> list(cache.iterkeys(reverse=True))
[4, 3, 2, 1, 0]

:param bool reverse: reverse sort order (default False)
:return: iterator of Cache keys

r  z>SELECT key, raw FROM Cache ORDER BY key DESC, raw DESC LIMIT 1zcSELECT key, raw FROM Cache WHERE key = ? AND raw < ? OR key < ? ORDER BY key DESC, raw DESC LIMIT ?z<SELECT key, raw FROM Cache ORDER BY key ASC, raw ASC LIMIT 1zaSELECT key, raw FROM Cache WHERE key = ? AND raw > ? OR key > ? ORDER BY key ASC, raw ASC LIMIT ?N)r  r	  r9   r  )r   reverser  rn  	_disk_getr)  iterater  rU   rn   r[  s              r   iterkeysCache.iterkeys  s      iiJJNN	7 
7 5 
5  &k""$MZc3!!wc 67@@BD )) ! s   BBc              #   d  #    U R                   nU" S5      R                  5       nUu  u  nS v   Uc  g US-   nSnU R                  R                  nU(       a  SOUnSU(       a  SOS-  n	 U(       a  XU4n
OSX4n
U" X5      R                  5       nU(       d  g U H  u  pnU" X5      v   M     MF  7f)NzSELECT MAX(rowid) FROM Cacher!   r  r   zYSELECT rowid, key, raw FROM Cache WHERE ? < rowid AND rowid < ? ORDER BY rowid %s LIMIT ?r  r  )r  r  r	  r9   )r   	ascendingr  r[  	max_rowidboundrn  r  r\  r)  r   rU   rn   s                r   _iterCache._iter  s     ii12;;=)AJJNN	E)  UV	- e,5(v$--/D#'C)) $( s   B.B0c                 <    U R                  5       n[        U5        U$ )z.Iterate keys in cache including expired items.r  nextr   r   s     r   __iter__Cache.__iter__  s    ::<Xr
   c                 :    U R                  SS9n[        U5        U$ )z6Reverse iterate keys in cache including expired items.F)r  r  r  s     r   __reversed__Cache.__reversed__  s    :::.Xr
   c                     U R                  S5      U R                  S5      4nU(       a$  U R                  SS5        U R                  SS5        U R                  SU5        U$ )zReturn cache statistics hits and misses.

:param bool enable: enable collecting statistics (default True)
:param bool reset: reset hits and misses to 0 (default False)
:return: (hits, misses)

r6   r7   r   r(   r  )r   enabler  rh   s       r   statsCache.stats	  sR     **V$djj&:;JJvq!JJx#

<(r
   c                     U R                  S5      R                  5       u  u  nU R                  U-  U R                  S5      -   nU$ )zGReturn estimated total size of cache on disk.

:return: size in bytes

zPRAGMA page_countr5   )r  r  r
  r  )r   
page_count
total_sizes      r   rl  Cache.volume	  sC      99%89BBD*__z1DJJv4FF
r
   c                     [        U R                  SS5      nUc  gUR                  5          [        U R                  S5        g! [         a     gf = f)zClose database connection.r!  N)r#  r   r  delattrAttributeError)r   r!  s     r   r  Cache.close!	  sJ    dkk5$/;			DKK' 		s   A 
AAc                     U R                   nU $ r   )r*  )r   
connections     r   	__enter__Cache.__enter__/	  s     YY
r
   c                 $    U R                  5         g r   )r  )r   	exceptions     r   __exit__Cache.__exit__5	  s    

r
   c                 $    U R                  S5      $ )z0Count of items in cache including expired items.r4   r  r   s    r   __len__Cache.__len__8	  s    zz'""r
   c                 Z    U R                   U R                  [        U R                  5      4$ r   )rD   r  rJ   r  r   s    r   __getstate__Cache.__getstate__<	  s    d499o>>r
   c                 "    U R                   " U6   g r   )rE   )r   states     r   __setstate__Cache.__setstate__?	  s    ur
   c                 (   U R                   nU R                  nU[        L a+  SnU" Xa45      R                  5       u  u  n[	        XU5        U$ U(       a  SnU" XrU45        UR                  S5      (       ad  USS n[        R                  " 5       n	   U" SU-  5      R                  5       u  u  n
X:g  nU(       a  U" SU< S	U< 35      R                  5         O1UR                  S5      (       a  USS n[	        U R                  X5        [	        XU5        U$ ! [         a    Sn Nsf = f! [        R                   aO  n[        U5      S
:w  a  e [        R                  " 5       U	-
  nUS:  a  e [        R                  " S5         SnAOSnAff = fGM  )a  Reset `key` and `value` item from Settings table.

Use `reset` to update the value of Cache settings correctly. Cache
settings are stored in the Settings table of the SQLite database. If
`update` is ``False`` then no attempt is made to update the database.

If `value` is not given, it is reloaded from the Settings
table. Otherwise, the Settings table is updated.

Settings with the ``disk_`` prefix correspond to Disk
attributes. Updating the value will change the unprefixed attribute on
the associated Disk instance.

Settings with the ``sqlite_`` prefix correspond to SQLite
pragmas. Updating the value will execute the corresponding PRAGMA
statement.

SQLite PRAGMA statements may be executed before the Settings table
exists in the database by setting `update` to ``False``.

:param str key: Settings key for item
:param value: value for item (optional)
:param bool update: update database Settings table (default True)
:return: updated value for item
:raises Timeout: if database timeout occurs

z(SELECT value FROM Settings WHERE key = ?r  r      NTz	PRAGMA %szPRAGMA z = r0  r   r1  r   r   )r  r   r   r  setattrr  r2  r   rK   r  rO   r3  r	  )r   rU   r   r   r  	sql_retryr)  r4  pragmar5  	old_valuer6  r7  attrs                 r   r  Cache.resetB	  s~   8 iiOO	F??F#FF3<<>KXeDu%LEIi.>>)$$WF IIKE&&*-'62+"(* () "+!3 >?HHJ ^^G$$qr7DDJJ,5!# & &!%&
 // &3x#7799;.DbyJJu%%& s7   !D 4%D+ D(%D+ 'D((D+ +F?AF		F)rA   r	  r   r
  r   r   )F)FN)NFNFr   )NF)r!   r   F)NFFFF)NFFF)T)Nr  NFNF)Nr~  r  FFF)TFFF)NFNNr   )FF)r   r   F)TF)>r   r   r   r   r   r=   rE   propertyrD   r  r  r*  r  r   r   contextmanagerr@  r?  r^  rb  rP  rQ  rR  rx  r{  r  r  r9   r  r   r  r  r  rt  r  r  r  r  r  r  r  r  r  rS  r:   r  r  r	  r  r  r  r  rl  r  r)  r-  r0  r3  r7  r   r  r   r   r
   r   r   r     s   %!%r kZ       # #J ! ! # #4  < &' &'P?B	)
:
.0"d#J4lIV6B cJ$( FK<|>. bL ur m^L^ EG]~BH
##K6K65n>6 =B48*t*B&#?  &d Rr
   r   ).r   r   
contextlibr   r   	functoolsr}   rl   r   r   os.pathpathrz   rb   rd   rK   rS   r   r   r2  r  rM   r	   r   r   r&  r   r    	MODE_NONEru   rx   r|   r   HIGHEST_PROTOCOLr  r  r  r=   r   	Exceptionr   UserWarningr   r   r   r   r   r
   r   <module>rK     sj       	  	          5
u  
	(	
9
		 . "33   	 " H# %I$ 1J-Bd$ d$N&t &R$i $9 9=k =<s sr
   