From 660bbe19716606f89ac11cf95fb5f3be2a343246 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sun, 4 Jun 2017 21:10:57 +0200 Subject: [PATCH] Trying to add a testsuite in pytest for the tests of pydocstyle. --- conftest.py | 30 ++++++++++++++++++++++++++++++ parso/normalizer.py | 11 ++++++++--- parso/python/normalizer.py | 20 ++++++++++---------- parso/tree.py | 2 +- pytest.ini | 2 +- 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/conftest.py b/conftest.py index 766ec64..2d2ad7a 100644 --- a/conftest.py +++ b/conftest.py @@ -2,6 +2,7 @@ import tempfile import shutil import logging import sys +import os import pytest @@ -34,6 +35,35 @@ def pytest_addoption(parser): help="Enables the logging output.") +def pytest_generate_tests(metafunc): + if 'normalizer_issue_file' in metafunc.fixturenames: + base_dir = os.path.join(os.path.dirname(__file__), 'test', 'normalizer_issue_files') + + cases = list(colllect_normalizer_tests(base_dir)) + metafunc.parametrize( + 'normalizer_issue_file', + cases, + ids=[c.name for c in cases] + ) + + +class NormalizerIssueCase(object): + """ + Static Analysis cases lie in the static_analysis folder. + The tests also start with `#!`, like the goto_definition tests. + """ + def __init__(self, path): + self.path = path + self.name = os.path.basename(path) + + +def colllect_normalizer_tests(base_dir): + for f_name in os.listdir(base_dir): + if f_name.endswith(".py"): + path = os.path.join(base_dir, f_name) + yield NormalizerIssueCase(path) + + def pytest_configure(config): if config.option.logging: root = logging.getLogger() diff --git a/parso/normalizer.py b/parso/normalizer.py index 0d8d204..96c5d01 100644 --- a/parso/normalizer.py +++ b/parso/normalizer.py @@ -13,6 +13,10 @@ class Normalizer(object): def normalize(self, leaf): return leaf.prefix + leaf.value + def add_issue(self, code, message, node): + issue = Issue(node, code, message) + self.issues.append(issue) + class NormalizerConfig(object): normalizer_class = Normalizer @@ -41,11 +45,12 @@ class NormalizerConfig(object): return rule -class Error(object): - def __init__(self, leaf, code, message): - self._leaf = leaf +class Issue(object): + def __init__(self, node, code, message): + self._node = node self.code = code self.message = message + self.start_pos = node.start_pos class Rule(object): diff --git a/parso/python/normalizer.py b/parso/python/normalizer.py index 375860f..b48e2b3 100644 --- a/parso/python/normalizer.py +++ b/parso/python/normalizer.py @@ -38,23 +38,23 @@ class PEP8Normalizer(Normalizer): self.indentation = 0 @contextmanager - def visit_node(self, state, node): + def visit_node(self, node): typ = node.type if typ in 'import_name': names = node.get_defined_names() if len(names) > 1: for name in names[:1]: - self.log_error(401, 'Multiple imports on one line', name) + self.add_issue(401, 'Multiple imports on one line', name) elif typ == 'lambdef': if node.parent.type == 'expr_stmt': - self.log_error(731, 'Do not assign a lambda expression, use a def', node) + self.add_issue(731, 'Do not assign a lambda expression, use a def', node) elif typ == 'try_stmt': 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.log_error(722, 'Do not use bare except, specify exception instead', node) + self.add_issue(722, 'Do not use bare except, specify exception instead', node) elif typ == 'comparison': odd = False for child in node.children: @@ -62,7 +62,7 @@ class PEP8Normalizer(Normalizer): if child not in ('is', '=='): break else: - if child.type == 'atom_expr': + if child.type != 'atom_expr': break trailer = child.children[-1] atom = child.children[-1] @@ -71,7 +71,7 @@ class PEP8Normalizer(Normalizer): break odd = not odd else: - self.log_error(721, "Do not compare types, use 'isinstance()", node) + self.add_issue(721, "Do not compare types, use 'isinstance()", node) if typ in IMPORT_TYPES: module = node.parent @@ -79,7 +79,7 @@ class PEP8Normalizer(Normalizer): index = module.children.index(node) for child in module.children[:index]: if child.type not in IMPORT_TYPES: - self.log_error(402, 'Module level import not at top of file', node) + self.add_issue(402, 'Module level import not at top of file', node) break if typ == 'suite': @@ -94,11 +94,11 @@ class PEP8Normalizer(Normalizer): if leaf.is_definition(): message = "Do not define %s named 'l', 'O', or 'I' one line" if leaf.parent.type == 'class' and leaf.parent.name == leaf: - self.log_error(742, message % 'classes', leaf) + self.add_issue(742, message % 'classes', leaf) elif leaf.parent.type == 'function' and leaf.parent.name == leaf: - self.log_error(743, message % 'function', leaf) + self.add_issue(743, message % 'function', leaf) else: - self.log_error(741, message % 'variables', leaf) + self.add_issuadd_issue(741, message % 'variables', leaf) for part in leaf._split_prefix(): part diff --git a/parso/tree.py b/parso/tree.py index ec51a45..7b2b139 100644 --- a/parso/tree.py +++ b/parso/tree.py @@ -178,7 +178,7 @@ class NodeOrLeaf(object): with normalizer.visit_node(self): return ''.join(child._normalize(normalizer) for child in children) - def _get_normalize_errors(self, normalizer_config=None): + def _get_normalizer_issues(self, normalizer_config=None): normalizer = self._get_normalizer(normalizer_config) self._normalize(normalizer) return normalizer.issues diff --git a/pytest.ini b/pytest.ini index 312830c..343d927 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,7 +2,7 @@ addopts = --doctest-modules # Ignore broken files inblackbox test directories -norecursedirs = .* docs scripts old* +norecursedirs = .* docs scripts normalizer_issue_files # Activate `clean_jedi_cache` fixture for all tests. This should be # fine as long as we are using `clean_jedi_cache` as a session scoped