# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import hashlib import os from trytond.config import config from trytond.tools import resolve __all__ = ['filestore'] class FileStore(object): def get(self, id, prefix=''): filename = self._filename(id, prefix) with open(filename, 'rb') as fp: return fp.read() def getmany(self, ids, prefix=''): return [self.get(id, prefix) for id in ids] def size(self, id, prefix=''): filename = self._filename(id, prefix) statinfo = os.stat(filename) return statinfo.st_size def sizemany(self, ids, prefix=''): return [self.size(id, prefix) for id in ids] def set(self, data, prefix=''): id = self._id(data) filename = self._filename(id, prefix) dirname = os.path.dirname(filename) os.makedirs(dirname, mode=0o770, exist_ok=True) collision = 0 while True: basename = os.path.basename(filename) if os.path.exists(filename): if data != self.get(basename, prefix): collision += 1 filename = self._filename( '%s-%s' % (id, collision), prefix) continue else: with open(filename, 'wb')as fp: fp.write(data) return basename def setmany(self, data, prefix=''): return [self.set(d, prefix) for d in data] def _filename(self, id, prefix): path = os.path.normpath(config.get('database', 'path')) filename = os.path.join(path, prefix, id[0:2], id[2:4], id) filename = os.path.normpath(filename) if not filename.startswith(path): raise ValueError('Bad prefix') return filename def _id(self, data): return hashlib.md5(data).hexdigest() if config.get('database', 'class'): FileStore = resolve(config.get('database', 'class')) # noqa: F811 filestore = FileStore()