31 |
31 |
32 class Storage(object): |
32 class Storage(object): |
33 """abstract storage |
33 """abstract storage |
34 |
34 |
35 * If `source_callback` is true (by default), the callback will be run during |
35 * If `source_callback` is true (by default), the callback will be run during |
36 query result process of fetched attribute's valu and should have the |
36 query result process of fetched attribute's value and should have the |
37 following prototype:: |
37 following prototype:: |
38 |
38 |
39 callback(self, source, value) |
39 callback(self, source, session, value) |
40 |
40 |
41 where `value` is the value actually stored in the backend. None values |
41 where `value` is the value actually stored in the backend. None values |
42 will be skipped (eg callback won't be called). |
42 will be skipped (eg callback won't be called). |
43 |
43 |
44 * if `source_callback` is false, the callback will be run during sql |
44 * if `source_callback` is false, the callback will be run during sql |
97 """store Bytes attribute value on the file system""" |
97 """store Bytes attribute value on the file system""" |
98 def __init__(self, defaultdir, fsencoding='utf-8'): |
98 def __init__(self, defaultdir, fsencoding='utf-8'): |
99 self.default_directory = defaultdir |
99 self.default_directory = defaultdir |
100 self.fsencoding = fsencoding |
100 self.fsencoding = fsencoding |
101 |
101 |
102 def callback(self, source, value): |
102 def callback(self, source, session, value): |
103 """sql generator callback when some attribute with a custom storage is |
103 """sql generator callback when some attribute with a custom storage is |
104 accessed |
104 accessed |
105 """ |
105 """ |
106 fpath = source.binary_to_str(value) |
106 fpath = source.binary_to_str(value) |
107 try: |
107 try: |
123 hook.set_operation(entity._cw, 'bfss_added', fpath, AddFileOp) |
123 hook.set_operation(entity._cw, 'bfss_added', fpath, AddFileOp) |
124 return binary |
124 return binary |
125 |
125 |
126 def entity_updated(self, entity, attr): |
126 def entity_updated(self, entity, attr): |
127 """an entity using this storage for attr has been updatded""" |
127 """an entity using this storage for attr has been updatded""" |
|
128 oldpath = self.current_fs_path(entity, attr) |
128 if entity._cw.transaction_data.get('fs_importing'): |
129 if entity._cw.transaction_data.get('fs_importing'): |
129 oldpath = self.current_fs_path(entity, attr) |
|
130 fpath = entity[attr].getvalue() |
130 fpath = entity[attr].getvalue() |
131 if oldpath != fpath: |
|
132 hook.set_operation(entity._cw, 'bfss_deleted', oldpath, |
|
133 DeleteFileOp) |
|
134 binary = Binary(file(fpath).read()) |
131 binary = Binary(file(fpath).read()) |
135 else: |
132 else: |
136 binary = entity.pop(attr) |
133 binary = entity.pop(attr) |
137 fpath = self.current_fs_path(entity, attr) |
134 fpath = self.new_fs_path(entity, attr) |
138 UpdateFileOp(entity._cw, filepath=fpath, filedata=binary.getvalue()) |
135 UpdateFileOp(entity._cw, filepath=fpath, filedata=binary.getvalue()) |
|
136 if oldpath != fpath: |
|
137 entity[attr] = Binary(fpath) |
|
138 hook.set_operation(entity._cw, 'bfss_deleted', oldpath, |
|
139 DeleteFileOp) |
139 return binary |
140 return binary |
140 |
141 |
141 def entity_deleted(self, entity, attr): |
142 def entity_deleted(self, entity, attr): |
142 """an entity using this storage for attr has been deleted""" |
143 """an entity using this storage for attr has been deleted""" |
143 fpath = self.current_fs_path(entity, attr) |
144 fpath = self.current_fs_path(entity, attr) |