mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Save to disk: When saving to a single directory, handle the case of the save to disk template containing path separators inside template expression correctly. Fixes #821912 (save only epub on disc using one folder file-name-error)
This commit is contained in:
commit
dc58208164
@ -50,7 +50,7 @@ class SaveToDiskAction(InterfaceAction):
|
||||
cm('single format', _('Save only %s format to disk')%
|
||||
prefs['output_format'].upper(),
|
||||
triggered=partial(self.save_single_format_to_disk, False))
|
||||
cm('fingle dir and format',
|
||||
cm('single dir and format',
|
||||
_('Save only %s format to disk in a single directory')%
|
||||
prefs['output_format'].upper(),
|
||||
triggered=partial(self.save_single_fmt_to_single_dir, False))
|
||||
@ -115,10 +115,7 @@ class SaveToDiskAction(InterfaceAction):
|
||||
opts.save_cover = False
|
||||
opts.write_opf = False
|
||||
opts.template = opts.send_template
|
||||
if single_dir:
|
||||
opts.template = opts.template.split('/')[-1].strip()
|
||||
if not opts.template:
|
||||
opts.template = '{title} - {authors}'
|
||||
opts.single_dir = single_dir
|
||||
self._saver = Saver(self.gui, self.gui.library_view.model().db,
|
||||
Dispatcher(self._books_saved), rows, path, opts,
|
||||
spare_server=self.gui.spare_server)
|
||||
|
@ -121,6 +121,9 @@ def config(defaults=None):
|
||||
help=_('Convert paths to lowercase.'))
|
||||
x('replace_whitespace', default=False,
|
||||
help=_('Replace whitespace with underscores.'))
|
||||
x('single_dir', default=False,
|
||||
help=_('Save into a single directory, ignoring the template'
|
||||
' directory structure'))
|
||||
return c
|
||||
|
||||
def preprocess_template(template):
|
||||
@ -131,7 +134,7 @@ def preprocess_template(template):
|
||||
template = template.decode(preferred_encoding, 'replace')
|
||||
return template
|
||||
|
||||
class SafeFormat(TemplateFormatter):
|
||||
class Formatter(TemplateFormatter):
|
||||
'''
|
||||
Provides a format function that substitutes '' for any missing value
|
||||
'''
|
||||
@ -165,7 +168,7 @@ class SafeFormat(TemplateFormatter):
|
||||
|
||||
def get_components(template, mi, id, timefmt='%b %Y', length=250,
|
||||
sanitize_func=ascii_filename, replace_whitespace=False,
|
||||
to_lowercase=False):
|
||||
to_lowercase=False, safe_format=True):
|
||||
|
||||
tsorder = tweaks['save_template_title_series_sorting']
|
||||
format_args = FORMAT_ARGS.copy()
|
||||
@ -225,8 +228,11 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
|
||||
format_args[key] = unicode(format_args[key])
|
||||
else:
|
||||
format_args[key] = ''
|
||||
components = SafeFormat().safe_format(template, format_args,
|
||||
if safe_format:
|
||||
components = Formatter().safe_format(template, format_args,
|
||||
'G_C-EXCEPTION!', mi)
|
||||
else:
|
||||
components = Formatter().unsafe_format(template, format_args, mi)
|
||||
components = [x.strip() for x in components.split('/')]
|
||||
components = [sanitize_func(x) for x in components if x]
|
||||
if not components:
|
||||
@ -283,10 +289,20 @@ def do_save_book_to_disk(id_, mi, cover, plugboards,
|
||||
if not formats:
|
||||
return True, id_, mi.title
|
||||
|
||||
try:
|
||||
components = get_components(opts.template, mi, id_, opts.timefmt, length,
|
||||
ascii_filename if opts.asciiize else sanitize_file_name_unicode,
|
||||
to_lowercase=opts.to_lowercase,
|
||||
replace_whitespace=opts.replace_whitespace)
|
||||
replace_whitespace=opts.replace_whitespace, safe_format=False)
|
||||
except Exception, e:
|
||||
raise ValueError(_('Failed to calculate path for '
|
||||
'save to disk. Template: %s\n'
|
||||
'Error: %s'%(opts.template, e)))
|
||||
if opts.single_dir:
|
||||
components = components[-1:]
|
||||
if not components:
|
||||
raise ValueError(_('Template evaluation resulted in no'
|
||||
' path components. Template: %s')%opts.template)
|
||||
base_path = os.path.join(root, *components)
|
||||
base_name = os.path.basename(base_path)
|
||||
dirpath = os.path.dirname(base_path)
|
||||
|
@ -310,7 +310,16 @@ class TemplateFormatter(string.Formatter):
|
||||
ans = string.Formatter.vformat(self, fmt, args, kwargs)
|
||||
return self.compress_spaces.sub(' ', ans).strip()
|
||||
|
||||
########## a formatter guaranteed not to throw and exception ############
|
||||
########## a formatter that throws exceptions ############
|
||||
|
||||
def unsafe_format(self, fmt, kwargs, book):
|
||||
self.kwargs = kwargs
|
||||
self.book = book
|
||||
self.composite_values = {}
|
||||
self.locals = {}
|
||||
return self.vformat(fmt, [], kwargs).strip()
|
||||
|
||||
########## a formatter guaranteed not to throw an exception ############
|
||||
|
||||
def safe_format(self, fmt, kwargs, error_value, book):
|
||||
self.kwargs = kwargs
|
||||
|
Loading…
x
Reference in New Issue
Block a user