Sync to trunk

This commit is contained in:
John Schember 2009-01-11 08:24:30 -05:00
commit 6f6fb1b1e8
19 changed files with 127 additions and 21 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.4.126' __version__ = '0.4.127'
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>" __author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
''' '''
Various run time constants. Various run time constants.

View File

@ -41,6 +41,20 @@ class Device(object):
'''Return the FDI description of this device for HAL on linux.''' '''Return the FDI description of this device for HAL on linux.'''
return '' return ''
@classmethod
def can_handle(cls, device_info):
'''
Optional method to perform further checks on a device to see if this driver
is capable of handling it. If it is not it should return False. This method
is only called after the vendor, product ids and the bcd have matched, so
it can do some relatively time intensive checks. The default implementation
returns True.
:param device_info: On windows a device ID string. On Unix a tuple of
``(vendor_id, product_id, bcd)``.
'''
return True
def open(self): def open(self):
''' '''
Perform any device specific initialization. Called after the device is Perform any device specific initialization. Called after the device is

View File

@ -63,11 +63,13 @@ class DeviceScanner(object):
for device_id in self.devices: for device_id in self.devices:
if vid in device_id and pid in device_id: if vid in device_id and pid in device_id:
if self.test_bcd_windows(device_id, getattr(device, 'BCD', None)): if self.test_bcd_windows(device_id, getattr(device, 'BCD', None)):
if device.can_handle(device_id):
return True return True
else: else:
for vendor, product, bcdDevice in self.devices: for vendor, product, bcdDevice in self.devices:
if device.VENDOR_ID == vendor and device.PRODUCT_ID == product: if device.VENDOR_ID == vendor and device.PRODUCT_ID == product:
if self.test_bcd(bcdDevice, getattr(device, 'BCD', None)): if self.test_bcd(bcdDevice, getattr(device, 'BCD', None)):
if device.can_handle((vendor, product, bcdDevice)):
return True return True
return False return False

View File

@ -67,6 +67,7 @@ def txt2opf(path, tdir, opts):
def pdf2opf(path, tdir, opts): def pdf2opf(path, tdir, opts):
from calibre.ebooks.lrf.pdf.convert_from import generate_html from calibre.ebooks.lrf.pdf.convert_from import generate_html
generate_html(path, tdir) generate_html(path, tdir)
opts.dont_split_on_page_breaks = True
return os.path.join(tdir, 'metadata.opf') return os.path.join(tdir, 'metadata.opf')
def epub2opf(path, tdir, opts): def epub2opf(path, tdir, opts):

View File

@ -560,7 +560,7 @@ class Processor(Parser):
hr = etree.Element('hr') hr = etree.Element('hr')
if elem.getprevious() is None: if elem.getprevious() is None:
elem.getparent()[:0] = [hr] elem.getparent()[:0] = [hr]
else: elif elem.getparent() is not None:
insert = None insert = None
for i, c in enumerate(elem.getparent()): for i, c in enumerate(elem.getparent()):
if c is elem: if c is elem:
@ -796,7 +796,18 @@ class Processor(Parser):
setting = '' setting = ''
face = font.attrib.pop('face', None) face = font.attrib.pop('face', None)
if face is not None: if face is not None:
setting += 'font-face:%s;'%face faces = []
for face in face.split(','):
if ' ' in face:
face = "%s" % face
faces.append(face)
for generic in ('serif', 'sans-serif', 'monospace'):
if generic in faces:
break
else:
faces.append('serif')
family = ', '.join(faces)
setting += 'font-family: %s;' % family
color = font.attrib.pop('color', None) color = font.attrib.pop('color', None)
if color is not None: if color is not None:
setting += 'color:%s'%color setting += 'color:%s'%color

View File

@ -425,7 +425,7 @@ def do_convert(path_to_file, opts, notification=lambda m, p: p, output_format='l
thumbnail = None thumbnail = None
if not pages: if not pages:
raise ValueError('Could not find any pages in the comic: %s'%source) raise ValueError('Could not find any pages in the comic: %s'%source)
if not opts.no_process: if not getattr(opts, 'no_process', False):
pages, failures, tdir2 = process_pages(pages, opts, notification) pages, failures, tdir2 = process_pages(pages, opts, notification)
if not pages: if not pages:
raise ValueError('Could not find any valid pages in the comic: %s'%source) raise ValueError('Could not find any valid pages in the comic: %s'%source)

View File

@ -29,7 +29,7 @@ def config(defaults=None):
c.add_opt('top_right_y', [ '-w', '--righty'], default=default_crop, c.add_opt('top_right_y', [ '-w', '--righty'], default=default_crop,
help=_('Number of pixels to crop from the right most y (default is %d)')%default_crop ) help=_('Number of pixels to crop from the right most y (default is %d)')%default_crop )
c.add_opt('bounding', ['-b', '--bounding'], c.add_opt('bounding', ['-b', '--bounding'],
help=_('A file generated by ghostscript which allows each page to be individually cropped')) help=_('A file generated by ghostscript which allows each page to be individually cropped [gs -dSAFER -dNOPAUSE -dBATCH -sDEVICE=bbox > bounding] '))
return c return c
@ -38,14 +38,24 @@ def option_parser():
return c.option_parser(usage=_('''\ return c.option_parser(usage=_('''\
%prog [options] file.pdf %prog [options] file.pdf
Crop a pdf. Crops a pdf.
''')) '''))
def main(args=sys.argv): def main(args=sys.argv):
parser = option_parser() parser = option_parser()
opts, args = parser.parse_args(args) opts, args = parser.parse_args(args)
try:
source = os.path.abspath(args[1]) source = os.path.abspath(args[1])
input_pdf = PdfFileReader(file(source, "rb")) input_pdf = PdfFileReader(file(source, "rb"))
except:
print "Unable to read input"
return 2
info = input_pdf.getDocumentInfo()
title = 'Unknown'
author = 'Unknown'
if info.title:
title = info.title
author = info.author
if opts.bounding != None: if opts.bounding != None:
try: try:
bounding = open( opts.bounding , 'r' ) bounding = open( opts.bounding , 'r' )
@ -53,7 +63,7 @@ def main(args=sys.argv):
except: except:
print 'Error opening %s' % opts.bounding print 'Error opening %s' % opts.bounding
return 1 return 1
output_pdf = PdfFileWriter() output_pdf = PdfFileWriter(title=title,author=author)
for page_number in range (0, input_pdf.getNumPages() ): for page_number in range (0, input_pdf.getNumPages() ):
page = input_pdf.getPage(page_number) page = input_pdf.getPage(page_number)
if opts.bounding != None: if opts.bounding != None:

View File

@ -75,7 +75,13 @@ def save_recipes(recipes):
def load_recipes(): def load_recipes():
config.refresh() config.refresh()
return [Recipe().unpickle(r) for r in config.get('scheduled_recipes', [])] recipes = []
for r in config.get('scheduled_recipes', []):
r = Recipe().unpickle(r)
if r.builtin and not str(r.id).startswith('recipe_'):
continue
recipes.append(r)
return recipes
class RecipeModel(QAbstractListModel, SearchQueryParser): class RecipeModel(QAbstractListModel, SearchQueryParser):
@ -438,7 +444,7 @@ class Scheduler(QObject):
self.lock.unlock() self.lock.unlock()
def main(args=sys.argv): def main(args=sys.argv):
app = QApplication([]) QApplication([])
from calibre.library.database2 import LibraryDatabase2 from calibre.library.database2 import LibraryDatabase2
d = SchedulerDialog(LibraryDatabase2('/home/kovid/documents/library')) d = SchedulerDialog(LibraryDatabase2('/home/kovid/documents/library'))
d.exec_() d.exec_()

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

View File

@ -217,8 +217,7 @@ class Server(object):
pos = pos.replace(month = 1) pos = pos.replace(month = 1)
else: else:
pos = pos.replace(month = pos.month + 1) pos = pos.replace(month = pos.month + 1)
_months = list(months(self.earliest, self.latest))[:-1][-12:]
_months = list(months(self.earliest, self.latest))[:-1][:12]
_months = [range_for_month(*m) for m in _months] _months = [range_for_month(*m) for m in _months]
_months = [self.get_slice(*m) for m in _months] _months = [self.get_slice(*m) for m in _months]
x = [m.min for m in _months] x = [m.min for m in _months]

View File

@ -35,7 +35,7 @@ class Distribution(object):
('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'), ('xdg-utils', '1.0.2', 'xdg-utils', 'xdg-utils', 'xdg-utils'),
('dbus-python', '0.82.2', 'dbus-python', 'python-dbus', 'dbus-python'), ('dbus-python', '0.82.2', 'dbus-python', 'python-dbus', 'dbus-python'),
('lxml', '2.0.5', 'lxml', 'python-lxml', 'python-lxml'), ('lxml', '2.0.5', 'lxml', 'python-lxml', 'python-lxml'),
('BeautifulSoup', '3.0.5', 'beautifulsoup', 'python-beautifulsoup', 'python-beautifulsoup'), ('BeautifulSoup', '3.0.5', 'beautifulsoup', 'python-beautifulsoup', 'python-BeautifulSoup'),
('help2man', '1.36.4', 'help2man', 'help2man', 'help2man'), ('help2man', '1.36.4', 'help2man', 'help2man', 'help2man'),
] ]

View File

@ -765,6 +765,8 @@ class BasicNewsRecipe(object, LoggingInterface):
self.log_debug(traceback.format_exc()) self.log_debug(traceback.format_exc())
if cu is not None: if cu is not None:
ext = cu.rpartition('.')[-1] ext = cu.rpartition('.')[-1]
if '?' in ext:
ext = ''
ext = ext.lower() if ext else 'jpg' ext = ext.lower() if ext else 'jpg'
self.report_progress(1, _('Downloading cover from %s')%cu) self.report_progress(1, _('Downloading cover from %s')%cu)
cpath = os.path.join(self.output_dir, 'cover.'+ext) cpath = os.path.join(self.output_dir, 'cover.'+ext)

View File

@ -21,7 +21,7 @@ recipe_modules = ['recipe_' + r for r in (
'linux_magazine', 'telegraph_uk', 'utne', 'sciencedaily', 'forbes', 'linux_magazine', 'telegraph_uk', 'utne', 'sciencedaily', 'forbes',
'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik', 'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik',
'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet', 'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet',
'joelonsoftware', 'joelonsoftware', 'telepolis', 'common_dreams',
)] )]
import re, imp, inspect, time, os import re, imp, inspect, time, os

View File

@ -42,3 +42,9 @@ class ChristianScienceMonitor(BasicNewsRecipe):
feeds[-1][1].append(art) feeds[-1][1].append(art)
return feeds return feeds
def postprocess_html(self, soup, first_fetch):
html = soup.find('html')
if html is None:
return soup
html.extract()
return html

View File

@ -0,0 +1,16 @@
from calibre.web.feeds.news import BasicNewsRecipe
class CommonDreams(BasicNewsRecipe):
title = u'Common Dreams'
description = u'Progressive news and views'
__author__ = u'XanthanGum'
oldest_article = 7
max_articles_per_feed = 100
feeds = [
(u'Common Dreams Headlines',
u'http://www.commondreams.org/feed/headlines_rss'),
(u'Common Dreams Views', u'http://www.commondreams.org/feed/views_rss'),
(u'Common Dreams Newswire', u'http://www.commondreams.org/feed/newswire_rss')
]

View File

@ -49,7 +49,9 @@ class Economist(BasicNewsRecipe):
if not index_started: if not index_started:
continue continue
text = string.capwords(text) text = string.capwords(text)
if text not in feeds.keys():
feeds[text] = [] feeds[text] = []
if text not in ans:
ans.append(text) ans.append(text)
key = text key = text
continue continue

View File

@ -0,0 +1,34 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
'''
www.heise.de/tp
'''
from calibre.web.feeds.news import BasicNewsRecipe
class Telepolis(BasicNewsRecipe):
title = 'Telepolis'
__author__ = 'Darko Miletic'
description = 'News from Germany in German'
oldest_article = 2
max_articles_per_feed = 100
no_stylesheets = True
use_embedded_content = False
encoding = 'utf-8'
html2lrf_options = [ '--comment' , description
, '--category' , 'blog,news'
]
keep_only_tags = [
dict(name='table', attrs={'class':'inhalt-table'})
,dict(name='table', attrs={'class':'blogtable' })
]
remove_tags = [
dict(name='table', attrs={'class':'img' })
,dict(name='img' , attrs={'src':'/tp/r4/icons/inline/extlink.gif'})
]
feeds = [(u'Telepolis Newsfeed', u'http://www.heise.de/tp/news.rdf')]

View File

@ -33,6 +33,7 @@ class TimesOnline(BasicNewsRecipe):
('Sports News', 'http://www.timesonline.co.uk/tol/feeds/rss/sport.xml'), ('Sports News', 'http://www.timesonline.co.uk/tol/feeds/rss/sport.xml'),
('Film News', 'http://www.timesonline.co.uk/tol/feeds/rss/film.xml'), ('Film News', 'http://www.timesonline.co.uk/tol/feeds/rss/film.xml'),
('Tech news', 'http://www.timesonline.co.uk/tol/feeds/rss/tech.xml'), ('Tech news', 'http://www.timesonline.co.uk/tol/feeds/rss/tech.xml'),
('Literary Supplement', 'http://www.timesonline.co.uk/tol/feeds/rss/thetls.xml'),
] ]
def print_version(self, url): def print_version(self, url):

View File

@ -55,7 +55,7 @@ from utils import readNonWhitespace, readUntilWhitespace, ConvertFunctionsToVirt
# This class supports writing PDF files out, given pages produced by another # This class supports writing PDF files out, given pages produced by another
# class (typically {@link #PdfFileReader PdfFileReader}). # class (typically {@link #PdfFileReader PdfFileReader}).
class PdfFileWriter(object): class PdfFileWriter(object):
def __init__(self): def __init__(self,title=u"Unknown",author=u"Unknown"):
self._header = "%PDF-1.3" self._header = "%PDF-1.3"
self._objects = [] # array of indirect objects self._objects = [] # array of indirect objects
@ -71,7 +71,9 @@ class PdfFileWriter(object):
# info object # info object
info = DictionaryObject() info = DictionaryObject()
info.update({ info.update({
NameObject("/Producer"): createStringObject(u"Python PDF Library - http://pybrary.net/pyPdf/") NameObject("/Producer"): createStringObject(u"Python PDF Library - http://pybrary.net/pyPdf/"),
NameObject("/Author"): createStringObject(author),
NameObject("/Title"): createStringObject(title),
}) })
self._info = self._addObject(info) self._info = self._addObject(info)