Skip to content

Commit e71a72f

Browse files
committed
Find Python files without extensions
Previously, only files ending with `*.py` would be detected as Python files while recursing a directory. This closes #149.
1 parent bce5564 commit e71a72f

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

pyflakes/api.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import sys
77
import os
8+
import re
89
import _ast
910

1011
from pyflakes import checker, __version__
@@ -13,6 +14,9 @@
1314
__all__ = ['check', 'checkPath', 'checkRecursive', 'iterSourceCode', 'main']
1415

1516

17+
PYTHON_SHEBANG_REGEX = re.compile(br'^#!.*\bpython[23]?\b\s*$')
18+
19+
1620
def check(codeString, filename, reporter=None):
1721
"""
1822
Check the Python source given by C{codeString} for flakes.
@@ -108,6 +112,25 @@ def checkPath(filename, reporter=None):
108112
return check(codestr, filename, reporter)
109113

110114

115+
def isPythonFile(filename):
116+
"""Return True if filename points to a Python file."""
117+
if filename.endswith('.py'):
118+
return True
119+
120+
max_bytes = 128
121+
122+
try:
123+
with open(filename, 'rb') as f:
124+
text = f.read(max_bytes)
125+
if not text:
126+
return False
127+
except IOError:
128+
return False
129+
130+
first_line = text.splitlines()[0]
131+
return PYTHON_SHEBANG_REGEX.match(first_line)
132+
133+
111134
def iterSourceCode(paths):
112135
"""
113136
Iterate over all Python source files in C{paths}.
@@ -120,8 +143,9 @@ def iterSourceCode(paths):
120143
if os.path.isdir(path):
121144
for dirpath, dirnames, filenames in os.walk(path):
122145
for filename in filenames:
123-
if filename.endswith('.py'):
124-
yield os.path.join(dirpath, filename)
146+
full_path = os.path.join(dirpath, filename)
147+
if isPythonFile(full_path):
148+
yield full_path
125149
else:
126150
yield path
127151

pyflakes/test/test_api.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,22 @@ def test_recurses(self):
187187
sorted(iterSourceCode([self.tempdir])),
188188
sorted([apath, bpath, cpath]))
189189

190+
def test_shebang(self):
191+
"""
192+
Find Python files that don't end with `.py`, but contain a Python
193+
shebang.
194+
"""
195+
apath = os.path.join(self.tempdir, 'a')
196+
fd = open(apath, 'w')
197+
fd.write('#!/usr/bin/env python\n')
198+
fd.close()
199+
200+
self.makeEmptyFile('b')
201+
202+
self.assertEqual(
203+
list(iterSourceCode([self.tempdir])),
204+
list([apath]))
205+
190206
def test_multipleDirectories(self):
191207
"""
192208
L{iterSourceCode} can be given multiple directories. It will recurse

0 commit comments

Comments
 (0)