Quote:
Originally Posted by kcz
Hmm, this is interesting. I was using the code of other functions as a template.
e.g. look at the re function. Very strange.
On my installation the re function looks like this:
Code:
def evaluate(self, formatter, kwargs, mi, locals, val, pattern, replacement):
return re.sub(pattern, replacement, val, flags=re.I)
|
That is accidental. See below
Quote:
This is all very confusing.
|
The first and most important thing is that the template language is not python. I defined it over time to meet our needs. The language is interpreted by a custom language interpreter. Calibre can also translate the language into python, but only as a sequence of calls to the python implementation of template functions in the interpreter.
It is an accident that the template function and the python module are both named "re". If you look at the template function, its parameter profile is totally different from the one in the python module.
Quote:
There are so many things that do not make any sense to me. Let's say I want to return either an integer or a float depending on the occurrences within a series. e.g. let's say there are 3 books in series x and the 2nd book has 1.50 as the index value, so a function should return a float in the format aa.bb for all the books in the series.
|
Template function should (actually, must) always return a string. That is the only datatype that the interpreter understands. If you return something else then it might work, but only because python is very willing to coerce types when needed.
In your example, you must return strings '1', '1.50', and '2', or some such. You would use python expressions to accomplish this.
Quote:
technically you would write a function which loops through all the books in a series and if one index is not an integer then return the current index as aa.bb (even if the current one is an integer like 2.00)
series x: book one - 1.00, book 2 - 1.50, book 3 - 3.00, so the function would return 01.00, 01.50, 03.00.
If the second book had an index of 2.00, then the function would return 01, 02, 03.
(the funcion is called once for every book in the series)
|
If I understand correctly, you want to choose the format of the series for a particular book based on the union of information from all books. You cannot do this in a template function. These functions can see only the book you are working on. They cannot see data for any other book.
Quote:
But I have no idea how to even reference the books in a series in python. Maybe this is not even possible. I'm used to code in C and thus would access the data via dynamic sql, ran the loop once and stored the result that one or more values are a float in shared memory. In that case I had a map which told me series x had a float or not.
whenever I call the function, it would check if an entry in the map existed and if not it'd use above routine to generate the entry in the map.
|
You would do something similar in python, but using calibre's data access layer. The problem is that a template function does not have access to the db, and in fact cannot have access to it. The reason: template functions can be evaluated in contexts where the db must not be opened, such as worker processes or file name generation during send-to operations.
Doing what you want requires writing a plugin. These can see the database and can do completely arbitrary things such as writing values into custom columns. Alternatively you could change calibre itself to do what you want.