mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
merge from trunk
This commit is contained in:
commit
7e0e3fbaf1
64
resources/recipes/gulfnews.recipe
Normal file
64
resources/recipes/gulfnews.recipe
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2011, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
gulfnews.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class GulfNews(BasicNewsRecipe):
|
||||||
|
title = 'Gulf News'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'News from United Arab Emirrates, persian gulf and rest of the world'
|
||||||
|
publisher = 'Al Nisr Publishing LLC'
|
||||||
|
category = 'news, politics, UAE, world'
|
||||||
|
oldest_article = 2
|
||||||
|
max_articles_per_feed = 200
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'utf8'
|
||||||
|
use_embedded_content = False
|
||||||
|
language = 'en'
|
||||||
|
remove_empty_feeds = True
|
||||||
|
publication_type = 'newsportal'
|
||||||
|
masthead_url = 'http://gulfnews.com/media/img/gulf_news_logo.jpg'
|
||||||
|
extra_css = """
|
||||||
|
body{font-family: Arial,Helvetica,sans-serif }
|
||||||
|
img{margin-bottom: 0.4em; display:block}
|
||||||
|
h1{font-family: Georgia, 'Times New Roman', Times, serif}
|
||||||
|
ol,ul{list-style: none}
|
||||||
|
.synopsis{font-size: small}
|
||||||
|
.details{font-size: x-small}
|
||||||
|
.image{font-size: xx-small}
|
||||||
|
"""
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name=['meta','link','object','embed'])
|
||||||
|
,dict(attrs={'class':['quickLinks','ratings']})
|
||||||
|
,dict(attrs={'id':'imageSelector'})
|
||||||
|
]
|
||||||
|
remove_attributes=['lang']
|
||||||
|
keep_only_tags=[
|
||||||
|
dict(name='h1')
|
||||||
|
,dict(attrs={'class':['synopsis','details','image','article']})
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'UAE News' , u'http://gulfnews.com/cmlink/1.446094')
|
||||||
|
,(u'Business' , u'http://gulfnews.com/cmlink/1.446098')
|
||||||
|
,(u'Entertainment' , u'http://gulfnews.com/cmlink/1.446095')
|
||||||
|
,(u'Sport' , u'http://gulfnews.com/cmlink/1.446096')
|
||||||
|
,(u'Life' , u'http://gulfnews.com/cmlink/1.446097')
|
||||||
|
]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return soup
|
@ -3,12 +3,17 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
|||||||
class AdvancedUserRecipe1274742400(BasicNewsRecipe):
|
class AdvancedUserRecipe1274742400(BasicNewsRecipe):
|
||||||
|
|
||||||
title = u'Las Vegas Review Journal'
|
title = u'Las Vegas Review Journal'
|
||||||
__author__ = 'Joel'
|
__author__ = 'Kovid Goyal'
|
||||||
language = 'en'
|
language = 'en'
|
||||||
|
|
||||||
oldest_article = 7
|
oldest_article = 7
|
||||||
|
|
||||||
max_articles_per_feed = 100
|
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 = [
|
feeds = [
|
||||||
(u'News', u'http://www.lvrj.com/news.rss'),
|
(u'News', u'http://www.lvrj.com/news.rss'),
|
||||||
|
@ -20,8 +20,8 @@ class LaVanguardia(BasicNewsRecipe):
|
|||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
use_embedded_content = False
|
use_embedded_content = False
|
||||||
delay = 1
|
delay = 5
|
||||||
encoding = 'cp1252'
|
# encoding = 'cp1252'
|
||||||
language = 'es'
|
language = 'es'
|
||||||
|
|
||||||
direction = 'ltr'
|
direction = 'ltr'
|
||||||
@ -35,7 +35,7 @@ class LaVanguardia(BasicNewsRecipe):
|
|||||||
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
||||||
|
|
||||||
feeds = [
|
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'Cultura' , u'http://feeds.feedburner.com/lavanguardia/cultura' )
|
||||||
,(u'Deportes' , u'http://feeds.feedburner.com/lavanguardia/deportes' )
|
,(u'Deportes' , u'http://feeds.feedburner.com/lavanguardia/deportes' )
|
||||||
,(u'Economia' , u'http://feeds.feedburner.com/lavanguardia/economia' )
|
,(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'Internet y tecnologia', u'http://feeds.feedburner.com/lavanguardia/internet' )
|
||||||
,(u'Motor' , u'http://feeds.feedburner.com/lavanguardia/motor' )
|
,(u'Motor' , u'http://feeds.feedburner.com/lavanguardia/motor' )
|
||||||
,(u'Politica' , u'http://feeds.feedburner.com/lavanguardia/politica' )
|
,(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 = [
|
keep_only_tags = [
|
||||||
dict(name='div', attrs={'class':'element1_3'})
|
dict(name='div', attrs={'class':'detalle noticia'})
|
||||||
]
|
]
|
||||||
|
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
dict(name=['object','link','script'])
|
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'})]
|
remove_tags_after = [dict(name='div', attrs={'class':'text'})]
|
||||||
@ -67,4 +67,3 @@ class LaVanguardia(BasicNewsRecipe):
|
|||||||
for item in soup.findAll(style=True):
|
for item in soup.findAll(style=True):
|
||||||
del item['style']
|
del item['style']
|
||||||
return soup
|
return soup
|
||||||
|
|
||||||
|
@ -98,6 +98,9 @@ class PRS505(USBMS):
|
|||||||
|
|
||||||
THUMBNAIL_HEIGHT = 200
|
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):
|
def windows_filter_pnp_id(self, pnp_id):
|
||||||
return '_LAUNCHER' in pnp_id
|
return '_LAUNCHER' in pnp_id
|
||||||
|
|
||||||
@ -201,10 +204,13 @@ class PRS505(USBMS):
|
|||||||
self._card_b_prefix if idx == 2 \
|
self._card_b_prefix if idx == 2 \
|
||||||
else self._main_prefix
|
else self._main_prefix
|
||||||
for book in bl:
|
for book in bl:
|
||||||
|
try:
|
||||||
p = os.path.join(prefix, book.lpath)
|
p = os.path.join(prefix, book.lpath)
|
||||||
self._upload_cover(os.path.dirname(p),
|
self._upload_cover(os.path.dirname(p),
|
||||||
os.path.splitext(os.path.basename(p))[0],
|
os.path.splitext(os.path.basename(p))[0],
|
||||||
book, p)
|
book, p)
|
||||||
|
except:
|
||||||
|
debug_print('FAILED to upload cover', p)
|
||||||
else:
|
else:
|
||||||
debug_print('PRS505: NOT uploading covers in sync_booklists')
|
debug_print('PRS505: NOT uploading covers in sync_booklists')
|
||||||
|
|
||||||
@ -232,8 +238,7 @@ class PRS505(USBMS):
|
|||||||
try:
|
try:
|
||||||
self._upload_cover(path, filename, metadata, filepath)
|
self._upload_cover(path, filename, metadata, filepath)
|
||||||
except:
|
except:
|
||||||
import traceback
|
debug_print('FAILED to upload cover', filepath)
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
def _upload_cover(self, path, filename, metadata, filepath):
|
def _upload_cover(self, path, filename, metadata, filepath):
|
||||||
if metadata.thumbnail and metadata.thumbnail[-1]:
|
if metadata.thumbnail and metadata.thumbnail[-1]:
|
||||||
|
@ -98,6 +98,9 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
# copy these back to the library
|
# copy these back to the library
|
||||||
BACKLOADING_ERROR_MESSAGE = None
|
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,
|
def reset(self, key='-1', log_packets=False, report_progress=None,
|
||||||
detected_device=None):
|
detected_device=None):
|
||||||
self._main_prefix = self._card_a_prefix = self._card_b_prefix = 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):
|
def create_upload_path(self, path, mdata, fname, create_dirs=True):
|
||||||
path = os.path.abspath(path)
|
path = os.path.abspath(path)
|
||||||
extra_components = []
|
maxlen = self.MAX_PATH_LEN
|
||||||
|
|
||||||
special_tag = None
|
special_tag = None
|
||||||
if mdata.tags:
|
if mdata.tags:
|
||||||
@ -902,7 +905,7 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
app_id = str(getattr(mdata, 'application_id', ''))
|
app_id = str(getattr(mdata, 'application_id', ''))
|
||||||
# The db id will be in the created filename
|
# The db id will be in the created filename
|
||||||
extra_components = get_components(template, mdata, fname,
|
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:
|
if not extra_components:
|
||||||
extra_components.append(sanitize(self.filename_callback(fname,
|
extra_components.append(sanitize(self.filename_callback(fname,
|
||||||
mdata)))
|
mdata)))
|
||||||
@ -937,12 +940,11 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
extra_components = list(map(remove_trailing_periods, extra_components))
|
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)
|
components = self.sanitize_path_components(components)
|
||||||
filepath = os.path.join(path, *components)
|
filepath = os.path.join(path, *components)
|
||||||
filedir = os.path.dirname(filepath)
|
filedir = os.path.dirname(filepath)
|
||||||
|
|
||||||
|
|
||||||
if create_dirs and not os.path.exists(filedir):
|
if create_dirs and not os.path.exists(filedir):
|
||||||
os.makedirs(filedir)
|
os.makedirs(filedir)
|
||||||
|
|
||||||
|
@ -42,6 +42,12 @@ option.
|
|||||||
For full documentation of the conversion system see
|
For full documentation of the conversion system see
|
||||||
''') + 'http://calibre-ebook.com/user_manual/conversion.html'
|
''') + '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):
|
def print_help(parser, log):
|
||||||
help = parser.format_help().encode(preferred_encoding, 'replace')
|
help = parser.format_help().encode(preferred_encoding, 'replace')
|
||||||
log(help)
|
log(help)
|
||||||
@ -83,6 +89,8 @@ def option_recommendation_to_cli_option(add_option, rec):
|
|||||||
if opt.long_switch == 'verbose':
|
if opt.long_switch == 'verbose':
|
||||||
attrs['action'] = 'count'
|
attrs['action'] = 'count'
|
||||||
attrs.pop('type', '')
|
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))
|
add_option(Option(*switches, **attrs))
|
||||||
|
|
||||||
def add_input_output_options(parser, plumber):
|
def add_input_output_options(parser, plumber):
|
||||||
@ -131,14 +139,11 @@ def add_pipeline_options(parser, plumber):
|
|||||||
),
|
),
|
||||||
|
|
||||||
'HEURISTIC PROCESSING' : (
|
'HEURISTIC PROCESSING' : (
|
||||||
_('Modify the document text and structure using common patterns.'),
|
_('Modify the document text and structure using common'
|
||||||
[
|
' patterns. Disabled by default. Use %s to enable. '
|
||||||
'enable_heuristics', 'markup_chapter_headings',
|
' Individual actions can be disabled with the %s options.')
|
||||||
'italicize_common_cases', 'fix_indents',
|
% ('--enable-heuristics', '--disable-*'),
|
||||||
'html_unwrap_factor', 'unwrap_lines',
|
['enable_heuristics'] + HEURISTIC_OPTIONS
|
||||||
'delete_blank_paragraphs', 'format_scene_breaks',
|
|
||||||
'dehyphenate', 'renumber_headings',
|
|
||||||
]
|
|
||||||
),
|
),
|
||||||
|
|
||||||
'SEARCH AND REPLACE' : (
|
'SEARCH AND REPLACE' : (
|
||||||
|
@ -490,19 +490,19 @@ OptionRecommendation(name='enable_heuristics',
|
|||||||
'heuristic processing to take place.')),
|
'heuristic processing to take place.')),
|
||||||
|
|
||||||
OptionRecommendation(name='markup_chapter_headings',
|
OptionRecommendation(name='markup_chapter_headings',
|
||||||
recommended_value=False, level=OptionRecommendation.LOW,
|
recommended_value=True, level=OptionRecommendation.LOW,
|
||||||
help=_('Detect unformatted chapter headings and sub headings. Change '
|
help=_('Detect unformatted chapter headings and sub headings. Change '
|
||||||
'them to h2 and h3 tags. This setting will not create a TOC, '
|
'them to h2 and h3 tags. This setting will not create a TOC, '
|
||||||
'but can be used in conjunction with structure detection to create '
|
'but can be used in conjunction with structure detection to create '
|
||||||
'one.')),
|
'one.')),
|
||||||
|
|
||||||
OptionRecommendation(name='italicize_common_cases',
|
OptionRecommendation(name='italicize_common_cases',
|
||||||
recommended_value=False, level=OptionRecommendation.LOW,
|
recommended_value=True, level=OptionRecommendation.LOW,
|
||||||
help=_('Look for common words and patterns that denote '
|
help=_('Look for common words and patterns that denote '
|
||||||
'italics and italicize them.')),
|
'italics and italicize them.')),
|
||||||
|
|
||||||
OptionRecommendation(name='fix_indents',
|
OptionRecommendation(name='fix_indents',
|
||||||
recommended_value=False, level=OptionRecommendation.LOW,
|
recommended_value=True, level=OptionRecommendation.LOW,
|
||||||
help=_('Turn indentation created from multiple non-breaking space entities '
|
help=_('Turn indentation created from multiple non-breaking space entities '
|
||||||
'into CSS indents.')),
|
'into CSS indents.')),
|
||||||
|
|
||||||
@ -515,28 +515,28 @@ OptionRecommendation(name='html_unwrap_factor',
|
|||||||
'be reduced')),
|
'be reduced')),
|
||||||
|
|
||||||
OptionRecommendation(name='unwrap_lines',
|
OptionRecommendation(name='unwrap_lines',
|
||||||
recommended_value=False, level=OptionRecommendation.LOW,
|
recommended_value=True, level=OptionRecommendation.LOW,
|
||||||
help=_('Unwrap lines using punctuation and other formatting clues.')),
|
help=_('Unwrap lines using punctuation and other formatting clues.')),
|
||||||
|
|
||||||
OptionRecommendation(name='delete_blank_paragraphs',
|
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 '
|
help=_('Remove empty paragraphs from the document when they exist between '
|
||||||
'every other paragraph')),
|
'every other paragraph')),
|
||||||
|
|
||||||
OptionRecommendation(name='format_scene_breaks',
|
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. '
|
help=_('Left aligned scene break markers are center aligned. '
|
||||||
'Replace soft scene breaks that use multiple blank lines with'
|
'Replace soft scene breaks that use multiple blank lines with'
|
||||||
'horizontal rules.')),
|
'horizontal rules.')),
|
||||||
|
|
||||||
OptionRecommendation(name='dehyphenate',
|
OptionRecommendation(name='dehyphenate',
|
||||||
recommended_value=False, level=OptionRecommendation.LOW,
|
recommended_value=True, level=OptionRecommendation.LOW,
|
||||||
help=_('Analyze hyphenated words throughout the document. The '
|
help=_('Analyze hyphenated words throughout the document. The '
|
||||||
'document itself is used as a dictionary to determine whether hyphens '
|
'document itself is used as a dictionary to determine whether hyphens '
|
||||||
'should be retained or removed.')),
|
'should be retained or removed.')),
|
||||||
|
|
||||||
OptionRecommendation(name='renumber_headings',
|
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. '
|
help=_('Looks for occurrences of sequential <h1> or <h2> tags. '
|
||||||
'The tags are renumbered to prevent splitting in the middle '
|
'The tags are renumbered to prevent splitting in the middle '
|
||||||
'of chapter headings.')),
|
'of chapter headings.')),
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Sections to include in catalog. All catalogs include 'Books by Author'.</string>
|
<string>Sections to include in catalog.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Included sections</string>
|
<string>Included sections</string>
|
||||||
@ -79,13 +79,13 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="generate_authors">
|
<widget class="QCheckBox" name="generate_authors">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Books by Author</string>
|
<string>Books by Author</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -12,7 +12,7 @@ from calibre.gui2 import error_dialog
|
|||||||
|
|
||||||
class SearchAndReplaceWidget(Widget, Ui_Form):
|
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.')
|
HELP = _('Modify the document text and structure using user defined patterns.')
|
||||||
COMMIT_NAME = 'search_and_replace'
|
COMMIT_NAME = 'search_and_replace'
|
||||||
ICON = I('search.png')
|
ICON = I('search.png')
|
||||||
|
@ -599,7 +599,7 @@ class BulkEnumeration(BulkBase, Enumeration):
|
|||||||
value = None
|
value = None
|
||||||
ret_value = None
|
ret_value = None
|
||||||
dialog_shown = False
|
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)
|
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 val and val not in self.col_metadata['display']['enum_values']:
|
||||||
if not dialog_shown:
|
if not dialog_shown:
|
||||||
@ -610,7 +610,7 @@ class BulkEnumeration(BulkBase, Enumeration):
|
|||||||
show=True, show_copy_button=False)
|
show=True, show_copy_button=False)
|
||||||
dialog_shown = True
|
dialog_shown = True
|
||||||
ret_value = ' nochange '
|
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 '
|
ret_value = ' nochange '
|
||||||
value = val
|
value = val
|
||||||
if ret_value is None:
|
if ret_value is None:
|
||||||
|
@ -29,7 +29,6 @@ FIELDS = ['all', 'author_sort', 'authors', 'comments',
|
|||||||
'series_index', 'series', 'size', 'tags', 'timestamp', 'title',
|
'series_index', 'series', 'size', 'tags', 'timestamp', 'title',
|
||||||
'uuid']
|
'uuid']
|
||||||
|
|
||||||
|
|
||||||
#Allowed fields for template
|
#Allowed fields for template
|
||||||
TEMPLATE_ALLOWED_FIELDS = [ 'author_sort', 'authors', 'id', 'isbn', 'pubdate',
|
TEMPLATE_ALLOWED_FIELDS = [ 'author_sort', 'authors', 'id', 'isbn', 'pubdate',
|
||||||
'publisher', 'series_index', 'series', 'tags', 'timestamp', 'title', 'uuid' ]
|
'publisher', 'series_index', 'series', 'tags', 'timestamp', 'title', 'uuid' ]
|
||||||
@ -605,43 +604,42 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
Option('--generate-authors',
|
Option('--generate-authors',
|
||||||
default=True,
|
default=False,
|
||||||
dest='generate_authors',
|
dest='generate_authors',
|
||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
help=_("Include 'Authors' section in catalog."
|
help=_("Include 'Authors' section in catalog.\n"
|
||||||
"This switch is ignored - Books By Author section is always generated."
|
|
||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
Option('--generate-descriptions',
|
Option('--generate-descriptions',
|
||||||
default=True,
|
default=False,
|
||||||
dest='generate_descriptions',
|
dest='generate_descriptions',
|
||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
help=_("Include book descriptions in catalog.\n"
|
help=_("Include 'Descriptions' section in catalog.\n"
|
||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
Option('--generate-genres',
|
Option('--generate-genres',
|
||||||
default=True,
|
default=False,
|
||||||
dest='generate_genres',
|
dest='generate_genres',
|
||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
help=_("Include 'Genres' section in catalog.\n"
|
help=_("Include 'Genres' section in catalog.\n"
|
||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
Option('--generate-titles',
|
Option('--generate-titles',
|
||||||
default=True,
|
default=False,
|
||||||
dest='generate_titles',
|
dest='generate_titles',
|
||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
help=_("Include 'Titles' section in catalog.\n"
|
help=_("Include 'Titles' section in catalog.\n"
|
||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
Option('--generate-series',
|
Option('--generate-series',
|
||||||
default=True,
|
default=False,
|
||||||
dest='generate_series',
|
dest='generate_series',
|
||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
help=_("Include 'Series' section in catalog.\n"
|
help=_("Include 'Series' section in catalog.\n"
|
||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
Option('--generate-recently-added',
|
Option('--generate-recently-added',
|
||||||
default=True,
|
default=False,
|
||||||
dest='generate_recently_added',
|
dest='generate_recently_added',
|
||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
help=_("Include 'Recently Added' section in catalog.\n"
|
help=_("Include 'Recently Added' section in catalog.\n"
|
||||||
@ -976,7 +974,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.__thumbWidth = 0
|
self.__thumbWidth = 0
|
||||||
self.__thumbHeight = 0
|
self.__thumbHeight = 0
|
||||||
self.__title = opts.catalog_title
|
self.__title = opts.catalog_title
|
||||||
self.__totalSteps = 8.0
|
self.__totalSteps = 6.0
|
||||||
self.__useSeriesPrefixInTitlesSection = False
|
self.__useSeriesPrefixInTitlesSection = False
|
||||||
self.__verbose = opts.verbose
|
self.__verbose = opts.verbose
|
||||||
|
|
||||||
@ -1014,17 +1012,21 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
(self.__archive_path, float(cached_thumb_width)))
|
(self.__archive_path, float(cached_thumb_width)))
|
||||||
|
|
||||||
# Tweak build steps based on optional sections: 1 call for HTML, 1 for NCX
|
# Tweak build steps based on optional sections: 1 call for HTML, 1 for NCX
|
||||||
|
incremental_jobs = 0
|
||||||
|
if self.opts.generate_authors:
|
||||||
|
incremental_jobs += 2
|
||||||
if self.opts.generate_titles:
|
if self.opts.generate_titles:
|
||||||
self.__totalSteps += 2
|
incremental_jobs += 2
|
||||||
if self.opts.generate_recently_added:
|
if self.opts.generate_recently_added:
|
||||||
self.__totalSteps += 2
|
incremental_jobs += 2
|
||||||
if self.generateRecentlyRead:
|
if self.generateRecentlyRead:
|
||||||
self.__totalSteps += 2
|
incremental_jobs += 2
|
||||||
if self.opts.generate_series:
|
if self.opts.generate_series:
|
||||||
self.__totalSteps += 2
|
incremental_jobs += 2
|
||||||
if self.opts.generate_descriptions:
|
if self.opts.generate_descriptions:
|
||||||
# +1 thumbs
|
# +1 thumbs
|
||||||
self.__totalSteps += 3
|
incremental_jobs += 3
|
||||||
|
self.__totalSteps += incremental_jobs
|
||||||
|
|
||||||
# Load section list templates
|
# Load section list templates
|
||||||
templates = []
|
templates = []
|
||||||
@ -1358,6 +1360,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
if self.opts.generate_descriptions:
|
if self.opts.generate_descriptions:
|
||||||
self.generateThumbnails()
|
self.generateThumbnails()
|
||||||
self.generateHTMLDescriptions()
|
self.generateHTMLDescriptions()
|
||||||
|
if self.opts.generate_authors:
|
||||||
self.generateHTMLByAuthor()
|
self.generateHTMLByAuthor()
|
||||||
if self.opts.generate_titles:
|
if self.opts.generate_titles:
|
||||||
self.generateHTMLByTitle()
|
self.generateHTMLByTitle()
|
||||||
@ -1365,6 +1368,13 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.generateHTMLBySeries()
|
self.generateHTMLBySeries()
|
||||||
if self.opts.generate_genres:
|
if self.opts.generate_genres:
|
||||||
self.generateHTMLByTags()
|
self.generateHTMLByTags()
|
||||||
|
# If this is the only Section, and there are no genres, bail
|
||||||
|
if self.opts.section_list == ['Genres'] and not self.genres:
|
||||||
|
error_msg = _("No Genres found to catalog.\nCheck 'Excluded genres'\nin E-book options.\n")
|
||||||
|
self.opts.log.error(error_msg)
|
||||||
|
self.error.append(_('No books available to catalog'))
|
||||||
|
self.error.append(error_msg)
|
||||||
|
return False
|
||||||
if self.opts.generate_recently_added:
|
if self.opts.generate_recently_added:
|
||||||
self.generateHTMLByDateAdded()
|
self.generateHTMLByDateAdded()
|
||||||
if self.generateRecentlyRead:
|
if self.generateRecentlyRead:
|
||||||
@ -1372,6 +1382,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
self.generateOPF()
|
self.generateOPF()
|
||||||
self.generateNCXHeader()
|
self.generateNCXHeader()
|
||||||
|
if self.opts.generate_authors:
|
||||||
self.generateNCXByAuthor("Authors")
|
self.generateNCXByAuthor("Authors")
|
||||||
if self.opts.generate_titles:
|
if self.opts.generate_titles:
|
||||||
self.generateNCXByTitle("Titles")
|
self.generateNCXByTitle("Titles")
|
||||||
@ -1508,7 +1519,6 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
for tag in exclude_tags:
|
for tag in exclude_tags:
|
||||||
search_terms.append("tag:=%s" % tag)
|
search_terms.append("tag:=%s" % tag)
|
||||||
search_phrase = "not (%s)" % " or ".join(search_terms)
|
search_phrase = "not (%s)" % " or ".join(search_terms)
|
||||||
|
|
||||||
# If a list of ids are provided, don't use search_text
|
# If a list of ids are provided, don't use search_text
|
||||||
if self.opts.ids:
|
if self.opts.ids:
|
||||||
self.opts.search_text = search_phrase
|
self.opts.search_text = search_phrase
|
||||||
@ -1879,6 +1889,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
# Link to author
|
# Link to author
|
||||||
emTag = Tag(soup, "em")
|
emTag = Tag(soup, "em")
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
|
if self.opts.generate_authors:
|
||||||
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(book['author']))
|
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(book['author']))
|
||||||
aTag.insert(0, NavigableString(book['author']))
|
aTag.insert(0, NavigableString(book['author']))
|
||||||
emTag.insert(0,aTag)
|
emTag.insert(0,aTag)
|
||||||
@ -2149,6 +2160,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
pAuthorTag = Tag(soup, "p")
|
pAuthorTag = Tag(soup, "p")
|
||||||
pAuthorTag['class'] = "author_index"
|
pAuthorTag['class'] = "author_index"
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
|
if self.opts.generate_authors:
|
||||||
aTag['name'] = "%s" % self.generateAuthorAnchor(current_author)
|
aTag['name'] = "%s" % self.generateAuthorAnchor(current_author)
|
||||||
aTag.insert(0,NavigableString(current_author))
|
aTag.insert(0,NavigableString(current_author))
|
||||||
pAuthorTag.insert(0,aTag)
|
pAuthorTag.insert(0,aTag)
|
||||||
@ -2276,6 +2288,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
# Link to author
|
# Link to author
|
||||||
emTag = Tag(soup, "em")
|
emTag = Tag(soup, "em")
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
|
if self.opts.generate_authors:
|
||||||
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(new_entry['author']))
|
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(new_entry['author']))
|
||||||
aTag.insert(0, NavigableString(new_entry['author']))
|
aTag.insert(0, NavigableString(new_entry['author']))
|
||||||
emTag.insert(0,aTag)
|
emTag.insert(0,aTag)
|
||||||
@ -2425,6 +2438,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
# Link to author
|
# Link to author
|
||||||
emTag = Tag(soup, "em")
|
emTag = Tag(soup, "em")
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
|
if self.opts.generate_authors:
|
||||||
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(new_entry['author']))
|
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(new_entry['author']))
|
||||||
aTag.insert(0, NavigableString(new_entry['author']))
|
aTag.insert(0, NavigableString(new_entry['author']))
|
||||||
emTag.insert(0,aTag)
|
emTag.insert(0,aTag)
|
||||||
@ -2473,6 +2487,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
# Link to author
|
# Link to author
|
||||||
emTag = Tag(soup, "em")
|
emTag = Tag(soup, "em")
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
|
if self.opts.generate_authors:
|
||||||
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(new_entry['author']))
|
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(new_entry['author']))
|
||||||
aTag.insert(0, NavigableString(new_entry['author']))
|
aTag.insert(0, NavigableString(new_entry['author']))
|
||||||
emTag.insert(0,aTag)
|
emTag.insert(0,aTag)
|
||||||
@ -2692,6 +2707,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
|
|
||||||
# Link to author
|
# Link to author
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
|
if self.opts.generate_authors:
|
||||||
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor",
|
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor",
|
||||||
self.generateAuthorAnchor(escape(' & '.join(book['authors']))))
|
self.generateAuthorAnchor(escape(' & '.join(book['authors']))))
|
||||||
aTag.insert(0, NavigableString(' & '.join(book['authors'])))
|
aTag.insert(0, NavigableString(' & '.join(book['authors'])))
|
||||||
@ -3074,10 +3090,34 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
textTag.insert(0, NavigableString(self.title))
|
textTag.insert(0, NavigableString(self.title))
|
||||||
navLabelTag.insert(0, textTag)
|
navLabelTag.insert(0, textTag)
|
||||||
navPointTag.insert(0, navLabelTag)
|
navPointTag.insert(0, navLabelTag)
|
||||||
|
|
||||||
|
if self.opts.generate_authors:
|
||||||
contentTag = Tag(soup, 'content')
|
contentTag = Tag(soup, 'content')
|
||||||
#contentTag['src'] = "content/book_%d.html" % int(self.booksByTitle[0]['id'])
|
|
||||||
contentTag['src'] = "content/ByAlphaAuthor.html"
|
contentTag['src'] = "content/ByAlphaAuthor.html"
|
||||||
navPointTag.insert(1, contentTag)
|
navPointTag.insert(1, contentTag)
|
||||||
|
elif self.opts.generate_titles:
|
||||||
|
contentTag = Tag(soup, 'content')
|
||||||
|
contentTag['src'] = "content/ByAlphaTitle.html"
|
||||||
|
navPointTag.insert(1, contentTag)
|
||||||
|
elif self.opts.generate_series:
|
||||||
|
contentTag = Tag(soup, 'content')
|
||||||
|
contentTag['src'] = "content/BySeries.html"
|
||||||
|
navPointTag.insert(1, contentTag)
|
||||||
|
elif self.opts.generate_genres:
|
||||||
|
contentTag = Tag(soup, 'content')
|
||||||
|
contentTag['src'] = "content/ByGenres.html"
|
||||||
|
navPointTag.insert(1, contentTag)
|
||||||
|
elif self.opts.generate_recently_added:
|
||||||
|
contentTag = Tag(soup, 'content')
|
||||||
|
contentTag['src'] = "content/ByDateAdded.html"
|
||||||
|
navPointTag.insert(1, contentTag)
|
||||||
|
else:
|
||||||
|
sort_descriptions_by = self.booksByAuthor if self.opts.sort_descriptions_by_author \
|
||||||
|
else self.booksByTitle
|
||||||
|
contentTag = Tag(soup, 'content')
|
||||||
|
contentTag['src'] = "content/book_%d.html" % int(sort_descriptions_by[0]['id'])
|
||||||
|
navPointTag.insert(1, contentTag)
|
||||||
|
|
||||||
cmiTag = Tag(soup, '%s' % 'calibre:meta-img')
|
cmiTag = Tag(soup, '%s' % 'calibre:meta-img')
|
||||||
cmiTag['name'] = "mastheadImage"
|
cmiTag['name'] = "mastheadImage"
|
||||||
cmiTag['src'] = "images/mastheadImage.gif"
|
cmiTag['src'] = "images/mastheadImage.gif"
|
||||||
@ -4140,6 +4180,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
pAuthorTag = Tag(soup, "p")
|
pAuthorTag = Tag(soup, "p")
|
||||||
pAuthorTag['class'] = "author_index"
|
pAuthorTag['class'] = "author_index"
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
|
if self.opts.generate_authors:
|
||||||
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(book['author']))
|
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(book['author']))
|
||||||
aTag.insert(0, book['author'])
|
aTag.insert(0, book['author'])
|
||||||
pAuthorTag.insert(0,aTag)
|
pAuthorTag.insert(0,aTag)
|
||||||
@ -4371,6 +4412,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
|
|
||||||
# Insert the author link (always)
|
# Insert the author link (always)
|
||||||
aTag = body.find('a', attrs={'class':'author'})
|
aTag = body.find('a', attrs={'class':'author'})
|
||||||
|
if self.opts.generate_authors:
|
||||||
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor",
|
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor",
|
||||||
self.generateAuthorAnchor(book['author']))
|
self.generateAuthorAnchor(book['author']))
|
||||||
|
|
||||||
@ -4860,6 +4902,8 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
|
|
||||||
opts.basename = "Catalog"
|
opts.basename = "Catalog"
|
||||||
opts.cli_environment = not hasattr(opts,'sync')
|
opts.cli_environment = not hasattr(opts,'sync')
|
||||||
|
|
||||||
|
# Hard-wired to always sort descriptions by author, with series after non-series
|
||||||
opts.sort_descriptions_by_author = True
|
opts.sort_descriptions_by_author = True
|
||||||
|
|
||||||
build_log = []
|
build_log = []
|
||||||
@ -4898,14 +4942,13 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
if opts_dict['ids']:
|
if opts_dict['ids']:
|
||||||
build_log.append(" book count: %d" % len(opts_dict['ids']))
|
build_log.append(" book count: %d" % len(opts_dict['ids']))
|
||||||
|
|
||||||
'''
|
|
||||||
sections_list = []
|
sections_list = []
|
||||||
if opts.generate_authors:
|
if opts.generate_authors:
|
||||||
sections_list.append('Authors')
|
sections_list.append('Authors')
|
||||||
'''
|
|
||||||
sections_list = ['Authors']
|
|
||||||
if opts.generate_titles:
|
if opts.generate_titles:
|
||||||
sections_list.append('Titles')
|
sections_list.append('Titles')
|
||||||
|
if opts.generate_series:
|
||||||
|
sections_list.append('Series')
|
||||||
if opts.generate_genres:
|
if opts.generate_genres:
|
||||||
sections_list.append('Genres')
|
sections_list.append('Genres')
|
||||||
if opts.generate_recently_added:
|
if opts.generate_recently_added:
|
||||||
@ -4913,7 +4956,21 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
if opts.generate_descriptions:
|
if opts.generate_descriptions:
|
||||||
sections_list.append('Descriptions')
|
sections_list.append('Descriptions')
|
||||||
|
|
||||||
|
if not sections_list:
|
||||||
|
if opts.cli_environment:
|
||||||
|
opts.log.warn('*** No Section switches specified, enabling all Sections ***')
|
||||||
|
opts.generate_authors = True
|
||||||
|
opts.generate_titles = True
|
||||||
|
opts.generate_series = True
|
||||||
|
opts.generate_genres = True
|
||||||
|
opts.generate_recently_added = True
|
||||||
|
opts.generate_descriptions = True
|
||||||
|
sections_list = ['Authors','Titles','Series','Genres','Recently Added','Descriptions']
|
||||||
|
else:
|
||||||
|
opts.log.warn('\n*** No enabled Sections, terminating catalog generation ***')
|
||||||
|
return ["No Included Sections","No enabled Sections.\nCheck E-book options tab\n'Included sections'\n"]
|
||||||
build_log.append(u" Sections: %s" % ', '.join(sections_list))
|
build_log.append(u" Sections: %s" % ', '.join(sections_list))
|
||||||
|
opts.section_list = sections_list
|
||||||
|
|
||||||
# Limit thumb_width to 1.0" - 2.0"
|
# Limit thumb_width to 1.0" - 2.0"
|
||||||
try:
|
try:
|
||||||
@ -4948,6 +5005,7 @@ then rebuild the catalog.\n''').format(author[0],author[1],current_author[1])
|
|||||||
|
|
||||||
# Launch the Catalog builder
|
# Launch the Catalog builder
|
||||||
catalog = self.CatalogBuilder(db, opts, self, report_progress=notification)
|
catalog = self.CatalogBuilder(db, opts, self, report_progress=notification)
|
||||||
|
|
||||||
if opts.verbose:
|
if opts.verbose:
|
||||||
log.info(" Begin catalog source generation")
|
log.info(" Begin catalog source generation")
|
||||||
catalog.createDirectoryStructure()
|
catalog.createDirectoryStructure()
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -42,30 +42,44 @@ def supports_long_names(path):
|
|||||||
else:
|
else:
|
||||||
return True
|
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)
|
filepath = os.sep.join(components)
|
||||||
extra = len(filepath) - length
|
extra = len(filepath) - (length - more_to_take)
|
||||||
if extra < 1:
|
if extra < 1:
|
||||||
return components
|
return components
|
||||||
delta = int(ceil(extra/float(len(components))))
|
deltas = []
|
||||||
ans = []
|
|
||||||
for x in components:
|
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):
|
if delta > len(x):
|
||||||
r = x[0] if x is components[-1] else ''
|
r = x[0] if x is components[-1] else ''
|
||||||
else:
|
else:
|
||||||
if x is components[-1]:
|
if x is components[-1]:
|
||||||
b, e = os.path.splitext(x)
|
b, e = os.path.splitext(x)
|
||||||
if e == '.': e = ''
|
if e == '.': e = ''
|
||||||
r = b[:-delta]+e
|
r = shorten_component(b, delta)+e
|
||||||
if r.startswith('.'): r = x[0]+r
|
if r.startswith('.'): r = x[0]+r
|
||||||
else:
|
else:
|
||||||
r = x[:-delta]
|
r = shorten_component(x, delta)
|
||||||
r = r.strip()
|
r = r.strip()
|
||||||
if not r:
|
if not r:
|
||||||
r = x.strip()[0] if x.strip() else 'x'
|
r = x.strip()[0] if x.strip() else 'x'
|
||||||
ans.append(r)
|
ans.append(r)
|
||||||
if len(os.sep.join(ans)) > length:
|
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
|
return ans
|
||||||
|
|
||||||
def find_executable_in_path(name, path=None):
|
def find_executable_in_path(name, path=None):
|
||||||
|
@ -75,7 +75,7 @@ class FormatterFunction(object):
|
|||||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
info = ': '.join(traceback.format_exception(exc_type, exc_value,
|
info = ': '.join(traceback.format_exception(exc_type, exc_value,
|
||||||
exc_traceback)[-2:]).replace('\n', '')
|
exc_traceback)[-2:]).replace('\n', '')
|
||||||
return _('Exception ' + info)
|
return _('Exception ') + info
|
||||||
|
|
||||||
all_builtin_functions = []
|
all_builtin_functions = []
|
||||||
class BuiltinFormatterFunction(FormatterFunction):
|
class BuiltinFormatterFunction(FormatterFunction):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user