Tool to test tag mapper rules easily

This commit is contained in:
Kovid Goyal 2015-09-24 15:44:35 +05:30
parent f8f9b2a0cd
commit f01a5ce349
2 changed files with 92 additions and 1 deletions

View File

@ -0,0 +1,53 @@
#!/usr/bin/env python2
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
from __future__ import (unicode_literals, division, absolute_import,
print_function)
import regex
REGEX_FLAGS = regex.VERSION1 | regex.WORD | regex.FULLCASE | regex.IGNORECASE | regex.UNICODE
def matcher(rule):
mt = rule['match_type']
if mt == 'one_of':
tags = {icu_lower(x.strip()) for x in rule['query'].split(',')}
return lambda x: x in tags
if mt == 'not_one_of':
tags = {icu_lower(x.strip()) for x in rule['query'].split(',')}
return lambda x: x not in tags
if mt == 'matches':
pat = regex.compile(rule['query'], flags=REGEX_FLAGS)
return lambda x: pat.match(x) is not None
if mt == 'not_matches':
pat = regex.compile(rule['query'], flags=REGEX_FLAGS)
return lambda x: pat.match(x) is None
return lambda x: False
def apply_rules(tag, rules):
for rule, matches in rules:
ltag = icu_lower(tag)
if matches(ltag):
ac = rule['action']
if ac == 'remove':
return None
if ac == 'keep':
return tag
if ac == 'replace':
tag = regex.sub(rule['query'], rule['replace'], flags=REGEX_FLAGS)
return tag
def map_tags(tags, rules=()):
if not tags:
return []
if not rules:
return list(tags)
rules = [(r, matcher(r)) for r in rules]
return [x for x in (apply_rules(t, rules) for t in tags) if x]

View File

@ -14,6 +14,7 @@ from PyQt5.Qt import (
QStaticText, Qt, QStyle, QToolButton, QInputDialog, QMenu QStaticText, Qt, QStyle, QToolButton, QInputDialog, QMenu
) )
from calibre.ebooks.metadata.tag_mapper import map_tags
from calibre.gui2 import error_dialog, elided_text, Application, question_dialog from calibre.gui2 import error_dialog, elided_text, Application, question_dialog
from calibre.gui2.widgets2 import Dialog from calibre.gui2.widgets2 import Dialog
from calibre.utils.config import JSONConfig from calibre.utils.config import JSONConfig
@ -272,11 +273,43 @@ class Rules(QWidget):
if 'action' in rule and 'match_type' in rule and 'query' in rule: if 'action' in rule and 'match_type' in rule and 'query' in rule:
RuleItem(rule, self.rule_list) RuleItem(rule, self.rule_list)
class Tester(Dialog):
def __init__(self, rules, parent=None):
self.rules = rules
Dialog.__init__(self, _('Test tag mapper rules'), 'test-tag-mapper-rules', parent=parent)
def setup_ui(self):
self.l = l = QVBoxLayout(self)
self.bb.setStandardButtons(self.bb.Close)
self.la = la = QLabel(_(
'Enter a comma separated list of &tags to test:'))
l.addWidget(la)
self.tags = t = QLineEdit(self)
la.setBuddy(t)
t.setPlaceholderText(_('Enter tags and click the Test button'))
self.h = h = QHBoxLayout()
l.addLayout(h)
h.addWidget(t)
self.test_button = b = QPushButton(_('&Test'), self)
b.clicked.connect(self.do_test)
h.addWidget(b)
self.result = la = QLabel(self)
la.setWordWrap(True)
l.addWidget(la)
l.addWidget(self.bb)
def do_test(self):
tags = [x.strip() for x in self.tags.text().split(',')]
tags = map_tags(tags, self.rules)
self.result.setText(_('<b>Resulting tags:</b> %s') % ', '.join(tags))
class RulesDialog(Dialog): class RulesDialog(Dialog):
def __init__(self, parent=None): def __init__(self, parent=None):
self.loaded_ruleset = None self.loaded_ruleset = None
Dialog.__init__(self, _('Edit tag mapper rules'), 'edit-tag-mapper-rules', parent=None) Dialog.__init__(self, _('Edit tag mapper rules'), 'edit-tag-mapper-rules', parent=parent)
def setup_ui(self): def setup_ui(self):
self.l = l = QVBoxLayout(self) self.l = l = QVBoxLayout(self)
@ -291,6 +324,8 @@ class RulesDialog(Dialog):
self.load_menu = QMenu(self) self.load_menu = QMenu(self)
b.setMenu(self.load_menu) b.setMenu(self.load_menu)
self.build_load_menu() self.build_load_menu()
self.test_button = b = self.bb.addButton(_('&Test rules'), self.bb.ActionRole)
b.clicked.connect(self.test_rules)
@property @property
def rules(self): def rules(self):
@ -336,6 +371,9 @@ class RulesDialog(Dialog):
del tag_maps[name] del tag_maps[name]
self.build_load_menu() self.build_load_menu()
def test_rules(self):
Tester(self.rules, self).exec_()
if __name__ == '__main__': if __name__ == '__main__':
app = Application([]) app = Application([])
d = RulesDialog() d = RulesDialog()