mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
merge from trunk
This commit is contained in:
commit
2ae92d4128
@ -3,12 +3,17 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
||||
class AdvancedUserRecipe1274742400(BasicNewsRecipe):
|
||||
|
||||
title = u'Las Vegas Review Journal'
|
||||
__author__ = 'Joel'
|
||||
__author__ = 'Kovid Goyal'
|
||||
language = 'en'
|
||||
|
||||
oldest_article = 7
|
||||
|
||||
max_articles_per_feed = 100
|
||||
keep_only_tags = [dict(id='content-main')]
|
||||
remove_tags = [dict(id=['right-col-content', 'trending-topics']),
|
||||
{'class':['ppy-outer']}
|
||||
]
|
||||
no_stylesheets = True
|
||||
|
||||
feeds = [
|
||||
(u'News', u'http://www.lvrj.com/news.rss'),
|
||||
|
@ -20,8 +20,8 @@ class LaVanguardia(BasicNewsRecipe):
|
||||
max_articles_per_feed = 100
|
||||
no_stylesheets = True
|
||||
use_embedded_content = False
|
||||
delay = 1
|
||||
encoding = 'cp1252'
|
||||
delay = 5
|
||||
# encoding = 'cp1252'
|
||||
language = 'es'
|
||||
|
||||
direction = 'ltr'
|
||||
@ -35,7 +35,7 @@ class LaVanguardia(BasicNewsRecipe):
|
||||
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
||||
|
||||
feeds = [
|
||||
(u'Ciudadanos' , u'http://feeds.feedburner.com/lavanguardia/ciudadanos' )
|
||||
(u'Portada' , u'http://feeds.feedburner.com/lavanguardia/home' )
|
||||
,(u'Cultura' , u'http://feeds.feedburner.com/lavanguardia/cultura' )
|
||||
,(u'Deportes' , u'http://feeds.feedburner.com/lavanguardia/deportes' )
|
||||
,(u'Economia' , u'http://feeds.feedburner.com/lavanguardia/economia' )
|
||||
@ -45,17 +45,17 @@ class LaVanguardia(BasicNewsRecipe):
|
||||
,(u'Internet y tecnologia', u'http://feeds.feedburner.com/lavanguardia/internet' )
|
||||
,(u'Motor' , u'http://feeds.feedburner.com/lavanguardia/motor' )
|
||||
,(u'Politica' , u'http://feeds.feedburner.com/lavanguardia/politica' )
|
||||
,(u'Sucessos' , u'http://feeds.feedburner.com/lavanguardia/sucesos' )
|
||||
,(u'Sucesos' , u'http://feeds.feedburner.com/lavanguardia/sucesos' )
|
||||
]
|
||||
|
||||
|
||||
keep_only_tags = [
|
||||
dict(name='div', attrs={'class':'element1_3'})
|
||||
dict(name='div', attrs={'class':'detalle noticia'})
|
||||
]
|
||||
|
||||
remove_tags = [
|
||||
dict(name=['object','link','script'])
|
||||
,dict(name='div', attrs={'class':['colC','peu']})
|
||||
,dict(name='div', attrs={'class':['colC','peu','jstoolbar']})
|
||||
]
|
||||
|
||||
remove_tags_after = [dict(name='div', attrs={'class':'text'})]
|
||||
@ -67,4 +67,3 @@ class LaVanguardia(BasicNewsRecipe):
|
||||
for item in soup.findAll(style=True):
|
||||
del item['style']
|
||||
return soup
|
||||
|
||||
|
@ -98,6 +98,9 @@ class PRS505(USBMS):
|
||||
|
||||
THUMBNAIL_HEIGHT = 200
|
||||
|
||||
MAX_PATH_LEN = 201 # 250 - (max(len(CACHE_THUMBNAIL), len(MEDIA_THUMBNAIL)) +
|
||||
# len('main_thumbnail.jpg') + 1)
|
||||
|
||||
def windows_filter_pnp_id(self, pnp_id):
|
||||
return '_LAUNCHER' in pnp_id
|
||||
|
||||
@ -201,10 +204,13 @@ class PRS505(USBMS):
|
||||
self._card_b_prefix if idx == 2 \
|
||||
else self._main_prefix
|
||||
for book in bl:
|
||||
try:
|
||||
p = os.path.join(prefix, book.lpath)
|
||||
self._upload_cover(os.path.dirname(p),
|
||||
os.path.splitext(os.path.basename(p))[0],
|
||||
book, p)
|
||||
except:
|
||||
debug_print('FAILED to upload cover', p)
|
||||
else:
|
||||
debug_print('PRS505: NOT uploading covers in sync_booklists')
|
||||
|
||||
@ -232,8 +238,7 @@ class PRS505(USBMS):
|
||||
try:
|
||||
self._upload_cover(path, filename, metadata, filepath)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
debug_print('FAILED to upload cover', filepath)
|
||||
|
||||
def _upload_cover(self, path, filename, metadata, filepath):
|
||||
if metadata.thumbnail and metadata.thumbnail[-1]:
|
||||
|
@ -98,6 +98,9 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
# copy these back to the library
|
||||
BACKLOADING_ERROR_MESSAGE = None
|
||||
|
||||
#: The maximum length of paths created on the device
|
||||
MAX_PATH_LEN = 250
|
||||
|
||||
def reset(self, key='-1', log_packets=False, report_progress=None,
|
||||
detected_device=None):
|
||||
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
|
||||
@ -875,7 +878,7 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
|
||||
def create_upload_path(self, path, mdata, fname, create_dirs=True):
|
||||
path = os.path.abspath(path)
|
||||
extra_components = []
|
||||
maxlen = self.MAX_PATH_LEN
|
||||
|
||||
special_tag = None
|
||||
if mdata.tags:
|
||||
@ -902,7 +905,7 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
app_id = str(getattr(mdata, 'application_id', ''))
|
||||
# The db id will be in the created filename
|
||||
extra_components = get_components(template, mdata, fname,
|
||||
timefmt=opts.send_timefmt, length=250-len(app_id)-1)
|
||||
timefmt=opts.send_timefmt, length=maxlen-len(app_id)-1)
|
||||
if not extra_components:
|
||||
extra_components.append(sanitize(self.filename_callback(fname,
|
||||
mdata)))
|
||||
@ -937,12 +940,11 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
return ans
|
||||
|
||||
extra_components = list(map(remove_trailing_periods, extra_components))
|
||||
components = shorten_components_to(250 - len(path), extra_components)
|
||||
components = shorten_components_to(maxlen - len(path), extra_components)
|
||||
components = self.sanitize_path_components(components)
|
||||
filepath = os.path.join(path, *components)
|
||||
filedir = os.path.dirname(filepath)
|
||||
|
||||
|
||||
if create_dirs and not os.path.exists(filedir):
|
||||
os.makedirs(filedir)
|
||||
|
||||
|
@ -42,6 +42,12 @@ option.
|
||||
For full documentation of the conversion system see
|
||||
''') + 'http://calibre-ebook.com/user_manual/conversion.html'
|
||||
|
||||
HEURISTIC_OPTIONS = ['markup_chapter_headings',
|
||||
'italicize_common_cases', 'fix_indents',
|
||||
'html_unwrap_factor', 'unwrap_lines',
|
||||
'delete_blank_paragraphs', 'format_scene_breaks',
|
||||
'dehyphenate', 'renumber_headings']
|
||||
|
||||
def print_help(parser, log):
|
||||
help = parser.format_help().encode(preferred_encoding, 'replace')
|
||||
log(help)
|
||||
@ -84,6 +90,8 @@ def option_recommendation_to_cli_option(add_option, rec):
|
||||
if opt.long_switch == 'verbose':
|
||||
attrs['action'] = 'count'
|
||||
attrs.pop('type', '')
|
||||
if opt.name in HEURISTIC_OPTIONS and rec.recommended_value is True:
|
||||
switches = ['--disable-'+opt.long_switch]
|
||||
add_option(Option(*switches, **attrs))
|
||||
|
||||
def add_input_output_options(parser, plumber):
|
||||
@ -132,14 +140,11 @@ def add_pipeline_options(parser, plumber):
|
||||
),
|
||||
|
||||
'HEURISTIC PROCESSING' : (
|
||||
_('Modify the document text and structure using common patterns.'),
|
||||
[
|
||||
'enable_heuristics', 'markup_chapter_headings',
|
||||
'italicize_common_cases', 'fix_indents',
|
||||
'html_unwrap_factor', 'unwrap_lines',
|
||||
'delete_blank_paragraphs', 'format_scene_breaks',
|
||||
'dehyphenate', 'renumber_headings',
|
||||
]
|
||||
_('Modify the document text and structure using common'
|
||||
' patterns. Disabled by default. Use %s to enable. '
|
||||
' Individual actions can be disabled with the %s options.')
|
||||
% ('--enable-heuristics', '--disable-*'),
|
||||
['enable_heuristics'] + HEURISTIC_OPTIONS
|
||||
),
|
||||
|
||||
'SEARCH AND REPLACE' : (
|
||||
|
@ -519,12 +519,12 @@ OptionRecommendation(name='unwrap_lines',
|
||||
help=_('Unwrap lines using punctuation and other formatting clues.')),
|
||||
|
||||
OptionRecommendation(name='delete_blank_paragraphs',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Remove empty paragraphs from the document when they exist between '
|
||||
'every other paragraph')),
|
||||
|
||||
OptionRecommendation(name='format_scene_breaks',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Left aligned scene break markers are center aligned. '
|
||||
'Replace soft scene breaks that use multiple blank lines with'
|
||||
'horizontal rules.')),
|
||||
@ -536,7 +536,7 @@ OptionRecommendation(name='dehyphenate',
|
||||
'should be retained or removed.')),
|
||||
|
||||
OptionRecommendation(name='renumber_headings',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Looks for occurrences of sequential <h1> or <h2> tags. '
|
||||
'The tags are renumbered to prevent splitting in the middle '
|
||||
'of chapter headings.')),
|
||||
|
@ -12,7 +12,7 @@ from calibre.gui2 import error_dialog
|
||||
|
||||
class SearchAndReplaceWidget(Widget, Ui_Form):
|
||||
|
||||
TITLE = _(u'Search\u00a0&\nReplace')
|
||||
TITLE = _('Search\n&\nReplace')
|
||||
HELP = _('Modify the document text and structure using user defined patterns.')
|
||||
COMMIT_NAME = 'search_and_replace'
|
||||
ICON = I('search.png')
|
||||
|
@ -599,7 +599,7 @@ class BulkEnumeration(BulkBase, Enumeration):
|
||||
value = None
|
||||
ret_value = None
|
||||
dialog_shown = False
|
||||
for book_id in book_ids:
|
||||
for i,book_id in enumerate(book_ids):
|
||||
val = self.db.get_custom(book_id, num=self.col_id, index_is_id=True)
|
||||
if val and val not in self.col_metadata['display']['enum_values']:
|
||||
if not dialog_shown:
|
||||
@ -610,7 +610,7 @@ class BulkEnumeration(BulkBase, Enumeration):
|
||||
show=True, show_copy_button=False)
|
||||
dialog_shown = True
|
||||
ret_value = ' nochange '
|
||||
elif value is not None and value != val:
|
||||
elif (value is not None and value != val) or (val and i != 0):
|
||||
ret_value = ' nochange '
|
||||
value = val
|
||||
if ret_value is None:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -42,30 +42,44 @@ def supports_long_names(path):
|
||||
else:
|
||||
return True
|
||||
|
||||
def shorten_components_to(length, components):
|
||||
def shorten_component(s, by_what):
|
||||
l = len(s)
|
||||
if l < by_what:
|
||||
return s
|
||||
l = (l - by_what)//2
|
||||
if l <= 0:
|
||||
return s
|
||||
return s[:l] + s[-l:]
|
||||
|
||||
def shorten_components_to(length, components, more_to_take=0):
|
||||
filepath = os.sep.join(components)
|
||||
extra = len(filepath) - length
|
||||
extra = len(filepath) - (length - more_to_take)
|
||||
if extra < 1:
|
||||
return components
|
||||
delta = int(ceil(extra/float(len(components))))
|
||||
ans = []
|
||||
deltas = []
|
||||
for x in components:
|
||||
pct = len(x)/float(len(filepath))
|
||||
deltas.append(int(ceil(pct*extra)))
|
||||
ans = []
|
||||
|
||||
for i, x in enumerate(components):
|
||||
delta = deltas[i]
|
||||
if delta > len(x):
|
||||
r = x[0] if x is components[-1] else ''
|
||||
else:
|
||||
if x is components[-1]:
|
||||
b, e = os.path.splitext(x)
|
||||
if e == '.': e = ''
|
||||
r = b[:-delta]+e
|
||||
r = shorten_component(b, delta)+e
|
||||
if r.startswith('.'): r = x[0]+r
|
||||
else:
|
||||
r = x[:-delta]
|
||||
r = shorten_component(x, delta)
|
||||
r = r.strip()
|
||||
if not r:
|
||||
r = x.strip()[0] if x.strip() else 'x'
|
||||
ans.append(r)
|
||||
if len(os.sep.join(ans)) > length:
|
||||
return shorten_components_to(length, ans)
|
||||
return shorten_components_to(length, components, more_to_take+2)
|
||||
return ans
|
||||
|
||||
def find_executable_in_path(name, path=None):
|
||||
|
@ -75,7 +75,7 @@ class FormatterFunction(object):
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
info = ': '.join(traceback.format_exception(exc_type, exc_value,
|
||||
exc_traceback)[-2:]).replace('\n', '')
|
||||
return _('Exception ' + info)
|
||||
return _('Exception ') + info
|
||||
|
||||
all_builtin_functions = []
|
||||
class BuiltinFormatterFunction(FormatterFunction):
|
||||
|
Loading…
x
Reference in New Issue
Block a user