Commit 8a846d73 authored by Pierre-Yves David's avatar Pierre-Yves David
Browse files

[fix] fix path unicity process in BytesFileSystemStorage.new_fs_path

The previous implementation was bugged (prefixing the whole path with '_'
instead of the base name). A new version (using number) replace it.
* * *
Improve BytesFileSystemStorage.new_fs_path to use available metadata

This version try to get some hint about how to name the file using metadata.
Using the real file name and extension when available.  Keeping the extension
might be usefull for exemple in the case of processing that use filename
extension to detect content-type.

--HG--
branch : stable
parent 08e7fa906cdb
"""custom storages for the system source"""
from os import unlink, path as osp
from yams.schema import role_name
from cubicweb import Binary
from cubicweb.server.hook import Operation
......@@ -54,6 +56,22 @@ class Storage(object):
# * better file path attribution
# * handle backup/restore
def uniquify_path(dirpath, basename):
"""return a unique file name for `basename` in `dirpath`, or None
if all attemps failed.
XXX subject to race condition.
"""
path = osp.join(dirpath, basename)
if not osp.isfile(path):
return path
base, ext = osp.splitext(path)
for i in xrange(1, 256):
path = '%s%s%s' % (base, i, ext)
if not osp.isfile(path):
return path
return None
class BytesFileSystemStorage(Storage):
"""store Bytes attribute value on the file system"""
def __init__(self, defaultdir):
......@@ -102,16 +120,27 @@ class BytesFileSystemStorage(Storage):
DeleteFileOp(entity._cw, filepath=self.current_fs_path(entity, attr))
def new_fs_path(self, entity, attr):
fspath = osp.join(self.default_directory, '%s_%s' % (entity.eid, attr))
while osp.exists(fspath):
fspath = '_' + fspath
basename = [str(entity.eid), attr]
# We try to get some hint about how to name the file using attributes
# metadata. Using the real file name and extension when available.
#
# Keeping the extension might be usefull for exemple in the case of PIL
# processing that use filename extension to detect content-type.
name = entity.attr_metadata(attr, 'name')
if name is not None:
basename.append(name.encode(entity._cw.encoding))
fspath = uniquify_path(self.default_directory, '_'.join(basename))
if fspath is None:
msg = entity._cw._('failed to uniquify path (%s, %s)') % (
dirpath, basename)
raise ValidationError(entity.eid, {role_name(attr, 'subject'): msg})
return fspath
def current_fs_path(self, entity, attr):
sysource = entity._cw.pool.source('system')
cu = sysource.doexec(entity._cw,
'SELECT cw_%s FROM cw_%s WHERE cw_eid=%s' % (
attr, entity.__regid__, entity.eid))
attr, entity.__regid__, entity.eid))
rawvalue = cu.fetchone()[0]
if rawvalue is None: # no previous value
return self.new_fs_path(entity, attr)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment