server/sources/storages.py
branchstable
changeset 5857 1a24c62aefc5
parent 5693 8af6623f3d4e
child 5863 4495b9bc49df
equal deleted inserted replaced
5856:a02129508378 5857:1a24c62aefc5
   104         """sql generator callback when some attribute with a custom storage is
   104         """sql generator callback when some attribute with a custom storage is
   105         accessed
   105         accessed
   106         """
   106         """
   107         fpath = source.binary_to_str(value)
   107         fpath = source.binary_to_str(value)
   108         try:
   108         try:
   109             return Binary(file(fpath).read())
   109             return Binary(file(fpath, 'rb').read())
   110         except OSError, ex:
   110         except OSError, ex:
   111             source.critical("can't open %s: %s", value, ex)
   111             source.critical("can't open %s: %s", value, ex)
   112             return None
   112             return None
   113 
   113 
   114     def entity_added(self, entity, attr):
   114     def entity_added(self, entity, attr):
   115         """an entity using this storage for attr has been added"""
   115         """an entity using this storage for attr has been added"""
   116         if entity._cw.transaction_data.get('fs_importing'):
   116         if entity._cw.transaction_data.get('fs_importing'):
   117             binary = Binary(file(entity[attr].getvalue()).read())
   117             binary = Binary(file(entity[attr].getvalue(), 'rb').read())
   118         else:
   118         else:
   119             binary = entity.pop(attr)
   119             binary = entity.pop(attr)
   120             fpath = self.new_fs_path(entity, attr)
   120             fpath = self.new_fs_path(entity, attr)
   121             # bytes storage used to store file's path
   121             # bytes storage used to store file's path
   122             entity[attr] = Binary(fpath)
   122             entity[attr] = Binary(fpath)
   123             file(fpath, 'w').write(binary.getvalue())
   123             file(fpath, 'wb').write(binary.getvalue())
   124             hook.set_operation(entity._cw, 'bfss_added', fpath, AddFileOp)
   124             hook.set_operation(entity._cw, 'bfss_added', fpath, AddFileOp)
   125         return binary
   125         return binary
   126 
   126 
   127     def entity_updated(self, entity, attr):
   127     def entity_updated(self, entity, attr):
   128         """an entity using this storage for attr has been updatded"""
   128         """an entity using this storage for attr has been updatded"""
       
   129         # get the name of the previous file containing the value
   129         oldpath = self.current_fs_path(entity, attr)
   130         oldpath = self.current_fs_path(entity, attr)
   130         if entity._cw.transaction_data.get('fs_importing'):
   131         if entity._cw.transaction_data.get('fs_importing'):
       
   132             # If we are importing from the filesystem, the file already exists.
       
   133             # We do not need to create it but we need to fetch the content of
       
   134             # the file as the actual content of the attribute
   131             fpath = entity[attr].getvalue()
   135             fpath = entity[attr].getvalue()
   132             binary = Binary(file(fpath).read())
   136             binary = Binary(file(fpath, 'rb').read())
   133         else:
   137         else:
       
   138             # We must store the content of the attributes
       
   139             # into a file to stay consistent with the behaviour of entity_add.
       
   140             # Moreover, the BytesFileSystemStorage expects to be able to
       
   141             # retrieve the current value of the attribute at anytime by reading
       
   142             # the file on disk. To be able to rollback things, use a new file
       
   143             # and keep the old one that will be removed on commit if everything
       
   144             # went ok.
       
   145             #
       
   146             # fetch the current attribute value in memory
   134             binary = entity.pop(attr)
   147             binary = entity.pop(attr)
       
   148             # Get filename for it
   135             fpath = self.new_fs_path(entity, attr)
   149             fpath = self.new_fs_path(entity, attr)
   136             UpdateFileOp(entity._cw, filepath=fpath, filedata=binary.getvalue())
   150             assert not osp.exists(fpath)
       
   151             # write attribute value on disk
       
   152             file(fpath, 'wb').write(binary.getvalue())
       
   153             # Mark the new file as added during the transaction.
       
   154             # The file will be removed on rollback
       
   155             hook.set_operation(entity._cw, 'bfss_added', fpath, AddFileOp)
   137         if oldpath != fpath:
   156         if oldpath != fpath:
       
   157             # register the new location for the file.
   138             entity[attr] = Binary(fpath)
   158             entity[attr] = Binary(fpath)
       
   159             # Mark the old file as useless so the file will be removed at
       
   160             # commit.
   139             hook.set_operation(entity._cw, 'bfss_deleted', oldpath,
   161             hook.set_operation(entity._cw, 'bfss_deleted', oldpath,
   140                                DeleteFileOp)
   162                                DeleteFileOp)
   141         return binary
   163         return binary
   142 
   164 
   143     def entity_deleted(self, entity, attr):
   165     def entity_deleted(self, entity, attr):
   198         for filepath in self.session.transaction_data.pop('bfss_deleted'):
   220         for filepath in self.session.transaction_data.pop('bfss_deleted'):
   199             try:
   221             try:
   200                 unlink(filepath)
   222                 unlink(filepath)
   201             except Exception, ex:
   223             except Exception, ex:
   202                 self.error('cant remove %s: %s' % (filepath, ex))
   224                 self.error('cant remove %s: %s' % (filepath, ex))
   203 
       
   204 class UpdateFileOp(hook.Operation):
       
   205     def precommit_event(self):
       
   206         try:
       
   207             file(self.filepath, 'w').write(self.filedata)
       
   208         except Exception, ex:
       
   209             self.exception(str(ex))