From ff74cd460d30d9ccf97bc1abff3aa519a681fca1 Mon Sep 17 00:00:00 2001 From: John Schember Date: Thu, 20 Aug 2009 21:05:47 -0400 Subject: [PATCH] Device drivers use file path template. --- src/calibre/devices/cybookg3/driver.py | 15 ++++--- src/calibre/devices/jetbook/driver.py | 23 +++++----- src/calibre/devices/prs500/books.py | 14 +++--- src/calibre/devices/prs500/driver.py | 6 +-- src/calibre/devices/prs505/books.py | 15 +++---- src/calibre/devices/prs505/driver.py | 20 +++++---- src/calibre/devices/usbms/device.py | 50 +++++---------------- src/calibre/devices/usbms/driver.py | 14 +++--- src/calibre/gui2/device.py | 60 ++++++++++---------------- 9 files changed, 86 insertions(+), 131 deletions(-) diff --git a/src/calibre/devices/cybookg3/driver.py b/src/calibre/devices/cybookg3/driver.py index 670438f94d..de5e96d053 100644 --- a/src/calibre/devices/cybookg3/driver.py +++ b/src/calibre/devices/cybookg3/driver.py @@ -45,24 +45,25 @@ class CYBOOKG3(USBMS): DELETE_EXTS = ['.mbp', '.dat', '_6090.t2b'] SUPPORTS_SUB_DIRS = True - def upload_books(self, files, names, on_card=None, end_session=True, - metadata=None): + def upload_books(self, files, metadatas, ids, on_card=None, + end_session=True): path = self._sanity_check(on_card, files) paths = [] - names = iter(names) - metadata = iter(metadata) + metadatas = iter(metadatas) + ids = iter(ids) for i, infile in enumerate(files): - mdata, fname = metadata.next(), names.next() - filepath = self.create_upload_path(path, mdata, fname) + mdata, id = metadatas.next(), ids.next() + ext = os.path.splitext(infile)[1] + filepath = self.create_upload_path(path, mdata, ext, id) paths.append(filepath) self.put_file(infile, filepath, replace_file=True) coverdata = None - cover = mdata.get('cover', None) + cover = mdata.cover if cover: coverdata = cover[2] diff --git a/src/calibre/devices/jetbook/driver.py b/src/calibre/devices/jetbook/driver.py index 8fcbe306a2..949438ae6f 100644 --- a/src/calibre/devices/jetbook/driver.py +++ b/src/calibre/devices/jetbook/driver.py @@ -15,7 +15,7 @@ from itertools import cycle from calibre.devices.usbms.driver import USBMS from calibre.utils.filenames import ascii_filename as sanitize -from calibre.ebooks.metadata import string_to_authors +from calibre.ebooks.metadata import authors_to_string, string_to_authors class JETBOOK(USBMS): name = 'Ectaco JetBook Device Interface' @@ -50,23 +50,22 @@ class JETBOOK(USBMS): r'(?P.+)#(?P.+)' ) - def upload_books(self, files, names, on_card=False, end_session=True, - metadata=None): - + def upload_books(self, files, metadatas, ids, on_card=None, + end_session=True): path = self._sanity_check(on_card, files) paths = [] - names = iter(names) - metadata = iter(metadata) + metadatas = iter(metadatas) + ids = iter(ids) for i, infile in enumerate(files): - mdata, fname = metadata.next(), names.next() - path = os.path.dirname(self.create_upload_path(path, mdata, fname)) + mdata, id = metadatas.next(), ids.next() + ext = os.path.splitext(infile)[1] + path = self.create_upload_path(path, mdata, ext, id) - author = sanitize(mdata.get('authors','Unknown')).replace(' ', '_') - title = sanitize(mdata.get('title', 'Unknown')).replace(' ', '_') - fileext = os.path.splitext(os.path.basename(fname))[1] - fname = '%s#%s%s' % (author, title, fileext) + author = sanitize(authors_to_string(mdata.authors)).replace(' ', '_') + title = sanitize(mdata.title).replace(' ', '_') + fname = '%s#%s%s' % (author, title, ext) filepath = os.path.join(path, fname) paths.append(filepath) diff --git a/src/calibre/devices/prs500/books.py b/src/calibre/devices/prs500/books.py index 5eb8d7f011..770c48caf9 100644 --- a/src/calibre/devices/prs500/books.py +++ b/src/calibre/devices/prs500/books.py @@ -9,6 +9,7 @@ from base64 import b64decode as decode from base64 import b64encode as encode import re +from calibre.ebooks.metadata import authors_to_string from calibre.devices.interface import BookList as _BookList from calibre.devices import strftime, strptime @@ -262,9 +263,9 @@ class BookList(_BookList): cid = self.max_id()+1 sourceid = str(self[0].sourceid) if len(self) else "1" attrs = { - "title" : info["title"], - 'titleSorter' : sortable_title(info['title']), - "author" : info["authors"] if info['authors'] else 'Unknown', \ + "title" : info.title, + 'titleSorter' : sortable_title(info.title), + "author" : authors_to_string(info.authors), \ "page":"0", "part":"0", "scale":"0", \ "sourceid":sourceid, "id":str(cid), "date":"", \ "mime":mime, "path":name, "size":str(size) @@ -273,7 +274,7 @@ class BookList(_BookList): node.setAttributeNode(self.document.createAttribute(attr)) node.setAttribute(attr, attrs[attr]) try: - w, h, data = info["cover"] + w, h, data = info.cover except TypeError: w, h, data = None, None, None @@ -290,10 +291,7 @@ class BookList(_BookList): book.datetime = ctime self.append(book) self.set_next_id(cid+1) - if self.prefix and info.has_key('tags'): # Playlists only supportted in main memory - if info.has_key('tag order'): - self.tag_order.update(info['tag order']) - self.set_playlists(book.id, info['tags']) + self.set_playlists(book.id, info.tags def playlist_by_title(self, title): diff --git a/src/calibre/devices/prs500/driver.py b/src/calibre/devices/prs500/driver.py index 4273101273..b6209f75af 100644 --- a/src/calibre/devices/prs500/driver.py +++ b/src/calibre/devices/prs500/driver.py @@ -863,14 +863,14 @@ class PRS500(DeviceConfig, DevicePlugin): self.upload_book_list(booklists[1], end_session=False) @safe - def upload_books(self, files, names, on_card=False, end_session=True, - metadata=None): + def upload_books(self, files, metadatas, ids, on_card=None, + end_session=True): card = self.card(end_session=False) prefix = card + '/' + self.CARD_PATH_PREFIX +'/' if on_card else '/Data/media/books/' if on_card and not self._exists(prefix)[0]: self.mkdir(prefix[:-1], False) paths, ctimes = [], [] - names = iter(names) + names = iter([m.title for m in metatdatas]) infiles = [file if hasattr(file, 'read') else open(file, 'rb') for file in files] for f in infiles: f.seek(0, 2) sizes = [f.tell() for f in infiles] diff --git a/src/calibre/devices/prs505/books.py b/src/calibre/devices/prs505/books.py index 6e268e734a..4b8a952816 100644 --- a/src/calibre/devices/prs505/books.py +++ b/src/calibre/devices/prs505/books.py @@ -8,7 +8,7 @@ import xml.dom.minidom as dom from base64 import b64decode as decode from base64 import b64encode as encode - +from calibre.ebooks.metadata import authors_to_string from calibre.devices.interface import BookList as _BookList from calibre.devices import strftime as _strftime from calibre.devices import strptime @@ -194,9 +194,9 @@ class BookList(_BookList): except: sourceid = '1' attrs = { - "title" : info["title"], - 'titleSorter' : sortable_title(info['title']), - "author" : info["authors"] if info['authors'] else _('Unknown'), + "title" : info.title, + 'titleSorter' : sortable_title(info.title), + "author" : authors_to_string(info.authors), "page":"0", "part":"0", "scale":"0", \ "sourceid":sourceid, "id":str(cid), "date":"", \ "mime":mime, "path":name, "size":str(size) @@ -205,7 +205,7 @@ class BookList(_BookList): node.setAttributeNode(self.document.createAttribute(attr)) node.setAttribute(attr, attrs[attr]) try: - w, h, data = info["cover"] + w, h, data = info.cover except TypeError: w, h, data = None, None, None @@ -221,10 +221,7 @@ class BookList(_BookList): book = Book(node, self.mountpath, [], prefix=self.prefix) book.datetime = ctime self.append(book) - if info.has_key('tags'): - if info.has_key('tag order'): - self.tag_order.update(info['tag order']) - self.set_tags(book, info['tags']) + self.set_tags(book, info.tags) def _delete_book(self, node): nid = node.getAttribute('id') diff --git a/src/calibre/devices/prs505/driver.py b/src/calibre/devices/prs505/driver.py index d1e1535e36..b4fccd2548 100644 --- a/src/calibre/devices/prs505/driver.py +++ b/src/calibre/devices/prs505/driver.py @@ -109,20 +109,22 @@ class PRS505(CLI, Device): self.report_progress(1.0, _('Getting list of books on device...')) return bl - def upload_books(self, files, names, on_card=None, end_session=True, - metadata=None): + def upload_books(self, files, metadatas, ids, on_card=None, + end_session=True): path = self._sanity_check(on_card, files) - paths, ctimes, sizes = [], [], [] - names = iter(names) - metadata = iter(metadata) - for i, infile in enumerate(files): - mdata, fname = metadata.next(), names.next() - filepath = self.create_upload_path(path, mdata, fname) + paths = [] + metadatas = iter(metadatas) + ids = iter(ids) + for i, infile in enumerate(files): + mdata, id = metadatas.next(), ids.next() + ext = os.path.splitext(infile)[1] + filepath = self.create_upload_path(path, mdata, ext, id) paths.append(filepath) - self.put_file(infile, paths[-1], replace_file=True) + + self.put_file(infile, filepath, replace_file=True) ctimes.append(os.path.getctime(paths[-1])) sizes.append(os.stat(paths[-1]).st_size) diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index 007d058941..f54e09e92f 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -23,7 +23,7 @@ from calibre.devices.interface import DevicePlugin from calibre.devices.errors import DeviceError, FreeSpaceError from calibre.devices.usbms.deviceconfig import DeviceConfig from calibre import iswindows, islinux, isosx, __appname__ -from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to +from calibre.utils.filenames import shorten_components_to class Device(DeviceConfig, DevicePlugin): @@ -667,46 +667,18 @@ class Device(DeviceConfig, DevicePlugin): raise FreeSpaceError(_("There is insufficient free space on the storage card")) return path - def create_upload_path(self, path, mdata, fname): - path = os.path.abspath(path) - newpath = path - extra_components = [] - - if self.SUPPORTS_SUB_DIRS and self.settings().use_subdirs: - if 'tags' in mdata.keys(): - for tag in mdata['tags']: - if tag.startswith(_('News')): - extra_components.append('news') - c = sanitize(mdata.get('title', '')) - if c: - extra_components.append(c) - c = sanitize(mdata.get('timestamp', '')) - if c: - extra_components.append(c) - break - elif tag.startswith('/'): - for c in tag.split('/'): - c = sanitize(c) - if not c: continue - extra_components.append(c) - break - - if not extra_components: - c = sanitize(mdata.get('authors', _('Unknown'))) - if c: - extra_components.append(c) - c = sanitize(mdata.get('title', _('Unknown'))) - if c: - extra_components.append(c) - newpath = os.path.join(newpath, c) - - fname = sanitize(fname) - extra_components.append(fname) - extra_components = [str(x) for x in extra_components] - components = shorten_components_to(250 - len(path), extra_components) - filepath = os.path.join(path, *components) + def create_upload_path(self, root, mdata, ext, id): + from calibre.library.save_to_disk import config, get_components + opts = config().parse() + components = get_components(opts.template, mdata, id, opts.timefmt, 250) + components = [str(x) for x in components] + components = shorten_components_to(250 - len(root), components) + filepath = '%s%s' % (os.path.join(root, *components), ext) filedir = os.path.dirname(filepath) + if not self.SUPPORTS_SUB_DIRS or not self.settings().use_subdirs: + filedir = root + filepath = os.path.join(root, os.path.basename(filepath)) if not os.path.exists(filedir): os.makedirs(filedir) diff --git a/src/calibre/devices/usbms/driver.py b/src/calibre/devices/usbms/driver.py index 5650a2f10e..6cfe0ed132 100644 --- a/src/calibre/devices/usbms/driver.py +++ b/src/calibre/devices/usbms/driver.py @@ -79,19 +79,19 @@ class USBMS(CLI, Device): return bl - def upload_books(self, files, names, on_card=None, end_session=True, - metadata=None): + def upload_books(self, files, metadatas, ids, on_card=None, + end_session=True): path = self._sanity_check(on_card, files) paths = [] - names = iter(names) - metadata = iter(metadata) + metadatas = iter(metadatas) + ids = iter(ids) for i, infile in enumerate(files): - mdata, fname = metadata.next(), names.next() - filepath = self.create_upload_path(path, mdata, fname) - + mdata, id = metadatas.next(), ids.next() + ext = os.path.splitext(infile)[1] + filepath = self.create_upload_path(path, mdata, ext, id) paths.append(filepath) self.put_file(infile, filepath, replace_file=True) diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 3a46352a70..75385008f0 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -214,18 +214,17 @@ class DeviceManager(Thread): return self.create_job(self._sync_booklists, done, args=[booklists], description=_('Send metadata to device')) - def _upload_books(self, files, names, on_card=None, metadata=None): + def _upload_books(self, files, metadata, ids, on_card=None): '''Upload books to device: ''' - return self.device.upload_books(files, names, on_card, - metadata=metadata, end_session=False) + return self.device.upload_books(files, metadata, ids, on_card, + end_session=False) - def upload_books(self, done, files, names, on_card=None, titles=None, - metadata=None): - desc = _('Upload %d books to device')%len(names) + def upload_books(self, done, files, metadata, ids, on_card=None, titles=None): + desc = _('Upload %d books to device')%len(files) if titles: desc += u':' + u', '.join(titles) - return self.create_job(self._upload_books, done, args=[files, names], - kwargs={'on_card':on_card,'metadata':metadata}, description=desc) + return self.create_job(self._upload_books, done, args=[files, metadata, ids], + kwargs={'on_card':on_card}, description=desc) def add_books_to_metadata(self, locations, metadata, booklists): self.device.add_books_to_metadata(locations, metadata, booklists) @@ -698,18 +697,18 @@ class DeviceGUI(object): dynamic.set('news_to_be_synced', set([])) return metadata = self.library_view.model().get_metadata(ids, - rows_are_ids=True) + rows_are_ids=True, full_metadata=True)[1] names = [] for mi in metadata: - prefix = ascii_filename(mi['title']) + prefix = ascii_filename(mi.title) if not isinstance(prefix, unicode): prefix = prefix.decode(preferred_encoding, 'replace') prefix = ascii_filename(prefix) names.append('%s_%d%s'%(prefix, id, os.path.splitext(f.name)[1])) - cdata = mi['cover'] + cdata = mi.cover if cdata: - mi['cover'] = self.cover_to_thumbnail(cdata) + mi.cover = self.cover_to_thumbnail(cdata) dynamic.set('news_to_be_synced', set([])) if config['upload_news_to_device'] and files: remove = ids if \ @@ -718,8 +717,7 @@ class DeviceGUI(object): self.location_view.model().free[1] : 'carda', self.location_view.model().free[2] : 'cardb' } on_card = space.get(sorted(space.keys(), reverse=True)[0], None) - self.upload_books(files, names, metadata, - on_card=on_card, + self.upload_books(files, metadata, ids, on_card=on_card, memory=[[f.name for f in files], remove]) self.status_bar.showMessage(_('Sending news to device.'), 5000) @@ -741,38 +739,28 @@ class DeviceGUI(object): else: _auto_ids = [] - metadata = self.library_view.model().get_metadata(ids, True) + metadata = self.library_view.model().get_metadata(ids, True, full_metadata=True)[1] ids = iter(ids) for mi in metadata: - cdata = mi['cover'] + cdata = mi.cover if cdata: mi['cover'] = self.cover_to_thumbnail(cdata) metadata = iter(metadata) files = [getattr(f, 'name', None) for f in _files] - bad, good, gf, names, remove_ids = [], [], [], [], [] + bad, mdata, gf, fids, remove_ids = [], [], [], [], [] for f in files: mi = metadata.next() id = ids.next() if f is None: - bad.append(mi['title']) + bad.append(mi.title) else: remove_ids.append(id) - good.append(mi) gf.append(f) - t = mi['title'] - if not t: - t = _('Unknown') - a = mi['authors'] - if not a: - a = _('Unknown') - prefix = ascii_filename(t+' - '+a) - if not isinstance(prefix, unicode): - prefix = prefix.decode(preferred_encoding, 'replace') - prefix = ascii_filename(prefix) - names.append('%s_%d%s'%(prefix, id, os.path.splitext(f)[1])) + mdata.append(mi) + fids.append(id) remove = remove_ids if delete_from_library else [] - self.upload_books(gf, names, good, on_card, memory=(_files, remove)) + self.upload_books(gf, mdata, fids, on_card, memory=(_files, remove)) self.status_bar.showMessage(_('Sending books to device.'), 5000) auto = [] @@ -834,17 +822,15 @@ class DeviceGUI(object): cp, fs = job.result self.location_view.model().update_devices(cp, fs) - def upload_books(self, files, names, metadata, on_card=None, memory=None): + def upload_books(self, files, metadata, ids, on_card=None, memory=None): ''' Upload books to device. :param files: List of either paths to files or file like objects ''' - titles = [i['title'] for i in metadata] + titles = [i.title for i in metadata] job = self.device_manager.upload_books( Dispatcher(self.books_uploaded), - files, names, on_card=on_card, - metadata=metadata, titles=titles - ) + files, metadata, ids, on_card=on_card, titles=titles) self.upload_memory[job] = (metadata, on_card, memory, files) def books_uploaded(self, job): @@ -857,7 +843,7 @@ class DeviceGUI(object): if isinstance(job.exception, FreeSpaceError): where = 'in main memory.' if 'memory' in str(job.exception) \ else 'on the storage card.' - titles = '\n'.join(['<li>'+mi['title']+'</li>' \ + titles = '\n'.join(['<li>'+mi.title+'</li>' \ for mi in metadata]) d = error_dialog(self, _('No space on device'), _('<p>Cannot upload books to device there '