From e51fc5458b81b6c56c359c79b13ce88b70e476ec Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Tue, 26 Jul 2016 19:41:41 -0500 Subject: [PATCH] Fix handling of logical lines with noqa When attempting to centralize all inline NoQA handling in the StyleGuide we inadvertently broke plugins relying on it in combination with checker state. For example, the check for E402 relies both on NoQA and the state to determine if it has seen a non-import line. Placing NoQA on the sole line that is not an import is more elegant than placing it on each of the following import lines. Closes #186 --- docs/source/release-notes/3.0.2.rst | 5 +++++ setup.py | 4 ++-- src/flake8/defaults.py | 17 +++++++++++++++++ src/flake8/processor.py | 13 +++++++------ src/flake8/style_guide.py | 18 ++---------------- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/docs/source/release-notes/3.0.2.rst b/docs/source/release-notes/3.0.2.rst index 4fbc0a4..4ff8a1f 100644 --- a/docs/source/release-notes/3.0.2.rst +++ b/docs/source/release-notes/3.0.2.rst @@ -6,7 +6,12 @@ - Fix indexing of column numbers. We accidentally were starting column indices at 0 instead of 1. +- Fix regression in handling of errors like E402 that rely on a combination of + attributes. (See also `GitLab#186`_) + .. links .. _GitLab#181: https://gitlab.com/pycqa/flake8/issues/181 +.. _GitLab#186: + https://gitlab.com/pycqa/flake8/issues/186 diff --git a/setup.py b/setup.py index 680e68f..d95530c 100644 --- a/setup.py +++ b/setup.py @@ -7,9 +7,9 @@ import sys import setuptools -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) # noqa -import flake8 # noqa +import flake8 tests_require = ['mock', 'pytest'] diff --git a/src/flake8/defaults.py b/src/flake8/defaults.py index ede2946..73cadf1 100644 --- a/src/flake8/defaults.py +++ b/src/flake8/defaults.py @@ -1,4 +1,5 @@ """Constants that define defaults.""" +import re EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg' IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504' @@ -15,3 +16,19 @@ STATISTIC_NAMES = ( 'physical lines', 'tokens', ) + +NOQA_INLINE_REGEXP = re.compile( + # We're looking for items that look like this: + # ``# noqa`` + # ``# noqa: E123`` + # ``# noqa: E123,W451,F921`` + # ``# NoQA: E123,W451,F921`` + # ``# NOQA: E123,W451,F921`` + # We do not care about the ``: `` that follows ``noqa`` + # We do not care about the casing of ``noqa`` + # We want a comma-separated list of errors + '# noqa(?:: (?P[A-Z0-9,]+))?', + re.IGNORECASE +) + +NOQA_FILE = re.compile(r'\s*# flake8[:=]\s*noqa', re.I) diff --git a/src/flake8/processor.py b/src/flake8/processor.py index dee0b15..1d0e3a4 100644 --- a/src/flake8/processor.py +++ b/src/flake8/processor.py @@ -2,7 +2,6 @@ import contextlib import io import logging -import re import sys import tokenize @@ -47,8 +46,6 @@ class FileProcessor(object): - :attr:`verbose` """ - NOQA_FILE = re.compile(r'\s*# flake8[:=]\s*noqa', re.I) - def __init__(self, filename, options, lines=None): """Initialice our file processor. @@ -147,6 +144,7 @@ class FileProcessor(object): self.previous_logical = self.logical_line self.blank_lines = 0 self.tokens = [] + self.noqa = False def build_logical_line_tokens(self): """Build the mapping, comments, and logical line lists.""" @@ -189,9 +187,12 @@ class FileProcessor(object): def build_logical_line(self): """Build a logical line from the current tokens list.""" comments, logical, mapping_list = self.build_logical_line_tokens() + joined_comments = ''.join(comments) self.logical_line = ''.join(logical) + if defaults.NOQA_INLINE_REGEXP.search(joined_comments): + self.noqa = True self.statistics['logical lines'] += 1 - return ''.join(comments), self.logical_line, mapping_list + return joined_comments, self.logical_line, mapping_list def split_line(self, token): """Split a physical line's line based on new-lines. @@ -316,12 +317,12 @@ class FileProcessor(object): """Check if ``# flake8: noqa`` is in the file to be ignored. :returns: - True if a line matches :attr:`FileProcessor.NOQA_FILE`, + True if a line matches :attr:`defaults.NOQA_FILE`, otherwise False :rtype: bool """ - ignore_file = self.NOQA_FILE.search + ignore_file = defaults.NOQA_FILE.search return any(ignore_file(line) for line in self.lines) def strip_utf_bom(self): diff --git a/src/flake8/style_guide.py b/src/flake8/style_guide.py index d9a6285..0cbab8f 100644 --- a/src/flake8/style_guide.py +++ b/src/flake8/style_guide.py @@ -3,8 +3,8 @@ import collections import enum import linecache import logging -import re +from flake8 import defaults from flake8 import statistics from flake8 import utils @@ -53,20 +53,6 @@ Error = collections.namedtuple( class StyleGuide(object): """Manage a Flake8 user's style guide.""" - NOQA_INLINE_REGEXP = re.compile( - # We're looking for items that look like this: - # ``# noqa`` - # ``# noqa: E123`` - # ``# noqa: E123,W451,F921`` - # ``# NoQA: E123,W451,F921`` - # ``# NOQA: E123,W451,F921`` - # We do not care about the ``: `` that follows ``noqa`` - # We do not care about the casing of ``noqa`` - # We want a comma-separated list of errors - '# noqa(?:: (?P[A-Z0-9,]+))?', - re.IGNORECASE - ) - def __init__(self, options, listener_trie, formatter): """Initialize our StyleGuide. @@ -177,7 +163,7 @@ class StyleGuide(object): if physical_line is None: physical_line = linecache.getline(error.filename, error.line_number) - noqa_match = self.NOQA_INLINE_REGEXP.search(physical_line) + noqa_match = defaults.NOQA_INLINE_REGEXP.search(physical_line) if noqa_match is None: LOG.debug('%r is not inline ignored', error) return False