diff options
author | Filip Lajszczak <filip.lajszczak@gmail.com> | 2020-02-06 18:14:17 +0300 |
---|---|---|
committer | Filip Lajszczak <filip.lajszczak@gmail.com> | 2020-02-06 18:14:17 +0300 |
commit | 2b051dd197804b5c93b6e38aae91c991278afdba (patch) | |
tree | e2872c7a8e89f03e0e4675e2d217c595d50a768c /linter_plugin.py | |
parent | b27e5804b9671e28f37a6da7e2f1f7fa9455d24a (diff) | |
parent | 7da5196206b33d5593bd15cd1dcce4d790db7e6d (diff) |
Merge branch 'master' of https://github.com/certbot/certbot
Diffstat (limited to 'linter_plugin.py')
-rw-r--r-- | linter_plugin.py | 77 |
1 files changed, 50 insertions, 27 deletions
diff --git a/linter_plugin.py b/linter_plugin.py index 4938755cf..1754b1a2a 100644 --- a/linter_plugin.py +++ b/linter_plugin.py @@ -1,29 +1,52 @@ -"""Certbot ACME PyLint plugin. - -http://docs.pylint.org/plugins.html - """ -from astroid import MANAGER -from astroid import nodes - - -def register(unused_linter): - """Register this module as PyLint plugin.""" - -def _transform(cls): - # fix the "no-member" error on instances of - # letsencrypt.acme.util.ImmutableMap subclasses (instance - # attributes are initialized dynamically based on __slots__) +Certbot PyLint plugin. - # TODO: this is too broad and applies to any tested class... - - if cls.slots() is not None: - for slot in cls.slots(): - cls.locals[slot.value] = [nodes.EmptyNode()] - - if cls.name == 'JSONObjectWithFields': - # _fields is magically introduced by JSONObjectWithFieldsMeta - cls.locals['_fields'] = [nodes.EmptyNode()] - - -MANAGER.register_transform(nodes.Class, _transform) +The built-in ImportChecker of Pylint does a similar job to ForbidStandardOsModule to detect +deprecated modules. You can check its behavior as a reference to what is coded here. +See https://github.com/PyCQA/pylint/blob/b20a2984c94e2946669d727dbda78735882bf50a/pylint/checkers/imports.py#L287 +See http://docs.pylint.org/plugins.html +""" +from pylint.checkers import BaseChecker +from pylint.interfaces import IAstroidChecker + +# Modules in theses packages can import the os module. +WHITELIST_PACKAGES = ['acme', 'certbot_compatibility_test', 'letshelp_certbot', 'lock_test'] + + +class ForbidStandardOsModule(BaseChecker): + """ + This checker ensures that standard os module (and submodules) is not imported by certbot + modules. Otherwise an 'os-module-forbidden' error will be registered for the faulty lines. + """ + __implements__ = IAstroidChecker + + name = 'forbid-os-module' + msgs = { + 'E5001': ( + 'Forbidden use of os module, certbot.compat.os must be used instead', + 'os-module-forbidden', + 'Some methods from the standard os module cannot be used for security reasons on Windows: ' + 'the safe wrapper certbot.compat.os must be used instead in Certbot.' + ) + } + priority = -1 + + def visit_import(self, node): + os_used = any(name for name in node.names if name[0] == 'os' or name[0].startswith('os.')) + if os_used and not _check_disabled(node): + self.add_message('os-module-forbidden', node=node) + + def visit_importfrom(self, node): + if node.modname == 'os' or node.modname.startswith('os.') and not _check_disabled(node): + self.add_message('os-module-forbidden', node=node) + + +def register(linter): + """Pylint hook to auto-register this linter""" + linter.register_checker(ForbidStandardOsModule(linter)) + + +def _check_disabled(node): + module = node.root() + return any(package for package in WHITELIST_PACKAGES + if module.name.startswith(package + '.') or module.name == package) |