comparison src/plugins/plugin_misc_file.py @ 1626:63cef4dbf2a4

core, plugins file, XEP-0234, bridge: progression api enhancement: - progressStarted have a new metadata parameter, useful to know the kind of progression, direction, etc. Check bridge doc - progressGetAllMetadata can be used to retrieve this data and discover on currently running progressions - progressFinished also have a new metadata parameter, used to e.g. indicate that hash is checked - core: fixed progressGetAll - file, XEP-0234: implemented the API modifications, hash is returned on progressFinished - file: SatFile.checkSize allows to check size independently of close (be sure that all the data have been transfered though)
author Goffi <goffi@goffi.org>
date Thu, 19 Nov 2015 18:13:26 +0100
parents 3ec7511dbf28
children 591e04f0103c
comparison
equal deleted inserted replaced
1625:8b8b1af5905f 1626:63cef4dbf2a4
69 self.uid = uid or unicode(uuid.uuid4()) 69 self.uid = uid or unicode(uuid.uuid4())
70 self._file = open(path, mode) 70 self._file = open(path, mode)
71 self.size = size 71 self.size = size
72 self.data_cb = data_cb 72 self.data_cb = data_cb
73 self.profile = profile 73 self.profile = profile
74 self.host.registerProgressCb(self.uid, self.getProgress, profile) 74 metadata = self.getProgressMetadata()
75 self.host.bridge.progressStarted(self.uid, self.profile) 75 self.host.registerProgressCb(self.uid, self.getProgress, metadata, profile=profile)
76 76 self.host.bridge.progressStarted(self.uid, metadata, self.profile)
77 def close(self): 77
78 def checkSize(self):
79 """Check that current size correspond to given size
80
81 must be used when the transfer is supposed to be finished
82 @return (bool): True if the position is the same as given size
83 @raise exceptions.NotFound: size has not be specified
84 """
78 position = self._file.tell() 85 position = self._file.tell()
86 if self.size is None:
87 raise exceptions.NotFound
88 return position == self.size
89
90
91 def close(self, progress_metadata=None, error=None):
92 """Close the current file
93
94 @param progress_metadata(None, dict): metadata to send with _onProgressFinished message
95 @param error(None, unicode): set to an error message if progress was not successful
96 mutually exclusive with progress_metadata
97 error can happen even if error is None, if current size differ from given size
98 """
99 if error is None:
100 try:
101 size_ok = self.checkSize()
102 except exceptions.NotFound:
103 size_ok = True
104 finally:
105 if not size_ok:
106 error = u'declared size and actual mismatch'
107 log.warning(u"successful close was requested, but there is a size mismatch")
108 progress_metadata = None
109
79 self._file.close() 110 self._file.close()
80 if not self.size or self.size == position: 111
81 self.host.bridge.progressFinished(self.uid, self.profile) 112 if error is None:
113 if progress_metadata is None:
114 progress_metadata = {}
115 self.host.bridge.progressFinished(self.uid, progress_metadata, self.profile)
82 else: 116 else:
83 self.host.bridge.progressError(self.uid, u"size doesn't match", self.profile) 117 assert progress_metadata is None
118 self.host.bridge.progressError(self.uid, error, self.profile)
119
84 self.host.removeProgressCb(self.uid, self.profile) 120 self.host.removeProgressCb(self.uid, self.profile)
85 121
86 def flush(self): 122 def flush(self):
87 self._file.flush() 123 self._file.flush()
88 124
100 def seek(self, offset, whence=os.SEEK_SET): 136 def seek(self, offset, whence=os.SEEK_SET):
101 self._file.seek(offset, whence) 137 self._file.seek(offset, whence)
102 138
103 def tell(self): 139 def tell(self):
104 return self._file.tell() 140 return self._file.tell()
141
142 def mode(self):
143 return self._file.mode()
144
145 def getProgressMetadata(self):
146 """Return progression metadata as given to progressStarted
147
148 @return (dict): metadata (check bridge for documentation)
149 """
150 metadata = {'type': C.META_TYPE_FILE}
151
152 mode = self._file.mode
153 if '+' in mode:
154 pass # we have no direction in read/write modes
155 elif mode in ('r', 'rb'):
156 metadata['direction'] = 'out'
157 elif mode in ('w', 'wb'):
158 metadata['direction'] = 'in'
159 elif 'U' in mode:
160 metadata['direction'] = 'out'
161 else:
162 raise exceptions.InternalError
163
164 metadata['name'] = self._file.name
165
166 return metadata
105 167
106 def getProgress(self, progress_id, profile): 168 def getProgress(self, progress_id, profile):
107 ret = {'position': self._file.tell()} 169 ret = {'position': self._file.tell()}
108 if self.size: 170 if self.size:
109 ret['size'] = self.size 171 ret['size'] = self.size