Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Software > Calibre > Library Management

Notices

Reply
 
Thread Tools Search this Thread
Old 05-07-2024, 05:29 PM   #1
tsparr
Junior Member
tsparr began at the beginning.
 
Posts: 6
Karma: 10
Join Date: May 2024
Device: Kindle Paperwhite (11th Generation)
Save to Disk Template Issue with Series vs Standalone

I have a Save to Disk template that seems like it should work; however, is throwing an error when actually running the task. It does work successfully for books with a series, but fails on the standalones with the following error.
Code:
Traceback (most recent call last):
      File "calibre\library\save_to_disk.py", line 282, in get_path_components
      File "calibre\library\save_to_disk.py", line 247, in get_components
      File "calibre\utils\formatter.py", line 1930, in unsafe_format
      File "calibre\utils\formatter.py", line 1847, in evaluate
      File "string.py", line 194, in vformat
      File "string.py", line 203, in _vformat
    ValueError: Single '}' encountered in format string
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "calibre\gui2\save.py", line 139, in do_one_collect
      File "calibre\gui2\save.py", line 147, in collect_data
      File "calibre\library\save_to_disk.py", line 288, in get_path_components
    ValueError: Failed to calculate path for save to disk. Template: {series:'re(ifempty($,field('title') & ' - ' & field('authors')),':',' -')'}/{series:'re(ifempty($,field('title') & ' - ' & field('authors')),':',' -')'}{series_index:0>2s| - | - {title}}
    Error: Single '}' encountered in format string
The template appears as if it should work in the editor, so not sure what I'm missing.
tsparr is offline   Reply With Quote
Old 05-07-2024, 07:36 PM   #2
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,097
Karma: 7908993
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
From the Advanced formatting section of the template language manual:
Quote:
Do not use subtemplates (`{ … }`) or functions (see below) in the prefix or the suffix.
The last template expression
Code:
{series_index:0>2s| - | - {title}}
does exactly that. I suspect you want
Code:
{series_index:0>2s| - | - }{title}
It also isn't obvious why you want the series twice in the path

IMO a template of this complexity should be written in Template Program Mode (TPM). Not only is branching easier, TPM templates are much easier to debug.
chaley is offline   Reply With Quote
Advert
Old 05-07-2024, 07:38 PM   #3
theducks
Well trained by Cats
theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.theducks ought to be getting tired of karma fortunes by now.
 
theducks's Avatar
 
Posts: 30,506
Karma: 58055868
Join Date: Aug 2009
Location: The Central Coast of California
Device: Kobo Libra2,Kobo Aura2v1, K4NT(Fixed: New Bat.), Galaxy Tab A
You did not close series index before Title
{ } are always pairs and are not nested
theducks is offline   Reply With Quote
Old 05-07-2024, 09:52 PM   #4
tsparr
Junior Member
tsparr began at the beginning.
 
Posts: 6
Karma: 10
Join Date: May 2024
Device: Kindle Paperwhite (11th Generation)
Quote:
Originally Posted by chaley View Post
From the Advanced formatting section of the template language manual:
The last template expression
Code:
{series_index:0>2s| - | - {title}}
does exactly that. I suspect you want
Code:
{series_index:0>2s| - | - }{title}
It also isn't obvious why you want the series twice in the path

IMO a template of this complexity should be written in Template Program Mode (TPM). Not only is branching easier, TPM templates are much easier to debug.
The problem if I do {title} outside of the template expression is that I would then have the title of the book in the filename twice if it's not in a series. The intent is to match up with a program I used called Kavita and their intended library structure of:
Library Root
┖── Series Name
┖── Series Name.epub

I'll look into the TPM template.
tsparr is offline   Reply With Quote
Old 05-07-2024, 09:54 PM   #5
tsparr
Junior Member
tsparr began at the beginning.
 
Posts: 6
Karma: 10
Join Date: May 2024
Device: Kindle Paperwhite (11th Generation)
Quote:
Originally Posted by theducks View Post
You did not close series index before Title
{ } are always pairs and are not nested
I think if this were the case, wouldn't the template editor complain? Again, it works fine for saving books in a series. It's only the standalone titles that it fails for. Simply removing {title} allows this template to work:

{series:'re(ifempty($,field('title') & ' - ' & field('authors')),':',' -')'}/{series:'re(ifempty($,field('title') & ' - ' & field('authors')),':',' -')'}{series_index:0>2s| - |}
tsparr is offline   Reply With Quote
Advert
Old 05-07-2024, 10:36 PM   #6
tsparr
Junior Member
tsparr began at the beginning.
 
Posts: 6
Karma: 10
Join Date: May 2024
Device: Kindle Paperwhite (11th Generation)
Sorry for the triple post at this point, but I ended up moving to Python because it just made way more sense to me. It's a little bit slower to run, but I'm only occasionally saving books out to disk.

Code:
python:
def evaluate(book, context):
	if book.series is None:
		author_str = ""
		for author in range(len(book.authors)):
			author_str += book.authors[author]
		book_str = book.title + ' - ' + author_str + '/' + book.title + ' - ' + author_str
	else:
		book_str = book.series + '/' + book.series + ' - ' + f"{int(book.series_index):02}" + ' - ' + book.title

	return book_str
tsparr is offline   Reply With Quote
Old 05-08-2024, 12:52 AM   #7
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,097
Karma: 7908993
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Your python template smashes all the author names together without separation. Is that what you want? I think you want this:
Code:
python:
def evaluate(book, context):
	if book.series is None:
		author_str = ' & '.join(book.authors)
		book_str = book.title + ' - ' + author_str + '/' + book.title + ' - ' + author_str
	else:
		book_str = book.series + '/' + book.series + ' - ' + f"{int(book.series_index):02}" + ' - ' + book.title
	return book_str
or perhaps this, simplified somewhat using 'f' strings:
Code:
python:
def evaluate(book, context):
	if book.series is None:
		author_str = ' & '.join(book.authors)
		book_str = f'{book.title} - {author_str}/{book.title} - {author_str}'
	else:
		book_str = f'{book.series}/{book.series} - {int(book.series_index):02} - {book.title}'
	return book_str
For completeness, here is the equivalent template in GPM:
Code:
program:
	if $series then
		res = template('{series}/{series} - {series_index:0>2s} - {title}')
	else
		res = template('{title} - {authors}/{title} - {authors}')
	fi;
	res
For both templates: it isn't clear that you will get what you want if the series index is a floating point number such as 2.3. The python template drops the fraction. The GPM template includes it but doesn't respect the length. If you really want to ignore the fraction then the series index part of the GPM template should be
Code:
{series_index:0>2.0f}
chaley is offline   Reply With Quote
Old 05-08-2024, 01:07 AM   #8
tsparr
Junior Member
tsparr began at the beginning.
 
Posts: 6
Karma: 10
Join Date: May 2024
Device: Kindle Paperwhite (11th Generation)
You're absolutely right in that I didn't want the names smashed together. I had actually already fixed that on my side, but didn't want to post a 4th time in a row and didn't see a way to edit my existing post.

Appreciate the simplified version and agreed it looks much cleaner. I was mainly just on a kick of adding each piece one at a time and validating the path in the template editor was showing as expected.

I don't currently have anything with a decimal in my library, so that's definitely an edge case I didn't consider. I'll manually adjust some metadata and play with that a little bit. I don't think I necessarily care if it's 00.5 vs 0.5. I just think it's cleaner to be 03 vs 3 especially when you get into series that go up into the double digits.
tsparr is offline   Reply With Quote
Old 05-08-2024, 01:16 AM   #9
tsparr
Junior Member
tsparr began at the beginning.
 
Posts: 6
Karma: 10
Join Date: May 2024
Device: Kindle Paperwhite (11th Generation)
Looks like this will handle the decimal series indexes:

Code:
python:
def evaluate(book, context):
	if book.series is None:
		author_str = ' & '.join(book.authors)
		book_str = f'{book.title} - {author_str}/{book.title} - {author_str}'
	else:
		if book.series_index.is_integer():
			book_str = f'{book.series}/{book.series} - {int(book.series_index):02} - {book.title}'
		else:
			book_str =  f'{book.series}/{book.series} - {book.series_index} - {book.title}'
	return book_str
tsparr is offline   Reply With Quote
Reply


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Save to disk title sort order different for series vs standalone books? threebluestars Library Management 0 01-07-2020 12:36 AM
Save to Disk Template Help Tanjamuse Library Management 2 08-09-2019 10:35 AM
save to disk template help bilaly Library Management 2 10-19-2018 08:19 PM
Save to Disk Template with series in brackets Vortex Calibre 18 10-12-2018 02:52 PM
Need help - Save to Disk template Gallips Calibre 8 06-28-2016 02:46 PM


All times are GMT -4. The time now is 03:41 AM.


MobileRead.com is a privately owned, operated and funded community.