pylint: add check for missing thrown exceptions

People sometimes instantiate exceptions but forget to throw them.
Add a check for it.

BUG=chromium:1005893
TEST=`./utils/run_pylint.py client/cros/power/power_status.py` flags a bad line

Change-Id: I06f541f2375999cd7ecd60716495ba6dd42a6ba0
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/1816141
Reviewed-by: Julius Werner <[email protected]>
Tested-by: Mike Frysinger <[email protected]>
Legacy-Commit-Queue: Commit Bot <[email protected]>
Commit-Queue: Mike Frysinger <[email protected]>
diff --git a/utils/run_pylint.py b/utils/run_pylint.py
index 6e58ad1..c2b8149 100755
--- a/utils/run_pylint.py
+++ b/utils/run_pylint.py
@@ -33,6 +33,7 @@
 # some files make pylint blow up, so make sure we ignore them
 BLACKLIST = ['/site-packages/*', '/contrib/*', '/frontend/afe/management.py']
 
+import astroid
 import pylint.lint
 from pylint.checkers import base, imports, variables
 
@@ -134,6 +135,24 @@
         node.modname = patch_modname(node.modname)
         return super(CustomVariablesChecker, self).visit_importfrom(node)
 
+    def visit_expr(self, node):
+        """
+        Flag exceptions instantiated but not used.
+
+        https://crbug.com/1005893
+        """
+        if not isinstance(node.value, astroid.Call):
+            return
+        func = node.value.func
+        try:
+            cls = next(func.infer())
+        except astroid.InferenceError:
+            return
+        if not isinstance(cls, astroid.ClassDef):
+            return
+        if any(x for x in cls.ancestors() if x.name == 'BaseException'):
+            self.add_message('W0104', node=node, line=node.fromlineno)
+
 
 class CustomDocStringChecker(base.DocStringChecker):
     """Modifies stock docstring checker to suit Autotest doxygen style."""
@@ -407,7 +426,8 @@
         pylint_base_opts = ['--rcfile=%s' % pylint_rc,
                             '--reports=no',
                             '--disable=W,R,E,C,F',
-                            '--enable=W0611,W1201,C0111,C0112,E0602,W0601',
+                            '--enable=W0104,W0611,W1201,C0111,C0112,E0602,'
+                            'W0601,E0633',
                             '--no-docstring-rgx=%s' % no_docstring_rgx,]
     else:
         all_failures = 'error,warning,refactor,convention'