write back $ˆl–Ðz¾”Ëm q@=q¦nõ1hßÉ „x/8ïÈÀË?÷"""Core disk and file backed cache API. """ import codecs import contextlib as cl import errno import functools as ft import io import json import os import os.path as op import pickle import pickletools import sqlite3 import struct import tempfile import threading import time import warnings import zlib def full_name(func): """Return full name of `func` by adding the module and function name.""" return func.__module__ + '.' + func.__qualname__ class Constant(tuple): """Pretty display of immutable constant.""" def __new__(cls, name): return tuple.__new__(cls, (name,)) def __repr__(self): return '%s' % self[0] DBNAME = 'cache.db' ENOVAL = Constant('ENOVAL') UNKNOWN = Constant('UNKNOWN') MODE_NONE = 0 MODE_RAW = 1 MODE_BINARY = 2 MODE_TEXT = 3 MODE_PICKLE = 4 DEFAULT_SETTINGS = { 'statistics': 0, # False 'tag_index': 0, # False 'eviction_policy': 'least-recently-stored', 'size_limit': 2**30, # 1gb 'cull_limit': 10, 'sqlite_auto_vacuum': 1, # FULL 'sqlite_cache_size': 2**13, # 8,192 pages 'sqlite_journal_mode': 'wal', 'sqlite_mmap_size': 2**26, # 64mb 'sqlite_synchronous': 1, # NORMAL 'disk_min_file_size': 2**15, # 32kb 'disk_pickle_protocol': pickle.HIGHEST_PROTOCOL, } METADATA = { 'count': 0, 'size': 0, 'hits': 0, 'misses': 0, } EVICTION_POLICY = { 'none': { 'init': None, 'get': None, 'cull': None, }, 'least-recently-stored': { 'init': ( 'CREATE INDEX IF NOT EXISTS Cache_store_time ON' ' Cache (store_time)' ), 'get': None, 'cull': 'SELECT {fields} FROM Cache ORDER BY store_time LIMIT ?', }, 'least-recently-used': { 'init': ( 'CREATE INDEX IF NOT EXISTS Cache_access_time ON' ' Cache (access_time)' ), 'get': 'access_time = {now}', 'cull': 'SELECT {fields} FROM Cache ORDER BY access_time LIMIT ?', }, 'least-frequently-used': { 'init': ( 'CREATE INDEX IF NOT EXISTS Cache_access_count ON' ' Cache (access_count)' ), 'get': 'access_count = access_count + 1', 'cull': 'SELECT {fields} FROM Cache ORDER BY access_count LIMIT ?', }, } class Disk: """Cache key and value serialization for SQLite database and files.""" def __init__(self, directory, min_file_size=0, pickle_protocol=0): """Initialize 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 """ self._directory = directory self.min_file_size = min_file_size self.pickle_protocol = pickle_protocol def hash(self, key): """Compute portable hash for `key`. :param key: key to hash :return: hash value """ mask = 0xFFFFFFFF disk_key, _ = self.put(key) type_disk_key = type(disk_key) if type_disk_key is sqlite3.Binary: return zlib.adler32(disk_key) & mask elif type_disk_key is str: return zlib.adler32(disk_key.encode('utf-8')) & mask # noqa elif type_disk_key is int: return disk_key % mask else: assert type_disk_key is float return zlib.adler32(struct.pack('!d', disk_key)) & mask def put(self, key): """Convert `key` to fields key and raw for Cache table. :param key: key to convert :return: (database key, raw boolean) pair """ # pylint: disable=unidiomatic-typecheck type_key = type(key) if type_key is bytes: return sqlite3.Binary(key), True elif ( (type_key is str) or ( type_key is int and -9223372036854775808 <= key <= 9223372036854775807 ) or (type_key is float) ):