summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Cordasco <graffatcolmingov@gmail.com>2016-02-22 21:47:43 -0600
committerIan Cordasco <graffatcolmingov@gmail.com>2016-02-22 21:47:43 -0600
commit8792c30872e7e49c2cf2076c5765238b2e92c729 (patch)
treeda610e4ed6a96582ccaadb11b912f5a65d8b160f
parenta21c328870cf177492927687445a55244bfc78ab (diff)
downloadflake8-8792c30872e7e49c2cf2076c5765238b2e92c729.tar.gz
Add utility functions around filename matching
We add utils.fnmatch and utils.filenames_for in anticipation of our checker manager creating file checkers for each file. We also include tests for these functions and a couple previously untested utility functions.
-rw-r--r--flake8/utils.py55
-rw-r--r--tests/unit/test_utils.py46
2 files changed, 101 insertions, 0 deletions
diff --git a/flake8/utils.py b/flake8/utils.py
index e642d26..54c1990 100644
--- a/flake8/utils.py
+++ b/flake8/utils.py
@@ -1,4 +1,5 @@
"""Utility methods for flake8."""
+import fnmatch as _fnmatch
import io
import os
import sys
@@ -89,3 +90,57 @@ def is_using_stdin(paths):
bool
"""
return '-' in paths
+
+
+def _default_predicate(*args):
+ return False
+
+
+def filenames_from(arg, predicate=None):
+ # type: (str) -> Generator
+ """Generate filenames from an argument.
+
+ :param str arg:
+ Parameter from the command-line.
+ :param callable predicate:
+ Predicate to use to filter out filenames. If the predicate
+ returns ``True`` we will exclude the filename, otherwise we
+ will yield it.
+ :returns:
+ Generator of paths
+ """
+ if predicate is None:
+ predicate = _default_predicate
+ if os.path.isdir(arg):
+ for root, sub_directories, files in os.walk(arg):
+ for filename in files:
+ joined = os.path.join(root, filename)
+ if predicate(filename) or predicate(joined):
+ continue
+ yield joined
+ # NOTE(sigmavirus24): os.walk() will skip a directory if you
+ # remove it from the list of sub-directories.
+ for directory in sub_directories:
+ if predicate(directory):
+ sub_directories.remove(directory)
+ else:
+ yield arg
+
+
+def fnmatch(filename, patterns, default=True):
+ # type: (str, List[str], bool) -> bool
+ """Wrap :func:`fnmatch.fnmatch` to add some functionality.
+
+ :param str filename:
+ Name of the file we're trying to match.
+ :param list patterns:
+ Patterns we're using to try to match the filename.
+ :param bool default:
+ The default value if patterns is empty
+ :returns:
+ True if a pattern matches the filename, False if it doesn't.
+ ``default`` if patterns is empty.
+ """
+ if not patterns:
+ return default
+ return any(_fnmatch.fnmatch(filename, pattern) for pattern in patterns)
diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py
index a6096d4..34b4909 100644
--- a/tests/unit/test_utils.py
+++ b/tests/unit/test_utils.py
@@ -1,5 +1,6 @@
"""Tests for flake8's utils module."""
import os
+import mock
import pytest
@@ -40,3 +41,48 @@ def test_normalize_path(value, expected):
def test_normalize_paths(value, expected):
"""Verify we normalize comma-separated paths provided to the tool."""
assert utils.normalize_paths(value) == expected
+
+
+def test_is_windows_checks_for_nt():
+ """Verify that we correctly detect Windows."""
+ with mock.patch.object(os, 'name', 'nt'):
+ assert utils.is_windows() is True
+
+ with mock.patch.object(os, 'name', 'posix'):
+ assert utils.is_windows() is False
+
+
+@pytest.mark.parametrize('filename,patterns,expected', [
+ ('foo.py', [], True),
+ ('foo.py', ['*.pyc'], False),
+ ('foo.pyc', ['*.pyc'], True),
+ ('foo.pyc', ['*.swp', '*.pyc', '*.py'], True),
+])
+def test_fnmatch(filename, patterns, expected):
+ """Verify that our fnmatch wrapper works as expected."""
+ assert utils.fnmatch(filename, patterns) is expected
+
+
+def test_filenames_from_a_directory():
+ """Verify that filenames_from walks a directory."""
+ filenames = list(utils.filenames_from('flake8/'))
+ assert len(filenames) > 2
+ assert 'flake8/__init__.py' in filenames
+
+
+def test_filenames_from_a_directory_with_a_predicate():
+ """Verify that predicates filter filenames_from."""
+ filenames = list(utils.filenames_from(
+ arg='flake8/',
+ predicate=lambda filename: filename == 'flake8/__init__.py',
+ ))
+ assert len(filenames) > 2
+ assert 'flake8/__init__.py' not in filenames
+
+
+def test_filenames_from_a_single_file():
+ """Verify that we simply yield that filename."""
+ filenames = list(utils.filenames_from('flake8/__init__.py'))
+
+ assert len(filenames) == 1
+ assert ['flake8/__init__.py'] == filenames