Browse Source

ref: add flake8 plugin to ban force_str / force_bytes (#53370)

blocked on https://github.com/getsentry/sentry/pull/53366 and
https://github.com/getsentry/getsentry/pull/11177
anthony sottile 1 year ago
parent
commit
e8c1d2a6d5
2 changed files with 26 additions and 3 deletions
  1. 18 3
      tests/tools/test_flake8_plugin.py
  2. 8 0
      tools/flake8_plugin.py

+ 18 - 3
tests/tools/test_flake8_plugin.py

@@ -1,13 +1,14 @@
+from __future__ import annotations
+
 import ast
 
 from tools.flake8_plugin import SentryCheck
 
 
-def _run(src):
+def _run(src: str, filename: str = "getsentry/t.py") -> list[str]:
     tree = ast.parse(src)
     return sorted(
-        "t.py:{}:{}: {}".format(*error)
-        for error in SentryCheck(tree=tree, filename="getsentry/foo.py").run()
+        "t.py:{}:{}: {}".format(*error) for error in SentryCheck(tree=tree, filename=filename).run()
     )
 
 
@@ -89,3 +90,17 @@ from sentry.models import User
     assert errors == [
         "t.py:1:0: S005 Do not import models from sentry.models but the actual module",
     ]
+
+
+def test_S006():
+    src = """\
+from django.utils.encoding import force_bytes
+from django.utils.encoding import force_str
+"""
+    # only error in tests until we can fix the rest
+    assert _run(src, filename="src/sentry/whatever.py") == []
+    errors = _run(src, filename="tests/test_foo.py")
+    assert errors == [
+        "t.py:1:0: S006 Do not use force_bytes / force_str -- test the types directly",
+        "t.py:2:0: S006 Do not use force_bytes / force_str -- test the types directly",
+    ]

+ 8 - 0
tools/flake8_plugin.py

@@ -20,6 +20,8 @@ S004_methods = frozenset(("assertRaises", "assertRaisesRegex"))
 
 S005_msg = "S005 Do not import models from sentry.models but the actual module"
 
+S006_msg = "S006 Do not use force_bytes / force_str -- test the types directly"
+
 
 class SentryVisitor(ast.NodeVisitor):
     def __init__(self, filename: str) -> None:
@@ -37,6 +39,12 @@ class SentryVisitor(ast.NodeVisitor):
                 and any(x.name.isupper() or x.name.istitle() for x in node.names)
             ):
                 self.errors.append((node.lineno, node.col_offset, S005_msg))
+            elif (
+                "tests/" in self.filename
+                and node.module == "django.utils.encoding"
+                and any(x.name in {"force_bytes", "force_str"} for x in node.names)
+            ):
+                self.errors.append((node.lineno, node.col_offset, S006_msg))
 
         self.generic_visit(node)