Created
April 14, 2020 03:52
-
-
Save RJ722/0e8578d0920d508fc52461402d304c8d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import tokenize | |
class DoubleQuotesChecker: | |
msg = "single quotes detected, use double quotes instead" | |
def __init__(self): | |
self.violations = [] | |
def find_violations(self, filename, tokens): | |
for token_type, token, (line, col), _, _ in tokens: | |
if ( | |
token_type == tokenize.STRING | |
and not token.startswith("'''") and | |
token.startswith("'") | |
): | |
self.violations.append((filename, line, col)) | |
def check(self, files): | |
for filename in files: | |
with tokenize.open(filename) as fd: | |
tokens = tokenize.generate_tokens(fd.readline) | |
self.find_violations(filename, tokens) | |
def report(self): | |
for violation in self.violations: | |
filename, line, col = violation | |
print(f"{filename}:{line}:{col}: {self.msg}") | |
if __name__ == '__main__': | |
files = sys.argv[1:] | |
checker = DoubleQuotesChecker() | |
checker.check(files) | |
checker.report() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def simulate_quote_warnin(): | |
''' | |
The docstring intentionally uses single quotes. | |
''' | |
if isinstance(shawn, 'sheep'): | |
print('Shawn the sheep!') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ast | |
from collections import defaultdict | |
import sys | |
import tokenize | |
def read_file(filename): | |
with tokenize.open(filename) as fd: | |
return fd.read() | |
class BaseChecker(ast.NodeVisitor): | |
def __init__(self): | |
self.violations = [] | |
def check(self, paths): | |
for filepath in paths: | |
self.filename = filepath | |
tree = ast.parse(read_file(filepath)) | |
self.visit(tree) | |
def report(self): | |
for violation in self.violations: | |
filename, lineno, msg = violation | |
print(f"{filename}:{lineno}: {msg}") | |
class UnusedImportChecker(BaseChecker): | |
def __init__(self): | |
self.import_map = defaultdict(set) | |
self.name_map = defaultdict(set) | |
def _add_imports(self, node): | |
for import_name in node.names: | |
# Store only top-level module name ("os.path" -> "os"). | |
# We can't easily detect when "os.path" is used. | |
name = import_name.name.partition(".")[0] | |
self.import_map[self.filename].add((name, node.lineno)) | |
def visit_Import(self, node): | |
self._add_imports(node) | |
def visit_ImportFrom(self, node): | |
self._add_imports(node) | |
def visit_Name(self, node): | |
# We only add those nodes for which a value is being read from. | |
if isinstance(node.ctx, ast.Load): | |
self.name_map[self.filename].add(node.id) | |
def report(self): | |
for path, imports in self.import_map.items(): | |
for name, line in imports: | |
if name not in self.name_map[path]: | |
print(f"{path}:{line}: unused import '{name}'") | |
if __name__ == '__main__': | |
files = sys.argv[1:] | |
checker = UnusedImportChecker() | |
checker.check(files) | |
checker.report() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import antigravity | |
import os.path.join | |
import sys | |
import this | |
tmpdir = os.path.join(sys.path[0], 'tmp') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ast | |
from collections import defaultdict | |
import sys | |
import tokenize | |
def read_file(filename): | |
with tokenize.open(filename) as fd: | |
return fd.read() | |
class BaseChecker(ast.NodeVisitor): | |
def __init__(self): | |
self.violations = [] | |
def check(self, paths): | |
for filepath in paths: | |
self.filename = filepath | |
tree = ast.parse(read_file(filepath)) | |
self.visit(tree) | |
def report(self): | |
for violation in self.violations: | |
filename, lineno, msg = violation | |
print(f"{filename}:{lineno}: {msg}") | |
class ListDefinitionChecker(BaseChecker): | |
msg = "usage of 'list()' detected, use '[]' instead" | |
def visit_Call(self, node): | |
name = getattr(node.func, "id", None) | |
if name and name == list.__name__ and not node.args: | |
self.violations.append((self.filename, node.lineno, self.msg)) | |
if __name__ == '__main__': | |
files = sys.argv[1:] | |
checker = ListDefinitionChecker() | |
checker.check(files) | |
checker.report() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def build_herd(): | |
herd = list() | |
for a_sheep in sheep: | |
herd.append(a_sheep) | |
return Herd(herd) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ast | |
from collections import defaultdict | |
import sys | |
import tokenize | |
def read_file(filename): | |
with tokenize.open(filename) as fd: | |
return fd.read() | |
class BaseChecker(ast.NodeVisitor): | |
def __init__(self): | |
self.violations = [] | |
def check(self, paths): | |
for filepath in paths: | |
self.filename = filepath | |
tree = ast.parse(read_file(filepath)) | |
self.visit(tree) | |
def report(self): | |
for violation in self.violations: | |
filename, lineno, msg = violation | |
print(f"{filename}:{lineno}: {msg}") | |
class TooManyForLoopChecker(BaseChecker): | |
msg = "too many nested for loops" | |
def visit_For(self, node, parent=True): | |
if parent: | |
self.current_loop_depth = 1 | |
else: | |
self.current_loop_depth += 1 | |
for child in node.body: | |
if type(child) == ast.For: | |
self.visit_For(child, parent=False) | |
if parent and self.current_loop_depth > 3: | |
self.violations.append((self.filename, node.lineno, self.msg)) | |
self.current_loop_depth = 0 | |
if __name__ == '__main__': | |
files = sys.argv[1:] | |
checker = TooManyForLoopChecker() | |
checker.check(files) | |
checker.report() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
for _ in range(10): | |
for _ in range(5): | |
for _ in range(3): | |
for _ in range(1): | |
print("Baa, Baa, black sheep") | |
for _ in range(4): | |
for _ in range(3): | |
print("Have you any wool?") | |
for _ in range(10): | |
for _ in range(5): | |
for _ in range(3): | |
if True: | |
for _ in range(3): | |
print("Yes, sir, yes, sir!") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cool blog. Thanks a lot for writing it.