mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Tool to test tag mapper rules easily
This commit is contained in:
parent
f8f9b2a0cd
commit
f01a5ce349
53
src/calibre/ebooks/metadata/tag_mapper.py
Normal file
53
src/calibre/ebooks/metadata/tag_mapper.py
Normal 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]
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user