qubes-installer-qubes-os/anaconda/tests/pylint/environ.py

108 lines
4.2 KiB
Python
Raw Normal View History

# setenv pylint module
#
# Copyright (C) 2015 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details. You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
# Red Hat Author(s): David Shea <dshea@redhat.com>
#
import astroid
from pylint.checkers import BaseChecker
from pylint.checkers.utils import check_messages, safe_infer
from pylint.interfaces import IAstroidChecker
import os
class EnvironChecker(BaseChecker):
__implements__ = (IAstroidChecker,)
name = "environ"
msgs = {"W9940" : ("Found potentially unsafe modification of environment",
"environment-modify",
"Potentially thread-unsafe modification of environment")}
def _is_environ(self, node):
# Guess whether a node being modified is os.environ
if isinstance(node, astroid.Getattr):
if node.attrname == "environ":
expr_node = safe_infer(node.expr)
if isinstance(expr_node, astroid.Module) and expr_node.name == "os":
return True
# If the node being modified is just "environ" assume that it's os.environ
if isinstance(node, astroid.Name):
if node.name == "environ":
return True
return False
@check_messages("environment-modify")
def visit_assign(self, node):
if not isinstance(node, astroid.Assign):
return
# Look for os.environ["WHATEVER"] = something
for target in node.targets:
if not isinstance(target, astroid.Subscript):
continue
if self._is_environ(target.value):
self.add_message("environment-modify", node=node)
@check_messages("environment-modify")
def visit_callfunc(self, node):
# Check both for uses of os.putenv and os.setenv and modifying calls
# to the os.environ object, such as os.environ.update
if not isinstance(node, astroid.CallFunc):
return
function_node = safe_infer(node.func)
if not isinstance(function_node, (astroid.Function, astroid.BoundMethod)):
return
# If the function is from the os or posix modules, look for calls that
# modify the environment
if function_node.root().name in ("os", os.name) and \
function_node.name in ("putenv", "unsetenv"):
self.add_message("environment-modify", node=node)
# Look for methods bound to the environ dict
if isinstance(function_node, astroid.BoundMethod) and \
isinstance(function_node.bound, astroid.Dict) and \
function_node.bound.root().name in ("os", os.name) and \
function_node.bound.name == "environ" and \
function_node.name in ("clear", "pop", "popitem", "setdefault", "update"):
self.add_message("environment-modify", node=node)
@check_messages("environment-modify")
def visit_delete(self, node):
if not isinstance(node, astroid.Delete):
return
# Look for del os.environ["WHATEVER"]
for target in node.targets:
if not isinstance(target, astroid.Subscript):
continue
if self._is_environ(target.value):
self.add_message("environment-modify", node=node)
def register(linter):
"""required method to auto register this checker """
linter.register_checker(EnvironChecker(linter))