diff options
| author | Martin <MartinBasti@users.noreply.github.com> | 2017-11-11 15:46:14 +0100 |
|---|---|---|
| committer | Claudiu Popa <pcmanticore@gmail.com> | 2017-11-11 15:46:14 +0100 |
| commit | 99abc893e4374e3695ca29a0f474decf4f837f52 (patch) | |
| tree | 1842483c79c88cba5e223367f169d0a67e61bcd1 /pylint/checkers/stdlib.py | |
| parent | 9125084de6d37b91c0683501444169d497262162 (diff) | |
| download | pylint-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.py | 20 |
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 |
