[bfss] Rename filenames according to their metadata on entity update.
--- a/server/sources/storages.py Wed May 26 18:32:27 2010 +0200
+++ b/server/sources/storages.py Fri May 28 08:05:17 2010 +0200
@@ -125,17 +125,18 @@
def entity_updated(self, entity, attr):
"""an entity using this storage for attr has been updatded"""
+ oldpath = self.current_fs_path(entity, attr)
if entity._cw.transaction_data.get('fs_importing'):
- oldpath = self.current_fs_path(entity, attr)
fpath = entity[attr].getvalue()
- if oldpath != fpath:
- hook.set_operation(entity._cw, 'bfss_deleted', oldpath,
- DeleteFileOp)
binary = Binary(file(fpath).read())
else:
binary = entity.pop(attr)
- fpath = self.current_fs_path(entity, attr)
+ fpath = self.new_fs_path(entity, attr)
UpdateFileOp(entity._cw, filepath=fpath, filedata=binary.getvalue())
+ if oldpath != fpath:
+ entity[attr] = Binary(fpath)
+ hook.set_operation(entity._cw, 'bfss_deleted', oldpath,
+ DeleteFileOp)
return binary
def entity_deleted(self, entity, attr):
--- a/server/test/unittest_storage.py Wed May 26 18:32:27 2010 +0200
+++ b/server/test/unittest_storage.py Fri May 28 08:05:17 2010 +0200
@@ -21,7 +21,7 @@
from __future__ import with_statement
-from logilab.common.testlib import unittest_main
+from logilab.common.testlib import unittest_main, tag
from cubicweb.devtools.testlib import CubicWebTC
import os.path as osp
@@ -180,7 +180,7 @@
self.assertEquals(f1.data.getvalue(), file(filepath).read(),
'files content differ')
-
+ @tag('Storage', 'BFSS', 'update')
def test_bfss_update_with_existing_data(self):
# use self.session to use server-side cache
f1 = self.session.create_entity('File', data=Binary('some data'),
@@ -194,6 +194,52 @@
f2 = self.execute('Any F WHERE F eid %(f)s, F is File', {'f': f1.eid}).get_entity(0, 0)
self.assertEquals(f2.data.getvalue(), 'some other data')
+ @tag('Storage', 'BFSS', 'update', 'extension', 'commit')
+ def test_bfss_update_with_different_extension_commited(self):
+ # use self.session to use server-side cache
+ f1 = self.session.create_entity('File', data=Binary('some data'),
+ data_format=u'text/plain', data_name=u'foo.txt')
+ # NOTE: do not use set_attributes() which would automatically
+ # update f1's local dict. We want the pure rql version to work
+ self.commit()
+ old_path = self.fspath(f1)
+ self.failUnless(osp.isfile(old_path))
+ self.assertEquals(osp.splitext(old_path)[1], '.txt')
+ self.execute('SET F data %(d)s, F data_name %(dn)s, F data_format %(df)s WHERE F eid %(f)s',
+ {'d': Binary('some other data'), 'f': f1.eid, 'dn': u'bar.jpg', 'df': u'image/jpeg'})
+ self.commit()
+ # the new file exists with correct extension
+ # the old file is dead
+ f2 = self.execute('Any F WHERE F eid %(f)s, F is File', {'f': f1.eid}).get_entity(0, 0)
+ new_path = self.fspath(f2)
+ self.failIf(osp.isfile(old_path))
+ self.failUnless(osp.isfile(new_path))
+ self.assertEquals(osp.splitext(new_path)[1], '.jpg')
+
+ @tag('Storage', 'BFSS', 'update', 'extension', 'rollback')
+ def test_bfss_update_with_different_extension_rollbacked(self):
+ # use self.session to use server-side cache
+ f1 = self.session.create_entity('File', data=Binary('some data'),
+ data_format=u'text/plain', data_name=u'foo.txt')
+ # NOTE: do not use set_attributes() which would automatically
+ # update f1's local dict. We want the pure rql version to work
+ self.commit()
+ old_path = self.fspath(f1)
+ old_data = f1.data.getvalue()
+ self.failUnless(osp.isfile(old_path))
+ self.assertEquals(osp.splitext(old_path)[1], '.txt')
+ self.execute('SET F data %(d)s, F data_name %(dn)s, F data_format %(df)s WHERE F eid %(f)s',
+ {'d': Binary('some other data'), 'f': f1.eid, 'dn': u'bar.jpg', 'df': u'image/jpeg'})
+ self.rollback()
+ # the new file exists with correct extension
+ # the old file is dead
+ f2 = self.execute('Any F WHERE F eid %(f)s, F is File', {'f': f1.eid}).get_entity(0, 0)
+ new_path = self.fspath(f2)
+ new_data = f2.data.getvalue()
+ self.failUnless(osp.isfile(new_path))
+ self.assertEquals(osp.splitext(new_path)[1], '.txt')
+ self.assertEquals(old_path, new_path)
+ self.assertEquals(old_data, new_data)
def test_bfss_update_with_fs_importing(self):
# use self.session to use server-side cache