diff --git a/src/calibre/devices/mtp/filesystem_cache.py b/src/calibre/devices/mtp/filesystem_cache.py index a52a20dfa3..4c7573f0a0 100644 --- a/src/calibre/devices/mtp/filesystem_cache.py +++ b/src/calibre/devices/mtp/filesystem_cache.py @@ -51,6 +51,21 @@ class FileOrFolder(object): self.fs_cache = weakref.ref(fs_cache) self.deleted = False + def __repr__(self): + name = 'Folder' if self.is_folder else 'File' + try: + path = unicode(self.full_path) + except: + path = '' + datum = 'size=%s'%(self.size) + if self.is_folder: + datum = 'children=%s'%(len(self.files) + len(self.folders)) + return '%s(id=%s, storage_id=%s, %s, path=%s)'%(name, self.object_id, + self.storage_id, datum, path) + + __str__ = __repr__ + __unicode__ = __repr__ + @property def id_map(self): return self.fs_cache().id_map diff --git a/src/calibre/devices/mtp/unix/driver.py b/src/calibre/devices/mtp/unix/driver.py index ff00f79ad4..a306fbcc0d 100644 --- a/src/calibre/devices/mtp/unix/driver.py +++ b/src/calibre/devices/mtp/unix/driver.py @@ -14,6 +14,7 @@ from collections import namedtuple from calibre import prints from calibre.constants import plugins +from calibre.ptempfile import SpooledTemporaryFile from calibre.devices.errors import OpenFailed, DeviceError from calibre.devices.mtp.base import MTPDeviceBase, synchronous from calibre.devices.mtp.filesystem_cache import FilesystemCache @@ -264,13 +265,17 @@ class MTP_DEVICE(MTPDeviceBase): return parent.add_child(ans) @synchronous - def get_file(self, f, stream, callback=None): + def get_file(self, f, stream=None, callback=None): if f.is_folder: raise ValueError('%s if a folder'%(f.full_path,)) + if stream is None: + stream = SpooledTemporaryFile(5*1024*1024, '_wpd_receive_file.dat') + stream.name = f.name ok, errs = self.dev.get_file(f.object_id, stream, callback) if not ok: raise DeviceError('Failed to get file: %s with errors: %s'%( f.full_path, self.format_errorstack(errs))) + return stream @synchronous def delete_file_or_folder(self, obj): @@ -315,13 +320,17 @@ if __name__ == '__main__': # fname = b'moose.txt' # src = BytesIO(raw) # print (d.put_file(dev._main_id, 0, fname, src, len(raw), PR())) - dev.filesystem_cache.dump() # with open('/tmp/flint.epub', 'wb') as f: # print(d.get_file(786, f, PR())) # print() # with open('/tmp/bleak.epub', 'wb') as f: # print(d.get_file(601, f, PR())) # print() + + dev.filesystem_cache.dump() + + # print (dev.filesystem_cache.entries[0].files[0]) + # print (dev.filesystem_cache.entries[0].folders[0]) dev.set_debug_level(dev.LIBMTP_DEBUG_ALL) del d dev.shutdown() diff --git a/src/calibre/devices/mtp/windows/driver.py b/src/calibre/devices/mtp/windows/driver.py index 03e3c65ad1..d030e2a53c 100644 --- a/src/calibre/devices/mtp/windows/driver.py +++ b/src/calibre/devices/mtp/windows/driver.py @@ -245,18 +245,18 @@ class MTP_DEVICE(MTPDeviceBase): return tuple(ans) @same_thread - def get_file(self, object_id, stream=None, callback=None): - f = self.filesystem_cache.id_map[object_id] + def get_file(self, f, stream=None, callback=None): if f.is_folder: - raise ValueError('%s is a folder on the device'%(f.full_path,)) + raise ValueError('%s if a folder'%(f.full_path,)) if stream is None: stream = SpooledTemporaryFile(5*1024*1024, '_wpd_receive_file.dat') + stream.name = f.name try: try: - self.dev.get_file(object_id, stream, callback) + self.dev.get_file(f.object_id, stream, callback) except self.wpd.WPDFileBusy: time.sleep(2) - self.dev.get_file(object_id, stream, callback) + self.dev.get_file(f.object_id, stream, callback) except Exception as e: raise DeviceError('Failed to fetch the file %s with error: %s'% f.full_path, as_unicode(e)) @@ -290,3 +290,21 @@ class MTP_DEVICE(MTPDeviceBase): self.dev.delete_object(obj.object_id) parent.remove_child(obj) + @same_thread + def put_file(self, parent, name, stream, size, callback=None, replace=True): + e = parent.folder_named(name) + if e is not None: + raise ValueError('Cannot upload file, %s already has a folder named: %s'%( + parent.full_path, e.name)) + e = parent.file_named(name) + if e is not None: + if not replace: + raise ValueError('Cannot upload file %s, it already exists'%( + e.full_path,)) + self.delete_file_or_folder(e) + sid, pid = parent.storage_id, parent.object_id + ans = self.dev.put_file(sid, pid, name, stream, size, callback) + ans['storage_id'] = parent.storage_id + return parent.add_child(ans) + + diff --git a/src/calibre/devices/mtp/windows/remote.py b/src/calibre/devices/mtp/windows/remote.py index 22e186c32d..a02b955522 100644 --- a/src/calibre/devices/mtp/windows/remote.py +++ b/src/calibre/devices/mtp/windows/remote.py @@ -70,12 +70,18 @@ def main(): print ('Connected to:', dev.get_gui_name()) print ('Total space', dev.total_space()) print ('Free space', dev.free_space()) - dev.filesystem_cache.dump() # pprint.pprint(dev.dev.create_folder(dev.filesystem_cache.entries[0].object_id, # 'zzz')) # print ('Fetching file: oFF (198214 bytes)') # stream = dev.get_file('oFF') # print ("Fetched size: ", stream.tell()) + size = 4 + stream = io.BytesIO(b'a'*size) + name = 'zzz-test-file.txt' + stream.seek(0) + f = dev.put_file(dev.filesystem_cache.entries[0], name, stream, size) + print ('Put file:', f) + # dev.filesystem_cache.dump() finally: dev.shutdown()