From 87bf9386d3df75064e0bb2d2c99aad1b9c7a3513 Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Mon, 26 Sep 2016 15:17:15 +0300 Subject: [PATCH] PY-20880 Fixed: Package requirements inspection does not support local version identifiers Update matching EQ version spec: if both versions contain local label, check if they are equals as strings; if only passed version contains local label, then just drop it and check public parts. --- .../requirement/PyRequirementVersionSpec.java | 18 +++++++++++++++++- .../python/packaging/PyRequirementTest.java | 18 ++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/python/openapi/src/com/jetbrains/python/packaging/requirement/PyRequirementVersionSpec.java b/python/openapi/src/com/jetbrains/python/packaging/requirement/PyRequirementVersionSpec.java index 62f6afa43a93..8dadd784a895 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/requirement/PyRequirementVersionSpec.java +++ b/python/openapi/src/com/jetbrains/python/packaging/requirement/PyRequirementVersionSpec.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.packaging.requirement; +import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import static com.intellij.webcore.packaging.PackageVersionComparator.VERSION_COMPARATOR; @@ -72,7 +73,13 @@ public class PyRequirementVersionSpec { case GTE: return VERSION_COMPARATOR.compare(version, myVersion) >= 0; case EQ: - return VERSION_COMPARATOR.compare(version, myVersion) == 0; + final Pair publicAndLocalVersions = splitIntoPublicAndLocalVersions(myVersion); + final Pair otherPublicAndLocalVersions = splitIntoPublicAndLocalVersions(version); + final boolean publicVersionsAreSame = + VERSION_COMPARATOR.compare(otherPublicAndLocalVersions.first, publicAndLocalVersions.first) == 0; + + return publicVersionsAreSame && + (publicAndLocalVersions.second.isEmpty() || otherPublicAndLocalVersions.second.equals(publicAndLocalVersions.second)); case NE: return VERSION_COMPARATOR.compare(version, myVersion) != 0; case COMPATIBLE: @@ -83,4 +90,13 @@ public class PyRequirementVersionSpec { return false; } } + + private static Pair splitIntoPublicAndLocalVersions(@NotNull String version) { + final String[] publicAndLocalVersions = version.split("\\+", 2); + + final String publicVersion = publicAndLocalVersions[0]; + final String localVersion = publicAndLocalVersions.length == 1 ? "" : publicAndLocalVersions[1]; + + return Pair.createNonNull(publicVersion, localVersion); + } } diff --git a/python/testSrc/com/jetbrains/python/packaging/PyRequirementTest.java b/python/testSrc/com/jetbrains/python/packaging/PyRequirementTest.java index 1a23db81b251..867fd96d95ca 100644 --- a/python/testSrc/com/jetbrains/python/packaging/PyRequirementTest.java +++ b/python/testSrc/com/jetbrains/python/packaging/PyRequirementTest.java @@ -2220,7 +2220,7 @@ public class PyRequirementTest extends PyTestCase { // PY-6355 public void testTrailingZeroesInVersion() { final PyRequirement req = PyRequirement.fromLine("foo==0.8.0"); - final PyPackage pkg = new PyPackage("foo", "0.8", null, Collections.emptyList()); + final PyPackage pkg = new PyPackage("foo", "0.8", null, Collections.emptyList()); assertNotNull(req); assertEquals(pkg, req.match(Collections.singletonList(pkg))); } @@ -2228,7 +2228,7 @@ public class PyRequirementTest extends PyTestCase { // PY-6438 public void testUnderscoreMatchesDash() { final PyRequirement req = PyRequirement.fromLine("pyramid_zcml"); - final PyPackage pkg = new PyPackage("pyramid-zcml", "0.1", null, Collections.emptyList()); + final PyPackage pkg = new PyPackage("pyramid-zcml", "0.1", null, Collections.emptyList()); assertNotNull(req); assertEquals(pkg, req.match(Collections.singletonList(pkg))); } @@ -2241,6 +2241,20 @@ public class PyRequirementTest extends PyTestCase { assertEquals(pkg, req.match(Collections.singletonList(pkg))); } + // PY-20880 + public void testMatchingLocalVersions() { + final PyPackage firstPackageWithLocalVersion = new PyPackage("foo", "1.0+foo0100", null, Collections.emptyList()); + final PyPackage secondPackageWithLocalVersion = new PyPackage("foo", "1.0+foo0101", null, Collections.emptyList()); + + final PyRequirement requirement = PyRequirement.fromLine("foo==1.0"); + assertEquals(firstPackageWithLocalVersion, requirement.match(Collections.singletonList(firstPackageWithLocalVersion))); + assertEquals(secondPackageWithLocalVersion, requirement.match(Collections.singletonList(secondPackageWithLocalVersion))); + + final PyRequirement requirementWithLocalVersion = PyRequirement.fromLine("foo==1.0+foo0100"); + assertEquals(firstPackageWithLocalVersion, requirementWithLocalVersion.match(Collections.singletonList(firstPackageWithLocalVersion))); + assertNull(requirementWithLocalVersion.match(Collections.singletonList(secondPackageWithLocalVersion))); + } + // OPTIONS public void testOptions() { assertEmpty(