Merge branch 'kovidgoyal:master' into master

This commit is contained in:
unkn0w7n 2023-04-27 20:49:35 +05:30 committed by GitHub
commit 1e3a61fe1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 147 additions and 143 deletions

View File

@ -495,7 +495,7 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
* ``eval(string)`` -- evaluates the string as a program, passing the local variables. This permits using the template processor to construct complex results from local variables. In :ref:`Template Program Mode <template_mode>`, because the `{` and `}` characters are interpreted before the template is evaluated you must use `[[` for the `{` character and `]]` for the ``}`` character. They are converted automatically. Note also that prefixes and suffixes (the `|prefix|suffix` syntax) cannot be used in the argument to this function when using :ref:`Template Program Mode <template_mode>`.
* ``extra_file_size(file_name)`` -- returns the size in bytes of the extra file ``file_name`` in the book's ``data/`` folder if it exists, otherwise ``-1``. See also the functions ``has_extra_files()``, ``extra_file_names()`` and ``extra_file_modtime()``. This function can be used only in the GUI.
* ``extra_file_modtime(file_name, format_spec)`` -- returns the modification time of the extra file ``file_name`` in the book's ``data/`` folder if it exists, otherwise ``-1``. The modtime is formatted according to ``format_spec`` (see ``format_date()`` for details). If ``format_spec`` is the empty string, returns the modtime as the floating point number of seconds since the epoch. See also the functions ``has_extra_files()``, ``extra_file_names()`` and ``extra_file_size()``. The epoch is OS dependent. This function can be used only in the GUI.
* ``extra_file_names(sep)`` -- returns a ``sep``-separated list of extra files in the book's ``data/`` folder. See also the functions ``has_extra_files()``, ``extra_file_size()`` and ``extra_file_modtime()``. This function can be used only in the GUI.
* ``extra_file_names(sep [, pattern])`` returns a ``sep``-separated list of extra files in the book's ``data/`` folder. If the optional parameter ``pattern``, a regular expression, is supplied then the list is filtered to files that match ``pattern``. The pattern match is case insensitive. See also the functions ``has_extra_files()``, ``extra_file_modtime()`` and ``extra_file_size()``. This function can be used only in the GUI.
* ``field(lookup_name)`` -- returns the value of the metadata field with lookup name ``lookup_name``.
* ``field_exists(field_name)`` -- checks if a field (column) with the lookup name ``field_name`` exists, returning ``'1'`` if so and the empty string if not.
* ``finish_formatting(val, fmt, prefix, suffix)`` -- apply the format, prefix, and suffix to a value in the same way as done in a template like ``{series_index:05.2f| - |- }``. This function is provided to ease conversion of complex single-function- or template-program-mode templates to `GPM` Templates. For example, the following program produces the same output as the above template::
@ -557,7 +557,7 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
* ``formats_sizes()`` -- return a comma-separated list of colon-separated ``FMT:SIZE`` items giving the sizes in bytes of the formats of a book. You can use the select function to get the size for a specific format. Note that format names are always uppercase, as in EPUB.
* ``fractional_part(x)`` -- returns the value after the decimal point. For example, ``fractional_part(3.14)`` returns ``0.14``. Throws an exception if ``x`` is not a number.
* ``has_cover()`` -- return ``'Yes'`` if the book has a cover, otherwise the empty string.
* ``has_extra_files()`` -- returns ``'Yes'`` if there are any extra files for the book (files in the folder ``data/`` in the book's folder), otherwise ``''`` (the empty string). See also the functions ``extra_file_names()``, ``extra_file_size()`` and ``extra_file_modtime()``. This function can be used only in the GUI.
* ``has_extra_files([pattern])`` -- returns the count of extra files, otherwise '' (the empty string). If the optional parameter ``pattern`` (a regular expression) is supplied then the list is filtered to files that match ``pattern`` before the files are counted. The pattern match is case insensitive. See also the functions ``extra_file_names()``, ``extra_file_size()`` and ``extra_file_modtime()``. This function can be used only in the GUI.
* ``is_marked()`` -- check whether the book is `marked` in calibre. If it is then return the value of the mark, either ``'true'`` (lower case) or a comma-separated list of named marks. Returns ``''`` (the empty string) if the book is not marked. This function works only in the GUI.
* ``language_codes(lang_strings)`` -- return the `language codes <https://www.loc.gov/standards/iso639-2/php/code_list.php>`_ for the language names passed in `lang_strings`. The strings must be in the language of the current locale. ``Lang_strings`` is a comma-separated list.
* ``list_contains(value, separator, [ pattern, found_val, ]* not_found_val)`` -- (Alias of ``in_list``) Interpreting the value as a list of items separated by ``separator``, evaluate the ``pattern`` against each value in the list. If the ``pattern`` matches any value then return ``found_val``, otherwise return ``not_found_val``. The ``pattern`` and ``found_value`` can be repeated as many times as desired, permitting returning different values depending on the search. The patterns are checked in order. The first match is returned. Aliases: ``in_list()``, ``list_contains()``

View File

@ -5,16 +5,17 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import sys
import os, sys
from qt.core import (Qt, QApplication, QStyle, QIcon, QDoubleSpinBox, QStyleOptionViewItem,
QSpinBox, QStyledItemDelegate, QComboBox, QTextDocument, QMenu, QKeySequence,
QSpinBox, QStyledItemDelegate, QComboBox, QTextDocument, QMenu, QKeySequence, QUrl,
QAbstractTextDocumentLayout, QFont, QFontInfo, QDate, QDateTimeEdit, QDateTime, QEvent,
QStyleOptionComboBox, QStyleOptionSpinBox, QLocale, QSize, QLineEdit, QDialog, QPalette)
from calibre.ebooks.metadata import rating_to_stars, title_sort
from calibre.gui2 import UNDEFINED_QDATETIME, rating_font, gprefs
from calibre.constants import iswindows
from calibre.gui2.markdown_editor import MarkdownEditDialog
from calibre.gui2.widgets import EnLineEdit
from calibre.gui2.widgets2 import populate_standard_spinbox_context_menu, RatingEditor, DateTimeEdit as DateTimeEditBase
from calibre.gui2.complete2 import EditWithComplete
@ -534,7 +535,14 @@ class CcLongTextDelegate(QStyledItemDelegate): # {{{
text = ''
else:
text = m.db.data[index.row()][m.custom_columns[col]['rec_index']]
d = PlainTextDialog(parent, text, column_name=m.custom_columns[col]['name'])
column_format = m.custom_columns[m.column_map[index.column()]]['display'].get('interpret_as')
if column_format == 'markdown':
path = m.db.abspath(index.row(), index_is_id=False)
base_url = QUrl.fromLocalFile(os.path.join(path, 'metadata.html')) if path else None
d = MarkdownEditDialog(parent, text, column_name=m.custom_columns[col]['name'],
base_url=base_url)
else:
d = PlainTextDialog(parent, text, column_name=m.custom_columns[col]['name'])
if d.exec() == QDialog.DialogCode.Accepted:
m.setData(index, d.text, Qt.ItemDataRole.EditRole)
return None

View File

@ -1153,10 +1153,9 @@ class BooksView(QTableView): # {{{
elif cc['datatype'] == 'enumeration':
set_item_delegate(colhead, self.cc_enum_delegate)
else:
if colhead in self._model.editable_cols:
dattr = colhead+'_delegate'
delegate = colhead if hasattr(self, dattr) else 'text'
set_item_delegate(colhead, getattr(self, delegate+'_delegate'))
dattr = colhead+'_delegate'
delegate = colhead if hasattr(self, dattr) else 'text'
set_item_delegate(colhead, getattr(self, delegate+'_delegate'))
self.restore_state()
self.set_ondevice_column_visibility()

View File

@ -3,13 +3,14 @@
import os
from qt.core import (
QPlainTextEdit, Qt, QTabWidget, QUrl, QVBoxLayout, QWidget, pyqtSignal,
QDialog, QDialogButtonBox, QPlainTextEdit, QSize, Qt, QTabWidget, QUrl,
QVBoxLayout, QWidget, pyqtSignal,
)
from calibre.gui2 import safe_open_url
from calibre.gui2 import safe_open_url, gprefs
from calibre.gui2.book_details import css
from calibre.gui2.widgets2 import HTMLDisplay
from calibre.library.comments import markdown
from calibre.library.comments import markdown as get_markdown
class Preview(HTMLDisplay):
@ -42,6 +43,56 @@ class MarkdownEdit(QPlainTextEdit):
m.exec(ev.globalPos())
class MarkdownEditDialog(QDialog):
def __init__(self, parent, text, column_name=None, base_url=None):
QDialog.__init__(self, parent)
self.setObjectName("MarkdownEditDialog")
self.setWindowTitle(_("Edit markdown"))
self.verticalLayout = l = QVBoxLayout(self)
self.textbox = editor = Editor(self)
editor.set_base_url(base_url)
self.buttonBox = bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, self)
bb.accepted.connect(self.accept)
bb.rejected.connect(self.reject)
l.addWidget(editor)
l.addWidget(bb)
# Remove help icon on title bar
icon = self.windowIcon()
self.setWindowFlags(self.windowFlags()&(~Qt.WindowType.WindowContextHelpButtonHint))
self.setWindowIcon(icon)
self.textbox.markdown =text
# self.textbox.wyswyg_dirtied()
if column_name:
self.setWindowTitle(_('Edit "{0}"').format(column_name))
self.restore_geometry(gprefs, 'markdown_edit_dialog_geom')
def sizeHint(self):
return QSize(650, 600)
def accept(self):
self.save_geometry(gprefs, 'markdown_edit_dialog_geom')
QDialog.accept(self)
def reject(self):
self.save_geometry(gprefs, 'markdown_edit_dialog_geom')
QDialog.reject(self)
def closeEvent(self, ev):
self.save_geometry(gprefs, 'markdown_edit_dialog_geom')
return QDialog.closeEvent(self, ev)
@property
def text(self):
return self.textbox.markdown
@text.setter
def text(self, val):
self.textbox.markdown = val or ''
class Editor(QWidget): # {{{
def __init__(self, parent=None):
@ -90,7 +141,7 @@ class Editor(QWidget): # {{{
self.update_preview()
def update_preview(self):
html = markdown(self.editor.toPlainText().strip())
html = get_markdown(self.editor.toPlainText().strip())
val = f'''\
<html>
<head></head>

View File

@ -29,14 +29,35 @@ class MarkdownHighlighter(QSyntaxHighlighter):
'BlockQuote': re.compile(r'(?u)^\s*>+\s*'),
'BlockQuoteCount': re.compile('^[ \t]*>[ \t]?'),
'CodeSpan': re.compile('(?P<delim>`+).+?(?P=delim)'),
'HR': re.compile(r'(?u)^(\s*(\*|-)\s*){3,}$'),
'eHR': re.compile(r'(?u)^(\s*(\*|=)\s*){3,}$'),
'HeaderLine': re.compile(r'(?u)^(-|=)+\s*$'),
'HR': re.compile(r'(?u)^(\s*(\*|-|_)\s*){3,}$'),
'Html': re.compile('<.+?>')
}
key_theme_maps = {
'Bold': "bold",
'uBold': "bold",
'Italic': "emphasis",
'uItalic': "emphasis",
'Link': "link",
'Image': "image",
'HeaderAtx': "header",
'Header': "header",
'HeaderLine': "header",
'CodeBlock': "codeblock",
'UnorderedList': "unorderedlist",
'UnorderedListStar': "unorderedlist",
'OrderedList': "orderedlist",
'BlockQuote': "blockquote",
'BlockQuoteCount': "blockquote",
'CodeSpan': "codespan",
'HR': "line",
'Html': "html",
}
light_theme = {
"bold": {"color":"#859900", "font-weight":"bold", "font-style":"normal"},
"emphasis": {"color":"#b58900", "font-weight":"bold", "font-style":"italic"},
"bold": {"font-weight":"bold"},
"emphasis": {"font-style":"italic"},
"link": {"color":light_link_color.name(), "font-weight":"normal", "font-style":"normal"},
"image": {"color":"#cb4b16", "font-weight":"normal", "font-style":"normal"},
"header": {"color":"#2aa198", "font-weight":"bold", "font-style":"normal"},
@ -50,8 +71,8 @@ class MarkdownHighlighter(QSyntaxHighlighter):
}
dark_theme = {
"bold": {"color":"#859900", "font-weight":"bold", "font-style":"normal"},
"emphasis": {"color":"#b58900", "font-weight":"bold", "font-style":"italic"},
"bold": {"font-weight":"bold"},
"emphasis": {"font-style":"italic"},
"link": {"color":dark_link_color.name(), "font-weight":"normal", "font-style":"normal"},
"image": {"color":"#cb4b16", "font-weight":"normal", "font-style":"normal"},
"header": {"color":"#2aa198", "font-weight":"bold", "font-style":"normal"},
@ -73,101 +94,14 @@ class MarkdownHighlighter(QSyntaxHighlighter):
self.theme = theme
self.MARKDOWN_KWS_FORMAT = {}
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['bold']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['bold']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['bold']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['Bold'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['bold']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['bold']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['bold']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['uBold'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['emphasis']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['emphasis']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['emphasis']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['Italic'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['emphasis']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['emphasis']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['emphasis']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['uItalic'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['link']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['link']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['link']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['Link'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['image']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['image']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['image']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['Image'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['header']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['header']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['header']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['Header'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['header']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['header']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['header']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['HeaderAtx'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['unorderedlist']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['unorderedlist']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['unorderedlist']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['UnorderedList'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['orderedlist']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['orderedlist']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['orderedlist']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['OrderedList'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['blockquote']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['blockquote']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['blockquote']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['BlockQuote'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['codespan']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['codespan']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['codespan']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['CodeSpan'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['codeblock']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['codeblock']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['codeblock']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['CodeBlock'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['line']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['line']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['line']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['HR'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['line']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['line']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['line']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['eHR'] = format
format = QTextCharFormat()
format.setForeground(QBrush(QColor(theme['html']['color'])))
format.setFontWeight(QFont.Weight.Bold if theme['html']['font-weight']=='bold' else QFont.Weight.Normal)
format.setFontItalic(True if theme['html']['font-style']=='italic' else False)
self.MARKDOWN_KWS_FORMAT['HTML'] = format
for k,t in self.key_theme_maps.items():
subtheme = theme[t]
format = QTextCharFormat()
if 'color' in subtheme:
format.setForeground(QBrush(QColor(subtheme['color'])))
format.setFontWeight(QFont.Weight.Bold if subtheme.get('font-weight') == 'bold' else QFont.Weight.Normal)
format.setFontItalic(subtheme.get('font-style') == 'italic')
self.MARKDOWN_KWS_FORMAT[k] = format
self.rehighlight()
@ -230,37 +164,27 @@ class MarkdownHighlighter(QSyntaxHighlighter):
def highlightHorizontalLine(self, text, cursor, bf, strt):
found = False
for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['HR'],text):
prevBlock = self.currentBlock().previous()
prevCursor = QTextCursor(prevBlock)
prev = prevBlock.text()
prevAscii = str(prev.replace('\u2029','\n'))
if prevAscii.strip():
#print "Its a header"
prevCursor.select(QTextCursor.LineUnderCursor)
#prevCursor.setCharFormat(self.MARKDOWN_KWS_FORMAT['Header'])
formatRange = QTextLayout.FormatRange()
formatRange.format = self.MARKDOWN_KWS_FORMAT['Header']
formatRange.length = prevCursor.block().length()
formatRange.start = 0
prevCursor.block().layout().setAdditionalFormats([formatRange])
self.setFormat(mo.start()+strt, mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HR'])
for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['eHR'],text):
for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['HeaderLine'],text):
prevBlock = self.currentBlock().previous()
prevCursor = QTextCursor(prevBlock)
prev = prevBlock.text()
prevAscii = str(prev.replace('\u2029','\n'))
if prevAscii.strip():
#print "Its a header"
prevCursor.select(QTextCursor.LineUnderCursor)
prevCursor.select(QTextCursor.SelectionType.LineUnderCursor)
#prevCursor.setCharFormat(self.MARKDOWN_KWS_FORMAT['Header'])
formatRange = QTextLayout.FormatRange()
formatRange.format = self.MARKDOWN_KWS_FORMAT['Header']
formatRange.length = prevCursor.block().length()
formatRange.start = 0
prevCursor.block().layout().setAdditionalFormats([formatRange])
prevCursor.block().layout().setFormats([formatRange])
self.setFormat(mo.start()+strt, mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HeaderLine'])
return True
for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['HR'],text):
self.setFormat(mo.start()+strt, mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HR'])
found = True
return found
def highlightAtxHeader(self, text, cursor, bf, strt):
@ -342,4 +266,4 @@ class MarkdownHighlighter(QSyntaxHighlighter):
def highlightHtml(self, text):
for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['Html'], text):
self.setFormat(mo.start(), mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HTML'])
self.setFormat(mo.start(), mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['Html'])

View File

@ -2391,16 +2391,28 @@ class BuiltinBookValues(BuiltinFormatterFunction):
class BuiltinHasExtraFiles(BuiltinFormatterFunction):
name = 'has_extra_files'
arg_count = 0
arg_count = -1
category = 'Template database functions'
__doc__ = doc = _("has_extra_files() -- returns 'Yes' if there are any extra "
__doc__ = doc = _("has_extra_files([pattern]) -- returns the count of extra "
"files, otherwise '' (the empty string). "
"If the optional parameter 'pattern' (a regular expression) "
"is supplied then the list is filtered to files that match "
"pattern before the files are counted. The pattern match is "
"case insensitive. "
'This function can be used only in the GUI.')
def evaluate(self, formatter, kwargs, mi, locals):
def evaluate(self, formatter, kwargs, mi, locals, *args):
if len(args) > 1:
raise ValueError(_('Incorrect number of arguments for function {0}').format('has_extra_files'))
pattern = args[0] if len(args) == 1 else None
db = self.get_database(mi).new_api
try:
return 'Yes' if db.list_extra_files(mi.id, use_cache=True, pattern=DATA_FILE_PATTERN) else ''
files = tuple(f.relpath.partition('/')[-1] for f in
db.list_extra_files(mi.id, use_cache=True, pattern=DATA_FILE_PATTERN))
if pattern:
r = re.compile(pattern, re.IGNORECASE)
files = tuple(filter(r.search, files))
return len(files) if len(files) > 0 else ''
except Exception as e:
traceback.print_exc()
raise ValueError(e)
@ -2408,17 +2420,27 @@ class BuiltinHasExtraFiles(BuiltinFormatterFunction):
class BuiltinExtraFileNames(BuiltinFormatterFunction):
name = 'extra_file_names'
arg_count = 1
arg_count = -1
category = 'Template database functions'
__doc__ = doc = _("extra_file_names(sep) -- returns a sep-separated list of "
"extra files in the book's '{}/' folder. "
__doc__ = doc = _("extra_file_names(sep [, pattern]) -- returns a sep-separated "
"list of extra files in the book's '{}/' folder. If the "
"optional parameter 'pattern', a regular expression, is "
"supplied then the list is filtered to files that match pattern. "
"The pattern match is case insensitive. "
'This function can be used only in the GUI.').format(DATA_DIR_NAME)
def evaluate(self, formatter, kwargs, mi, locals, sep):
def evaluate(self, formatter, kwargs, mi, locals, sep, *args):
if len(args) > 1:
raise ValueError(_('Incorrect number of arguments for function {0}').format('has_extra_files'))
pattern = args[0] if len(args) == 1 else None
db = self.get_database(mi).new_api
try:
files = db.list_extra_files(mi.id, use_cache=True, pattern=DATA_FILE_PATTERN)
return sep.join(file.relpath.partition('/')[-1] for file in files)
files = tuple(f.relpath.partition('/')[-1] for f in
db.list_extra_files(mi.id, use_cache=True, pattern=DATA_FILE_PATTERN))
if pattern:
r = re.compile(pattern, re.IGNORECASE)
files = tuple(filter(r.search, files))
return sep.join(files)
except Exception as e:
traceback.print_exc()
raise ValueError(e)