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() |
def simulate_quote_warnin(): | |
''' | |
The docstring intentionally uses single quotes. | |
''' | |
if isinstance(shawn, 'sheep'): | |
print('Shawn the sheep!') |
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() |
import antigravity | |
import os.path.join | |
import sys | |
import this | |
tmpdir = os.path.join(sys.path[0], 'tmp') |
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() |
def build_herd(): | |
herd = list() | |
for a_sheep in sheep: | |
herd.append(a_sheep) | |
return Herd(herd) |
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() |
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