Enable re stubs (PY-24440, PY-22308)

The most important part of this commit is that local module has more priority against typeshed one.
This commit is contained in:
Semyon Proshev
2017-12-18 19:34:05 +03:00
parent e207dcd063
commit 32d1620185
20 changed files with 57 additions and 2011 deletions
-298
View File
@@ -1,298 +0,0 @@
"""Skeleton for 're' stdlib module."""
def compile(pattern, flags=0):
"""Compile a regular expression pattern, returning a pattern object.
:type pattern: bytes | unicode
:type flags: int
:rtype: __Regex
"""
pass
def search(pattern, string, flags=0):
"""Scan through string looking for a match, and return a corresponding
match instance. Return None if no position in the string matches.
:type pattern: bytes | unicode | __Regex
:type string: T <= bytes | unicode
:type flags: int
:rtype: __Match[T] | None
"""
pass
def match(pattern, string, flags=0):
"""Matches zero or more characters at the beginning of the string.
:type pattern: bytes | unicode | __Regex
:type string: T <= bytes | unicode
:type flags: int
:rtype: __Match[T] | None
"""
pass
def fullmatch(pattern, string, flags=0):
"""Matches the whole string.
:type pattern: bytes | unicode | __Regex
:type string: T <= bytes | unicode
:type flags: int
:rtype: __Match[T] | None
"""
pass
def split(pattern, string, maxsplit=0, flags=0):
"""Split string by the occurrences of pattern.
:type pattern: bytes | unicode | __Regex
:type string: T <= bytes | unicode
:type maxsplit: int
:type flags: int
:rtype: list[T]
"""
pass
def findall(pattern, string, flags=0):
"""Return a list of all non-overlapping matches of pattern in string.
:type pattern: bytes | unicode | __Regex
:type string: T <= bytes | unicode
:type flags: int
:rtype: list[T]
"""
pass
def finditer(pattern, string, flags=0):
"""Return an iterator over all non-overlapping matches for the pattern in
string. For each match, the iterator returns a match object.
:type pattern: bytes | unicode | __Regex
:type string: T <= bytes | unicode
:type flags: int
:rtype: collections.Iterable[__Match[T]]
"""
pass
def sub(pattern, repl, string, count=0, flags=0):
"""Return the string obtained by replacing the leftmost non-overlapping
occurrences of pattern in string by the replacement repl.
:type pattern: bytes | unicode | __Regex
:type repl: bytes | unicode | collections.Callable
:type string: T <= bytes | unicode
:type count: int
:type flags: int
:rtype: T
"""
pass
def subn(pattern, repl, string, count=0, flags=0):
"""Return the tuple (new_string, number_of_subs_made) found by replacing
the leftmost non-overlapping occurrences of pattern with the
replacement repl.
:type pattern: bytes | unicode | __Regex
:type repl: bytes | unicode | collections.Callable
:type string: T <= bytes | unicode
:type count: int
:type flags: int
:rtype: (T, int)
"""
pass
def escape(string):
"""Escape all the characters in pattern except ASCII letters and numbers.
:type string: T <= bytes | unicode
:type: T
"""
pass
class __Regex(object):
"""Mock class for a regular expression pattern object."""
def __init__(self, flags, groups, groupindex, pattern):
"""Create a new pattern object.
:type flags: int
:type groups: int
:type groupindex: dict[bytes | unicode, int]
:type pattern: bytes | unicode
"""
self.flags = flags
self.groups = groups
self.groupindex = groupindex
self.pattern = pattern
def search(self, string, pos=0, endpos=-1):
"""Scan through string looking for a match, and return a corresponding
match instance. Return None if no position in the string matches.
:type string: T <= bytes | unicode
:type pos: int
:type endpos: int
:rtype: __Match[T] | None
"""
pass
def match(self, string, pos=0, endpos=-1):
"""Matches zero | more characters at the beginning of the string.
:type string: T <= bytes | unicode
:type pos: int
:type endpos: int
:rtype: __Match[T] | None
"""
pass
def fullmatch(self, string, pos=0, endpos=-1):
"""Matches the whole string.
:type string: T <= bytes | unicode
:type pos: int
:type endpos: int
:rtype: __Match[T] | None
"""
pass
def split(self, string, maxsplit=0):
"""Split string by the occurrences of pattern.
:type string: T <= bytes | unicode
:type maxsplit: int
:rtype: list[T]
"""
pass
def findall(self, string, pos=0, endpos=-1):
"""Return a list of all non-overlapping matches of pattern in string.
:type string: T <= bytes | unicode
:type pos: int
:type endpos: int
:rtype: list[T]
"""
pass
def finditer(self, string, pos=0, endpos=-1):
"""Return an iterator over all non-overlapping matches for the
pattern in string. For each match, the iterator returns a
match object.
:type string: T <= bytes | unicode
:type pos: int
:type endpos: int
:rtype: collections.Iterable[__Match[T]]
"""
pass
def sub(self, repl, string, count=0):
"""Return the string obtained by replacing the leftmost non-overlapping
occurrences of pattern in string by the replacement repl.
:type repl: bytes | unicode | collections.Callable
:type string: T <= bytes | unicode
:type count: int
:rtype: T
"""
pass
def subn(self, repl, string, count=0):
"""Return the tuple (new_string, number_of_subs_made) found by replacing
the leftmost non-overlapping occurrences of pattern with the
replacement repl.
:type repl: bytes | unicode | collections.Callable
:type string: T <= bytes | unicode
:type count: int
:rtype: (T, int)
"""
pass
class __Match(object):
"""Mock class for a match object."""
def __init__(self, pos, endpos, lastindex, lastgroup, re, string):
"""Create a new match object.
:type pos: int
:type endpos: int
:type lastindex: int | None
:type lastgroup: int | bytes | unicode | None
:type re: __Regex
:type string: bytes | unicode
:rtype: __Match[T]
"""
self.pos = pos
self.endpos = endpos
self.lastindex = lastindex
self.lastgroup = lastgroup
self.re = re
self.string = string
def expand(self, template):
"""Return the string obtained by doing backslash substitution on the
template string template.
:type template: T
:rtype: T
"""
pass
def group(self, *args):
"""Return one or more subgroups of the match.
:rtype: T | tuple
"""
pass
def groups(self, default=None):
"""Return a tuple containing all the subgroups of the match, from 1 up
to however many groups are in the pattern.
:rtype: tuple
"""
pass
def groupdict(self, default=None):
"""Return a dictionary containing all the named subgroups of the match,
keyed by the subgroup name.
:rtype: dict[bytes | unicode, T]
"""
pass
def start(self, group=0):
"""Return the index of the start of the substring matched by group.
:type group: int | bytes | unicode
:rtype: int
"""
pass
def end(self, group=0):
"""Return the index of the end of the substring matched by group.
:type group: int | bytes | unicode
:rtype: int
"""
pass
def span(self, group=0):
"""Return a 2-tuple (start, end) for the substring matched by group.
:type group: int | bytes | unicode
:rtype: (int, int)
"""
pass
@@ -141,7 +141,7 @@ public class PythonRegexpInjector implements MultiHostInjector {
private RegexpMethodDescriptor findRegexpMethodDescriptor(@Nullable PsiElement element) {
if (element == null ||
!(ScopeUtil.getScopeOwner(element) instanceof PyFile) ||
!element.getContainingFile().getName().equals("re.py") ||
!ArrayUtil.contains(element.getContainingFile().getName(), "re.py", "re.pyi") ||
!(element instanceof PyFunction)) {
return null;
}
@@ -41,7 +41,7 @@ import java.io.File
object PyTypeShed {
private val ONLY_SUPPORTED_PY2_MINOR = 7
private val SUPPORTED_PY3_MINORS = 2..7
val WHITE_LIST = setOf(TYPING, "six", "__builtin__", "builtins", "exceptions", "types", "datetime", "functools", "shutil")
val WHITE_LIST = setOf(TYPING, "six", "__builtin__", "builtins", "exceptions", "types", "datetime", "functools", "shutil", "re")
private val BLACK_LIST = setOf<String>()
/**
@@ -83,7 +83,7 @@ fun resolveQualifiedName(name: QualifiedName, context: PyQualifiedNameResolveCon
resultsFromRoots(name, context),
relativeResultsFromSkeletons(name, context)).flatten().distinct()
val allResults = pythonResults + foreignResults
val results = if (name.componentCount > 0) findFirstResults(pythonResults) + foreignResults else allResults
val results = if (name.componentCount > 0) findFirstResults(pythonResults, context.module) + foreignResults else allResults
if (mayCache) {
cache?.put(key, results)
@@ -207,15 +207,25 @@ fun relativeResultsForStubsFromRoots(name: QualifiedName, context: PyQualifiedNa
/**
* Filters the results according to their import priority in sys.path.
*/
private fun findFirstResults(results: List<PsiElement>) =
private fun findFirstResults(results: List<PsiElement>, module: Module?) =
if (results.all(::isNamespacePackage))
results
else {
val result = results.firstOrNull { !isNamespacePackage(it) }
val stubFile = results.firstOrNull { it is PyiFile || PyUtil.turnDirIntoInit(it) is PyiFile }
if (stubFile != null)
listOf(stubFile)
else
listOfNotNull(results.firstOrNull { !isNamespacePackage(it) })
val resultVFile = (result as? PsiFileSystemItem)?.virtualFile
val stubVFile = (stubFile as? PsiFileSystemItem)?.virtualFile
if (stubFile == null ||
module != null &&
stubVFile != null && PyTypeShed.isInside(stubVFile) &&
resultVFile != null && ModuleUtilCore.moduleContainsFile(module, resultVFile, false)) {
listOfNotNull(result)
}
else {
listOfNotNull(stubFile)
}
}
private fun isNamespacePackage(element: PsiElement): Boolean {
@@ -1,4 +0,0 @@
class date(object):
@classmethod
def today(cls):
return date(0, 0, 0)
File diff suppressed because it is too large Load Diff
@@ -199,7 +199,6 @@ public class Py3CompletionTest extends PyTestCase {
// PY-21060
public void testGenericTypeInheritor() {
myFixture.copyDirectoryToProject("../typing", "");
runWithLanguageLevel(LanguageLevel.PYTHON35, this::doTest);
}
@@ -359,7 +359,6 @@ public class Py3ResolveTest extends PyResolveTestCase {
// PY-20864
public void testTopLevelVariableAnnotationFromTyping() {
myFixture.copyDirectoryToProject("typing", "");
runWithLanguageLevel(LanguageLevel.PYTHON36, () -> assertResolvesTo(PyElement.class, "List"));
}
@@ -70,7 +70,6 @@ public class Py3TypeTest extends PyTestCase {
}
public void testYieldFromHomogeneousTuple() {
myFixture.copyDirectoryToProject("typing", "");
doTest("str",
"import typing\n"+
"def get_tuple() -> typing.Tuple[str, ...]:\n" +
@@ -82,7 +81,6 @@ public class Py3TypeTest extends PyTestCase {
}
public void testYieldFromHeterogeneousTuple() {
myFixture.copyDirectoryToProject("typing", "");
doTest("Union[int, str]",
"import typing\n" +
"def get_tuple() -> typing.Tuple[int, int, str]:\n" +
@@ -93,7 +93,6 @@ public class PyOptimizeImportsTest extends PyTestCase {
// PY-18521
public void testImportsFromTypingUnusedInTypeComments() {
myFixture.copyDirectoryToProject("../typing", "");
doTest();
}
@@ -439,8 +439,6 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
// PY-22005
public void testWithSpecifiedType() {
myFixture.copyDirectoryToProject("typing", "");
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
@@ -462,8 +460,6 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
// PY-22004
public void testMultiResolved() {
myFixture.copyDirectoryToProject("typing", "");
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
@@ -479,8 +475,6 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
}
public void testOverloadsInImportedClass() {
myFixture.copyDirectoryToProject("typing", "");
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
@@ -496,8 +490,6 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
}
public void testOverloadsInImportedModule() {
myFixture.copyDirectoryToProject("typing", "");
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
@@ -512,8 +504,6 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
}
public void testOverloadsWithDifferentNumberOfArgumentsInImportedClass() {
myFixture.copyDirectoryToProject("typing", "");
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
@@ -529,8 +519,6 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
}
public void testOverloadsWithDifferentNumberOfArgumentsInImportedModule() {
myFixture.copyDirectoryToProject("typing", "");
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
@@ -21,12 +21,14 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.testFramework.LightProjectDescriptor;
import com.jetbrains.python.codeInsight.regexp.PythonRegexpParserDefinition;
import com.jetbrains.python.codeInsight.regexp.PythonVerboseRegexpLanguage;
import com.jetbrains.python.codeInsight.regexp.PythonVerboseRegexpParserDefinition;
import com.jetbrains.python.fixtures.PyLexerTestCase;
import com.jetbrains.python.fixtures.PyTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -187,6 +189,12 @@ public class PyRegexpTest extends PyTestCase {
"\\w+");
}
@Nullable
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return getName().equals("testFullmatch") ? ourPy3Descriptor : super.getProjectDescriptor();
}
@NotNull
private PsiElement doTestInjectedText(@NotNull String text, @NotNull String expected) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
@@ -908,16 +908,12 @@ public class PyTypeTest extends PyTestCase {
public void testHomogeneousTupleSubstitution() {
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
myFixture.copyDirectoryToProject("typing", "");
doTest("Tuple[int, ...]",
"from typing import TypeVar, Tuple\n" +
"T = TypeVar('T')\n" +
"def foo(i: T) -> Tuple[T, ...]:\n" +
" pass\n" +
"expr = foo(5)");
}
() -> doTest("Tuple[int, ...]",
"from typing import TypeVar, Tuple\n" +
"T = TypeVar('T')\n" +
"def foo(i: T) -> Tuple[T, ...]:\n" +
" pass\n" +
"expr = foo(5)")
);
}
@@ -846,30 +846,32 @@ public class PyTypingTest extends PyTestCase {
}
public void testAsyncGeneratorAnnotation() {
runWithLanguageLevel(LanguageLevel.PYTHON36, () -> {
doTest("AsyncGenerator[int, str]",
"from typing import AsyncGenerator\n" +
"\n" +
"async def g() -> AsyncGenerator[int, str]:\n" +
" s = (yield 42)\n" +
" \n" +
"expr = g()");
});
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("AsyncGenerator[int, str]",
"from typing import AsyncGenerator\n" +
"\n" +
"async def g() -> AsyncGenerator[int, str]:\n" +
" s = (yield 42)\n" +
" \n" +
"expr = g()")
);
}
public void testCoroutineReturnsGenerator() {
runWithLanguageLevel(LanguageLevel.PYTHON36, () -> {
doTest("Coroutine[Any, Any, Generator[int, Any, Any]]",
"from typing import Generator\n" +
"\n" +
"async def coroutine() -> Generator[int, Any, Any]:\n" +
" def gen():\n" +
" yield 42\n" +
" \n" +
" return gen()\n" +
" \n" +
"expr = coroutine()");
});
runWithLanguageLevel(
LanguageLevel.PYTHON36,
() -> doTest("Coroutine[Any, Any, Generator[int, Any, Any]]",
"from typing import Generator\n" +
"\n" +
"async def coroutine() -> Generator[int, Any, Any]:\n" +
" def gen():\n" +
" yield 42\n" +
" \n" +
" return gen()\n" +
" \n" +
"expr = coroutine()")
);
}
public void testGenericRenamedParameter() {
@@ -1329,7 +1331,6 @@ public class PyTypingTest extends PyTestCase {
}
private void doTest(@NotNull String expectedType, @NotNull String text) {
myFixture.copyDirectoryToProject("typing", "");
myFixture.configureByText(PythonFileType.INSTANCE, text);
final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
final TypeEvalContext codeAnalysis = TypeEvalContext.codeAnalysis(expr.getProject(), expr.getContainingFile());
@@ -1340,7 +1341,6 @@ public class PyTypingTest extends PyTestCase {
private void doMultiFileStubAwareTest(@NotNull final String expectedType, @NotNull final String text) {
myFixture.copyDirectoryToProject("types/" + getTestName(false), "");
myFixture.copyDirectoryToProject("typing", "");
myFixture.configureByText(PythonFileType.INSTANCE, text);
final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
@@ -84,7 +84,6 @@ public class Py3TypeCheckerInspectionTest extends PyInspectionTestCase {
// PY-18762
public void testHomogeneousTuples() {
myFixture.copyDirectoryToProject("typing/typing.py", TEST_DIRECTORY);
doTest();
}
@@ -122,14 +122,14 @@ public class Py3UnresolvedReferencesInspectionTest extends PyInspectionTestCase
for (PyClass cls : classes) {
final PsiFile file = cls.getContainingFile();
if (file instanceof PyFile) {
assertNotParsed((PyFile)file);
assertNotParsed(file);
}
}
}
// PY-9011
public void testDatetimeDateAttributesOutsideClass() {
doMultiFileTest("a.py");
doTest();
}
public void testObjectNewAttributes() {
@@ -157,7 +157,6 @@ public class Py3UnresolvedReferencesInspectionTest extends PyInspectionTestCase
// PY-17841
public void testTypingParameterizedTypeIndexing() {
myFixture.copyDirectoryToProject("typing", "");
doTest();
}
@@ -532,13 +532,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
// PY-18521
public void testFunctionTypeCommentUsesImportsFromTyping() {
myFixture.copyDirectoryToProject("typing", "");
runWithLanguageLevel(LanguageLevel.PYTHON30, this::doTest);
}
// PY-22620
public void testTupleTypeCommentsUseImportsFromTyping() {
myFixture.copyDirectoryToProject("typing", "");
doTest();
}
@@ -47,7 +47,6 @@ public class PyiInspectionsTest extends PyTestCase {
private void doTestByFileName(@NotNull Class<? extends LocalInspectionTool> inspectionClass, String fileName) {
myFixture.copyDirectoryToProject("pyi/inspections/" + getTestName(true), "");
myFixture.copyDirectoryToProject("typing", "");
PsiDocumentManager.getInstance(myFixture.getProject()).commitAllDocuments();
final PsiFile file = myFixture.configureByFile(fileName);
myFixture.enableInspections(inspectionClass);
@@ -81,7 +81,6 @@ public class PyiTypeTest extends PyTestCase {
private void doTest(@NotNull String expectedType) {
myFixture.copyDirectoryToProject("pyi/type/" + getTestName(true), "");
myFixture.copyDirectoryToProject("typing", "");
PsiDocumentManager.getInstance(myFixture.getProject()).commitAllDocuments();
final String fileName = getTestName(false) + ".py";
myFixture.configureByFile(fileName);