Pull from trunk

This commit is contained in:
Kovid Goyal 2009-04-19 15:49:37 -07:00
commit 6411a81fef
5 changed files with 31 additions and 42 deletions

View File

@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
__appname__ = 'calibre' __appname__ = 'calibre'
__version__ = '0.5.7' __version__ = '0.5.8'
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>" __author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
''' '''
Various run time constants. Various run time constants.

View File

@ -4,13 +4,15 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
Fetch cover from LibraryThing.com based on ISBN number. Fetch cover from LibraryThing.com based on ISBN number.
''' '''
import sys, socket, os, re, mechanize import sys, socket, os, re
from calibre import browser as _browser from calibre import browser as _browser
from calibre.utils.config import OptionParser from calibre.utils.config import OptionParser
from calibre.ebooks.BeautifulSoup import BeautifulSoup from calibre.ebooks.BeautifulSoup import BeautifulSoup
browser = None browser = None
OPENLIBRARY = 'http://covers.openlibrary.org/b/isbn/%s-L.jpg?default=false'
class LibraryThingError(Exception): class LibraryThingError(Exception):
pass pass
@ -30,15 +32,21 @@ def login(username, password, force=True):
browser['formusername'] = username browser['formusername'] = username
browser['formpassword'] = password browser['formpassword'] = password
browser.submit() browser.submit()
def cover_from_isbn(isbn, timeout=5.):
def cover_from_isbn(isbn, timeout=5., username=None, password=None):
global browser global browser
if browser is None: if browser is None:
browser = _browser() browser = _browser()
_timeout = socket.getdefaulttimeout() _timeout = socket.getdefaulttimeout()
socket.setdefaulttimeout(timeout) socket.setdefaulttimeout(timeout)
src = None src = None
try:
return browser.open(OPENLIBRARY%isbn).read(), 'jpg'
except:
pass # Cover not found
if username and password:
login(username, password, force=False)
try: try:
src = browser.open('http://www.librarything.com/isbn/'+isbn).read().decode('utf-8', 'replace') src = browser.open('http://www.librarything.com/isbn/'+isbn).read().decode('utf-8', 'replace')
except Exception, err: except Exception, err:
@ -55,7 +63,7 @@ def cover_from_isbn(isbn, timeout=5.):
url = url.find('img') url = url.find('img')
if url is None: if url is None:
raise LibraryThingError(_('LibraryThing.com server error. Try again later.')) raise LibraryThingError(_('LibraryThing.com server error. Try again later.'))
url = re.sub(r'_SX\d+', '', url['src']) url = re.sub(r'_S[XY]\d+', '', url['src'])
cover_data = browser.open(url).read() cover_data = browser.open(url).read()
return cover_data, url.rpartition('.')[-1] return cover_data, url.rpartition('.')[-1]
finally: finally:
@ -68,9 +76,9 @@ _('''
Fetch a cover image for the book identified by ISBN from LibraryThing.com Fetch a cover image for the book identified by ISBN from LibraryThing.com
''')) '''))
parser.add_option('-u', '--username', default=None, parser.add_option('-u', '--username', default=None,
help='Username for LibraryThing.com') help='Username for LibraryThing.com')
parser.add_option('-p', '--password', default=None, parser.add_option('-p', '--password', default=None,
help='Password for LibraryThing.com') help='Password for LibraryThing.com')
return parser return parser
@ -81,13 +89,8 @@ def main(args=sys.argv):
parser.print_help() parser.print_help()
return 1 return 1
isbn = args[1] isbn = args[1]
if opts.username and opts.password: cover_data, ext = cover_from_isbn(isbn, username=opts.username,
try: password=opts.password)
login(opts.username, opts.password)
except mechanize.FormNotFoundError:
raise LibraryThingError(_('LibraryThing.com server error. Try again later.'))
cover_data, ext = cover_from_isbn(isbn)
if not ext: if not ext:
ext = 'jpg' ext = 'jpg'
oname = os.path.abspath(isbn+'.'+ext) oname = os.path.abspath(isbn+'.'+ext)
@ -96,4 +99,4 @@ def main(args=sys.argv):
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())

View File

@ -20,12 +20,11 @@ from calibre.gui2.dialogs.password import PasswordDialog
from calibre.gui2.widgets import ProgressIndicator from calibre.gui2.widgets import ProgressIndicator
from calibre.ebooks import BOOK_EXTENSIONS from calibre.ebooks import BOOK_EXTENSIONS
from calibre.ebooks.metadata import authors_to_sort_string, string_to_authors, authors_to_string from calibre.ebooks.metadata import authors_to_sort_string, string_to_authors, authors_to_string
from calibre.ebooks.metadata.library_thing import login, cover_from_isbn from calibre.ebooks.metadata.library_thing import cover_from_isbn
from calibre import islinux from calibre import islinux
from calibre.ebooks.metadata.meta import get_metadata from calibre.ebooks.metadata.meta import get_metadata
from calibre.utils.config import prefs from calibre.utils.config import prefs
from calibre.customize.ui import run_plugins_on_import from calibre.customize.ui import run_plugins_on_import
from calibre.gui2 import config as gui_conf
class CoverFetcher(QThread): class CoverFetcher(QThread):
@ -60,9 +59,8 @@ class CoverFetcher(QThread):
return return
self.isbn = results[0] self.isbn = results[0]
if self.username and self.password: self.cover_data = cover_from_isbn(self.isbn, timeout=self.timeout,
login(self.username, self.password, force=False) username=self.username, password=self.password)[0]
self.cover_data = cover_from_isbn(self.isbn, timeout=self.timeout)[0]
except Exception, e: except Exception, e:
self.exception = e self.exception = e
self.traceback = traceback.format_exc() self.traceback = traceback.format_exc()
@ -290,7 +288,6 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
self.series_index.setValue(self.db.series_index(row)) self.series_index.setValue(self.db.series_index(row))
QObject.connect(self.series, SIGNAL('currentIndexChanged(int)'), self.enable_series_index) QObject.connect(self.series, SIGNAL('currentIndexChanged(int)'), self.enable_series_index)
QObject.connect(self.series, SIGNAL('editTextChanged(QString)'), self.enable_series_index) QObject.connect(self.series, SIGNAL('editTextChanged(QString)'), self.enable_series_index)
QObject.connect(self.password_button, SIGNAL('clicked()'), self.change_password)
self.show() self.show()
height_of_rest = self.frameGeometry().height() - self.cover.height() height_of_rest = self.frameGeometry().height() - self.cover.height()
@ -378,15 +375,15 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
def fetch_cover(self): def fetch_cover(self):
isbn = unicode(self.isbn.text()).strip() isbn = unicode(self.isbn.text()).strip()
d = self.lt_password_dialog() #d = self.lt_password_dialog()
if not gui_conf['asked_library_thing_password'] and \ #if not gui_conf['asked_library_thing_password'] and \
(not d.username() or not d.password()): # (not d.username() or not d.password()):
d.exec_() # d.exec_()
gui_conf['asked_library_thing_password'] = True # gui_conf['asked_library_thing_password'] = True
self.fetch_cover_button.setEnabled(False) self.fetch_cover_button.setEnabled(False)
self.setCursor(Qt.WaitCursor) self.setCursor(Qt.WaitCursor)
title, author = map(unicode, (self.title.text(), self.authors.text())) title, author = map(unicode, (self.title.text(), self.authors.text()))
self.cover_fetcher = CoverFetcher(d.username(), d.password(), isbn, self.cover_fetcher = CoverFetcher(None, None, isbn,
self.timeout, title, author) self.timeout, title, author)
self.cover_fetcher.start() self.cover_fetcher.start()
self._hangcheck = QTimer(self) self._hangcheck = QTimer(self)

View File

@ -589,17 +589,7 @@
<item> <item>
<widget class="QPushButton" name="fetch_cover_button"> <widget class="QPushButton" name="fetch_cover_button">
<property name="text"> <property name="text">
<string>Fetch &amp;cover image from server</string> <string>Download &amp;cover</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="password_button">
<property name="toolTip">
<string>Change the username and/or password for your account at LibraryThing.com</string>
</property>
<property name="text">
<string>Change &amp;password</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -655,7 +645,6 @@
<tabstop>comments</tabstop> <tabstop>comments</tabstop>
<tabstop>fetch_metadata_button</tabstop> <tabstop>fetch_metadata_button</tabstop>
<tabstop>fetch_cover_button</tabstop> <tabstop>fetch_cover_button</tabstop>
<tabstop>password_button</tabstop>
<tabstop>formats</tabstop> <tabstop>formats</tabstop>
<tabstop>add_format_button</tabstop> <tabstop>add_format_button</tabstop>
<tabstop>remove_format_button</tabstop> <tabstop>remove_format_button</tabstop>

View File

@ -266,7 +266,7 @@ class BasicNewsRecipe(object):
def get_feeds(self): def get_feeds(self):
''' '''
Return a list of :term:RSS feeds to fetch for this profile. Each element of the list Return a list of :term:`RSS` feeds to fetch for this profile. Each element of the list
must be a 2-element tuple of the form (title, url). If title is None or an must be a 2-element tuple of the form (title, url). If title is None or an
empty string, the title from the feed is used. This method is useful if your recipe empty string, the title from the feed is used. This method is useful if your recipe
needs to do some processing to figure out the list of feeds to download. If needs to do some processing to figure out the list of feeds to download. If