From d1d02ba3f5187cb7610b03c97c2aed2192452657 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sun, 4 Jun 2017 23:59:44 +0200 Subject: [PATCH] Create the first tests for the pydocstyle finder. --- LICENSE.txt | 5 +- parso/python/normalizer.py | 29 +++++------ test/normalizer_issue_files/E72.py | 78 ++++++++++++++++++++++++++++ test/normalizer_issue_files/LICENSE | 29 +++++++++++ test/test_normalizer_issues_files.py | 44 ++++++++++++++++ 5 files changed, 167 insertions(+), 18 deletions(-) create mode 100644 test/normalizer_issue_files/E72.py create mode 100644 test/normalizer_issue_files/LICENSE create mode 100644 test/test_normalizer_issues_files.py diff --git a/LICENSE.txt b/LICENSE.txt index 441ce53..08c41db 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -4,11 +4,14 @@ Some Python files have been taken from the standard library and are therefore PSF licensed. Modifications on these files are dual licensed (both MIT and PSF). These files are: -- parso/pgen2 +- parso/pgen2/* - parso/tokenize.py - parso/token.py - test/test_pgen2.py +Also some test files under test/normalizer_issue_files have been copied from +https://github.com/PyCQA/pycodestyle (Expat License == MIT License). + ------------------------------------------------------------------------------- The MIT License (MIT) diff --git a/parso/python/normalizer.py b/parso/python/normalizer.py index b48e2b3..3d43b7f 100644 --- a/parso/python/normalizer.py +++ b/parso/python/normalizer.py @@ -53,25 +53,20 @@ class PEP8Normalizer(Normalizer): for child in node.children: # Here we can simply check if it's an except, because otherwise # it would be an except_clause. - if child == 'except': - self.add_issue(722, 'Do not use bare except, specify exception instead', node) + if child.type == 'keyword' and child.value == 'except': + self.add_issue(722, 'Do not use bare except, specify exception instead', child) elif typ == 'comparison': - odd = False for child in node.children: - if odd: - if child not in ('is', '=='): - break - else: - if child.type != 'atom_expr': - break - trailer = child.children[-1] - atom = child.children[-1] - if not (trailer.type == 'trailer' and atom.type == 'name' - and atom.value == 'type'): - break - odd = not odd - else: - self.add_issue(721, "Do not compare types, use 'isinstance()", node) + if child.type != 'atom_expr': + continue + if len(child.children) > 2: + continue + trailer = child.children[1] + atom = child.children[0] + if trailer.type == 'trailer' and atom.type == 'name' \ + and atom.value == 'type': + self.add_issue(721, "Do not compare types, use 'isinstance()", node) + break if typ in IMPORT_TYPES: module = node.parent diff --git a/test/normalizer_issue_files/E72.py b/test/normalizer_issue_files/E72.py new file mode 100644 index 0000000..0f99a09 --- /dev/null +++ b/test/normalizer_issue_files/E72.py @@ -0,0 +1,78 @@ + #: E721 +if type(res) == type(42): + pass + #: E721 +if type(res) != type(""): + pass + +import types + +if res == types.IntType: + pass + +import types + +#: E721:3 +if type(res) is not types.ListType: + pass +#: E721:7 E721:35 +assert type(res) == type(False) or type(res) == type(None) +#: E721:7 +assert type(res) == type([]) +#: E721:7 +assert type(res) == type(()) +#: E721:7 +assert type(res) == type((0,)) +#: E721:7 +assert type(res) == type((0)) +#: E721:7 +assert type(res) != type((1, )) +#: E721:7 +assert type(res) is type((1, )) +#: E721:7 +assert type(res) is not type((1, )) + +# Okay +import types + +if isinstance(res, int): + pass +if isinstance(res, str): + pass +if isinstance(res, types.MethodType): + pass + +#: E721:3 E721:25 +if type(a) != type(b) or type(a) == type(ccc): + pass +#: E721 +type(a) != type(b) +#: E721 +1 != type(b) +#: E721 +type(b) != 1 +1 != 1 + +try: + pass +#: E722 +except: + pass +try: + pass +except Exception: + pass +#: E722 +except: + pass +# Okay +fake_code = """" +try: + do_something() +except: + pass +""" +try: + pass +except Exception: + pass diff --git a/test/normalizer_issue_files/LICENSE b/test/normalizer_issue_files/LICENSE new file mode 100644 index 0000000..a63b8c5 --- /dev/null +++ b/test/normalizer_issue_files/LICENSE @@ -0,0 +1,29 @@ +Copyright © 2006-2009 Johann C. Rocholl +Copyright © 2009-2014 Florent Xicluna +Copyright © 2014-2016 Ian Lee +Copyright © 2014-2017 Dave Halter + +Dave: The files in this folder were ported from pydocstyle and some +modifications where made. + +Licensed under the terms of the Expat License + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/test/test_normalizer_issues_files.py b/test/test_normalizer_issues_files.py new file mode 100644 index 0000000..39d1aac --- /dev/null +++ b/test/test_normalizer_issues_files.py @@ -0,0 +1,44 @@ +""" +To easily verify if our normalizer raises the right error codes, just use the +tests of pydocstyle. +""" + +import re +from textwrap import dedent + +import parso + + +def collect_errors(code): + for line_nr, line in enumerate(code.splitlines(), 1): + match = re.match(r'(\s*)#: (.*)$', line) + if match is not None: + codes = match.group(2) + for code in codes.split(): + column = len(match.group(1)) + if ':' in code: + code, _, add_indent = code.partition(':') + column += int(add_indent) + + yield "%s@(%s,%s)" % (code, line_nr + 1, column) + + +def test_normalizer_issue(normalizer_issue_file): + with open(normalizer_issue_file.path) as f: + code = f.read() + + desired = list(collect_errors(code)) + + module = parso.parse(code) + issues = module._get_normalizer_issues() + + i = set("E%s@(%s,%s)" % (i.code, i.start_pos[0], i.start_pos[1]) for i in issues) + d = set(desired) + assert i == d, dedent(""" + Test %r failed (%s of %s passed). + not raised = %s + unspecified = %s + """) % ( + normalizer_issue_file.name, len(i & d), len(d), + sorted(d - i), sorted(i - d) + )