View Single Post
Old 10-13-2022, 12:53 PM   #55
un_pogaz
Chalut o/
un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.un_pogaz ought to be getting tired of karma fortunes by now.
 
un_pogaz's Avatar
 
Posts: 443
Karma: 672378
Join Date: Dec 2017
Device: Kobo
Quote:
Originally Posted by chaley View Post
All this opens the question "What is the difference between a python template and a python formatter function? Good question. Formatter functions can "see" into the formatter and easily use existing formatter builtin functions, but templates cannot.
Actually...
This is no longer the case. At least not on my repositories.
I have created a system that allows to easily call and use the functions currently loaded in the formatter.
Voilą, voilą.

@chaley, @kovidgoyal, could you check this out, thanks. I don't want to make a pull request right now because it's a big change for my knowledge and I don't want to make a big problem. (also if is need to improve the code doc)

So, as it works:
This adds 2 attributes at th context: .formatter and .funcs.
.formatter is the current TemplateFormatter. It's good, but it's not best.
There .funcs enters on stage (that's where the fun start). He will which allows you to easily call any function currently loaded in the TemplateFormatter. You use them like any other function just with the name of the one you want as an attribute (plus an _ 'underscore' at the end to avoid conflicts with Python keywords). And you don't need to handle the special arguments of these (formatter, kwargs, mi, locals | book, context), it does it all by itself, you just need to provide the yours real arguments to your function.

Example: I want to convert formats_sizes() to human_readable(), easy:
Code:
python:
def evaluate(book, context):
	formats = {}
	for f in context.funcs.formats_sizes_().split(','):
		f = f.strip().split(':', 1)
		formats[f[0].lower()] = context.funcs.human_readable_(f[1])
	
	return ','.join([k+':'+v for k,v in formats.items()])
That's it, it's all. No need to think or to bother to get the code of the functions already present in calibre, let's use them directly.

And of course, user functions and stored templates can be used in the same way.
(however, what was less fun was to return an exception that made sense)

Last edited by un_pogaz; 10-13-2022 at 03:33 PM.
un_pogaz is offline   Reply With Quote