From ef800f8179613ab674609f3bb89edb98f489dc32 Mon Sep 17 00:00:00 2001 From: Torsten Marek Date: Wed, 6 Nov 2013 13:54:33 -0800 Subject: Combine 'no-space-after-operator', 'no-space-after-comma' and 'no-space-before-operator' into 'bad-whitespace' Changes: - consistent whitespace (single space on either side) is enforced for assignment operators - some constructs are now configurable - whitespace after trailing comma - spacing around key/value separators in dicts - checks now happen on the token stream itself rather than evaluationg regular expressions against the raw code --- ChangeLog | 3 + __pkginfo__.py | 24 +- checkers/format.py | 265 ++++++++++++++------- test/input/func_assert_2uple.py | 2 +- test/input/func_dangerous_default.py | 14 +- test/input/func_noerror_classes_meth_signature.py | 2 +- .../func_noerror_defined_and_used_on_same_line.py | 6 +- test/input/func_noerror_inner_classes.py | 2 +- test/input/func_noerror_new_style_class_py_30.py | 2 +- test/input/func_noerror_nonregr.py | 2 +- test/input/func_noerror_static_method.py | 4 +- test/input/func_set_literal_as_default_py27.py | 3 +- test/input/func_unpacking_non_sequence.py | 2 +- test/input/func_use_for_or_listcomp_var.py | 2 +- test/input/func_w0108.py | 2 +- test/messages/func_format.txt | 40 ++-- test/test_format.py | 265 ++++++++++----------- 17 files changed, 364 insertions(+), 276 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9bbba9..fa74c07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ ChangeLog for Pylint * Avoid false used-before-assignment for except handler defined identifier used on the same line (#111) + * Combine 'no-space-after-operator', 'no-space-after-comma' and + 'no-space-before-operator' into a new warning 'bad-whitespace' + * Add a new warning 'superfluous-parens' for unnecessary parentheses after certain keywords. diff --git a/__pkginfo__.py b/__pkginfo__.py index 997b9a5..614828e 100644 --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -30,18 +30,18 @@ mailinglist = "mailto://python-projects@lists.logilab.org" author = 'Logilab' author_email = 'python-projects@lists.logilab.org' -classifiers = ['Development Status :: 4 - Beta', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: GNU General Public License (GPL)', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 3', - 'Topic :: Software Development :: Debuggers', - 'Topic :: Software Development :: Quality Assurance', - 'Topic :: Software Development :: Testing', - ] +classifiers = ['Development Status :: 4 - Beta', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: GNU General Public License (GPL)', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', + 'Topic :: Software Development :: Debuggers', + 'Topic :: Software Development :: Quality Assurance', + 'Topic :: Software Development :: Testing', + ] long_desc = """\ diff --git a/checkers/format.py b/checkers/format.py index 0209add..470f4bf 100644 --- a/checkers/format.py +++ b/checkers/format.py @@ -21,12 +21,13 @@ http://www.python.org/doc/essays/styleguide.html Some parts of the process_token method is based from The Tab Nanny std module. """ -import re, sys +import keyword +import sys import tokenize + if not hasattr(tokenize, 'NL'): raise ValueError("tokenize.NL doesn't exist -- tokenize module too old") -from logilab.common.textutils import pretty_match from astroid import nodes from pylint.interfaces import ITokenChecker, IAstroidChecker, IRawChecker @@ -37,6 +38,24 @@ from pylint.utils import WarningScope, OPTION_RGX _KEYWORD_TOKENS = ['assert', 'del', 'elif', 'except', 'for', 'if', 'in', 'not', 'print', 'raise', 'return', 'while', 'yield'] +_SPACED_OPERATORS = ['==', '<', '>', '!=', '<>', '<=', '>=', + '+=', '-=', '*=', '**=', '/=', '//=', '&=', '|=', '^=', + '%=', '>>=', '<<='] +_OPENING_BRACKETS = ['(', '[', '{'] +_CLOSING_BRACKETS = [')', ']', '}'] + +_EOL = frozenset([tokenize.NEWLINE, tokenize.NL, tokenize.COMMENT]) + +# Whitespace checking policy constants +_MUST = 0 +_MUST_NOT = 1 +_IGNORE = 2 + +# Whitespace checking config constants +_DICT_SEPARATOR = 'dict-separator' +_TRAILING_COMMA = 'trailing-comma' +_NO_SPACE_CHECK_CHOICES = [_TRAILING_COMMA, _DICT_SEPARATOR] + MSGS = { 'C0301': ('Line too long (%s/%s)', 'line-too-long', @@ -67,26 +86,20 @@ MSGS = { 'multiple-statements', 'Used when more than on statement are found on the same line.', {'scope': WarningScope.NODE}), - 'C0322': ('Operator not preceded by a space\n%s', - 'no-space-before-operator', - 'Used when one of the following operator (!= | <= | == | >= | < ' - '| > | = | \\+= | -= | \\*= | /= | %) is not preceded by a space.', - {'scope': WarningScope.NODE}), - 'C0323': ('Operator not followed by a space\n%s', - 'no-space-after-operator', - 'Used when one of the following operator (!= | <= | == | >= | < ' - '| > | = | \\+= | -= | \\*= | /= | %) is not followed by a space.', - {'scope': WarningScope.NODE}), - 'C0324': ('Comma not followed by a space\n%s', - 'no-space-after-comma', - 'Used when a comma (",") is not followed by a space.', - {'scope': WarningScope.NODE}), 'C0325' : ('Unnecessary parens after %r keyword', 'superfluous-parens', 'Used when a single item in parentheses follows an if, for, or ' 'other keyword.'), + 'C0326': ('%s space %s %s %s\n%s', + 'bad-whitespace', + ('Used when a wrong number of spaces is used around an operator, ' + 'bracket or block opener.'), + {'old_names': [('C0323', 'no-space-after-operator'), + ('C0324', 'no-space-after-comma'), + ('C0322', 'no-space-before-operator')]}) } + if sys.version_info < (3, 0): MSGS.update({ @@ -106,74 +119,21 @@ if sys.version_info < (3, 0): {'scope': WarningScope.NODE}), }) -# simple quoted string rgx -SQSTRING_RGX = r'"([^"\\]|\\.)*?"' -# simple apostrophed rgx -SASTRING_RGX = r"'([^'\\]|\\.)*?'" -# triple quoted string rgx -TQSTRING_RGX = r'"""([^"]|("(?!"")))*?(""")' -# triple apostrophe'd string rgx -TASTRING_RGX = r"'''([^']|('(?!'')))*?(''')" - -# finally, the string regular expression -STRING_RGX = re.compile('(%s)|(%s)|(%s)|(%s)' % (TQSTRING_RGX, TASTRING_RGX, - SQSTRING_RGX, SASTRING_RGX), - re.MULTILINE|re.DOTALL) - -COMMENT_RGX = re.compile("#.*$", re.M) - -OPERATORS = r'!=|<=|==|>=|<|>|=|\+=|-=|\*=|/=|%' - -OP_RGX_MATCH_1 = r'[^(]*(?|=|\+|-|\*|/|!|%%|&|\|)(%s).*' % OPERATORS -OP_RGX_SEARCH_1 = r'(?|=|\+|-|\*|/|!|%%|&|\|)(%s)' % OPERATORS -OP_RGX_MATCH_2 = r'[^(]*(%s)(?!\s|=|>|<).*' % OPERATORS -OP_RGX_SEARCH_2 = r'(%s)(?!\s|=|>)' % OPERATORS +def _underline_token(token): + length = token[3][1] - token[2][1] + offset = token[2][1] + return token[4] + (' ' * offset) + ('^' * length) -BAD_CONSTRUCT_RGXS = ( - (re.compile(OP_RGX_MATCH_1, re.M), - re.compile(OP_RGX_SEARCH_1, re.M), - 'C0322'), - - (re.compile(OP_RGX_MATCH_2, re.M), - re.compile(OP_RGX_SEARCH_2, re.M), - 'C0323'), - - (re.compile(r'.*,[^(\s|\]|}|\))].*', re.M), - re.compile(r',[^\s)]', re.M), - 'C0324'), - ) - - -def get_string_coords(line): - """return a list of string positions (tuple (start, end)) in the line - """ - result = [] - for match in re.finditer(STRING_RGX, line): - result.append( (match.start(), match.end()) ) - return result - -def in_coords(match, string_coords): - """return true if the match is in the string coord""" - mstart = match.start() - for start, end in string_coords: - if mstart >= start and mstart < end: - return True - return False - -def check_line(line): - """check a line for a bad construction - if it founds one, return a message describing the problem - else return None - """ - cleanstr = COMMENT_RGX.sub('', STRING_RGX.sub('', line)) - for rgx_match, rgx_search, msg_id in BAD_CONSTRUCT_RGXS: - if rgx_match.match(cleanstr): - string_positions = get_string_coords(line) - for match in re.finditer(rgx_search, line): - if not in_coords(match, string_positions): - return msg_id, pretty_match(match, line.rstrip()) +def _column_distance(token1, token2): + if token1 == token2: + return 0 + if token2[3] < token1[3]: + token1, token2 = token2, token1 + if token1[3][0] != token2[2][0]: + return None + return token2[2][1] - token1[3][1] class FormatChecker(BaseTokenChecker): @@ -204,6 +164,12 @@ class FormatChecker(BaseTokenChecker): {'default': False, 'type' : 'yn', 'metavar' : '', 'help' : ('Allow the body of an if to be on the same ' 'line as the test if there is no else.')}), + ('no-space-check', + {'default': ','.join(_NO_SPACE_CHECK_CHOICES), + 'type': 'multiple_choice', + 'choices': _NO_SPACE_CHECK_CHOICES, + 'help': ('List of optional constructs for which whitespace ' + 'checking is disabled')}), ('max-module-lines', {'default' : 1000, 'type' : 'int', 'metavar' : '', 'help': 'Maximum number of lines in a module'} @@ -302,10 +268,139 @@ class FormatChecker(BaseTokenChecker): elif token[1] == 'for': return + def _opening_bracket(self, tokens, i): + self._bracket_stack.append(tokens[i][1]) + # Special case: ignore slices + if tokens[i][1] == '[' and tokens[i+1][1] == ':': + return + + if (i > 0 and (tokens[i-1][0] == tokenize.NAME and + not (keyword.iskeyword(tokens[i-1][1])) + or tokens[i-1][1] in _CLOSING_BRACKETS)): + self._check_space(tokens, i, (_MUST_NOT, _MUST_NOT)) + else: + self._check_space(tokens, i, (_IGNORE, _MUST_NOT)) + + def _closing_bracket(self, tokens, i): + self._bracket_stack.pop() + # Special case: ignore slices + if tokens[i-1][1] == ':' and tokens[i][1] == ']': + return + policy_before = _MUST_NOT + if tokens[i][1] in _CLOSING_BRACKETS and tokens[i-1][1] == ',': + if _TRAILING_COMMA in self.config.no_space_check: + policy_before = _IGNORE + + self._check_space(tokens, i, (policy_before, _IGNORE)) + + def _check_equals_spacing(self, tokens, i): + """Check the spacing of a single equals sign.""" + if self._inside_brackets('(') or self._inside_brackets('lambda'): + self._check_space(tokens, i, (_MUST_NOT, _MUST_NOT)) + else: + self._check_space(tokens, i, (_MUST, _MUST)) + + def _open_lambda(self, unused_tokens, unused_i): + self._bracket_stack.append('lambda') + + def _handle_colon(self, tokens, i): + # Special case: ignore slices + if self._inside_brackets('['): + return + if (self._inside_brackets('{') and + _DICT_SEPARATOR in self.config.no_space_check): + policy = (_IGNORE, _IGNORE) + else: + policy = (_MUST_NOT, _MUST) + self._check_space(tokens, i, policy) + + if self._inside_brackets('lambda'): + self._bracket_stack.pop() + + def _handle_comma(self, tokens, i): + # Only require a following whitespace if this is + # not a hanging comma before a closing bracket. + if tokens[i+1][1] in _CLOSING_BRACKETS: + self._check_space(tokens, i, (_MUST_NOT, _IGNORE)) + else: + self._check_space(tokens, i, (_MUST_NOT, _MUST)) + + def _check_surrounded_by_space(self, tokens, i): + """Check that a binary operator is surrounded by exactly one space.""" + self._check_space(tokens, i, (_MUST, _MUST)) + + def _check_space(self, tokens, i, policies): + def _policy_string(policy): + if policy == _MUST: + return 'Exactly one', 'required' + else: + return 'No', 'allowed' + + def _name_construct(token): + if tokens[i][1] == ',': + return 'comma' + elif tokens[i][1] == ':': + return ':' + elif tokens[i][1] in '()[]{}': + return 'bracket' + elif tokens[i][1] in ('<', '>', '<=', '>=', '!='): + return 'comparison' + else: + if self._inside_brackets('('): + return 'keyword argument assignment' + else: + return 'assignment' + + good_space = [True, True] + pairs = [(tokens[i-1], tokens[i]), (tokens[i], tokens[i+1])] + + for other_idx, (policy, token_pair) in enumerate(zip(policies, pairs)): + current_idx = 1 - other_idx + if token_pair[other_idx][0] in _EOL or policy == _IGNORE: + continue + + distance = _column_distance(*token_pair) + if distance is None: + continue + good_space[other_idx] = ( + (policy == _MUST and distance == 1) or + (policy == _MUST_NOT and distance == 0)) + + warnings = [] + if not any(good_space) and policies[0] == policies[1]: + warnings.append((policies[0], 'around')) + else: + for ok, policy, position in zip(good_space, policies, ('before', 'after')): + if not ok: + warnings.append((policy, position)) + for policy, position in warnings: + construct = _name_construct(tokens[i]) + count, state = _policy_string(policy) + self.add_message('C0326', line=tokens[i][2][0], + args=(count, state, position, construct, + _underline_token(tokens[i]))) + + def _inside_brackets(self, left): + return self._bracket_stack[-1] == left + def _prepare_token_dispatcher(self): raw = [ (_KEYWORD_TOKENS, self._check_keyword_parentheses), + + (_OPENING_BRACKETS, self._opening_bracket), + + (_CLOSING_BRACKETS, self._closing_bracket), + + (['='], self._check_equals_spacing), + + (_SPACED_OPERATORS, self._check_surrounded_by_space), + + ([','], self._handle_comma), + + ([':'], self._handle_colon), + + (['lambda'], self._open_lambda), ] dispatch = {} @@ -323,6 +418,7 @@ class FormatChecker(BaseTokenChecker): _ optionally bad construct (if given, bad_construct must be a compiled regular expression). """ + self._bracket_stack = [None] indent = tokenize.INDENT dedent = tokenize.DEDENT newline = tokenize.NEWLINE @@ -444,13 +540,6 @@ class FormatChecker(BaseTokenChecker): lines.append(self._lines[line].rstrip()) except KeyError: lines.append('') - try: - msg_def = check_line('\n'.join(lines)) - if msg_def: - self.add_message(msg_def[0], node=node, args=msg_def[1]) - except KeyError: - # FIXME: internal error ! - pass def _check_multi_statement_line(self, node, line): """Check for lines containing multiple statements.""" diff --git a/test/input/func_assert_2uple.py b/test/input/func_assert_2uple.py index a6746ce..de93d3b 100644 --- a/test/input/func_assert_2uple.py +++ b/test/input/func_assert_2uple.py @@ -8,4 +8,4 @@ assert (1 == 1, ), "no error" assert (1 == 1, ) assert (1 == 1, 2 == 2, 3 == 5), "no error" assert () -assert (True,'error msg') #this should generate a warning +assert (True, 'error msg') #this should generate a warning diff --git a/test/input/func_dangerous_default.py b/test/input/func_dangerous_default.py index a68aaec..3e07415 100644 --- a/test/input/func_dangerous_default.py +++ b/test/input/func_dangerous_default.py @@ -4,11 +4,11 @@ __revision__ = '' HEHE = {} -def function1(value = []): +def function1(value=[]): """docstring""" print value -def function2(value = HEHE): +def function2(value=HEHE): """docstring""" print value @@ -16,24 +16,24 @@ def function3(value): """docstring""" print value -def function4(value = set()): +def function4(value=set()): """set is mutable and dangerous.""" print value -def function5(value = frozenset()): +def function5(value=frozenset()): """frozenset is immutable and safe.""" print value GLOBAL_SET = set() -def function6(value = GLOBAL_SET): +def function6(value=GLOBAL_SET): """set is mutable and dangerous.""" print value -def function7(value = dict()): +def function7(value=dict()): """dict is mutable and dangerous.""" print value -def function8(value = list()): +def function8(value=list()): """list is mutable and dangerous.""" print value diff --git a/test/input/func_noerror_classes_meth_signature.py b/test/input/func_noerror_classes_meth_signature.py index 8f120cd..2aa5b18 100644 --- a/test/input/func_noerror_classes_meth_signature.py +++ b/test/input/func_noerror_classes_meth_signature.py @@ -34,5 +34,5 @@ class Sub(Super): def ___private3(self, arg): pass - def method(self, param = 'abc'): + def method(self, param='abc'): pass diff --git a/test/input/func_noerror_defined_and_used_on_same_line.py b/test/input/func_noerror_defined_and_used_on_same_line.py index db700cf..2ed0b1f 100644 --- a/test/input/func_noerror_defined_and_used_on_same_line.py +++ b/test/input/func_noerror_defined_and_used_on_same_line.py @@ -16,14 +16,14 @@ def func(xxx): return xxx def func2(xxx): return xxx + func2(1) -import sys; print sys.exc_info( ) +import sys; print sys.exc_info() for i in range(10): print i j = 4; LAMB = lambda x: x+j -FUNC4 = lambda a, b : a != b -FUNC3 = lambda (a, b) : a != b +FUNC4 = lambda a, b: a != b +FUNC3 = lambda (a, b): a != b # test http://www.logilab.org/ticket/6954: diff --git a/test/input/func_noerror_inner_classes.py b/test/input/func_noerror_inner_classes.py index 02391a2..84fb43d 100644 --- a/test/input/func_noerror_inner_classes.py +++ b/test/input/func_noerror_inner_classes.py @@ -6,7 +6,7 @@ __revision__ = "alpha" class Aaa(object): """docstring""" def __init__(self): - self.__setattr__('a','b') + self.__setattr__('a', 'b') def one_public(self): diff --git a/test/input/func_noerror_new_style_class_py_30.py b/test/input/func_noerror_new_style_class_py_30.py index d08ab46..87bfb9e 100644 --- a/test/input/func_noerror_new_style_class_py_30.py +++ b/test/input/func_noerror_new_style_class_py_30.py @@ -35,7 +35,7 @@ self.mode) self.was_modified = True # - def close(self) : + def close(self): """Close the file.""" if self.verbose: diff --git a/test/input/func_noerror_nonregr.py b/test/input/func_noerror_nonregr.py index 992f9f3..c4c8c38 100644 --- a/test/input/func_noerror_nonregr.py +++ b/test/input/func_noerror_nonregr.py @@ -3,7 +3,7 @@ __revision__ = 1 -def function1(cbarg = lambda: None): +def function1(cbarg=lambda: None): """ File "/usr/lib/python2.4/site-packages/logilab/astroid/scoped_nodes.py", line 391, in mularg_class # this method doesn't exist anymore diff --git a/test/input/func_noerror_static_method.py b/test/input/func_noerror_static_method.py index d109d2e..ea5f7d8 100644 --- a/test/input/func_noerror_static_method.py +++ b/test/input/func_noerror_static_method.py @@ -23,7 +23,5 @@ class MyClass(object): class_met = classmethod(class_met) if __name__ == '__main__': - MyClass.static_met("var1","var2") + MyClass.static_met("var1", "var2") MyClass.class_met("var1") - - diff --git a/test/input/func_set_literal_as_default_py27.py b/test/input/func_set_literal_as_default_py27.py index 04fb9b5..5c7200e 100644 --- a/test/input/func_set_literal_as_default_py27.py +++ b/test/input/func_set_literal_as_default_py27.py @@ -2,7 +2,6 @@ __revision__ = '' -def function1(value = {1}): +def function1(value={1}): """set is mutable and dangerous.""" print value - diff --git a/test/input/func_unpacking_non_sequence.py b/test/input/func_unpacking_non_sequence.py index 973c40d..cd35328 100644 --- a/test/input/func_unpacking_non_sequence.py +++ b/test/input/func_unpacking_non_sequence.py @@ -41,7 +41,7 @@ a, b = [1, 2] a, b = (1, 2) a, b = set([1, 2]) a, b = {1: 2, 2: 3} -a, b = "xy" +a, b = "xy" a, b = Seq() a, b = Iter() a, b = (number for number in range(2)) diff --git a/test/input/func_use_for_or_listcomp_var.py b/test/input/func_use_for_or_listcomp_var.py index a8918df..3de5a72 100644 --- a/test/input/func_use_for_or_listcomp_var.py +++ b/test/input/func_use_for_or_listcomp_var.py @@ -24,4 +24,4 @@ for line in __revision__: for x in []: pass for x in range(3): - print (lambda : x)() # OK + print (lambda: x)() # OK diff --git a/test/input/func_w0108.py b/test/input/func_w0108.py index 0da9a96..0d4cc62 100644 --- a/test/input/func_w0108.py +++ b/test/input/func_w0108.py @@ -21,7 +21,7 @@ _ = lambda x, y, z, *args, **kwargs: _ANYARGS(x, y, z, *args, **kwargs) # Lambdas that are *not* unnecessary and should *not* trigger warnings. _ = lambda x: x _ = lambda x: x() -_ = lambda x = 4: hash(x) +_ = lambda x=4: hash(x) _ = lambda x, y: range(y, x) _ = lambda x: range(5, x) _ = lambda x, y: range(x, 5) diff --git a/test/messages/func_format.txt b/test/messages/func_format.txt index 5ee36cd..ce5df81 100644 --- a/test/messages/func_format.txt +++ b/test/messages/func_format.txt @@ -1,32 +1,44 @@ -C: 6: Operator not preceded by a space +C: 6: Exactly one space required before assignment notpreceded= 1 ^ -C: 7: Operator not followed by a space +C: 7: Exactly one space required after assignment notfollowed =1 ^ -C: 8: Operator not followed by a space +C: 8: Exactly one space required after comparison notfollowed <=1 ^^ -C: 19: Comma not followed by a space +C: 19: Exactly one space required after comma aaaa,bbbb = 1,2 - ^^ + ^ +C: 19: Exactly one space required after comma +aaaa,bbbb = 1,2 + ^ C: 24: More than one statement on a single line -C: 26: Comma not followed by a space +C: 26: Exactly one space required after comma + aaaa,bbbb = 1,2 + ^ +C: 26: Exactly one space required after comma aaaa,bbbb = 1,2 - ^^ -C: 27: Comma not followed by a space + ^ +C: 27: Exactly one space required after comma + aaaa,bbbb = bbbb,aaaa + ^ +C: 27: Exactly one space required after comma aaaa,bbbb = bbbb,aaaa - ^^ -C: 29: Comma not followed by a space + ^ +C: 29: Exactly one space required after comma bbbb = (1,2,3) - ^^ -C: 51:other: Operator not preceded by a space + ^ +C: 29: Exactly one space required after comma +bbbb = (1,2,3) + ^ +C: 51: Exactly one space required before assignment funky= funky+2 ^ -C: 71:_gc_debug: Operator not preceded by a space +C: 71: Exactly one space required before assignment ocount[obj.__class__]+= 1 ^^ -C: 73:_gc_debug: Operator not preceded by a space +C: 73: Exactly one space required around assignment ocount[obj.__class__]=1 ^ C: 91: More than one statement on a single line diff --git a/test/test_format.py b/test/test_format.py index 3be2cff..b682671 100644 --- a/test/test_format.py +++ b/test/test_format.py @@ -27,151 +27,13 @@ from astroid import test_utils from pylint.checkers.format import * -from pylint.testutils import TestReporter, CheckerTestCase, Message +from pylint.testutils import CheckerTestCase, Message -REPORTER = TestReporter() def tokenize_str(code): return list(tokenize.generate_tokens(StringIO.StringIO(code).readline)) -class StringRgxTest(TestCase): - """test the STRING_RGX regular expression""" - - def test_known_values_1(self): - self.assertEqual(STRING_RGX.sub('', '"yo"'), '') - - def test_known_values_2(self): - self.assertEqual(STRING_RGX.sub('', "'yo'"), '') - - def test_known_values_tq_1(self): - self.assertEqual(STRING_RGX.sub('', '"""yo"""'), '') - - def test_known_values_tq_2(self): - self.assertEqual(STRING_RGX.sub('', '"""yo\n"""'), '') - - def test_known_values_ta_1(self): - self.assertEqual(STRING_RGX.sub('', "'''yo'''"), '') - - def test_known_values_ta_2(self): - self.assertEqual(STRING_RGX.sub('', "'''yo\n'''"), '') - - def test_known_values_5(self): - self.assertEqual(STRING_RGX.sub('', r'"yo\"yo"'), '') - - def test_known_values_6(self): - self.assertEqual(STRING_RGX.sub('', r"'yo\'yo'"), '') - - def test_known_values_7(self): - self.assertEqual(STRING_RGX.sub('', '"yo"upi"yo"upi'), 'upiupi') - - def test_known_values_8(self): - self.assertEqual(STRING_RGX.sub('', r"'yo\'yo\''"), '') - - def test_known_values_9(self): - self.assertEqual(STRING_RGX.sub('', r'"yoyo\""'), '') - - def test_known_values_10(self): - self.assertEqual(STRING_RGX.sub('', 'self.filterFunc = eval(\'lambda %s: %s\'%(\',\'.join(variables),formula),{},{})'), - 'self.filterFunc = eval(%(.join(variables),formula),{},{})') - - def test_known_values_11(self): - self.assertEqual(STRING_RGX.sub('', 'cond_list[index] = OLD_PROG.sub(r\'getattr(__old__,"\1")\',cond)'), - 'cond_list[index] = OLD_PROG.sub(r,cond)') - - - def test_no_crash(self): - crash_str = """wizardBmp = ('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\n', (115, 260), None)""" - re.sub(SQSTRING_RGX, '', crash_str) - re.sub(TQSTRING_RGX, '', crash_str) - re.sub(SASTRING_RGX, '', crash_str) - re.sub(TASTRING_RGX, '', crash_str) - self.skipTest('XXX: explain the test, remove it or assert something') - -if linesep != '\n': - LINE_RGX = re.compile(linesep) - def ulines(strings): - return strings[0], LINE_RGX.sub('\n', strings[1]) -else: - def ulines(strings): - return strings - -class ChecklineFunctionTest(TestCase): - """test the check_line method""" - - def test_known_values_opspace_1(self): - self.assertEqual(ulines(check_line('a=1')), ('C0322', 'a=1\n ^')) - - def test_known_values_opspace_2(self): - self.assertEqual(ulines(check_line('a= 1')), ('C0322', 'a= 1\n ^') ) - - def test_known_values_opspace_3(self): - self.assertEqual(ulines(check_line('a =1')), ('C0323', 'a =1\n ^')) - - def test_known_values_opspace_4(self): - self.assertEqual(check_line('f(a=1)'), None) - - def test_known_values_opspace_4(self): - self.assertEqual(check_line('f(a=1)'), None) - - def test_known_values_colonnl_2(self): - self.assertEqual(check_line('a[:1]'), None) - - def test_known_values_colonnl_3(self): - self.assertEqual(check_line('a[1:]'), None) - - def test_known_values_colonnl_4(self): - self.assertEqual(check_line('a[1:2]'), None) - - def test_known_values_colonnl_5(self): - self.assertEqual(check_line('def intersection(list1, list2):'), None) - - def test_known_values_colonnl_6(self): - self.assertEqual(check_line('def intersection(list1, list2):\n'), None) - - def test_known_values_colonnl_7(self): - self.assertEqual(check_line('if file[:pfx_len] == path:\n'), None) - - def test_known_values_colonnl_9(self): - self.assertEqual(check_line('if file[:pfx_len[1]] == path:\n'), None) - - def test_known_values_colonnl_10(self): - self.assertEqual(check_line('if file[pfx_len[1]] == path:\n'), None) - - def test_known_values_commaspace_1(self): - self.assertEqual(ulines(check_line('a, b = 1,2')), - ('C0324', 'a, b = 1,2\n ^^')) - - def test_known_values_commaspace_2(self): - self.assertEqual(check_line('should_not_warn = [1, 2, 3,]\n'), - None) - - def test_known_values_commaspace_3(self): - self.assertEqual(check_line('should_not_warn = {1:2, 3:4,}\n'), - None) - - def test_known_values_commaspace_4(self): - self.assertEqual(check_line('should_not_warn = (1, 2, 3,)\n'), - None) - - def test_known_values_instring_1(self): - self.assertEqual(check_line('f("a=1")'), None) - - def test_known_values_instring_2(self): - self.assertEqual(ulines(check_line('print >>1, ("a:1")')), - ('C0323', 'print >>1, ("a:1")\n ^')) - - def test_known_values_all_1(self): - self.assertEqual(ulines(check_line("self.filterFunc = eval('lambda %s: %s'%(','.join(variables),formula),{},{})")), - ('C0324', "self.filterFunc = eval('lambda %s: %s'%(','.join(variables),formula),{},{})\n ^^")) - - def test_known_values_tqstring(self): - self.assertEqual(check_line('print """