Merge from trunk

This commit is contained in:
Charles Haley 2010-06-08 08:17:59 +01:00
commit 468cc178d5
8 changed files with 67 additions and 43 deletions

View File

@ -16,7 +16,7 @@ class NYTimes(BasicNewsRecipe):
title = 'New York Times Top Stories'
__author__ = 'GRiker'
language = _('English')
language = 'en'
description = 'Top Stories from the New York Times'
# List of sections typically included in Top Stories. Use a keyword from the

View File

@ -14,7 +14,6 @@ from calibre.devices.interface import DevicePlugin
from calibre.ebooks.BeautifulSoup import BeautifulSoup
from calibre.ebooks.metadata import MetaInformation
from calibre.library.server.utils import strftime
from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils.config import Config, config_dir
from calibre.utils.date import parse_date
from calibre.utils.logging import Log
@ -775,10 +774,12 @@ class ITUNES(DevicePlugin):
self._remove_from_iTunes(self.cached_books[path])
# Add to iTunes Library|Books
if isinstance(file,PersistentTemporaryFile):
added = self.iTunes.add(appscript.mactypes.File(file._name))
else:
added = self.iTunes.add(appscript.mactypes.File(file))
fpath = file
if getattr(file, 'orig_file_path', None) is not None:
fpath = file.orig_file_path
elif getattr(file, 'name', None) is not None:
fpath = file.name
added = self.iTunes.add(appscript.mactypes.File(fpath))
thumb = None
if metadata[i].cover:
@ -815,7 +816,7 @@ class ITUNES(DevicePlugin):
this_book.device_collections = []
this_book.library_id = added
this_book.path = path
this_book.size = self._get_device_book_size(file, added.size())
this_book.size = self._get_device_book_size(fpath, added.size())
this_book.thumbnail = thumb
this_book.iTunes_id = added
@ -922,12 +923,15 @@ class ITUNES(DevicePlugin):
self.log.info(" '%s' not in cached_books" % metadata[i].title)
# Add to iTunes Library|Books
if isinstance(file,PersistentTemporaryFile):
op_status = lib_books.AddFile(file._name)
self.log.info("ITUNES.upload_books():\n iTunes adding '%s'" % file._name)
else:
op_status = lib_books.AddFile(file)
self.log.info(" iTunes adding '%s'" % file)
fpath = file
if getattr(file, 'orig_file_path', None) is not None:
fpath = file.orig_file_path
elif getattr(file, 'name', None) is not None:
fpath = file.name
op_status = lib_books.AddFile(fpath)
self.log.info("ITUNES.upload_books():\n iTunes adding '%s'"
% fpath)
if DEBUG:
sys.stdout.write(" iTunes copying '%s' ..." % metadata[i].title)
@ -1464,7 +1468,7 @@ class ITUNES(DevicePlugin):
# Read the current storage path for iTunes media
cmd = "defaults read com.apple.itunes NSNavLastRootDirectory"
proc = subprocess.Popen( cmd, shell=True, cwd=os.curdir, stdout=subprocess.PIPE)
retcode = proc.wait()
proc.wait()
media_dir = os.path.abspath(proc.communicate()[0].strip())
if os.path.exists(media_dir):
self.iTunes_media = media_dir

View File

@ -287,7 +287,9 @@ class DevicePlugin(Plugin):
This method should raise a L{FreeSpaceError} if there is not enough
free space on the device. The text of the FreeSpaceError must contain the
word "card" if C{on_card} is not None otherwise it must contain the word "memory".
:files: A list of paths and/or file-like objects.
:files: A list of paths and/or file-like objects. If they are paths and
the paths point to temporary files, they may have an additional
attribute, original_file_path pointing to the originals.
:names: A list of file names that the books should have
once uploaded to the device. len(names) == len(files)
:return: A list of 3-element tuples. The list is meant to be passed

View File

@ -108,7 +108,7 @@ class BookList(_BookList):
def add_book(self, book, replace_metadata):
try:
b = self.index(book)
except ValueError, IndexError:
except (ValueError, IndexError):
b = None
if b is None:
self.append(book)

View File

@ -765,12 +765,8 @@ class Device(DeviceConfig, DevicePlugin):
path = existing[0]
def get_size(obj):
if hasattr(obj, 'seek'):
obj.seek(0, os.SEEK_END)
size = obj.tell()
obj.seek(0)
return size
return os.path.getsize(obj)
path = getattr(obj, 'name', obj)
return os.path.getsize(path)
sizes = [get_size(f) for f in files]
size = sum(sizes)

View File

@ -1,6 +1,8 @@
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
# Imports {{{
import os, traceback, Queue, time, socket, cStringIO, re
from threading import Thread, RLock
from itertools import repeat
@ -27,7 +29,9 @@ from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \
config as email_config
from calibre.devices.folder_device.driver import FOLDER_DEVICE
class DeviceJob(BaseJob):
# }}}
class DeviceJob(BaseJob): # {{{
def __init__(self, func, done, job_manager, args=[], kwargs={},
description=''):
@ -78,8 +82,9 @@ class DeviceJob(BaseJob):
def log_file(self):
return cStringIO.StringIO(self._details.encode('utf-8'))
# }}}
class DeviceManager(Thread):
class DeviceManager(Thread): # {{{
def __init__(self, connected_slot, job_manager, open_feedback_slot, sleep_time=2):
'''
@ -338,8 +343,9 @@ class DeviceManager(Thread):
return self.create_job(self._view_book, done, args=[path, target],
description=_('View book on device'))
# }}}
class DeviceAction(QAction):
class DeviceAction(QAction): # {{{
a_s = pyqtSignal(object)
@ -356,9 +362,9 @@ class DeviceAction(QAction):
def __repr__(self):
return self.__class__.__name__ + ':%s:%s:%s'%(self.dest, self.delete,
self.specific)
# }}}
class DeviceMenu(QMenu):
class DeviceMenu(QMenu): # {{{
fetch_annotations = pyqtSignal()
connect_to_folder = pyqtSignal()
@ -532,8 +538,9 @@ class DeviceMenu(QMenu):
annot_enable = enable and getattr(device, 'SUPPORTS_ANNOTATIONS', False)
self.annotation_action.setEnabled(annot_enable)
# }}}
class Emailer(Thread):
class Emailer(Thread): # {{{
def __init__(self, timeout=60):
Thread.__init__(self)
@ -590,6 +597,7 @@ class Emailer(Thread):
results.append([jobname, e, traceback.format_exc()])
callback(results)
# }}}
class DeviceGUI(object):
@ -637,7 +645,7 @@ class DeviceGUI(object):
if not ids or len(ids) == 0:
return
files, _auto_ids = self.library_view.model().get_preferred_formats_from_ids(ids,
fmts, paths=True, set_metadata=True,
fmts, set_metadata=True,
specific_format=specific_format,
exclude_auto=do_auto_convert)
if do_auto_convert:
@ -647,7 +655,6 @@ class DeviceGUI(object):
_auto_ids = []
full_metadata = self.library_view.model().metadata_for(ids)
files = [getattr(f, 'name', None) for f in files]
bad, remove_ids, jobnames = [], [], []
texts, subjects, attachments, attachment_names = [], [], [], []
@ -760,7 +767,7 @@ class DeviceGUI(object):
for account, fmts in accounts:
files, auto = self.library_view.model().\
get_preferred_formats_from_ids([id], fmts)
files = [f.name for f in files if f is not None]
files = [f for f in files if f is not None]
if not files:
continue
attachment = files[0]
@ -824,7 +831,7 @@ class DeviceGUI(object):
prefix = prefix.decode(preferred_encoding, 'replace')
prefix = ascii_filename(prefix)
names.append('%s_%d%s'%(prefix, id,
os.path.splitext(f.name)[1]))
os.path.splitext(f)[1]))
if mi.cover and os.access(mi.cover, os.R_OK):
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover,
'rb').read())
@ -837,7 +844,7 @@ class DeviceGUI(object):
on_card = space.get(sorted(space.keys(), reverse=True)[0], None)
self.upload_books(files, names, metadata,
on_card=on_card,
memory=[[f.name for f in files], remove])
memory=[files, remove])
self.status_bar.showMessage(_('Sending catalogs to device.'), 5000)
@ -884,7 +891,7 @@ class DeviceGUI(object):
prefix = prefix.decode(preferred_encoding, 'replace')
prefix = ascii_filename(prefix)
names.append('%s_%d%s'%(prefix, id,
os.path.splitext(f.name)[1]))
os.path.splitext(f)[1]))
if mi.cover and os.access(mi.cover, os.R_OK):
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover,
'rb').read())
@ -898,7 +905,7 @@ class DeviceGUI(object):
on_card = space.get(sorted(space.keys(), reverse=True)[0], None)
self.upload_books(files, names, metadata,
on_card=on_card,
memory=[[f.name for f in files], remove])
memory=[files, remove])
self.status_bar.showMessage(_('Sending news to device.'), 5000)
@ -914,7 +921,7 @@ class DeviceGUI(object):
_files, _auto_ids = self.library_view.model().get_preferred_formats_from_ids(ids,
settings.format_map,
paths=True, set_metadata=True,
set_metadata=True,
specific_format=specific_format,
exclude_auto=do_auto_convert)
if do_auto_convert:
@ -930,9 +937,8 @@ class DeviceGUI(object):
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover, 'rb').read())
imetadata = iter(metadata)
files = [getattr(f, 'name', None) for f in _files]
bad, good, gf, names, remove_ids = [], [], [], [], []
for f in files:
for f in _files:
mi = imetadata.next()
id = ids.next()
if f is None:

View File

@ -21,7 +21,8 @@ from calibre.utils.date import dt_factory, qt_to_dt, isoformat
from calibre.ebooks.metadata.meta import set_metadata as _set_metadata
from calibre.utils.search_query_parser import SearchQueryParser
from calibre.library.caches import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH
from calibre import strftime
from calibre import strftime, isbytestring
from calibre.constants import filesystem_encoding
from calibre.gui2.library import DEFAULT_SORT
def human_readable(size, precision=1):
@ -33,6 +34,13 @@ TIME_FMT = '%d %b %Y'
ALIGNMENT_MAP = {'left': Qt.AlignLeft, 'right': Qt.AlignRight, 'center':
Qt.AlignHCenter}
class FormatPath(unicode):
def __new__(cls, path, orig_file_path):
ans = unicode.__new__(cls, path)
ans.orig_file_path = orig_file_path
return ans
class BooksModel(QAbstractTableModel): # {{{
about_to_be_sorted = pyqtSignal(object, name='aboutToBeSorted')
@ -379,7 +387,7 @@ class BooksModel(QAbstractTableModel): # {{{
else:
return metadata
def get_preferred_formats_from_ids(self, ids, formats, paths=False,
def get_preferred_formats_from_ids(self, ids, formats,
set_metadata=False, specific_format=None,
exclude_auto=False, mode='r+b'):
ans = []
@ -404,12 +412,20 @@ class BooksModel(QAbstractTableModel): # {{{
as_file=True)) as src:
shutil.copyfileobj(src, pt)
pt.flush()
if getattr(src, 'name', None):
pt.orig_file_path = os.path.abspath(src.name)
pt.seek(0)
if set_metadata:
_set_metadata(pt, self.db.get_metadata(id, get_cover=True, index_is_id=True),
format)
pt.close() if paths else pt.seek(0)
ans.append(pt)
pt.close()
def to_uni(x):
if isbytestring(x):
x = x.decode(filesystem_encoding)
return x
name, op = map(to_uni, map(os.path.abspath, (pt.name,
pt.orig_file_path)))
ans.append(FormatPath(name, op))
else:
need_auto.append(id)
if not exclude_auto:

View File

@ -186,7 +186,7 @@ class TagsView(QTreeView): # {{{
def is_visible(self, idx):
item = idx.internalPointer()
if item.type == TagTreeItem.TAG:
if getattr(item, 'type', None) == TagTreeItem.TAG:
idx = idx.parent()
return self.isExpanded(idx)