1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- import ast
- from collections import namedtuple
- from functools import partial
- class SentryVisitor(ast.NodeVisitor):
- def __init__(self):
- self.errors = []
- def visit_ImportFrom(self, node):
- if node.module in S003.modules:
- for nameproxy in node.names:
- if nameproxy.name in S003.names:
- self.errors.append(S003(node.lineno, node.col_offset))
- break
- def visit_Import(self, node):
- for alias in node.names:
- if alias.name.split(".", 1)[0] in S003.modules:
- self.errors.append(S003(node.lineno, node.col_offset))
- def visit_Attribute(self, node):
- if node.attr in S001.methods:
- self.errors.append(S001(node.lineno, node.col_offset, vars=(node.attr,)))
- def visit_Name(self, node):
- if node.id == "print":
- self.errors.append(S002(lineno=node.lineno, col=node.col_offset))
- class SentryCheck:
- name = "sentry-flake8"
- version = "0"
- def __init__(self, tree: ast.AST) -> None:
- self.tree = tree
- def run(self):
- visitor = SentryVisitor()
- visitor.visit(self.tree)
- for e in visitor.errors:
- yield self.adapt_error(e)
- @classmethod
- def adapt_error(cls, e):
- """Adapts the extended error namedtuple to be compatible with Flake8."""
- return e._replace(message=e.message.format(*e.vars))[:4]
- error = namedtuple("error", "lineno col message type vars")
- Error = partial(partial, error, message="", type=SentryCheck, vars=())
- S001 = Error(
- message="S001: Avoid using the {} mock call as it is "
- "confusing and prone to causing invalid test "
- "behavior."
- )
- S001.methods = {
- "not_called",
- "called_once",
- "called_once_with",
- }
- S002 = Error(message="S002: print functions or statements are not allowed.")
- S003 = Error(message="S003: Use ``from sentry.utils import json`` instead.")
- S003.modules = {"json", "simplejson"}
- S003.names = {
- "load",
- "loads",
- "dump",
- "dumps",
- "JSONEncoder",
- "JSONDecodeError",
- "_default_encoder",
- }
|