2 from os import unlink, path as osp |
2 from os import unlink, path as osp |
3 |
3 |
4 from yams.schema import role_name |
4 from yams.schema import role_name |
5 |
5 |
6 from cubicweb import Binary |
6 from cubicweb import Binary |
7 from cubicweb.server.hook import Operation |
7 from cubicweb.server import hook |
8 |
8 |
9 def set_attribute_storage(repo, etype, attr, storage): |
9 def set_attribute_storage(repo, etype, attr, storage): |
10 repo.system_source.set_storage(etype, attr, storage) |
10 repo.system_source.set_storage(etype, attr, storage) |
11 |
11 |
12 def unset_attribute_storage(repo, etype, attr): |
12 def unset_attribute_storage(repo, etype, attr): |
97 binary = entity.pop(attr) |
97 binary = entity.pop(attr) |
98 fpath = self.new_fs_path(entity, attr) |
98 fpath = self.new_fs_path(entity, attr) |
99 # bytes storage used to store file's path |
99 # bytes storage used to store file's path |
100 entity[attr] = Binary(fpath) |
100 entity[attr] = Binary(fpath) |
101 file(fpath, 'w').write(binary.getvalue()) |
101 file(fpath, 'w').write(binary.getvalue()) |
102 AddFileOp(entity._cw, filepath=fpath) |
102 hook.set_operation(entity._cw, 'bfss_added', fpath, AddFileOp) |
103 return binary |
103 return binary |
104 |
104 |
105 def entity_updated(self, entity, attr): |
105 def entity_updated(self, entity, attr): |
106 """an entity using this storage for attr has been updatded""" |
106 """an entity using this storage for attr has been updatded""" |
107 if entity._cw.transaction_data.get('fs_importing'): |
107 if entity._cw.transaction_data.get('fs_importing'): |
108 oldpath = self.current_fs_path(entity, attr) |
108 oldpath = self.current_fs_path(entity, attr) |
109 fpath = entity[attr].getvalue() |
109 fpath = entity[attr].getvalue() |
110 if oldpath != fpath: |
110 if oldpath != fpath: |
111 DeleteFileOp(entity._cw, filepath=oldpath) |
111 hook.set_operation(entity._cw, 'bfss_deleted', oldpath, |
|
112 DeleteFileOp) |
112 binary = Binary(file(fpath).read()) |
113 binary = Binary(file(fpath).read()) |
113 else: |
114 else: |
114 binary = entity.pop(attr) |
115 binary = entity.pop(attr) |
115 fpath = self.current_fs_path(entity, attr) |
116 fpath = self.current_fs_path(entity, attr) |
116 UpdateFileOp(entity._cw, filepath=fpath, filedata=binary.getvalue()) |
117 UpdateFileOp(entity._cw, filepath=fpath, filedata=binary.getvalue()) |
117 return binary |
118 return binary |
118 |
119 |
119 def entity_deleted(self, entity, attr): |
120 def entity_deleted(self, entity, attr): |
120 """an entity using this storage for attr has been deleted""" |
121 """an entity using this storage for attr has been deleted""" |
121 DeleteFileOp(entity._cw, filepath=self.current_fs_path(entity, attr)) |
122 fpath = self.current_fs_path(entity, attr) |
|
123 hook.set_operation(entity._cw, 'bfss_deleted', fpath, DeleteFileOp) |
122 |
124 |
123 def new_fs_path(self, entity, attr): |
125 def new_fs_path(self, entity, attr): |
124 # We try to get some hint about how to name the file using attribute's |
126 # We try to get some hint about how to name the file using attribute's |
125 # name metadata, so we use the real file name and extension when |
127 # name metadata, so we use the real file name and extension when |
126 # available. Keeping the extension is useful for example in the case of |
128 # available. Keeping the extension is useful for example in the case of |
147 return self.new_fs_path(entity, attr) |
149 return self.new_fs_path(entity, attr) |
148 return sysource._process_value(rawvalue, cu.description[0], |
150 return sysource._process_value(rawvalue, cu.description[0], |
149 binarywrap=str) |
151 binarywrap=str) |
150 |
152 |
151 |
153 |
152 class AddFileOp(Operation): |
154 |
|
155 class AddFileOp(hook.Operation): |
153 def rollback_event(self): |
156 def rollback_event(self): |
154 try: |
157 for filepath in self.session.transaction_data.pop('bfss_added'): |
155 unlink(self.filepath) |
158 try: |
156 except: |
159 unlink(filepath) |
157 pass |
160 except Exception, ex: |
|
161 self.error('cant remove %s: %s' % (filepath, ex)) |
158 |
162 |
159 class DeleteFileOp(Operation): |
163 class DeleteFileOp(hook.Operation): |
160 def commit_event(self): |
164 def commit_event(self): |
161 try: |
165 for filepath in self.session.transaction_data.pop('bfss_deleted'): |
162 unlink(self.filepath) |
166 try: |
163 except: |
167 unlink(filepath) |
164 pass |
168 except Exception, ex: |
|
169 self.error('cant remove %s: %s' % (filepath, ex)) |
165 |
170 |
166 class UpdateFileOp(Operation): |
171 class UpdateFileOp(hook.Operation): |
167 def precommit_event(self): |
172 def precommit_event(self): |
168 try: |
173 try: |
169 file(self.filepath, 'w').write(self.filedata) |
174 file(self.filepath, 'w').write(self.filedata) |
170 except Exception, ex: |
175 except Exception, ex: |
171 self.exception(str(ex)) |
176 self.exception(str(ex)) |