Skip to content

Instantly share code, notes, and snippets.

@RJ722
Created April 14, 2020 03:52
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save RJ722/0e8578d0920d508fc52461402d304c8d to your computer and use it in GitHub Desktop.
Save RJ722/0e8578d0920d508fc52461402d304c8d to your computer and use it in GitHub Desktop.
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!")
@jalotra
Copy link

jalotra commented Dec 22, 2021

Cool blog. Thanks a lot for writing it.

@morentharia
Copy link

morentharia commented Aug 16, 2023

plus one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment