From a8deb0ed7d2b349a82711f96cb0ed28a3db16156 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 25 May 2011 09:56:27 -0600 Subject: [PATCH 1/5] ... --- src/calibre/devices/android/driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/devices/android/driver.py b/src/calibre/devices/android/driver.py index db473a755e..1cdf394c24 100644 --- a/src/calibre/devices/android/driver.py +++ b/src/calibre/devices/android/driver.py @@ -59,7 +59,7 @@ class ANDROID(USBMS): 0x0489 : { 0xc001 : [0x0226], 0xc004 : [0x0226], }, # Acer - 0x502 : { 0x3203 : [0x0100]}, + 0x502 : { 0x3203 : [0x0100, 0x224]}, # Dell 0x413c : { 0xb007 : [0x0100, 0x0224, 0x0226]}, From ce6cedf730c2c59b0cc41bcce7c29a969edf2eaf Mon Sep 17 00:00:00 2001 From: Li Fanxi Date: Thu, 26 May 2011 00:24:04 +0800 Subject: [PATCH 2/5] [Bug] Error in passing API key to douban API. --- src/calibre/ebooks/metadata/sources/douban.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/sources/douban.py b/src/calibre/ebooks/metadata/sources/douban.py index 3c6bb7b6c7..8a95c4ed6b 100644 --- a/src/calibre/ebooks/metadata/sources/douban.py +++ b/src/calibre/ebooks/metadata/sources/douban.py @@ -211,7 +211,7 @@ class Douban(Source): 'q': q, }) if self.DOUBAN_API_KEY and self.DOUBAN_API_KEY != '': - url = url + "?apikey=" + self.DOUBAN_API_KEY + url = url + "&apikey=" + self.DOUBAN_API_KEY return url # }}} From 70d1f3c046913e90cfd649859b2a2d32528a88b9 Mon Sep 17 00:00:00 2001 From: Li Fanxi Date: Thu, 26 May 2011 00:31:47 +0800 Subject: [PATCH 3/5] [Bug] Error in passing API key to douban API when search by isbn or douban id --- src/calibre/ebooks/metadata/sources/douban.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/sources/douban.py b/src/calibre/ebooks/metadata/sources/douban.py index 8a95c4ed6b..70bf01a00e 100644 --- a/src/calibre/ebooks/metadata/sources/douban.py +++ b/src/calibre/ebooks/metadata/sources/douban.py @@ -211,7 +211,10 @@ class Douban(Source): 'q': q, }) if self.DOUBAN_API_KEY and self.DOUBAN_API_KEY != '': - url = url + "&apikey=" + self.DOUBAN_API_KEY + if t == "isbn" or t == "subject": + url = url + "?apikey=" + self.DOUBAN_API_KEY + else: + url = url + "&apikey=" + self.DOUBAN_API_KEY return url # }}} From b707ae28202b550a704c0729b040e254fcaca51e Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 25 May 2011 17:44:47 +0100 Subject: [PATCH 4/5] Addition of boolean template functions and, or, not. Change documentation to include them. Add a function classification summary to the documentation. --- src/calibre/manual/template_lang.rst | 20 +++++++++- src/calibre/utils/formatter_functions.py | 51 ++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/calibre/manual/template_lang.rst b/src/calibre/manual/template_lang.rst index 69c77e5bfd..16a90f7531 100644 --- a/src/calibre/manual/template_lang.rst +++ b/src/calibre/manual/template_lang.rst @@ -229,13 +229,14 @@ For various values of series_index, the program returns: The following functions are available in addition to those described in single-function mode. Remember from the example above that the single-function mode functions require an additional first parameter specifying the field to operate on. With the exception of the ``id`` parameter of assign, all parameters can be statements (sequences of expressions): + * ``and(value, value, ...)`` -- returns the string "1" if all values are not empty, otherwise returns the empty string. This function works well with test or first_non_empty. You can have as many values as you want. * ``add(x, y)`` -- returns x + y. Throws an exception if either x or y are not numbers. * ``assign(id, val)`` -- assigns val to id, then returns val. id must be an identifier, not an expression * ``booksize()`` -- returns the value of the |app| 'size' field. Returns '' if there are no formats. * ``cmp(x, y, lt, eq, gt)`` -- compares x and y after converting both to numbers. Returns ``lt`` if x < y. Returns ``eq`` if x == y. Otherwise returns ``gt``. * ``divide(x, y)`` -- returns x / y. Throws an exception if either x or y are not numbers. * ``field(name)`` -- returns the metadata field named by ``name``. - * ``first_non_empty(value, value, ...) -- returns the first value that is not empty. If all values are empty, then the empty value is returned. You can have as many values as you want. + * ``first_non_empty(value, value, ...)`` -- returns the first value that is not empty. If all values are empty, then the empty value is returned. You can have as many values as you want. * ``format_date(x, date_format)`` -- format_date(val, format_string) -- format the value, which must be a date field, using the format_string, returning a string. The formatting codes are:: d : the day as number without a leading zero (1 to 31) @@ -251,7 +252,9 @@ The following functions are available in addition to those described in single-f iso : the date with time and timezone. Must be the only format present. * ``eval(string)`` -- evaluates the string as a program, passing the local variables (those ``assign`` ed to). This permits using the template processor to construct complex results from local variables. + * ``not(value)`` -- returns the string "1" if the value is empty, otherwise returns the empty string. This function works well with test or first_non_empty. You can have as many values as you want. * ``multiply(x, y)`` -- returns x * y. Throws an exception if either x or y are not numbers. + * ``or(value, value, ...)`` -- returns the string "1" if any value is not empty, otherwise returns the empty string. This function works well with test or first_non_empty. You can have as many values as you want. * ``print(a, b, ...)`` -- prints the arguments to standard output. Unless you start calibre from the command line (``calibre-debug -g``), the output will go to a black hole. * ``raw_field(name)`` -- returns the metadata field named by name without applying any formatting. * ``strcat(a, b, ...)`` -- can take any number of arguments. Returns a string formed by concatenating all the arguments. @@ -259,7 +262,22 @@ The following functions are available in addition to those described in single-f * ``substr(str, start, end)`` -- returns the ``start``'th through the ``end``'th characters of ``str``. The first character in ``str`` is the zero'th character. If end is negative, then it indicates that many characters counting from the right. If end is zero, then it indicates the last character. For example, ``substr('12345', 1, 0)`` returns ``'2345'``, and ``substr('12345', 1, -1)`` returns ``'234'``. * ``subtract(x, y)`` -- returns x - y. Throws an exception if either x or y are not numbers. * ``template(x)`` -- evaluates x as a template. The evaluation is done in its own context, meaning that variables are not shared between the caller and the template evaluation. Because the `{` and `}` characters are special, you must use `[[` for the `{` character and `]]` for the '}' character; they are converted automatically. For example, ``template('[[title_sort]]') will evaluate the template ``{title_sort}`` and return its value. + +Function classification summary: + * Get values from metadata: ``field``. ``raw_field``. In some situations, ``lookup`` can be used in place of ``field``. + * Arithmetic: ``add``, ``subtract``, ``multiply``, ``divide`` + * Boolean: ``and``, ``or``, ``not``. The function ``if_empty`` is similar to ``and`` called with one argument. + * If-then-else: ``contains``, ``test`` + * Iterating over values: ``first_non_empty``, ``lookup``, ``switch`` + * List lookup: ``in_list``, ``list_item``, ``select``, + * List manipulation: ``count``, ``sublist``, ``subitems`` + * Recursion: ``eval``, ``template`` + * Relational: ``cmp`` , ``strcmp`` for strings + * String case changes: ``lowercase``, ``uppercase``, ``titlecase``, ``capitalize`` + * String manipulation: ``re``, ``shorten``, ``substr`` + * Other: ``assign``, ``booksize``, ``print``, ``format_date``, + .. _general_mode: Using general program mode diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index c53277f3ce..a3a156648f 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -594,7 +594,56 @@ class BuiltinFirstNonEmpty(BuiltinFormatterFunction): i += 1 return '' +class BuiltinAnd(BuiltinFormatterFunction): + name = 'and' + arg_count = -1 + doc = _('and(value, value, ...) -- ' + 'returns the string "1" if all values are not empty, otherwise ' + 'returns the empty string. This function works well with test or ' + 'first_non_empty. You can have as many values as you want.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + i = 0 + while i < len(args): + if not args[i]: + return '' + i += 1 + return '1' + +class BuiltinOr(BuiltinFormatterFunction): + name = 'or' + arg_count = -1 + doc = _('or(value, value, ...) -- ' + 'returns the string "1" if any value is not empty, otherwise ' + 'returns the empty string. This function works well with test or ' + 'first_non_empty. You can have as many values as you want.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + i = 0 + while i < len(args): + if args[i]: + return '1' + i += 1 + return '' + +class BuiltinNot(BuiltinFormatterFunction): + name = 'not' + arg_count = 1 + doc = _('not(value) -- ' + 'returns the string "1" if the value is empty, otherwise ' + 'returns the empty string. This function works well with test or ' + 'first_non_empty. You can have as many values as you want.') + + def evaluate(self, formatter, kwargs, mi, locals, *args): + i = 0 + while i < len(args): + if args[i]: + return '1' + i += 1 + return '' + builtin_add = BuiltinAdd() +builtin_and = BuiltinAnd() builtin_assign = BuiltinAssign() builtin_booksize = BuiltinBooksize() builtin_capitalize = BuiltinCapitalize() @@ -612,6 +661,8 @@ builtin_list_item = BuiltinListitem() builtin_lookup = BuiltinLookup() builtin_lowercase = BuiltinLowercase() builtin_multiply = BuiltinMultiply() +builtin_not = BuiltinNot() +builtin_or = BuiltinOr() builtin_print = BuiltinPrint() builtin_raw_field = BuiltinRaw_field() builtin_re = BuiltinRe() From aa30d964db0b8fbacfb963cfce3fd08cb30759cd Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Wed, 25 May 2011 18:09:41 +0100 Subject: [PATCH 5/5] Slight improvement to user device faq entry --- src/calibre/manual/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index d3784eda6f..b120fd4a1b 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -138,7 +138,7 @@ Follow these steps to find the problem: My device is non-standard or unusual. What can I do to connect to it? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In addition to the :guilabel:`Connect to Folder` function found under the Connect/Share button, |app| provides a ``User Defined`` device plugin that can be used to connect to any USB device that presents that shows up as a disk drive in your operating system. See the device plugin ``Preferences -> Plugins -> Device Plugins -> User Defined`` and ``Preferences -> Miscellaneous -> Get information to setup the user defined device`` for more information. +In addition to the :guilabel:`Connect to Folder` function found under the Connect/Share button, |app| provides a ``User Defined`` device plugin that can be used to connect to any USB device that shows up as a disk drive in your operating system. Note: on windows, the device must have a drive letter for calibre to use it. See the device plugin ``Preferences -> Plugins -> Device Plugins -> User Defined`` and ``Preferences -> Miscellaneous -> Get information to setup the user defined device`` for more information. How does |app| manage collections on my SONY reader? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~