From 9c0ecff67e32fcf930aa73d277949c68e8642a9d Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Wed, 17 Feb 2016 15:27:56 +0300 Subject: [PATCH] PY-18322 Fixed: PyCharm cannot detect obvious unresolved method Correctly determine openFunctionType in Python 2. Update read and write types of builtin file in skeletons --- .../helpers/python-skeletons/__builtin__.py | 14 +++++----- .../stdlib/PyStdlibTypeProvider.java | 27 +++++++++---------- .../{bytesIORead.py => bytesIOMethods.py} | 0 .../fileMethods.py | 7 +++++ .../com/jetbrains/python/PyTypeTest.java | 6 ++--- .../PyUnresolvedReferencesInspectionTest.java | 7 ++++- 6 files changed, 36 insertions(+), 25 deletions(-) rename python/testData/inspections/PyUnresolvedReferencesInspection/{bytesIORead.py => bytesIOMethods.py} (100%) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/fileMethods.py diff --git a/python/helpers/python-skeletons/__builtin__.py b/python/helpers/python-skeletons/__builtin__.py index d9f63538c4d9..95ace39a878a 100644 --- a/python/helpers/python-skeletons/__builtin__.py +++ b/python/helpers/python-skeletons/__builtin__.py @@ -2390,7 +2390,7 @@ class file(object): def next(self): """Returns the next input line. - :rtype: bytes | unicode + :rtype: bytes """ return '' @@ -2399,7 +2399,7 @@ class file(object): before obtaining size bytes). :type size: numbers.Integral - :rtype: bytes | unicode + :rtype: bytes """ return '' @@ -2407,7 +2407,7 @@ class file(object): """Read one entire line from the file. :type size: numbers.Integral - :rtype: bytes | unicode + :rtype: bytes """ return '' @@ -2416,14 +2416,14 @@ class file(object): lines thus read. :type sizehint: numbers.Integral - :rtype: list[bytes | unicode] + :rtype: list[bytes] """ return [] def xreadlines(self): """This method returns the same thing as iter(f). - :rtype: collections.Iterable[bytes | unicode] + :rtype: collections.Iterable[bytes] """ return [] @@ -2454,7 +2454,7 @@ class file(object): def write(self, str): """"Write a string to the file. - :type str: bytes | unicode + :type str: bytes :rtype: None """ pass @@ -2462,7 +2462,7 @@ class file(object): def writelines(self, sequence): """Write a sequence of strings to the file. - :type sequence: collections.Iterable[bytes | unicode] + :type sequence: collections.Iterable[bytes] :rtype: None """ pass diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java index b7a3c49c3bf4..ec08ba2ab102 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,8 +44,10 @@ import static com.jetbrains.python.psi.PyUtil.as; public class PyStdlibTypeProvider extends PyTypeProviderBase { private static final Set OPEN_FUNCTIONS = ImmutableSet.of("__builtin__.open", "io.open", "os.fdopen", "pathlib.Path.open"); - private static final String BINARY_FILE_TYPE = "io.FileIO[bytes]"; - private static final String TEXT_FILE_TYPE = "io.TextIOWrapper[unicode]"; + + private static final String PY2K_FILE_TYPE = "file"; + private static final String PY3K_BINARY_FILE_TYPE = "io.FileIO[bytes]"; + private static final String PY3K_TEXT_FILE_TYPE = "io.TextIOWrapper[unicode]"; @Nullable public static PyStdlibTypeProvider getInstance() { @@ -275,19 +277,16 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase { } } final LanguageLevel level = LanguageLevel.forElement(anchor); - // Binary mode - if (mode.contains("b")) { - return PyTypeParser.getTypeByName(anchor, BINARY_FILE_TYPE); - } - // Text mode - else { - if (level.isPy3K() || "io.open".equals(callQName)) { - return PyTypeParser.getTypeByName(anchor, TEXT_FILE_TYPE); - } - else { - return PyTypeParser.getTypeByName(anchor, BINARY_FILE_TYPE); + + if (level.isPy3K() || "io.open".equals(callQName)) { + if (mode.contains("b")) { + return PyTypeParser.getTypeByName(anchor, PY3K_BINARY_FILE_TYPE); + } else { + return PyTypeParser.getTypeByName(anchor, PY3K_TEXT_FILE_TYPE); } } + + return PyTypeParser.getTypeByName(anchor, PY2K_FILE_TYPE); } @Nullable diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/bytesIORead.py b/python/testData/inspections/PyUnresolvedReferencesInspection/bytesIOMethods.py similarity index 100% rename from python/testData/inspections/PyUnresolvedReferencesInspection/bytesIORead.py rename to python/testData/inspections/PyUnresolvedReferencesInspection/bytesIOMethods.py diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/fileMethods.py b/python/testData/inspections/PyUnresolvedReferencesInspection/fileMethods.py new file mode 100644 index 000000000000..8f69c667fa99 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/fileMethods.py @@ -0,0 +1,7 @@ +f = open("file.txt") +f.writelines("a") # OK +f.writeliness("a") + +f = open("file.txt", "rb") +f.writelines("a") # OK +f.writeliness("a") \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java index 93e2973b1933..247e1da55543 100644 --- a/python/testSrc/com/jetbrains/python/PyTypeTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java @@ -694,17 +694,17 @@ public class PyTypeTest extends PyTestCase { } public void testOpenDefault() { - doTest("FileIO[str]", + doTest("file", "expr = open('foo')\n"); } public void testOpenText() { - doTest("FileIO[str]", + doTest("file", "expr = open('foo', 'r')\n"); } public void testOpenBinary() { - doTest("FileIO[str]", + doTest("file", "expr = open('foo', 'rb')\n"); } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index 9f979def0fd4..a79347e74771 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -348,7 +348,12 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doMultiFileTest("a.py"); } - public void testBytesIORead() { + public void testBytesIOMethods() { + doTest(); + } + + // PY-18322 + public void testFileMethods() { doTest(); }