diff --git a/python/helpers/python-skeletons/os/__init__.py b/python/helpers/python-skeletons/os/__init__.py index 3d8867d67d98..693818ce40e1 100644 --- a/python/helpers/python-skeletons/os/__init__.py +++ b/python/helpers/python-skeletons/os/__init__.py @@ -2,6 +2,9 @@ from __future__ import unicode_literals +import io +import os +import subprocess import sys @@ -311,11 +314,44 @@ def popen(command, mode='r', bufsize=-1): :type command: string :type mode: string :type bufsize: int - :rtype: io.FileIO[bytes] + :rtype: os._wrap_close """ pass +class _wrap_close: + def __init__(self, stream, proc): + """ + :type stream: io.TextIOWrapper[unicode] + :type proc: subprocess.Popen + """ + pass + + def close(self): + """ + :rtype: int | None + """ + pass + + def __enter__(self): + """ + :rtype: os._wrap_close + """ + pass + + def __exit__(self, *args): + pass + + def __getattr__(self, name): + pass + + def __iter__(self): + """ + :rtype: collections.Iterator[unicode] + """ + pass + + def tmpfile(): """Return a new file object opened in update mode (w+b). diff --git a/python/testData/inspections/PyNoneFunctionAssignmentInspection/OsPopenClose/a.py b/python/testData/inspections/PyNoneFunctionAssignmentInspection/OsPopenClose/a.py new file mode 100644 index 000000000000..d46a5cac74a6 --- /dev/null +++ b/python/testData/inspections/PyNoneFunctionAssignmentInspection/OsPopenClose/a.py @@ -0,0 +1,2 @@ +from os import popen +ret = popen("non-existent-command").close() \ No newline at end of file diff --git a/python/testData/inspections/PyNoneFunctionAssignmentInspection/OsPopenClose/os.py b/python/testData/inspections/PyNoneFunctionAssignmentInspection/OsPopenClose/os.py new file mode 100644 index 000000000000..be3e93c6ac47 --- /dev/null +++ b/python/testData/inspections/PyNoneFunctionAssignmentInspection/OsPopenClose/os.py @@ -0,0 +1,6 @@ +def popen(command, mode='r', bufsize=-1): + pass + +class _wrap_close: + def close(self): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/Py3NoneFunctionAssignmentInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/Py3NoneFunctionAssignmentInspectionTest.java new file mode 100644 index 000000000000..933729ffdb18 --- /dev/null +++ b/python/testSrc/com/jetbrains/python/inspections/Py3NoneFunctionAssignmentInspectionTest.java @@ -0,0 +1,41 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.inspections; + +import com.intellij.testFramework.LightProjectDescriptor; +import com.jetbrains.python.fixtures.PyTestCase; +import org.jetbrains.annotations.Nullable; + +public class Py3NoneFunctionAssignmentInspectionTest extends PyTestCase { + + @Nullable + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return ourPy3Descriptor; + } + + // PY-21040 + public void testOsPopenClose() { + doMultiFileTest(); + } + + private void doMultiFileTest() { + myFixture.copyDirectoryToProject("inspections/PyNoneFunctionAssignmentInspection/" + getTestName(false) + "/", ""); + myFixture.configureByFile("a.py"); + myFixture.enableInspections(PyNoneFunctionAssignmentInspection.class); + myFixture.checkHighlighting(false, false, true); + } +}