diff --git a/python/testData/packaging/PyPackageUtil/AbsentRequirementsTxtReading/script.py b/python/testData/packaging/PyPackageUtil/AbsentRequirementsTxtReading/script.py new file mode 100644 index 000000000000..2fa1fc2410cb --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/AbsentRequirementsTxtReading/script.py @@ -0,0 +1 @@ +print("abc") \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/AbsentRequirementsTxtUpdating/script.py b/python/testData/packaging/PyPackageUtil/AbsentRequirementsTxtUpdating/script.py new file mode 100644 index 000000000000..2fa1fc2410cb --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/AbsentRequirementsTxtUpdating/script.py @@ -0,0 +1 @@ +print("abc") \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/AbsentSetupCallReading/setup.py b/python/testData/packaging/PyPackageUtil/AbsentSetupCallReading/setup.py new file mode 100644 index 000000000000..c7a82bcc02fd --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/AbsentSetupCallReading/setup.py @@ -0,0 +1 @@ +from distutils.core import setup \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/AbsentSetupCallUpdating/setup.py b/python/testData/packaging/PyPackageUtil/AbsentSetupCallUpdating/setup.py new file mode 100644 index 000000000000..c7a82bcc02fd --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/AbsentSetupCallUpdating/setup.py @@ -0,0 +1 @@ +from distutils.core import setup \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/AbsentSetupPyReading/script.py b/python/testData/packaging/PyPackageUtil/AbsentSetupPyReading/script.py new file mode 100644 index 000000000000..2fa1fc2410cb --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/AbsentSetupPyReading/script.py @@ -0,0 +1 @@ +print("abc") \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/AbsentSetupPyRequiresReading/setup.py b/python/testData/packaging/PyPackageUtil/AbsentSetupPyRequiresReading/setup.py new file mode 100644 index 000000000000..12c97a91b0c7 --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/AbsentSetupPyRequiresReading/setup.py @@ -0,0 +1,4 @@ +from distutils.core import setup + +setup(name='foo', + version=0.1) \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/AbsentSetupPyUpdating/script.py b/python/testData/packaging/PyPackageUtil/AbsentSetupPyUpdating/script.py new file mode 100644 index 000000000000..2fa1fc2410cb --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/AbsentSetupPyUpdating/script.py @@ -0,0 +1 @@ +print("abc") \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/DistutilsSetupPyUpdating/setup.py b/python/testData/packaging/PyPackageUtil/DistutilsSetupPyUpdating/setup.py new file mode 100644 index 000000000000..ed67fc1af868 --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/DistutilsSetupPyUpdating/setup.py @@ -0,0 +1,12 @@ +from distutils.core import setup + +tests_require = [ + 'mynose' +] + +setup(name='foo', + version=0.1, + tests_require=tests_require, + setup_requires=[ + 'numpy' + ]) \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/EmptyRequirementsTxtReading/requirements.txt b/python/testData/packaging/PyPackageUtil/EmptyRequirementsTxtReading/requirements.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/packaging/PyPackageUtil/RequirementsTxtReading/requirements.txt b/python/testData/packaging/PyPackageUtil/RequirementsTxtReading/requirements.txt new file mode 100644 index 000000000000..4ab2a88c0efe --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/RequirementsTxtReading/requirements.txt @@ -0,0 +1,4 @@ +Markdown +NewDjango==1.3.1 +numpy +mynose \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/RequirementsTxtUpdating/requirements.txt b/python/testData/packaging/PyPackageUtil/RequirementsTxtUpdating/requirements.txt new file mode 100644 index 000000000000..3937b1de95f3 --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/RequirementsTxtUpdating/requirements.txt @@ -0,0 +1,3 @@ +NewDjango==1.3.1 +numpy +mynose \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/SetupPyReading/setup.py b/python/testData/packaging/PyPackageUtil/SetupPyReading/setup.py new file mode 100644 index 000000000000..a3dd5ebdd87d --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/SetupPyReading/setup.py @@ -0,0 +1,18 @@ +from distutils.core import setup + +tests_require = [ + 'mynose' +] + +setup(name='foo', + version=0.1, + requires=[ + 'Markdown', + ], + install_requires=[ + 'NewDjango==1.3.1', + ], + tests_require=tests_require, + setup_requires=[ + 'numpy' + ]) \ No newline at end of file diff --git a/python/testData/packaging/PyPackageUtil/SetuptoolsSetupPyUpdating/setup.py b/python/testData/packaging/PyPackageUtil/SetuptoolsSetupPyUpdating/setup.py new file mode 100644 index 000000000000..6ea376a6125d --- /dev/null +++ b/python/testData/packaging/PyPackageUtil/SetuptoolsSetupPyUpdating/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup + +tests_require = [ + 'mynose' +] + +setup(name='foo', + version=0.1, + tests_require=tests_require, + setup_requires=[ + 'numpy' + ]) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/packaging/PyPackageUtilTest.java b/python/testSrc/com/jetbrains/python/packaging/PyPackageUtilTest.java new file mode 100644 index 000000000000..d57afce0ddaa --- /dev/null +++ b/python/testSrc/com/jetbrains/python/packaging/PyPackageUtilTest.java @@ -0,0 +1,217 @@ +/* + * 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.packaging; + +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.module.Module; +import com.jetbrains.python.fixtures.PyTestCase; +import com.jetbrains.python.psi.LanguageLevel; +import com.jetbrains.python.psi.PyCallExpression; +import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.PyFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class PyPackageUtilTest extends PyTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + + myFixture.copyDirectoryToProject("packaging/PyPackageUtil/" + getTestName(false), ""); + } + + public void testAbsentSetupPyReading() { + doTestSetupPyReading(false, false, false); + } + + public void testAbsentSetupCallReading() { + doTestSetupPyReading(true, false, false); + } + + public void testAbsentSetupPyRequiresReading() { + doTestSetupPyReading(true, true, false); + } + + public void testSetupPyReading() { + doTestSetupPyReading(true, true, true); + } + + public void testAbsentRequirementsTxtReading() { + doTestRequirementsTxtReading(false, false); + } + + public void testEmptyRequirementsTxtReading() { + doTestRequirementsTxtReading(true, false); + } + + public void testRequirementsTxtReading() { + doTestRequirementsTxtReading(true, true); + } + + public void testAbsentSetupPyUpdating() { + doTestUselessRequirementsTxtOrSetupPyUpdating(false); + } + + public void testAbsentSetupCallUpdating() { + doTestUselessRequirementsTxtOrSetupPyUpdating(false); + } + + public void testDistutilsSetupPyUpdating() { + doTestSetupPyUpdating("requires"); + } + + public void testSetuptoolsSetupPyUpdating() { + doTestSetupPyUpdating("install_requires"); + } + + public void testAbsentRequirementsTxtUpdating() { + doTestUselessRequirementsTxtOrSetupPyUpdating(true); + } + + public void testRequirementsTxtUpdating() { + final Module module = myFixture.getModule(); + + checkRequirements(PyPackageUtil.getRequirementsFromTxt(module), 1); + + WriteCommandAction.runWriteCommandAction(myFixture.getProject(), + () -> PyPackageUtil.addRequirementToTxtOrSetupPy(module, "Markdown", LanguageLevel.PYTHON30)); + + checkRequirements(PyPackageUtil.getRequirementsFromTxt(module)); + } + + private void doTestSetupPyReading(boolean hasFile, boolean hasCall, boolean requires) { + final Module module = myFixture.getModule(); + + if (hasFile) { + assertTrue(PyPackageUtil.hasSetupPy(module)); + + final PyFile setupPy = PyPackageUtil.findSetupPy(module); + assertNotNull(setupPy); + + if (hasCall) { + final PyCallExpression callByModule = PyPackageUtil.findSetupCall(module); + final PyCallExpression callByFile = PyPackageUtil.findSetupCall(setupPy); + + assertNotNull(callByModule); + assertNotNull(callByFile); + assertSame(callByFile, callByModule); + + if (requires) { + checkRequirements(PyPackageUtil.findSetupPyRequires(module)); + } + else { + final List requirements = PyPackageUtil.findSetupPyRequires(module); + assertNotNull(requirements); + assertEmpty(requirements); + } + } + else { + assertNull(PyPackageUtil.findSetupCall(module)); + assertNull(PyPackageUtil.findSetupCall(setupPy)); + assertNull(PyPackageUtil.findSetupPyRequires(module)); + } + } + else { + assertFalse(PyPackageUtil.hasSetupPy(module)); + assertNull(PyPackageUtil.findSetupPy(module)); + assertNull(PyPackageUtil.findSetupCall(module)); + assertNull(PyPackageUtil.findSetupPyRequires(module)); + } + } + + private void doTestRequirementsTxtReading(boolean hasFile, boolean hasRequirements) { + final Module module = myFixture.getModule(); + + if (hasFile) { + assertTrue(PyPackageUtil.hasRequirementsTxt(module)); + assertNotNull(PyPackageUtil.findRequirementsTxt(module)); + + if (hasRequirements) { + checkRequirements(PyPackageUtil.getRequirementsFromTxt(module)); + } + else { + final List requirements = PyPackageUtil.getRequirementsFromTxt(module); + assertNotNull(requirements); + assertEmpty(requirements); + } + } + else { + assertFalse(PyPackageUtil.hasRequirementsTxt(module)); + assertNull(PyPackageUtil.findRequirementsTxt(module)); + assertNull(PyPackageUtil.getRequirementsFromTxt(module)); + } + } + + private void doTestUselessRequirementsTxtOrSetupPyUpdating(boolean isRequirementsTxt) { + final Module module = myFixture.getModule(); + + assertNull(isRequirementsTxt ? PyPackageUtil.getRequirementsFromTxt(module) : PyPackageUtil.findSetupPyRequires(module)); + + WriteCommandAction.runWriteCommandAction(myFixture.getProject(), + () -> PyPackageUtil.addRequirementToTxtOrSetupPy(module, "Markdown", LanguageLevel.PYTHON30)); + + assertNull(isRequirementsTxt ? PyPackageUtil.getRequirementsFromTxt(module) : PyPackageUtil.findSetupPyRequires(module)); + } + + private static void checkRequirements(@Nullable List actual) { + checkRequirements(actual, 0); + } + + private static void checkRequirements(@Nullable List actual, int fromIndex) { + final List expected = PyRequirement.fromText("Markdown\nNewDjango==1.3.1\nnumpy\nmynose"); + assertEquals(expected.subList(fromIndex, expected.size()), actual); + } + + private void doTestSetupPyUpdating(@NotNull String keyword) { + final Module module = myFixture.getModule(); + + checkSetupArgumentText(module, keyword, null); + checkRequirements(PyPackageUtil.findSetupPyRequires(module), 2); + + final Runnable introduceRequires = () -> PyPackageUtil.addRequirementToTxtOrSetupPy(module, "NewDjango==1.3.1", LanguageLevel.PYTHON30); + WriteCommandAction.runWriteCommandAction(myFixture.getProject(), introduceRequires); + + checkSetupArgumentText(module, keyword, "['NewDjango==1.3.1']"); + checkRequirements(PyPackageUtil.findSetupPyRequires(module), 1); + + final Runnable updateRequires = () -> PyPackageUtil.addRequirementToTxtOrSetupPy(module, "Markdown", LanguageLevel.PYTHON30); + WriteCommandAction.runWriteCommandAction(myFixture.getProject(), updateRequires); + + checkSetupArgumentText(module, keyword, "['NewDjango==1.3.1', 'Markdown']"); + + final List actual = PyPackageUtil.findSetupPyRequires(module); + final List expected = PyRequirement.fromText("NewDjango==1.3.1\nMarkdown\nnumpy\nmynose"); + assertEquals(expected, actual); + } + + private static void checkSetupArgumentText(@NotNull Module module, @NotNull String keyword, @Nullable String text) { + final PyCallExpression setupCall = PyPackageUtil.findSetupCall(module); + assertNotNull(setupCall); + + final PyExpression argument = setupCall.getKeywordArgument(keyword); + + if (text == null) { + assertNull(argument); + } + else { + assertNotNull(argument); + assertEquals(text, argument.getText()); + } + } +} \ No newline at end of file