Resolve hashlib.md5 in Python 2 to __all__ (PY-28053)

This commit is contained in:
Semyon Proshev
2018-03-12 21:33:03 +03:00
parent 0b21943efc
commit 3fcd22a5b5
6 changed files with 62 additions and 1 deletions
@@ -718,6 +718,7 @@
<typeProvider implementation="com.jetbrains.python.codeInsight.stdlib.PyNamedTuplesOverridingTypeProvider"/>
<typeProvider implementation="com.jetbrains.python.psi.types.PyCollectionTypeByModificationsProvider"/>
<pyModuleMembersProvider implementation="com.jetbrains.python.codeInsight.stdlib.PyStdlibModuleMembersProvider"/>
<pyModuleMembersProvider implementation="com.jetbrains.python.codeInsight.stdlib.PyStdlibOverridingModuleMembersProvider"/>
<documentationLinkProvider implementation="com.jetbrains.python.codeInsight.stdlib.PyStdlibDocumentationLinkProvider"/>
<canonicalPathProvider implementation="com.jetbrains.python.codeInsight.stdlib.PyStdlibCanonicalPathProvider"/>
<inspectionExtension implementation="com.jetbrains.python.inspections.stdlib.PyStdlibInspectionExtension"/>
@@ -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<PyCustomMember>()
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
}
}
@@ -0,0 +1,6 @@
from hashlib import md5
md5("str")
def f():
md5("str")
@@ -0,0 +1,8 @@
__all__ = ['md5']
def my_md5(s):
return s
globals()["md5"] = my_md5
@@ -0,0 +1,3 @@
import warnings
warnings.warn("the md5 module is deprecated; use hashlib instead",
DeprecationWarning, 2)
@@ -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);
}
}