summaryrefslogtreecommitdiff
path: root/pylint/checkers/stdlib.py
diff options
context:
space:
mode:
authorMartin <MartinBasti@users.noreply.github.com>2017-11-11 15:46:14 +0100
committerClaudiu Popa <pcmanticore@gmail.com>2017-11-11 15:46:14 +0100
commit99abc893e4374e3695ca29a0f474decf4f837f52 (patch)
tree1842483c79c88cba5e223367f169d0a67e61bcd1 /pylint/checkers/stdlib.py
parent9125084de6d37b91c0683501444169d497262162 (diff)
downloadpylint-git-99abc893e4374e3695ca29a0f474decf4f837f52.tar.gz
New warning: shallow copy of os.environ (#1733)
Shallow copy of os.environ doesn't work as people may expect. os.environ is not a dict object but rather a proxy object, so any changes made on the copy may have unexpected effects on os.environ Instead of copy.copy(os.environ) method os.environ.copy() should be used. Message id is: `shallow-copy-environ` See https://bugs.python.org/issue15373 for details. Resolves: #1301
Diffstat (limited to 'pylint/checkers/stdlib.py')
-rw-r--r--pylint/checkers/stdlib.py20
1 files changed, 19 insertions, 1 deletions
diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py
index 4c2d504cb..45247c4e6 100644
--- a/pylint/checkers/stdlib.py
+++ b/pylint/checkers/stdlib.py
@@ -23,6 +23,8 @@ from pylint.checkers import utils
OPEN_FILES = {'open', 'file'}
UNITTEST_CASE = 'unittest.case'
THREADING_THREAD = 'threading.Thread'
+COPY_COPY = 'copy.copy'
+OS_ENVIRON = 'os._Environ'
if sys.version_info >= (3, 0):
OPEN_MODULE = '_io'
else:
@@ -105,6 +107,12 @@ class StdlibChecker(BaseChecker):
'The warning is emitted when a threading.Thread class '
'is instantiated without the target function being passed. '
'By default, the first parameter is the group param, not the target param. '),
+ 'W1507': ('Using copy.copy(os.environ). Use os.environ.copy() ' # TODO: number
+ 'instead. ',
+ 'shallow-copy-environ',
+ 'os.environ is not a dict object but proxy object, so '
+ 'shallow copy has still effects on original object. '
+ 'See https://bugs.python.org/issue15373 for reference. '),
}
deprecated = {
@@ -186,9 +194,17 @@ class StdlibChecker(BaseChecker):
if not node.kwargs and node.args:
self.add_message('bad-thread-instantiation', node=node)
+ def _check_shallow_copy_environ(self, node):
+ arg = utils.get_argument_from_call(node, position=0)
+ for inferred in arg.inferred():
+ if inferred.qname() == OS_ENVIRON:
+ self.add_message('shallow-copy-environ', node=node)
+ break
+
@utils.check_messages('bad-open-mode', 'redundant-unittest-assert',
'deprecated-method',
- 'bad-thread-instantiation')
+ 'bad-thread-instantiation',
+ 'shallow-copy-environ')
def visit_call(self, node):
"""Visit a Call node."""
try:
@@ -202,6 +218,8 @@ class StdlibChecker(BaseChecker):
self._check_redundant_assert(node, inferred)
if isinstance(inferred, astroid.ClassDef) and inferred.qname() == THREADING_THREAD:
self._check_bad_thread_instantiation(node)
+ if isinstance(inferred, astroid.FunctionDef) and inferred.qname() == COPY_COPY:
+ self._check_shallow_copy_environ(node)
self._check_deprecated_method(node, inferred)
except astroid.InferenceError:
return