From 3fcd22a5b589822d00489278f146452bff7c80aa Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Fri, 2 Mar 2018 14:09:58 +0300 Subject: [PATCH] Resolve `hashlib.md5` in Python 2 to `__all__` (PY-28053) --- python/src/META-INF/python-core-common.xml | 1 + ...PyStdlibOverridingModuleMembersProvider.kt | 36 +++++++++++++++++++ python/testData/deprecation/hashlibMd5/a.py | 6 ++++ .../deprecation/hashlibMd5/hashlib.py | 8 +++++ python/testData/deprecation/hashlibMd5/md5.py | 3 ++ .../jetbrains/python/PyDeprecationTest.java | 9 ++++- 6 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibOverridingModuleMembersProvider.kt create mode 100644 python/testData/deprecation/hashlibMd5/a.py create mode 100644 python/testData/deprecation/hashlibMd5/hashlib.py create mode 100644 python/testData/deprecation/hashlibMd5/md5.py diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml index 92f1aa90db51..c9a09bf3623f 100644 --- a/python/src/META-INF/python-core-common.xml +++ b/python/src/META-INF/python-core-common.xml @@ -718,6 +718,7 @@ + diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibOverridingModuleMembersProvider.kt b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibOverridingModuleMembersProvider.kt new file mode 100644 index 000000000000..de0473238b86 --- /dev/null +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibOverridingModuleMembersProvider.kt @@ -0,0 +1,36 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.jetbrains.python.codeInsight.stdlib + +import com.intellij.psi.PsiElement +import com.intellij.psi.util.QualifiedName +import com.jetbrains.extensions.getQName +import com.jetbrains.python.PyNames +import com.jetbrains.python.codeInsight.PyCustomMember +import com.jetbrains.python.psi.PyFile +import com.jetbrains.python.psi.resolve.PyResolveContext +import com.jetbrains.python.psi.types.PyOverridingModuleMembersProvider + +class PyStdlibOverridingModuleMembersProvider: PyOverridingModuleMembersProvider() { + + override fun getMembersByQName(module: PyFile?, qName: String?) = emptyList() + + override fun resolveMember(module: PyFile, name: String, resolveContext: PyResolveContext): PsiElement? { + if (module.languageLevel.isPython2 && + name == "md5" && + module.name == "hashlib.py" && + module.getQName() == QualifiedName.fromComponents("hashlib")) { + // When module member is not found in it, + // `__all__` and nearby module with the specified name are suggested as a fallback. + + // In case of `hashlib` in Python 2 stdlib, returned `md5` module is not used in `hashlib` + // so the behaviour has to be overridden. + + // Please note that it's important to check against `hashlib.py` + // because `hashlib.pyi` stub is defined correctly. + + return module.findExportedName(PyNames.ALL) + } + + return null + } +} \ No newline at end of file diff --git a/python/testData/deprecation/hashlibMd5/a.py b/python/testData/deprecation/hashlibMd5/a.py new file mode 100644 index 000000000000..81c701c6c51e --- /dev/null +++ b/python/testData/deprecation/hashlibMd5/a.py @@ -0,0 +1,6 @@ +from hashlib import md5 + +md5("str") + +def f(): + md5("str") \ No newline at end of file diff --git a/python/testData/deprecation/hashlibMd5/hashlib.py b/python/testData/deprecation/hashlibMd5/hashlib.py new file mode 100644 index 000000000000..0ec5b6dcbde7 --- /dev/null +++ b/python/testData/deprecation/hashlibMd5/hashlib.py @@ -0,0 +1,8 @@ +__all__ = ['md5'] + + +def my_md5(s): + return s + + +globals()["md5"] = my_md5 diff --git a/python/testData/deprecation/hashlibMd5/md5.py b/python/testData/deprecation/hashlibMd5/md5.py new file mode 100644 index 000000000000..d76ce92718ab --- /dev/null +++ b/python/testData/deprecation/hashlibMd5/md5.py @@ -0,0 +1,3 @@ +import warnings +warnings.warn("the md5 module is deprecated; use hashlib instead", + DeprecationWarning, 2) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyDeprecationTest.java b/python/testSrc/com/jetbrains/python/PyDeprecationTest.java index 8a778873ae84..db2fba2884bd 100644 --- a/python/testSrc/com/jetbrains/python/PyDeprecationTest.java +++ b/python/testSrc/com/jetbrains/python/PyDeprecationTest.java @@ -98,6 +98,13 @@ public class PyDeprecationTest extends PyTestCase { assertEquals("the deprecated module is deprecated; use a non-deprecated module instead", file.getDeprecationMessage()); assertNotParsed(file); - + } + + // PY-28053 + public void testHashlibMd5() { + myFixture.enableInspections(PyDeprecationInspection.class); + myFixture.copyDirectoryToProject("deprecation/hashlibMd5", ""); + myFixture.configureByFile("a.py"); + myFixture.checkHighlighting(true, false, false); } }