From 043188778a0f78df677fec18c40a868729d086b3 Mon Sep 17 00:00:00 2001 From: Will Kahn-Greene Date: Sat, 5 Nov 2016 21:08:53 -0400 Subject: [PATCH] Fix --varformat to alloww nay formats This fixes th' --varformat flag fer both lint and translate to alloww fer nay variable formats by passin' in an empty strin'. Fixes #83 --- dennis/linter.py | 21 +++++++----- dennis/tools.py | 47 +++++++++++++++++--------- tests/test_linter.py | 80 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 115 insertions(+), 33 deletions(-) diff --git a/dennis/linter.py b/dennis/linter.py index 5a76ac5..df6ec9c 100644 --- a/dennis/linter.py +++ b/dennis/linter.py @@ -102,9 +102,7 @@ class MalformedNoTypeLintRule(LintRule): def lint(self, vartok, linted_entry): msgs = [] - # This only applies if one of the variable tokenizers - # is python-format. - # FIXME: Generalize this. + # This only applies if one of the variable tokenizers is python-format. if not vartok.contains('python-format'): return msgs @@ -143,9 +141,7 @@ class MalformedMissingRightBraceLintRule(LintRule): def lint(self, vartok, linted_entry): msgs = [] - # This only applies if one of the variable tokenizers - # is python-brace-format. - # FIXME: Generalize this. + # This only applies if one of the variable tokenizers is python-brace-format. if not vartok.contains('python-brace-format'): return [] @@ -179,9 +175,7 @@ class MalformedMissingLeftBraceLintRule(LintRule): def lint(self, vartok, linted_entry): msgs = [] - # This only applies if one of the variable tokenizers - # is python-brace-format. - # FIXME: Generalize this. + # This only applies if one of the variable tokenizers is python-brace-format. if not vartok.contains('python-brace-format'): return [] @@ -253,6 +247,11 @@ class MissingVarsLintRule(LintRule): def lint(self, vartok, linted_entry): msgs = [] + + # If there are no variable formats, skip this rule. + if not vartok.formats: + return [] + for trstr in linted_entry.strs: if not trstr.msgstr_string: continue @@ -443,6 +442,10 @@ class InvalidVarsLintRule(LintRule): desc = 'Checks for variables not in msgid, but in msgstr' def lint(self, vartok, linted_entry): + # If there are no variable formats, skip this rule. + if not vartok.formats: + return [] + msgs = [] for trstr in linted_entry.strs: if not trstr.msgstr_string: diff --git a/dennis/tools.py b/dennis/tools.py index 3d0a473..8a7101e 100644 --- a/dennis/tools.py +++ b/dennis/tools.py @@ -108,22 +108,30 @@ def __init__(self, formats=None): if formats is None: formats = all_formats.keys() - # Convert names to classes - self.formats = [] - - for fmt in formats: - try: - self.formats.append(all_formats[fmt]) - except KeyError: - raise UnknownFormat( - '{0} is not a known variable format'.format(fmt)) - - # Generate variable regexp - self.vars_re = re.compile( - r'(' + - '|'.join([vt.regexp for vt in self.formats]) + - r')' - ) + formats = [fmt for fmt in formats if fmt] + + # If they don't want variable tokenizing at all + if not formats: + self.formats = [] + self.vars_re = None + + else: + # Convert names to classes + self.formats = [] + + for fmt in formats: + try: + self.formats.append(all_formats[fmt]) + except KeyError: + raise UnknownFormat( + '{0} is not a known variable format'.format(fmt)) + + # Generate variable regexp + self.vars_re = re.compile( + r'(' + + '|'.join([vt.regexp for vt in self.formats]) + + r')' + ) def contains(self, fmt): """Does this tokenizer contain specified variable format?""" @@ -139,10 +147,15 @@ def tokenize(self, text): :returns: list of tokens---every even one is a Python variable """ + if not self.vars_re: + return [text] return [token for token in self.vars_re.split(text) if token] def extract_tokens(self, text, unique=True): """Returns the set of variable in the text""" + if not self.vars_re: + return set() + try: tokens = self.vars_re.findall(text) if unique: @@ -153,6 +166,8 @@ def extract_tokens(self, text, unique=True): def is_token(self, text): """Is this text a variable?""" + if not self.vars_re: + return False return self.vars_re.match(text) is not None def extract_variable_name(self, text): diff --git a/tests/test_linter.py b/tests/test_linter.py index 9ebdcab..5fc9f7a 100644 --- a/tests/test_linter.py +++ b/tests/test_linter.py @@ -161,6 +161,16 @@ def test_ignore_non_formatting_tokens(self): msgs = self.lintrule.lint(self.vartok, linted_entry) assert msgs == [] + def test_varformat_empty(self): + vartok = VariableTokenizer([]) + linted_entry = build_linted_entry( + '#: foo/foo.py:5\n' + 'msgid "%s foo"\n' + 'msgstr "%a FOO"\n' + ) + msgs = self.lintrule.lint(vartok, linted_entry) + assert msgs == [] + class TestMalformedNoTypeLintRule(LintRuleTestCase): lintrule = MalformedNoTypeLintRule() @@ -180,7 +190,7 @@ def test_fine(self): 'msgstr "Oof: {foo}"\n') msgs = self.lintrule.lint(self.vartok, linted_entry) - assert len(msgs) == 0 + assert msgs == [] def test_python_var_with_space(self): linted_entry = build_linted_entry( @@ -228,7 +238,19 @@ def test_python_var_not_malformed(self): 'msgstr "%(stars)s de %(user)s el %(date)s (%(locale)s)"\n') msgs = self.lintrule.lint(self.vartok, linted_entry) - assert len(msgs) == 0 + assert msgs == [] + + def test_varformat_empty(self): + vartok = VariableTokenizer([]) + + linted_entry = build_linted_entry( + '#: kitsune/questions/templates/questions/answers.html:56\n' + 'msgid "%(count)s view"\n' + 'msgid_plural "%(count)s views"\n' + 'msgstr[0] "%(count) zoo"\n') + + msgs = self.lintrule.lint(vartok, linted_entry) + assert msgs == [] class TestMalformedMissingRightBraceLintRule(LintRuleTestCase): @@ -292,6 +314,16 @@ def test_python_var_missing_right_curly_brace_two_vars(self): 'missing right curly-brace: {0]" excede el tamano de {' ) + def test_varformat_empty(self): + vartok = VariableTokenizer([]) + + linted_entry = build_linted_entry( + 'msgid "Value for key \\"{0}\\" exceeds the length of {1}"\n' + 'msgstr "Valor para la clave \\"{0}\\" excede el tamano de {1]"\n') + + msgs = self.lintrule.lint(vartok, linted_entry) + assert msgs == [] + class TestMalformedMissingLeftBraceLintRuleTest(LintRuleTestCase): lintrule = MalformedMissingLeftBraceLintRule() @@ -339,6 +371,17 @@ def test_python_var_missing_left_curly_brace(self): 'missing left curly-brace: }}' ) + def test_varformat_empty(self): + vartok = VariableTokenizer([]) + + linted_entry = build_linted_entry( + '#: kitsune/questions/templates/questions/question_details.html:14\n' + 'msgid "{q} | {product} Support Forum"\n' + 'msgstr "{q} | {product}} foo bar"\n') + + msgs = self.lintrule.lint(vartok, linted_entry) + assert msgs == [] + class TestMissingVarsLintRule(LintRuleTestCase): lintrule = MissingVarsLintRule() @@ -471,6 +514,17 @@ def test_python_format_are_errors_unnamed(self): 'missing variables: %s' ) + def test_varformat_empty(self): + vartok = VariableTokenizer([]) + + linted_entry = build_linted_entry( + '#: kitsune/kbforums/feeds.py:23\n' + 'msgid "Recently updated threads about %s"\n' + 'msgstr "RECENTLY UPDATED THREADS"\n' + ) + msgs = self.lintrule.lint(vartok, linted_entry) + assert msgs == [] + class TestInvalidVarsLintRule(LintRuleTestCase): lintrule = InvalidVarsLintRule() @@ -482,7 +536,7 @@ def test_fine(self): 'msgstr "Oof"\n') msgs = self.lintrule.lint(self.vartok, linted_entry) - assert len(msgs) == 0 + assert msgs == [] linted_entry = build_linted_entry( '#: foo/foo.py:5\n' @@ -490,7 +544,7 @@ def test_fine(self): 'msgstr "Oof: {foo}"\n') msgs = self.lintrule.lint(self.vartok, linted_entry) - assert len(msgs) == 0 + assert msgs == [] def test_invalid(self): linted_entry = build_linted_entry( @@ -539,7 +593,7 @@ def test_plurals(self): 'msgstr[0] "{n} mooo"\n') msgs = self.lintrule.lint(self.vartok, linted_entry) - assert len(msgs) == 0 + assert msgs == [] def test_double_percent(self): # Double-percent shouldn't be picked up as a variable. @@ -550,7 +604,7 @@ def test_double_percent(self): 'msgstr "more than 50%% of the traffic"\n') msgs = self.lintrule.lint(self.vartok, linted_entry) - assert len(msgs) == 0 + assert msgs == [] def test_urlencoded_urls(self): # urlencoding uses % and that shouldn't get picked up @@ -562,7 +616,7 @@ def test_urlencoded_urls(self): 'msgstr "http://example.com/foo%20%E5%B4%A9%E6%BA%83 is best"\n') msgs = self.lintrule.lint(self.vartok, linted_entry) - assert len(msgs) == 0 + assert msgs == [] def test_msgid_no_vars(self): linted_entry = build_linted_entry( @@ -571,7 +625,17 @@ def test_msgid_no_vars(self): 'msgstr "http://it.wikipedia.org/wiki/Canvas_%28elemento_HTML%29"\n') msgs = self.lintrule.lint(self.vartok, linted_entry) - assert len(msgs) == 0 + assert msgs == [] + + def test_varformat_empty(self): + vartok = VariableTokenizer([]) + linted_entry = build_linted_entry( + '#: foo/foo.py:5\n' + 'msgid "Foo {bar}"\n' + 'msgstr "Oof: {foo}"\n') + + msgs = self.lintrule.lint(vartok, linted_entry) + assert msgs == [] class TestBlankLintRule(LintRuleTestCase):