URL: https://github.com/freeipa/freeipa/pull/462
Author: MartinBasti
 Title: #462: [WIP] pylint: add custom check for forbidden imports
Action: opened

PR body:
"""
Some modules of FreeIPA should not be imported to some other FreeIPA
modules, like ipalib into ipapython

This is WIP, it misses a lot of rules and I had hard time with naming 
variables, feedback more than welcome.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/462/head:pr462
git checkout pr462
From aaf13c5ed25ec619aab9c1566248812593fd6342 Mon Sep 17 00:00:00 2001
From: Martin <martin.ba...@gmail.com>
Date: Tue, 14 Feb 2017 01:14:25 +0100
Subject: [PATCH] pylint: add custom check for forbidden imports

Some modules of FreeIPA should not be importe to some other FreeIPA
modules, like ipalib into ipapython
---
 pylint_plugins.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 64 insertions(+), 4 deletions(-)

diff --git a/pylint_plugins.py b/pylint_plugins.py
index fc2ce9b..078a802 100644
--- a/pylint_plugins.py
+++ b/pylint_plugins.py
@@ -9,10 +9,9 @@
 
 from astroid import MANAGER
 from astroid import scoped_nodes
-
-
-def register(linter):
-    pass
+from pylint.checkers import BaseChecker
+from pylint.checkers.utils import check_messages
+from pylint.interfaces import IAstroidChecker
 
 
 def _warning_already_exists(cls, member):
@@ -249,9 +248,70 @@ def fake_class(name_or_class_obj, members=()):
 }
 
 
+# prefix match is used for all values specified here --> all submodules are
+# matched
+# module names must be specified in absolute path
+FORBIDDEN_IMPORTS = (
+    # ( checked module, [# forbidden.import.1, # forbidden.import.2])
+    ('ipapython', ('ipalib',)),
+)
+
+
 def fix_ipa_classes(cls):
     class_name_with_module = "{}.{}".format(cls.root().name, cls.name)
     if class_name_with_module in ipa_class_members:
         fake_class(cls, ipa_class_members[class_name_with_module])
 
+
+class IPAImportChecker(BaseChecker):
+    """Check for specified imports from FORBIDDEN_IMPORTS and return
+    warning when module is not allowed ot be imported
+    into the particular module"""
+
+    __implements__ = IAstroidChecker
+
+    name = 'ipa-imports'
+    msgs = {
+        'W9999': (
+            'IPA: forbidden import "%s" ("%s" should not import "%s")',
+            'ipa-forbidden-import',
+            'Used when import of module is not '
+            'allowed in the particular module.'
+        ),
+    }
+    priority = -2
+
+    def _check_imports(self, node, import_abs_name):
+        # name of the module where import statement is
+        current = node.root().name
+        for importer, imports in FORBIDDEN_IMPORTS:
+            if current.startswith(importer):
+                # current node is listed in rules
+                for imprt in imports:
+                    if import_abs_name.startswith(imprt):
+                        self.add_message(
+                            'ipa-forbidden-import',
+                            args=(import_abs_name, importer, imprt),
+                            node=node)
+                        break
+                break
+
+    @check_messages('ipa-forbidden-import')
+    def visit_import(self, node):
+        """triggered when an import statement is seen"""
+        modnode = [name for name, _ in node.names]
+        for m in modnode:
+            self._check_imports(node, m)
+
+    @check_messages('ipa-forbidden-import')
+    def visit_importfrom(self, node):
+        """triggered when a from statement is seen"""
+        basename = node.modname
+        self._check_imports(node, basename)
+
+
+def register(linter):
+    linter.register_checker(IPAImportChecker(linter))
+
+
 MANAGER.register_transform(scoped_nodes.Class, fix_ipa_classes)
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to