Upgrade python error checker to use pyflakes 0.4 and fix te new errors found by it

This commit is contained in:
Kovid Goyal 2009-12-01 17:57:49 +00:00
parent c1bad65f7f
commit 1327e15337
53 changed files with 163 additions and 901 deletions

View File

@ -11,7 +11,7 @@ from calibre.web.feeds.news import BasicNewsRecipe
class ChicagoBreakingNews(BasicNewsRecipe): class ChicagoBreakingNews(BasicNewsRecipe):
title = 'Chicago Breaking News' title = 'Chicago Breaking News'
__author__ = 'Darko Miletic' __author__ = 'Darko Miletic'
description = 'Breaking News from Chicago' description = 'Breaking News from Chicago'
oldest_article = 1 oldest_article = 1
max_articles_per_feed = 100 max_articles_per_feed = 100
no_stylesheets = True no_stylesheets = True
@ -21,19 +21,18 @@ class ChicagoBreakingNews(BasicNewsRecipe):
encoding = 'utf8' encoding = 'utf8'
language = 'en' language = 'en'
html2lrf_options = [ html2lrf_options = [
'--comment', description '--comment', description
, '--category', category , '--category', category
, '--publisher', publisher , '--publisher', publisher
] ]
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"' html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
feeds = [(u'Breaking news', u'http://feeds2.feedburner.com/ChicagoBreakingNews/')] feeds = [(u'Breaking news', u'http://feeds2.feedburner.com/ChicagoBreakingNews/')]
def preprocess_html(self, soup): def preprocess_html(self, soup):
links = soup.findAll('a')
for item in soup.findAll('a'): for item in soup.findAll('a'):
if item['href'].find('http://feedads.googleadservices.com') > -1: if item['href'].find('http://feedads.googleadservices.com') > -1:
item.extract() item.extract()

View File

@ -80,7 +80,6 @@ class GlasSrpske(BasicNewsRecipe):
for item in soup.findAll('div', attrs={'class':'gl_rub'}): for item in soup.findAll('div', attrs={'class':'gl_rub'}):
atag = item.find('a') atag = item.find('a')
ptag = item.find('p') ptag = item.find('p')
datetag = item.find('span')
url = self.INDEX + atag['href'] url = self.INDEX + atag['href']
title = self.tag_to_string(atag) title = self.tag_to_string(atag)
description = self.tag_to_string(ptag) description = self.tag_to_string(ptag)

View File

@ -147,7 +147,6 @@ class NYTimes(BasicNewsRecipe):
# Fetch the outer table # Fetch the outer table
table = soup.find('table') table = soup.find('table')
previousTable = table previousTable = table
contentTable = None
# Find the deepest table containing the stories # Find the deepest table containing the stories
while True : while True :

View File

@ -53,8 +53,8 @@ class NYTimes(BasicNewsRecipe):
articles = {} articles = {}
key = None key = None
ans = [] ans = []
allSectionKeywords = ['The Front Page', 'International','National','Obituaries','Editorials', #allSectionKeywords = ['The Front Page', 'International','National','Obituaries','Editorials',
'New York','Business Day','Sports','Dining','Arts','Home','Styles'] #'New York','Business Day','Sports','Dining','Arts','Home','Styles']
excludeSectionKeywords = ['Dining','Styles'] excludeSectionKeywords = ['Dining','Styles']

View File

@ -71,7 +71,6 @@ class ScientificAmerican(BasicNewsRecipe):
feeds.append(('Features', features)) feeds.append(('Features', features))
section = [] section = []
found = []
title = None title = None
for x in soup.find(id='magazine-main_col1').findAll(['div', 'a']): for x in soup.find(id='magazine-main_col1').findAll(['div', 'a']):

View File

@ -72,7 +72,6 @@ class Time(BasicNewsRecipe):
return feeds return feeds
def find_articles(self, seched): def find_articles(self, seched):
articles = []
for a in seched.findNextSiblings( attrs={'class':['toc_hed','rule2']}): for a in seched.findNextSiblings( attrs={'class':['toc_hed','rule2']}):
if a.name in "div": if a.name in "div":
break break

View File

@ -1,76 +1,76 @@
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import Tag from calibre.ebooks.BeautifulSoup import Tag
class VrijNederlandRecipe(BasicNewsRecipe) : class VrijNederlandRecipe(BasicNewsRecipe) :
__license__ = 'GPL v3' __license__ = 'GPL v3'
__author__ = 'kwetal' __author__ = 'kwetal'
language = 'nl_NL' language = 'nl_NL'
locale = 'nl_NL' locale = 'nl_NL'
version = 1 version = 1
title = u'Vrij Nederland' title = u'Vrij Nederland'
publisher = u'Weekbladpers Tijdschriften' publisher = u'Weekbladpers Tijdschriften'
category = u'News, Opinion' category = u'News, Opinion'
description = u'Weekly opinion magazine from the Netherlands' description = u'Weekly opinion magazine from the Netherlands'
oldest_article = 7 oldest_article = 7
max_articles_per_feed = 100 max_articles_per_feed = 100
use_embedded_content = False use_embedded_content = False
no_stylesheets = True no_stylesheets = True
remove_javascript = True remove_javascript = True
# Does not seem to work # Does not seem to work
#extra_css = '''li.calibre2 {padding-bottom: 40px}''' #extra_css = '''li.calibre2 {padding-bottom: 40px}'''
conversion_options = {'publisher': publisher, 'tags': category, 'comments': description} conversion_options = {'publisher': publisher, 'tags': category, 'comments': description}
feeds = [] feeds = []
feeds.append((u'Politiek', u'http://www.vn.nl/politiek.rss')) feeds.append((u'Politiek', u'http://www.vn.nl/politiek.rss'))
feeds.append((u'Buitenland', u'http://www.vn.nl/buitenland.rss')) feeds.append((u'Buitenland', u'http://www.vn.nl/buitenland.rss'))
feeds.append((u'Economie', u'http://www.vn.nl/economie.rss')) feeds.append((u'Economie', u'http://www.vn.nl/economie.rss'))
feeds.append((u'Justitie', u'http://www.vn.nl/justitie.rss')) feeds.append((u'Justitie', u'http://www.vn.nl/justitie.rss'))
feeds.append((u'Samenleving', u'http://www.vn.nl/samenleving.rss')) feeds.append((u'Samenleving', u'http://www.vn.nl/samenleving.rss'))
feeds.append((u'Crime', u'http://www.vn.nl/crime.rss')) feeds.append((u'Crime', u'http://www.vn.nl/crime.rss'))
feeds.append((u'Media', u'http://www.vn.nl/media.rss')) feeds.append((u'Media', u'http://www.vn.nl/media.rss'))
feeds.append((u'De Republiek der Letteren', u'http://www.vn.nl/republiek.rss')) feeds.append((u'De Republiek der Letteren', u'http://www.vn.nl/republiek.rss'))
feeds.append((u'Max van Weezel', u'http://www.vn.nl/vanweezel.rss')) feeds.append((u'Max van Weezel', u'http://www.vn.nl/vanweezel.rss'))
feeds.append((u'Ko Colijn', u'http://www.vn.nl/colijn.rss')) feeds.append((u'Ko Colijn', u'http://www.vn.nl/colijn.rss'))
feeds.append((u'Kees Kraaijeveld', u'http://www.vn.nl/kraaijeveld.rss')) feeds.append((u'Kees Kraaijeveld', u'http://www.vn.nl/kraaijeveld.rss'))
feeds.append((u'Frank Kalshoven', u'http://www.vn.nl/kalshoven.rss')) feeds.append((u'Frank Kalshoven', u'http://www.vn.nl/kalshoven.rss'))
feeds.append((u'Stephan Sanders', u'http://www.vn.nl/sanders.rss')) feeds.append((u'Stephan Sanders', u'http://www.vn.nl/sanders.rss'))
feeds.append((u'Micha Wertheim', u'http://www.vn.nl/wertheim.rss')) feeds.append((u'Micha Wertheim', u'http://www.vn.nl/wertheim.rss'))
feeds.append((u'Arnon Grunberg', u'http://www.vn.nl/grunberg.rss')) feeds.append((u'Arnon Grunberg', u'http://www.vn.nl/grunberg.rss'))
feeds.append((u'Carel Peeters', u'http://www.vn.nl/carelpeeters.rss')) feeds.append((u'Carel Peeters', u'http://www.vn.nl/carelpeeters.rss'))
keep_only_tags = [dict(name = 'div', attrs = {'class' : 'cl-column column-one'})] keep_only_tags = [dict(name = 'div', attrs = {'class' : 'cl-column column-one'})]
remove_tags = [] remove_tags = []
remove_tags.append(dict(name = 'div', attrs = {'class' : 'wpg-element guest-book-overview'})) remove_tags.append(dict(name = 'div', attrs = {'class' : 'wpg-element guest-book-overview'}))
remove_tags.append(dict(name = 'div', attrs = {'class' : 'wpg-element forum-message-form'})) remove_tags.append(dict(name = 'div', attrs = {'class' : 'wpg-element forum-message-form'}))
remove_tags.append(dict(name = 'div', attrs = {'class' : 'mediaterms'})) remove_tags.append(dict(name = 'div', attrs = {'class' : 'mediaterms'}))
remove_tags.append(dict(name = 'div', attrs = {'class': 'label-term'})) remove_tags.append(dict(name = 'div', attrs = {'class': 'label-term'}))
remove_tags.append(dict(name = 'div', attrs = {'class': 'wpg-element Media-Collection-Element-Artikel-Lijst'})) remove_tags.append(dict(name = 'div', attrs = {'class': 'wpg-element Media-Collection-Element-Artikel-Lijst'}))
remove_tags.append(dict(name = 'object')) remove_tags.append(dict(name = 'object'))
remove_tags.append(dict(name = 'link')) remove_tags.append(dict(name = 'link'))
remove_tags.append(dict(name = 'meta')) remove_tags.append(dict(name = 'meta'))
def preprocess_html(self, soup): def preprocess_html(self, soup):
# Just clean up the result a little # Just clean up the result a little
meta = soup.find('div', attrs = {'class': 'meta'}) meta = soup.find('div', attrs = {'class': 'meta'})
if meta: if meta:
link = meta.find('span', attrs = {'class': 'link'}) link = meta.find('span', attrs = {'class': 'link'})
if link: if link:
link.extract() link.extract()
for seperator in meta.findAll('span', attrs = {'class': 'seperator'}): for seperator in meta.findAll('span', attrs = {'class': 'seperator'}):
seperator.extract() seperator.extract()
# Their header is full of 'if IE6/7/8' tags. Just get rid of it altogether # Their header is full of 'if IE6/7/8' tags. Just get rid of it altogether
theirHead = soup.head theirHead = soup.head
theirHead.extract() theirHead.extract()
myHead = Tag(soup, 'head') myHead = Tag(soup, 'head')
soup.insert(0, myHead) soup.insert(0, myHead)
return soup return soup

View File

@ -7,33 +7,57 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import sys, os, cPickle, subprocess import sys, os, cPickle, subprocess
from operator import attrgetter
from setup import Command from setup import Command
import __builtin__
def check_for_python_errors(filename, builtins): def set_builtins(builtins):
from pyflakes import checker, ast for x in builtins:
if not hasattr(__builtin__, x):
setattr(__builtin__, x, True)
yield x
contents = open(filename, 'rb').read() class Message:
def __init__(self, filename, lineno, msg):
self.filename, self.lineno, self.msg = filename, lineno, msg
def __str__(self):
return '%s:%s: %s'%(self.filename, self.lineno, self.msg)
def check_for_python_errors(code_string, filename):
# Since compiler.parse does not reliably report syntax errors, use the
# built in compiler first to detect those.
try: try:
tree = ast.parse(contents, filename)
except:
import traceback
traceback.print_exc()
try: try:
value = sys.exc_info()[1] compile(code_string, filename, "exec")
lineno, offset, line = value[1][1:] except MemoryError:
except IndexError: # Python 2.4 will raise MemoryError if the source can't be
lineno, offset, line = 1, 0, '' # decoded.
if line.endswith("\n"): if sys.version_info[:2] == (2, 4):
line = line[:-1] raise SyntaxError(None)
raise
except (SyntaxError, IndentationError), value:
msg = value.args[0]
return [SyntaxError(filename, lineno, offset, str(value))] (lineno, offset, text) = value.lineno, value.offset, value.text
# If there's an encoding problem with the file, the text is None.
if text is None:
# Avoid using msg, since for the only known case, it contains a
# bogus message that claims the encoding the file declared was
# unknown.
msg = "%s: problem decoding source" % filename
return [Message(filename, lineno, msg)]
else: else:
w = checker.Checker(tree, filename, builtins = builtins) # Okay, it's syntactically valid. Now parse it into an ast and check
w.messages.sort(key = attrgetter('lineno')) # it.
return w.messages import compiler
checker = __import__('pyflakes.checker').checker
tree = compiler.parse(code_string)
w = checker.Checker(tree, filename)
w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno))
return [Message(x.filename, x.lineno, x.message%x.message_args) for x in
w.messages]
class Check(Command): class Check(Command):
@ -65,15 +89,18 @@ class Check(Command):
cache = {} cache = {}
if os.path.exists(self.CACHE): if os.path.exists(self.CACHE):
cache = cPickle.load(open(self.CACHE, 'rb')) cache = cPickle.load(open(self.CACHE, 'rb'))
builtins = list(set_builtins(self.BUILTINS))
for f, mtime in self.get_files(cache): for f, mtime in self.get_files(cache):
self.info('\tChecking', f) self.info('\tChecking', f)
w = check_for_python_errors(f, self.BUILTINS) w = check_for_python_errors(open(f, 'rb').read(), f)
if w: if w:
self.report_errors(w) self.report_errors(w)
cPickle.dump(cache, open(self.CACHE, 'wb'), -1) cPickle.dump(cache, open(self.CACHE, 'wb'), -1)
subprocess.call(['gvim', '-f', f]) subprocess.call(['gvim', '-f', f])
raise SystemExit(1) raise SystemExit(1)
cache[f] = mtime cache[f] = mtime
for x in builtins:
delattr(__builtin__, x)
cPickle.dump(cache, open(self.CACHE, 'wb'), -1) cPickle.dump(cache, open(self.CACHE, 'wb'), -1)
wn_path = os.path.expanduser('~/work/servers/src/calibre_servers/main') wn_path = os.path.expanduser('~/work/servers/src/calibre_servers/main')
if os.path.exists(wn_path): if os.path.exists(wn_path):
@ -85,11 +112,5 @@ class Check(Command):
def report_errors(self, errors): def report_errors(self, errors):
for err in errors: for err in errors:
if isinstance(err, SyntaxError): self.info('\t\t', str(err))
print '\t\tSyntax Error'
else:
col = getattr(err, 'col', 0) if getattr(err, 'col', 0) else 0
lineno = err.lineno if err.lineno else 0
self.info('\t\t%d:%d:'%(lineno, col),
err.message%err.message_args)

View File

@ -606,7 +606,6 @@ class Device(DeviceConfig, DevicePlugin):
def eject_linux(self): def eject_linux(self):
drives = self.find_device_nodes() drives = self.find_device_nodes()
success = False
for drive in drives: for drive in drives:
if drive: if drive:
cmd = 'calibre-mount-helper' cmd = 'calibre-mount-helper'

View File

@ -43,7 +43,6 @@ class FB2Input(InputFormatPlugin):
from calibre.ebooks.oeb.base import XLINK_NS from calibre.ebooks.oeb.base import XLINK_NS
NAMESPACES = {'f':FB2NS, 'l':XLINK_NS} NAMESPACES = {'f':FB2NS, 'l':XLINK_NS}
log.debug('Parsing XML...') log.debug('Parsing XML...')
parser = etree.XMLParser(recover=True, no_network=True)
doc = etree.fromstring(stream.read()) doc = etree.fromstring(stream.read())
self.extract_embedded_content(doc) self.extract_embedded_content(doc)
log.debug('Converting XML to HTML...') log.debug('Converting XML to HTML...')

View File

@ -106,7 +106,7 @@ def process_file(lrfpath, opts, logger=None):
os.makedirs(opts.out) os.makedirs(opts.out)
document = LRFDocument(open(lrfpath, 'rb')) document = LRFDocument(open(lrfpath, 'rb'))
conv = LRFConverter(document, opts, logger) LRFConverter(document, opts, logger)
def main(args=sys.argv): def main(args=sys.argv):

View File

@ -2207,7 +2207,7 @@ class JumpButton(LrsObject, LrsContainer):
def toElement(self, se): def toElement(self, se):
b = self.lrsObjectElement("Button") b = self.lrsObjectElement("Button")
pb = SubElement(b, "PushButton") pb = SubElement(b, "PushButton")
jt = SubElement(pb, "JumpTo", SubElement(pb, "JumpTo",
refpage=str(self.textBlock.parent.objId), refpage=str(self.textBlock.parent.objId),
refobj=str(self.textBlock.objId)) refobj=str(self.textBlock.objId))
return b return b

View File

@ -323,7 +323,7 @@ class MobiReader(object):
self.log.warning('Malformed markup, parsing using BeautifulSoup') self.log.warning('Malformed markup, parsing using BeautifulSoup')
try: try:
root = soupparser.fromstring(self.processed_html) root = soupparser.fromstring(self.processed_html)
except Exception, err: except Exception:
self.log.warning('MOBI markup appears to contain random bytes. Stripping.') self.log.warning('MOBI markup appears to contain random bytes. Stripping.')
self.processed_html = self.remove_random_bytes(self.processed_html) self.processed_html = self.remove_random_bytes(self.processed_html)
root = soupparser.fromstring(self.processed_html) root = soupparser.fromstring(self.processed_html)

View File

@ -510,7 +510,7 @@ class MobiWriter(object):
self._oeb.log.warning('_generate_flat_indexed_navpoints: Failed to generate index') self._oeb.log.warning('_generate_flat_indexed_navpoints: Failed to generate index')
# Zero out self._HTMLRecords, return False # Zero out self._HTMLRecords, return False
self._HTMLRecords = [] self._HTMLRecords = []
last_name = None #last_name = None
return False return False
previousOffset = offset previousOffset = offset
@ -545,7 +545,7 @@ class MobiWriter(object):
if self.opts.verbose > 3 : self._oeb.logger.info(" node %03d: %-15.15s... spans HTML records %03d - %03d \t offset: 0x%06X length: 0x%06X" % \ if self.opts.verbose > 3 : self._oeb.logger.info(" node %03d: %-15.15s... spans HTML records %03d - %03d \t offset: 0x%06X length: 0x%06X" % \
(myIndex, child.title if child.title.strip() > "" else "(missing)", myStartingRecord, myStartingRecord, offset, length) ) (myIndex, child.title if child.title.strip() > "" else "(missing)", myStartingRecord, myStartingRecord, offset, length) )
last_name = "%04X" % myIndex #last_name = "%04X" % myIndex
myIndex += 1 myIndex += 1
# Successfully parsed the entries # Successfully parsed the entries
@ -625,7 +625,7 @@ class MobiWriter(object):
self._oeb.log.warning('_generate_indexed_navpoints: Failed to generate index') self._oeb.log.warning('_generate_indexed_navpoints: Failed to generate index')
# Zero out self._HTMLRecords, return False # Zero out self._HTMLRecords, return False
self._HTMLRecords = [] self._HTMLRecords = []
last_name = None #last_name = None
return False return False
previousOffset = offset previousOffset = offset
@ -659,7 +659,7 @@ class MobiWriter(object):
# *** This should check currentSectionNumber, because content could start late # *** This should check currentSectionNumber, because content could start late
if thisRecord > 0: if thisRecord > 0:
sectionChangesInThisRecord = True sectionChangesInThisRecord = True
sectionChangesInRecordNumber = thisRecord #sectionChangesInRecordNumber = thisRecord
self._currentSectionIndex += 1 self._currentSectionIndex += 1
self._HTMLRecords[thisRecord].nextSectionNumber = self._currentSectionIndex self._HTMLRecords[thisRecord].nextSectionNumber = self._currentSectionIndex
# The following node opens the nextSection # The following node opens the nextSection
@ -717,7 +717,7 @@ class MobiWriter(object):
if self.opts.verbose > 3 : self._oeb.logger.info(" node: %03d %-10.10s %-15.15s... spans HTML records %03d-%03d \t offset: 0x%06X length: 0x%06X" % \ if self.opts.verbose > 3 : self._oeb.logger.info(" node: %03d %-10.10s %-15.15s... spans HTML records %03d-%03d \t offset: 0x%06X length: 0x%06X" % \
(myIndex, self._ctoc_map[i]['klass'], child.title if child.title.strip() > "" else "(missing)", thisRecord, thisRecord, offset, length) ) (myIndex, self._ctoc_map[i]['klass'], child.title if child.title.strip() > "" else "(missing)", thisRecord, thisRecord, offset, length) )
last_name = "%04X" % myIndex #last_name = "%04X" % myIndex
myIndex += 1 myIndex += 1
# Successfully parsed the entries # Successfully parsed the entries
@ -1999,7 +1999,7 @@ class MobiWriter(object):
self._articleCount = 0 self._articleCount = 0
self._chapterCount = 0 self._chapterCount = 0
first = True #first = True
if self._conforming_periodical_toc : if self._conforming_periodical_toc :
self._oeb.logger.info('Generating structured CTOC ...') self._oeb.logger.info('Generating structured CTOC ...')
@ -2007,7 +2007,7 @@ class MobiWriter(object):
if self.opts.verbose > 2 : if self.opts.verbose > 2 :
self._oeb.logger.info(" %s" % child) self._oeb.logger.info(" %s" % child)
self._add_structured_ctoc_node(child, self._ctoc) self._add_structured_ctoc_node(child, self._ctoc)
first = False #first = False
else : else :
self._oeb.logger.info('Generating flat CTOC ...') self._oeb.logger.info('Generating flat CTOC ...')
@ -2025,7 +2025,6 @@ class MobiWriter(object):
# Test to see if this child's offset is the same as the previous child's # Test to see if this child's offset is the same as the previous child's
# offset, skip it # offset, skip it
h = child.href h = child.href
first = False
if h is None: if h is None:
self._oeb.logger.warn(' Ignoring TOC entry with no href:', self._oeb.logger.warn(' Ignoring TOC entry with no href:',
@ -2345,7 +2344,7 @@ class MobiWriter(object):
self._oeb.logger.info( "Writing NCXEntries for mobiType 0x%03X" % myDoc.mobiType) self._oeb.logger.info( "Writing NCXEntries for mobiType 0x%03X" % myDoc.mobiType)
sectionParent = myDoc.documentStructure.sectionParents[0] sectionParent = myDoc.documentStructure.sectionParents[0]
articleCount = len(sectionParent.articles) #articleCount = len(sectionParent.articles)
# Write opening periodical 0xDF entry # Write opening periodical 0xDF entry
index = 0 index = 0
@ -2361,7 +2360,7 @@ class MobiWriter(object):
while sectionCount <= lastSection : while sectionCount <= lastSection :
# section # section
sectionParent = myDoc.documentStructure.sectionParents[sectionCount - 1] sectionParent = myDoc.documentStructure.sectionParents[sectionCount - 1]
articleCount = len(sectionParent.articles) #articleCount = len(sectionParent.articles)
#index += 1 #index += 1
offset = sectionParent.startAddress offset = sectionParent.startAddress
length = sectionParent.sectionLength length = sectionParent.sectionLength

View File

@ -168,7 +168,6 @@ class OEBReader(object):
manifest = self.oeb.manifest manifest = self.oeb.manifest
known = set(manifest.hrefs) known = set(manifest.hrefs)
unchecked = set(manifest.values()) unchecked = set(manifest.values())
bad = []
while unchecked: while unchecked:
new = set() new = set()
for item in unchecked: for item in unchecked:

View File

@ -103,7 +103,7 @@ def run(opts, pathtopdf, log):
pdfreflow.reflow(data) pdfreflow.reflow(data)
index = os.path.join(os.getcwdu(), 'index.xml') index = os.path.join(os.getcwdu(), 'index.xml')
xml = open(index, 'rb').read() xml = open(index, 'rb').read()
#pdfdoc = PDFDocument(xml, opts, log) PDFDocument(xml, opts, log)
def option_parser(): def option_parser():
from optparse import OptionParser from optparse import OptionParser

View File

@ -20,7 +20,7 @@ def is_valid_pdf(pdf_path):
try: try:
with open(os.path.abspath(pdf_path), 'rb') as pdf_file: with open(os.path.abspath(pdf_path), 'rb') as pdf_file:
pdf = PdfFileReader(pdf_file) PdfFileReader(pdf_file)
except: except:
return False return False
return True return True

View File

@ -610,7 +610,6 @@ class DeviceGUI(object):
def emails_sent(self, results, remove=[]): def emails_sent(self, results, remove=[]):
errors, good = [], [] errors, good = [], []
for jobname, exception, tb in results: for jobname, exception, tb in results:
id = jobname.partition(':')[0]
title = jobname.partition(':')[-1] title = jobname.partition(':')[-1]
if exception is not None: if exception is not None:
errors.append([title, exception, tb]) errors.append([title, exception, tb])

View File

@ -135,7 +135,7 @@ class FetchMetadata(QDialog, Ui_FetchMetadata):
set_isbndb_key(key) set_isbndb_key(key)
else: else:
key = None key = None
title = author = publisher = isbn = pubdate = None title = author = publisher = isbn = None
if self.isbn: if self.isbn:
isbn = self.isbn isbn = self.isbn
if self.title: if self.title:

View File

@ -50,7 +50,7 @@ class TagEditor(QDialog, Ui_TagEditor):
confirms, deletes = [], [] confirms, deletes = [], []
items = self.available_tags.selectedItems() if item is None else [item] items = self.available_tags.selectedItems() if item is None else [item]
if not items: if not items:
d = error_dialog(self, 'No tags selected', 'You must select at least one tag from the list of Available tags.').exec_() error_dialog(self, 'No tags selected', 'You must select at least one tag from the list of Available tags.').exec_()
return return
for item in items: for item in items:
if self.db.is_tag_used(qstring_to_unicode(item.text())): if self.db.is_tag_used(qstring_to_unicode(item.text())):

View File

@ -125,7 +125,6 @@ class JobManager(QAbstractTableModel):
def _update(self): def _update(self):
# Update running time # Update running time
rows = set([])
for i, j in enumerate(self.jobs): for i, j in enumerate(self.jobs):
if j.run_state == j.RUNNING: if j.run_state == j.RUNNING:
idx = self.index(i, 3) idx = self.index(i, 3)

View File

@ -186,7 +186,7 @@ class TextBlock(object):
try: try:
self.populate(tb.content) self.populate(tb.content)
self.end_line() self.end_line()
except TextBlock.HeightExceeded, err: except TextBlock.HeightExceeded:
pass pass
#logger.warning('TextBlock height exceeded, skipping line:\n%s'%(err,)) #logger.warning('TextBlock height exceeded, skipping line:\n%s'%(err,))

View File

@ -440,7 +440,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.stack.setCurrentIndex(0) self.stack.setCurrentIndex(0)
try: try:
db = LibraryDatabase2(self.library_path) db = LibraryDatabase2(self.library_path)
except Exception, err: except Exception:
import traceback import traceback
error_dialog(self, _('Bad database location'), error_dialog(self, _('Bad database location'),
_('Bad database location')+':'+self.library_path, _('Bad database location')+':'+self.library_path,
@ -1033,7 +1033,6 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
def download_metadata(self, checked, covers=True, set_metadata=True, def download_metadata(self, checked, covers=True, set_metadata=True,
set_social_metadata=None): set_social_metadata=None):
rows = self.library_view.selectionModel().selectedRows() rows = self.library_view.selectionModel().selectedRows()
previous = self.library_view.currentIndex()
if not rows or len(rows) == 0: if not rows or len(rows) == 0:
d = error_dialog(self, _('Cannot download metadata'), d = error_dialog(self, _('Cannot download metadata'),
_('No books selected')) _('No books selected'))
@ -1071,7 +1070,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
x = self._download_book_metadata x = self._download_book_metadata
self._download_book_metadata = None self._download_book_metadata = None
if x.exception is None: if x.exception is None:
db = self.library_view.model().refresh_ids( self.library_view.model().refresh_ids(
x.updated, cr) x.updated, cr)
if x.failures: if x.failures:
details = ['%s: %s'%(title, reason) for title, details = ['%s: %s'%(title, reason) for title,

View File

@ -141,6 +141,7 @@ class TagsModel(QAbstractItemModel):
data=self.categories[i], category_icon=self.cmap[i]) data=self.categories[i], category_icon=self.cmap[i])
for tag in data[r]: for tag in data[r]:
t = TagTreeItem(parent=c, data=tag, icon_map=self.icon_map) t = TagTreeItem(parent=c, data=tag, icon_map=self.icon_map)
t
self.db.add_listener(self.database_changed) self.db.add_listener(self.database_changed)
self.connect(self, SIGNAL('need_refresh()'), self.refresh, self.connect(self, SIGNAL('need_refresh()'), self.refresh,
@ -229,7 +230,6 @@ class TagsModel(QAbstractItemModel):
def reset_all_states(self): def reset_all_states(self):
for i in xrange(self.rowCount(QModelIndex())): for i in xrange(self.rowCount(QModelIndex())):
category_index = self.index(i, 0, QModelIndex()) category_index = self.index(i, 0, QModelIndex())
category_item = category_index.internalPointer()
for j in xrange(self.rowCount(category_index)): for j in xrange(self.rowCount(category_index)):
tag_index = self.index(j, 0, category_index) tag_index = self.index(j, 0, category_index)
tag_item = tag_index.internalPointer() tag_item = tag_index.internalPointer()

View File

@ -95,10 +95,6 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, out_format
return jobs, changed, bad return jobs, changed, bad
def convert_bulk_ebook(parent, queue, db, book_ids, out_format=None, args=[]): def convert_bulk_ebook(parent, queue, db, book_ids, out_format=None, args=[]):
changed = False
jobs = []
bad = []
total = len(book_ids) total = len(book_ids)
if total == 0: if total == 0:
return None, None, None return None, None, None

View File

@ -437,7 +437,7 @@ def move_library(oldloc, newloc, parent, callback_on_complete):
# Try to load existing library at new location # Try to load existing library at new location
try: try:
ndb = LibraryDatabase2(newloc) LibraryDatabase2(newloc)
except Exception, err: except Exception, err:
det = traceback.format_exc() det = traceback.format_exc()
error_dialog(parent, _('Invalid database'), error_dialog(parent, _('Invalid database'),

View File

@ -889,10 +889,8 @@ class LibraryDatabase2(LibraryDatabase):
def formats(self, index, index_is_id=False): def formats(self, index, index_is_id=False):
''' Return available formats as a comma separated list or None if there are no available formats ''' ''' Return available formats as a comma separated list or None if there are no available formats '''
id = index if index_is_id else self.id(index) id = index if index_is_id else self.id(index)
path = os.path.join(self.library_path, self.path(id, index_is_id=True))
try: try:
formats = self.conn.get('SELECT format FROM data WHERE book=?', (id,)) formats = self.conn.get('SELECT format FROM data WHERE book=?', (id,))
name = self.conn.get('SELECT name FROM data WHERE book=?', (id,), all=False)
formats = map(lambda x:x[0], formats) formats = map(lambda x:x[0], formats)
except: except:
return None return None
@ -910,7 +908,10 @@ class LibraryDatabase2(LibraryDatabase):
def format_abspath(self, index, format, index_is_id=False): def format_abspath(self, index, format, index_is_id=False):
'Return absolute path to the ebook file of format `format`' 'Return absolute path to the ebook file of format `format`'
id = index if index_is_id else self.id(index) id = index if index_is_id else self.id(index)
name = self.conn.get('SELECT name FROM data WHERE book=? AND format=?', (id, format), all=False) try:
name = self.conn.get('SELECT name FROM data WHERE book=? AND format=?', (id, format), all=False)
except:
return None
if name: if name:
path = os.path.join(self.library_path, self.path(id, index_is_id=True)) path = os.path.join(self.library_path, self.path(id, index_is_id=True))
format = ('.' + format.lower()) if format else '' format = ('.' + format.lower()) if format else ''
@ -1813,11 +1814,9 @@ books_series_link feeds
else: else:
actual_formats = [x.lower() for x in actual_formats.split(',')] actual_formats = [x.lower() for x in actual_formats.split(',')]
mismatch = False
for fmt in formats: for fmt in formats:
if fmt in actual_formats: if fmt in actual_formats:
continue continue
mismatch = True
if id not in bad: if id not in bad:
bad[id] = [] bad[id] = []
bad[id].append(fmt) bad[id].append(fmt)

View File

@ -636,10 +636,6 @@ class LibraryServer(object):
'type="application/atom+xml" href="/stanza/?%s"/>\n' 'type="application/atom+xml" href="/stanza/?%s"/>\n'
) % '&amp;'.join(q) ) % '&amp;'.join(q)
author_list=[]
tag_list=[]
series_list=[]
for record in nrecord_list: for record in nrecord_list:
r = record[FIELD_MAP['formats']] r = record[FIELD_MAP['formats']]
r = r.upper() if r else '' r = r.upper() if r else ''

View File

@ -388,7 +388,7 @@ class PostInstall:
finally: finally:
os.chdir(cwd) os.chdir(cwd)
shutil.rmtree(tdir) shutil.rmtree(tdir)
except Exception, err: except Exception:
if self.opts.fatal_errors: if self.opts.fatal_errors:
raise raise
self.task_failed('Setting up desktop integration failed') self.task_failed('Setting up desktop integration failed')

View File

@ -127,7 +127,6 @@ def generate_ebook_convert_help(preamble, info):
input and the output formats, the various combinations are listed below: input and the output formats, the various combinations are listed below:
''') ''')
sections = []
toc = {} toc = {}
sec_templ = textwrap.dedent('''\ sec_templ = textwrap.dedent('''\
.. include:: ../global.rst .. include:: ../global.rst
@ -141,7 +140,6 @@ def generate_ebook_convert_help(preamble, info):
''') ''')
for i, ip in enumerate(input_format_plugins()): for i, ip in enumerate(input_format_plugins()):
path = os.path.join('cli', 'ebook-convert-%d.rst'%i)
sraw = sec_templ.format(ip.name) sraw = sec_templ.format(ip.name)
toc[ip.name] = 'ebook-convert-%d'%i toc[ip.name] = 'ebook-convert-%d'%i
for op in output_format_plugins(): for op in output_format_plugins():

View File

@ -262,7 +262,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
shortname = shortname[:-2] shortname = shortname[:-2]
id = '%s.%s' % (id, shortname) id = '%s.%s' % (id, shortname)
else: else:
id = descr = None id = None
if id: if id:
item = ' '*12 + '<keyword name="%s" id="%s" ref="%s"/>' % ( item = ' '*12 + '<keyword name="%s" id="%s" ref="%s"/>' % (

View File

@ -1,80 +0,0 @@
'''
Trac Macro to generate an end use Changelog from the svn logs.
'''
import re, collections, time, os
from bzrlib import log as blog, branch
from cStringIO import StringIO
from trac.wiki.formatter import Formatter
from trac.wiki.macros import WikiMacroBase
from trac.util import Markup
BZR_PATH = '/usr/local/calibre'
class ChangelogFormatter(blog.LogFormatter):
supports_tags = True
supports_merge_revisions = False
_show_advice = False
def __init__(self, num_of_versions=20):
self.num_of_versions = num_of_versions
self.messages = collections.deque()
self.entries = []
self.current_entry = None
def log_revision(self, r):
if len(self.entries) > self.num_of_versions-1:
return
msg = r.rev.message
match = re.match(r'version\s+(\d+\.\d+.\d+)', msg)
if match:
if self.current_entry is not None:
self.entries.append((self.current_entry, set(self.messages)))
timestamp = r.rev.timezone + r.rev.timestamp
self.current_entry = match.group(1) + time.strftime(' (%d %b, %Y)', time.gmtime(timestamp))
self.messages = collections.deque()
else:
if re.search(r'[a-zA-Z]', msg) and len(msg.strip()) > 5:
if 'translation' not in msg and not msg.startswith('IGN'):
self.messages.append(msg.strip())
def to_wiki_txt(self):
txt = ['= Changelog =\n[[PageOutline]]']
for entry in self.entries:
txt.append(u'----\n== Version '+entry[0]+' ==')
if entry[0].strip().startswith('0.6.0'):
txt.append(u'For a list of new features in 0.6.0 see http://calibre.kovidgoyal.net/new_in_6')
else:
for msg in entry[1]:
txt.append(u' * ' + msg)
return (u'\n'.join(txt)).encode('ascii', 'replace')
def bzr_log_to_txt():
path = BZR_PATH
if not os.path.exists(path):
path = '/home/kovid/work/calibre'
b = branch.Branch.open(path)
lf = ChangelogFormatter()
blog.show_log(b, lf)
return lf.to_wiki_txt()
class ChangeLogMacro(WikiMacroBase):
def expand_macro(self, formatter, name, args):
txt = bzr_log_to_txt().encode('ascii', 'xmlcharrefreplace')
out = StringIO()
Formatter(formatter.env, formatter.context).format(txt, out)
return Markup(out.getvalue().decode('utf8'))
if __name__ == '__main__':
print bzr_log_to_txt().encode('utf-8')

View File

@ -1,3 +0,0 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'

View File

@ -1,405 +0,0 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
__appname__ = 'calibre'
import re, textwrap
DEPENDENCIES = [
#(Generic, version, gentoo, ubuntu, fedora)
('python', '2.6', None, None, None),
('Python Imaging Library', '1.1.6', 'imaging', 'python-imaging', 'python-imaging'),
('libusb', '0.1.12', None, None, None),
('Qt', '4.5.1', 'qt', 'libqt4-core libqt4-gui', 'qt4'),
('PyQt', '4.6.1', 'PyQt4', 'python-qt4', 'PyQt4'),
('python-mechanize', '0.1.11', 'dev-python/mechanize', 'python-mechanize', 'python-mechanize'),
('ImageMagick', '6.3.5', 'imagemagick', 'imagemagick', 'ImageMagick'),
('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'),
('lxml', '2.1.5', 'lxml', 'python-lxml', 'python-lxml'),
('python-dateutil', '1.4.1', 'python-dateutil', 'python-dateutil', 'python-dateutil'),
('BeautifulSoup', '3.0.5', 'beautifulsoup', 'python-beautifulsoup', 'python-BeautifulSoup'),
('dnspython', '1.6.0', 'dnspython', 'dnspython', 'dnspython', 'dnspython'),
('poppler', '0.12.0', 'poppler', 'poppler', 'poppler', 'poppler'),
('podofo', '0.7', 'podofo', 'podofo', 'podofo', 'podofo'),
('libwmf', '0.2.8', 'libwmf', 'libwmf', 'libwmf', 'libwmf'),
]
STATUS = 'http://status.calibre-ebook.com/dist'
class CoolDistro:
def __init__(self, name, title, prefix=''):
self.title = title
url = prefix + '/chrome/dl/images/%s_logo.png'
self.img = url%name
def get_linux_data(version='1.0.0'):
data = {'version':version, 'app':__appname__}
data['title'] = 'Download calibre for linux'
data['supported'] = []
for name, title in [
('debian', 'Debian Sid'),
('exherbo', 'Exherbo'),
('foresight', 'Foresight 2.1'),
('gentoo', 'Gentoo'),
('ubuntu', 'Ubuntu Jaunty Jackalope'),
('linux_mint', 'Linux Mint Gloria'),
]:
data['supported'].append(CoolDistro(name, title,
prefix='http://calibre.kovidgoyal.net'))
data['dependencies'] = DEPENDENCIES
return data
if __name__ == '__main__':
import os
from calibre.utils.genshi.template import MarkupTemplate
import cherrypy
class Test:
def index(self):
raw = open(os.path.dirname(os.path.abspath(__file__))+'/templates/linux.html').read()
return MarkupTemplate(raw).generate(**get_linux_data()).render('xhtml')
index.exposed = True
t = Test()
t.index()
cherrypy.quickstart(t)
else:
from pkg_resources import resource_filename
from trac.core import Component, implements
from trac.web.chrome import INavigationContributor, ITemplateProvider, add_stylesheet
from trac.web.main import IRequestHandler
from trac.util import Markup
DOWNLOAD_DIR = '/var/www/calibre.kovidgoyal.net/htdocs/downloads'
MOBILEREAD = 'https://dev.mobileread.com/dist/kovid/calibre/'
#MOBILEREAD = 'http://calibre.kovidgoyal.net/downloads/'
class OS(dict):
"""Dictionary with a default value for unknown keys."""
def __init__(self, dict):
self.update(dict)
if not dict.has_key('img'):
self['img'] = self['name']
class Download(Component):
implements(INavigationContributor, IRequestHandler, ITemplateProvider)
request_pat = re.compile(r'\/download$|\/download_\S+')
# INavigationContributor methods
def get_active_navigation_item(self, req):
return 'download'
def get_navigation_items(self, req):
yield 'mainnav', 'download', Markup('<a href="/download">Get %s</a>'%(__appname__,))
def get_templates_dirs(self):
return [resource_filename(__name__, 'templates')]
def get_htdocs_dirs(self):
return [('dl', resource_filename(__name__, 'htdocs'))]
# IRequestHandler methods
def match_request(self, req):
return self.__class__.request_pat.match(req.path_info)
def process_request(self, req):
add_stylesheet(req, 'dl/css/download.css')
if req.path_info == '/download':
return self.top_level(req)
elif req.path_info == '/download_linux_binary_installer':
req.send(LINUX_INSTALLER.replace('%version', self.version_from_filename()), 'text/x-python')
else:
match = re.match(r'\/download_(\S+)', req.path_info)
if match:
os = match.group(1)
if os == 'windows':
return self.windows(req)
elif os == 'osx':
return self.osx(req)
elif os == 'linux':
return self.linux(req)
def top_level(self, req):
operating_systems = [
OS({'name' : 'windows', 'title' : 'Windows'}),
OS({'name' : 'osx', 'title' : 'OS X'}),
OS({'name' : 'linux', 'title' : 'Linux'}),
]
data = dict(title='Get ' + __appname__,
operating_systems=operating_systems, width=200,
font_size='xx-large', top_level=True)
return 'download.html', data, None
def version_from_filename(self):
try:
return open(DOWNLOAD_DIR+'/latest_version', 'rb').read().strip()
except:
return '0.0.0'
def windows(self, req):
version = self.version_from_filename()
file = '%s-%s.msi'%(__appname__, version,)
data = dict(version = version, name='windows',
installer_name='Windows installer',
title='Download %s for windows'%(__appname__),
compatibility=('%(a)s works on Windows XP, Vista and 7.'
'If you are upgrading from a version older than 0.6.17, '
'please uninstall %(a)s first.')%dict(a=__appname__,),
path=STATUS+'/win32', app=__appname__,
note=Markup(\
'''
<p>If you are updating from a version of calibre older than 0.6.12 on
<b>Windows XP</b>, first uninstall calibre, then delete the C:\Program
Files\calibre folder (the location may be different if you previously
installed calibre elsewhere) and only then install the new version of
calibre.</p><p><br /></p>
<p>If you are using the <b>SONY PRS-500</b> and %(appname)s does not detect your reader, read on:</p>
<blockquote>
<p>
If you are using 64-bit windows, you're out of luck.
</p>
<p>
There may be a conflict with the USB driver from SONY. In windows, you cannot install two drivers
for one device. In order to resolve the conflict:
<ol>
<li>Start Device Manager by clicking Start->Run, typing devmgmt.msc and pressing enter.</li>
<li>Uninstall all PRS500 related drivers. You will find them in two locations:
<ul>
<li>Under "Libusb-Win32"</li>
<li>Under "Universal Serial ..." (... depends on the version of windows)</li>
</ul>
You can uninstall a driver by right clicking on it and selecting uninstall.
</li>
<li>Once the drivers have been uninstalled, find the file prs500.inf (it will be in the
driver folder in the folder in which you installed %(appname)s. Right click on it and
select Install.</li>
</ol>
</p>
</blockquote>
'''%dict(appname=__appname__)))
return 'binary.html', data, None
def osx(self, req):
version = self.version_from_filename()
file = 'calibre-%s.dmg'%(version,)
data = dict(version = version, name='osx',
installer_name='OS X universal dmg',
title='Download %s for OS X'%(__appname__),
compatibility='%s works on OS X Tiger, Leopard, and Snow Leopard.'%(__appname__,),
path=STATUS+'/osx32', app=__appname__,
note=Markup(\
u'''
<ol>
<li>To install the command line tools, go to Preferences-&gt;Advanced</li>
<li>The app cannot be run from within the dmg. You must drag it to a folder on your filesystem (The Desktop, Applications, wherever).</li>
<li>In order for localization of the user interface in your language, select your language in the preferences (by pressing u\2318+P) and select your language.</li>
</ol>
'''))
return 'binary.html', data, None
def linux(self, req):
data = get_linux_data(version=self.version_from_filename())
return 'linux.html', data, None
LINUX_INSTALLER = textwrap.dedent(r'''
import sys, os, shutil, tarfile, subprocess, tempfile, urllib2, re, stat
MOBILEREAD='https://dev.mobileread.com/dist/kovid/calibre/'
#MOBILEREAD='http://calibre.kovidgoyal.net/downloads/'
class TerminalController:
BOL = '' #: Move the cursor to the beginning of the line
UP = '' #: Move the cursor up one line
DOWN = '' #: Move the cursor down one line
LEFT = '' #: Move the cursor left one char
RIGHT = '' #: Move the cursor right one char
# Deletion:
CLEAR_SCREEN = '' #: Clear the screen and move to home position
CLEAR_EOL = '' #: Clear to the end of the line.
CLEAR_BOL = '' #: Clear to the beginning of the line.
CLEAR_EOS = '' #: Clear to the end of the screen
# Output modes:
BOLD = '' #: Turn on bold mode
BLINK = '' #: Turn on blink mode
DIM = '' #: Turn on half-bright mode
REVERSE = '' #: Turn on reverse-video mode
NORMAL = '' #: Turn off all modes
# Cursor display:
HIDE_CURSOR = '' #: Make the cursor invisible
SHOW_CURSOR = '' #: Make the cursor visible
# Terminal size:
COLS = None #: Width of the terminal (None for unknown)
LINES = None #: Height of the terminal (None for unknown)
# Foreground colors:
BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
# Background colors:
BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = ''
BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = ''
_STRING_CAPABILITIES = """
BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold
BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0
HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split()
_COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
_ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
def __init__(self, term_stream=sys.stdout):
# Curses isn't available on all platforms
try: import curses
except: return
# If the stream isn't a tty, then assume it has no capabilities.
if not hasattr(term_stream, 'isatty') or not term_stream.isatty(): return
# Check the terminal type. If we fail, then assume that the
# terminal has no capabilities.
try: curses.setupterm()
except: return
# Look up numeric capabilities.
self.COLS = curses.tigetnum('cols')
self.LINES = curses.tigetnum('lines')
# Look up string capabilities.
for capability in self._STRING_CAPABILITIES:
(attrib, cap_name) = capability.split('=')
setattr(self, attrib, self._tigetstr(cap_name) or '')
# Colors
set_fg = self._tigetstr('setf')
if set_fg:
for i,color in zip(range(len(self._COLORS)), self._COLORS):
setattr(self, color, curses.tparm(set_fg, i) or '')
set_fg_ansi = self._tigetstr('setaf')
if set_fg_ansi:
for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
setattr(self, color, curses.tparm(set_fg_ansi, i) or '')
set_bg = self._tigetstr('setb')
if set_bg:
for i,color in zip(range(len(self._COLORS)), self._COLORS):
setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '')
set_bg_ansi = self._tigetstr('setab')
if set_bg_ansi:
for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '')
def _tigetstr(self, cap_name):
# String capabilities can include "delays" of the form "$<2>".
# For any modern terminal, we should be able to just ignore
# these, so strip them out.
import curses
cap = curses.tigetstr(cap_name) or ''
return re.sub(r'\$<\d+>[/*]?', '', cap)
def render(self, template):
return re.sub(r'\$\$|\${\w+}', self._render_sub, template)
def _render_sub(self, match):
s = match.group()
if s == '$$': return s
else: return getattr(self, s[2:-1])
class ProgressBar:
BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
def __init__(self, term, header):
self.term = term
if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
raise ValueError("Terminal isn't capable enough -- you "
"should use a simpler progress dispaly.")
self.width = self.term.COLS or 75
self.bar = term.render(self.BAR)
self.header = self.term.render(self.HEADER % header.center(self.width))
self.cleared = 1 #: true if we haven't drawn the bar yet.
def update(self, percent, message=''):
if isinstance(message, unicode):
message = message.encode('utf-8', 'ignore')
if self.cleared:
sys.stdout.write(self.header)
self.cleared = 0
n = int((self.width-10)*percent)
msg = message.center(self.width)
sys.stdout.write(
self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
(self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) +
self.term.CLEAR_EOL + msg)
sys.stdout.flush()
def clear(self):
if not self.cleared:
sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
self.term.UP + self.term.CLEAR_EOL +
self.term.UP + self.term.CLEAR_EOL)
self.cleared = 1
def download_tarball():
try:
pb = ProgressBar(TerminalController(sys.stdout), 'Downloading calibre...')
except ValueError:
print 'Downloading calibre...'
pb = None
local = 'calibre-test.tar.bz2'
src = open(local) if os.access(local, os.R_OK) else urllib2.urlopen(MOBILEREAD+'calibre-%version-i686.tar.bz2')
if hasattr(src, 'info'):
size = int(src.info()['content-length'])
else:
src.seek(0, 2)
size = src.tell()
src.seek(0)
f = tempfile.NamedTemporaryFile()
while f.tell() < size:
f.write(src.read(4*1024))
percent = f.tell()/float(size)
if pb is not None:
pb.update(percent)
else:
print '%d%%, '%int(percent*100),
f.seek(0)
return f
def extract_tarball(tar, destdir):
print 'Extracting application files...'
if hasattr(tar, 'read'):
subprocess.check_call(['tar', 'xjf', tar.name, '-C', destdir])
else:
subprocess.check_call(['tar', 'xjf', tar, '-C', destdir])
def main():
defdir = '/opt/calibre'
destdir = raw_input('Enter the installation directory for calibre (Its contents will be deleted!)[%s]: '%defdir).strip()
if not destdir:
destdir = defdir
destdir = os.path.abspath(destdir)
if os.path.exists(destdir):
shutil.rmtree(destdir)
os.makedirs(destdir)
f = download_tarball()
print 'Extracting files to %s ...'%destdir
extract_tarball(f, destdir)
mh = os.path.join(destdir, 'calibre-mount-helper')
if os.geteuid() == 0:
os.chown(mh, 0, 0)
os.chmod(mh,
stat.S_ISUID|stat.S_ISGID|stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
else:
print 'WARNING: Not running as root. Cannot install mount helper.',
print 'Device automounting may not work.'
pi = os.path.join(destdir, 'calibre_postinstall')
subprocess.call(pi, shell=True)
return 0
''')

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

View File

@ -1,40 +0,0 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="layout.html" />
<head>
<title>$title</title>
</head>
<body>
<div id="ctxtnav" class="nav"></div>
<div id="content" class="binary">
<h1>$title</h1>
<p>$compatibility</p>
<p>
<a style="border: 0px" href="$path">
<img width="50" height="50" style="border:1px red solid" src="${href.chrome('/dl/images/%s_logo.png'%(name,))}" /> $installer_name
</a> (Version: $version <a href="/wiki/Changelog">Changelog</a>)
</p>
While you wait for the download to complete, please consider donating to support the development
of ${app}. If the above link does not work, the files are also available from
<a href="https://sourceforge.net/projects/calibre/">sourceforge</a>.
<div>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="hosted_button_id" value="3029289" />
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="Donate to support calibre development" />
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" />
</form>
<br />
</div>
<h2>Note</h2>
<div class="note">$note</div>
</div>
</body>
</html>

View File

@ -1,41 +0,0 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="layout.html" />
<head>
<title>$title</title>
</head>
<body>
<div id="ctxtnav" class="nav"></div>
<p py:if="not top_level">If you have a 64bit computer, or an outdated operating system, the distribution
specific installation may not work for you. In that case, first try the binary installer.
If that also does not work, your only recourse is to try to install from source. In order
to do that you will have to install all the dependencies as well as the -dev package of PyQt4.
</p>
<div id="content" class="download">
<h1>$title</h1>
<center>
<table cellspacing="40px">
<tr>
<td style="text-align:center; font-size: ${font_size}" py:for="os in operating_systems">
<a href="download_${os['name']}" style="text-decoration:none; border:0;">
<img width="${width}" height="${width+20}" src="${href.chrome('/dl/images/%s_logo.png'%(os['img'],))}" />
</a>
<a href="download_${os['name']}" style="text-decoration:none; border:0">
<br />
${os['title']}
</a>
</td>
</tr>
</table>
<br />
</center>
</div>
</body>
</html>

View File

@ -1,165 +0,0 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="layout.html" />
<head>
<title>${title}</title>
<style type="text/css">
table tr th.distro_type {
font-family: monospace;
font-weight: bold;
font-size: larger;
vertical-align:middle;
text-align: center;
border-bottom: solid 1pt black;
}
.right {
margin-left:2em;
border-left: solid 1pt black;
}
table#install_info {
border-collapse: collapse;
border-width: 1pt;
border-style: solid;
table-layout: fixed;
width: 95%;
background: #F7F7F0 none repeat scroll 0 0;
}
table#dependencies {
border-collapse: collapse;
border-width: 0pt;
font-family:monospace;
}
.tdata {vertical-align: top;}
</style>
</head>
<body>
<div id="ctxtnav" class="nav"></div>
<div id="content" class="download">
<h1>${title}</h1>
<p>
The latest release of ${app} is ${version}. See the
<a href="/wiki/Changelog">Changelog</a> for a list of new features.
</p>
<p>
${app} is available in the software repositories of the following
supported linux distributions:
<table id="install_info">
<col width="150" /><col width="*" />
<tr>
<th class="left distro_type">Supported<br/>distributions</th>
<th class="right distro_type">Unsupported distributions</th>
</tr>
<tr class="tdata">
<td class="left" style="overflow-y:scroll">
<div py:for="distro in supported"
style="text-align:center;margin-top:2ex;">
<div>
<img width="64px" height="64px"
src="${distro.img}" alt="${distro.title}" />
</div>
${distro.title}
</div>
</td>
<td class="right">
<div style="margin-left:2em">
<h3>Binary install</h3>
<p>
${app} has a binary installer that has been
tested on a number of distributions on both
32-bit and 64-bit x86 machines. To install,
copy paste the following command into a terminal
and press Enter:
</p>
<pre class="wiki">
sudo python -c "import urllib2; exec urllib2.urlopen('http://status.calibre-ebook.com/linux_installer').read(); main()"
</pre>
<h4>Note</h4>
<ul>
<li>
When running the command line utilities,
they will segfault after completion. This can
be ignored.
</li>
<li>
You must have xdg-utils installed
on your system before running the installer.
</li>
</ul>
<h3>Source install</h3>
<p>
<ol>
<li>
Make sure your system has python &ge; ${dependencies[0][1]}
</li>
<li>
Install the various dependencies listed below
</li>
<li>
Run the following commands in a terminal:
</li>
</ol>
<pre class="wiki">
wget -O- http://status.calibre-ebook.com/dist/src | tar xvz
cd calibre*
sudo python setup.py install
</pre>
Note that if your distribution does not have a
correctly compiled libunrar.so, ${app} will not
support rar files. In order to compile ${app} successfully
poppler headers must include XPdf headers. That is, poppler
must have been configured with --enable-xpdf-headers. Also,
some distributions have buggy libpng headers. See
<a href="https://bugs.launchpad.net/ubuntu/+source/libpng/+bug/218409">here</a>
for example.
</p>
</div>
</td>
</tr>
</table>
</p>
<p>
While you wait for the download to complete, please consider
donating to support the development of ${app}.
</p>
<div>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick" />
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" />
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" />
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----" />
</form>
</div>
<hr/>
<h3>Note</h3>
<p>
If your kernel is compiled with CONFIG_SYSFS_DEPRECATED device detection may not work.
</p>
<hr/>
<h3>Dependencies</h3>
${app} has the following dependencies (the listed version is the minimum version)
<br/><br/>
<table id="dependencies">
<tr>
<th class="distro_type" style="margin-right:2em">Package</th>
<th class="distro_type">Version</th>
</tr>
<tr class="dependency" py:for="dep in dependencies">
<td style="margin-right:2em">${dep[0]}</td><td>${dep[1]}</td>
</tr>
</table>
<h3>Current calibre versions available in various distros</h3>
<div id="osw_calibre"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
<script src="http://static.oswatershed.org/js/package_badge.js" type="text/javascript"></script>
<script>$(document).ready(function(){ package_badge("calibre", "#osw_calibre"); });</script>
</div>
</body>
</html>

View File

@ -1544,7 +1544,7 @@ class Zeroconf(object):
# This is a quick test to see if we can parse the packets we generate # This is a quick test to see if we can parse the packets we generate
#temp = DNSIncoming(out.packet()) #temp = DNSIncoming(out.packet())
try: try:
bytes_sent = self.socket.sendto(out.packet(), 0, (addr, port)) self.socket.sendto(out.packet(), 0, (addr, port))
except: except:
# Ignore this, it may be a temporary loss of network connection # Ignore this, it may be a temporary loss of network connection
pass pass

View File

@ -65,7 +65,6 @@ def set_translators():
# CALIBRE_OVERRIDE_LANG=de_DE.utf8 program # CALIBRE_OVERRIDE_LANG=de_DE.utf8 program
lang = get_lang() lang = get_lang()
if lang: if lang:
translations = available_translations()
buf = iso639 = None buf = iso639 = None
if os.access(lang+'.po', os.R_OK): if os.access(lang+'.po', os.R_OK):
from calibre.translations.msgfmt import make from calibre.translations.msgfmt import make

View File

@ -11,7 +11,7 @@ from calibre.constants import iswindows
def find_executable(): def find_executable():
name = 'sigil' + ('.exe' if iswindows else '') name = 'sigil' + ('.exe' if iswindows else '')
path = find_executable_in_path(name) find_executable_in_path(name)
#if path is None and iswindows: #if path is None and iswindows:
# path = search_program_files() # path = search_program_files()

View File

@ -79,7 +79,6 @@ def save_soup(soup, target):
html = unicode(soup) html = unicode(soup)
with open(target, 'wb') as f: with open(target, 'wb') as f:
idx = html.find('hoping')
f.write(html.encode('utf-8')) f.write(html.encode('utf-8'))
class response(str): class response(str):
@ -259,7 +258,7 @@ class RecursiveFetcher(object):
continue continue
try: try:
data = self.fetch_url(iurl) data = self.fetch_url(iurl)
except Exception, err: except Exception:
self.log.exception('Could not fetch stylesheet %s'% iurl) self.log.exception('Could not fetch stylesheet %s'% iurl)
continue continue
stylepath = os.path.join(diskpath, 'style'+str(c)+'.css') stylepath = os.path.join(diskpath, 'style'+str(c)+'.css')
@ -282,7 +281,7 @@ class RecursiveFetcher(object):
continue continue
try: try:
data = self.fetch_url(iurl) data = self.fetch_url(iurl)
except Exception, err: except Exception:
self.log.exception('Could not fetch stylesheet %s'% iurl) self.log.exception('Could not fetch stylesheet %s'% iurl)
continue continue
c += 1 c += 1
@ -314,7 +313,7 @@ class RecursiveFetcher(object):
continue continue
try: try:
data = self.fetch_url(iurl) data = self.fetch_url(iurl)
except Exception, err: except Exception:
self.log.exception('Could not fetch image %s'% iurl) self.log.exception('Could not fetch image %s'% iurl)
continue continue
c += 1 c += 1
@ -443,7 +442,7 @@ class RecursiveFetcher(object):
save_soup(soup, res) save_soup(soup, res)
self.localize_link(tag, 'href', res) self.localize_link(tag, 'href', res)
except Exception, err: except Exception:
self.failed_links.append((iurl, traceback.format_exc())) self.failed_links.append((iurl, traceback.format_exc()))
self.log.exception('Could not fetch link', iurl) self.log.exception('Could not fetch link', iurl)
finally: finally: