mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fix matching compatible and asterisk versions (PY-27076)
Use new package version comparator where possible
This commit is contained in:
@@ -299,6 +299,7 @@ public class PyRequirement {
|
||||
* @deprecated This method will be removed in 2018.2.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public PyRequirement withVersionComparator(@NotNull Comparator<String> comparator) {
|
||||
return new PyRequirement(myName,
|
||||
ContainerUtil.map(myVersionSpecs, spec -> spec.withVersionComparator(comparator)), myInstallOptions, myExtras);
|
||||
|
||||
+8
-4
@@ -129,8 +129,12 @@ public class PyRequirementVersionSpec {
|
||||
case COMPATIBLE:
|
||||
Objects.requireNonNull(myParsedVersion);
|
||||
|
||||
return new PyRequirementVersionSpec(PyRequirementRelation.GTE, myParsedVersion).matches(version) &&
|
||||
new PyRequirementVersionSpec(PyRequirementRelation.EQ, toEqPartOfCompatibleRelation(myParsedVersion)).matches(version);
|
||||
return new PyRequirementVersionSpec(PyRequirementRelation.GTE, myParsedVersion)
|
||||
.withVersionComparator(myVersionComparator)
|
||||
.matches(version) &&
|
||||
new PyRequirementVersionSpec(PyRequirementRelation.EQ, toEqPartOfCompatibleRelation(myParsedVersion))
|
||||
.withVersionComparator(myVersionComparator)
|
||||
.matches(version);
|
||||
case STR_EQ:
|
||||
return version.equals(myVersion);
|
||||
default:
|
||||
@@ -159,10 +163,10 @@ public class PyRequirementVersionSpec {
|
||||
@NotNull
|
||||
private static PyRequirementVersion toEqPartOfCompatibleRelation(@NotNull PyRequirementVersion version) {
|
||||
final String release = version.getRelease();
|
||||
final int lastPoint = release.lastIndexOf(".");
|
||||
final int lastPoint = release.lastIndexOf('.');
|
||||
|
||||
if (lastPoint == -1) return version;
|
||||
|
||||
return new PyRequirementVersion(version.getEpoch(), release.substring(0, lastPoint) + "*", null, null, null, null);
|
||||
return new PyRequirementVersion(version.getEpoch(), release.substring(0, lastPoint + 1) + "*", null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl {
|
||||
if (fields.size() >= 4) {
|
||||
final String requiresLine = fields.get(3);
|
||||
final String requiresSpec = StringUtil.join(StringUtil.split(requiresLine, ":"), "\n");
|
||||
requirements.addAll(PyRequirement.fromText(requiresSpec));
|
||||
requirements.addAll(PyPackageUtil.fix(PyRequirement.fromText(requiresSpec)));
|
||||
}
|
||||
if (!"Python".equals(name)) {
|
||||
packages.add(new PyPackage(name, version, "", requirements));
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.util.net.HttpConfigurable;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
@@ -356,8 +355,7 @@ public class PyPackageManagerImpl extends PyPackageManager {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<PyRequirement> parseRequirements(@NotNull String text) {
|
||||
return ContainerUtil.map(PyRequirement.fromText(text),
|
||||
req -> req.withVersionComparator(PyPackageVersionComparator.getSTR_COMPARATOR()));
|
||||
return PyPackageUtil.fix(PyRequirement.fromText(text));
|
||||
}
|
||||
|
||||
// public List<PyPackage> refreshAndGetPackagesIfNotInProgress(boolean alwaysRefresh) throws ExecutionException
|
||||
@@ -526,7 +524,7 @@ public class PyPackageManagerImpl extends PyPackageManager {
|
||||
if (fields.size() >= 4) {
|
||||
final String requiresLine = fields.get(3);
|
||||
final String requiresSpec = StringUtil.join(StringUtil.split(requiresLine, ":"), "\n");
|
||||
requirements.addAll(PyRequirement.fromText(requiresSpec));
|
||||
requirements.addAll(PyPackageUtil.fix(PyRequirement.fromText(requiresSpec)));
|
||||
}
|
||||
if (!"Python".equals(name)) {
|
||||
packages.add(new PyPackage(name, version, location, requirements));
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
@@ -155,19 +156,39 @@ public class PyPackageUtil {
|
||||
private static List<PyRequirement> getSetupPyRequiresFromArguments(@NotNull Module module,
|
||||
@NotNull PyCallExpression setupCall,
|
||||
@NotNull String... argumentNames) {
|
||||
return PyRequirement.fromText(
|
||||
Stream
|
||||
.of(argumentNames)
|
||||
.map(setupCall::getKeywordArgument)
|
||||
.map(requires -> resolveRequiresValue(module, requires))
|
||||
.filter(requires -> requires != null)
|
||||
.flatMap(requires -> Stream.of(requires.getElements()))
|
||||
.filter(PyStringLiteralExpression.class::isInstance)
|
||||
.map(requirement -> ((PyStringLiteralExpression)requirement).getStringValue())
|
||||
.collect(Collectors.joining("\n"))
|
||||
return fix(
|
||||
PyRequirement.fromText(
|
||||
Stream
|
||||
.of(argumentNames)
|
||||
.map(setupCall::getKeywordArgument)
|
||||
.map(requires -> resolveRequiresValue(module, requires))
|
||||
.filter(requires -> requires != null)
|
||||
.flatMap(requires -> Stream.of(requires.getElements()))
|
||||
.filter(PyStringLiteralExpression.class::isInstance)
|
||||
.map(requirement -> ((PyStringLiteralExpression)requirement).getStringValue())
|
||||
.collect(Collectors.joining("\n"))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 2018.2.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public static PyRequirement fix(@NotNull PyRequirement requirement) {
|
||||
return requirement.withVersionComparator(PyPackageVersionComparator.getSTR_COMPARATOR());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 2018.2.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public static List<PyRequirement> fix(@NotNull List<PyRequirement> requirements) {
|
||||
return ContainerUtil.map(requirements, PyPackageUtil::fix);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyRequirement> mergeSetupPyRequirements(@NotNull List<PyRequirement> requirementsFromRequires,
|
||||
@NotNull List<PyRequirement> requirementsFromLinks) {
|
||||
@@ -363,7 +384,7 @@ public class PyPackageUtil {
|
||||
public static List<PyRequirement> getRequirementsFromTxt(@NotNull Module module) {
|
||||
final VirtualFile requirementsTxt = findRequirementsTxt(module);
|
||||
if (requirementsTxt != null) {
|
||||
return PyRequirement.fromFile(requirementsTxt);
|
||||
return fix(PyRequirement.fromFile(requirementsTxt));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class PyPackageTest extends TestCase {
|
||||
|
||||
@NotNull
|
||||
private static PyRequirement createRequirement(@NotNull String options) {
|
||||
final PyRequirement requirement = PyRequirement.fromLine(options);
|
||||
final PyRequirement requirement = PyPackageUtil.fix(PyRequirement.fromLine(options));
|
||||
assertNotNull(requirement);
|
||||
return requirement;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.jetbrains.python.packaging.PyPackageUtil.fix;
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
*/
|
||||
@@ -2244,7 +2246,7 @@ public class PyRequirementTest extends PyTestCase {
|
||||
|
||||
// PY-6355
|
||||
public void testTrailingZeroesInVersion() {
|
||||
final PyRequirement req = PyRequirement.fromLine("foo==0.8.0");
|
||||
final PyRequirement req = fix(PyRequirement.fromLine("foo==0.8.0"));
|
||||
final PyPackage pkg = new PyPackage("foo", "0.8", null, Collections.emptyList());
|
||||
assertNotNull(req);
|
||||
assertEquals(pkg, req.match(Collections.singletonList(pkg)));
|
||||
@@ -2252,7 +2254,7 @@ public class PyRequirementTest extends PyTestCase {
|
||||
|
||||
// PY-6438
|
||||
public void testUnderscoreMatchesDash() {
|
||||
final PyRequirement req = PyRequirement.fromLine("pyramid_zcml");
|
||||
final PyRequirement req = fix(PyRequirement.fromLine("pyramid_zcml"));
|
||||
final PyPackage pkg = new PyPackage("pyramid-zcml", "0.1", null, Collections.emptyList());
|
||||
assertNotNull(req);
|
||||
assertEquals(pkg, req.match(Collections.singletonList(pkg)));
|
||||
@@ -2260,7 +2262,7 @@ public class PyRequirementTest extends PyTestCase {
|
||||
|
||||
// PY-20242
|
||||
public void testVersionInterpretedAsString() {
|
||||
final PyRequirement req = PyRequirement.fromLine("foo===version");
|
||||
final PyRequirement req = fix(PyRequirement.fromLine("foo===version"));
|
||||
final PyPackage pkg = new PyPackage("foo", "version", null, Collections.emptyList());
|
||||
assertNotNull(req);
|
||||
assertEquals(pkg, req.match(Collections.singletonList(pkg)));
|
||||
@@ -2271,11 +2273,11 @@ public class PyRequirementTest extends PyTestCase {
|
||||
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");
|
||||
final PyRequirement requirement = fix(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");
|
||||
final PyRequirement requirementWithLocalVersion = fix(PyRequirement.fromLine("foo==1.0+foo0100"));
|
||||
assertEquals(firstPackageWithLocalVersion, requirementWithLocalVersion.match(Collections.singletonList(firstPackageWithLocalVersion)));
|
||||
assertNull(requirementWithLocalVersion.match(Collections.singletonList(secondPackageWithLocalVersion)));
|
||||
}
|
||||
@@ -2283,7 +2285,7 @@ public class PyRequirementTest extends PyTestCase {
|
||||
// https://www.python.org/dev/peps/pep-0440/#version-matching
|
||||
// PY-22275
|
||||
public void testMatchingStar() {
|
||||
final PyRequirement requirement = PyRequirement.fromLine("foo==1.1.*");
|
||||
final PyRequirement requirement = fix(PyRequirement.fromLine("foo==1.1.*"));
|
||||
final PyPackage release = new PyPackage("foo", "1.1.2", null, Collections.emptyList());
|
||||
final PyPackage pre = new PyPackage("foo", "1.1.2a1", null, Collections.emptyList());
|
||||
final PyPackage post = new PyPackage("foo", "1.1.2.post1", null, Collections.emptyList());
|
||||
@@ -2296,7 +2298,7 @@ public class PyRequirementTest extends PyTestCase {
|
||||
assertEquals(dev, requirement.match(Collections.singletonList(dev)));
|
||||
assertEquals(localVersion, requirement.match(Collections.singletonList(localVersion)));
|
||||
|
||||
final PyRequirement negativeRequirement = PyRequirement.fromLine("foo!=1.1.*");
|
||||
final PyRequirement negativeRequirement = fix(PyRequirement.fromLine("foo!=1.1.*"));
|
||||
final PyPackage negativeRelease = new PyPackage("foo", "1.2.2", null, Collections.emptyList());
|
||||
final PyPackage negativePre = new PyPackage("foo", "1.2.2a1", null, Collections.emptyList());
|
||||
final PyPackage negativePost = new PyPackage("foo", "1.2.2.post1", null, Collections.emptyList());
|
||||
@@ -2314,7 +2316,7 @@ public class PyRequirementTest extends PyTestCase {
|
||||
// https://www.python.org/dev/peps/pep-0440/#compatible-release
|
||||
// PY-20522
|
||||
public void testMatchingCompatible() {
|
||||
final PyRequirement requirement = PyRequirement.fromLine("foo~=2.2");
|
||||
final PyRequirement requirement = fix(PyRequirement.fromLine("foo~=2.2"));
|
||||
final PyPackage release = new PyPackage("foo", "2.3", null, Collections.emptyList());
|
||||
final PyPackage pre = new PyPackage("foo", "2.3a1", null, Collections.emptyList());
|
||||
final PyPackage post = new PyPackage("foo", "2.3.post1", null, Collections.emptyList());
|
||||
@@ -2327,14 +2329,14 @@ public class PyRequirementTest extends PyTestCase {
|
||||
assertEquals(dev, requirement.match(Collections.singletonList(dev)));
|
||||
assertEquals(localVersion, requirement.match(Collections.singletonList(localVersion)));
|
||||
|
||||
final PyRequirement moreModernRequirement = PyRequirement.fromLine("foo~=2.4");
|
||||
final PyRequirement moreModernRequirement = fix(PyRequirement.fromLine("foo~=2.4"));
|
||||
assertNull(moreModernRequirement.match(Arrays.asList(release, pre, post, dev, localVersion)));
|
||||
}
|
||||
|
||||
// https://www.python.org/dev/peps/pep-0440/#compatible-release
|
||||
// PY-20522
|
||||
public void testMatchingCompatibleWithTrailingZero() {
|
||||
final PyRequirement requirement = PyRequirement.fromLine("foo~=2.20.0");
|
||||
final PyRequirement requirement = fix(PyRequirement.fromLine("foo~=2.20.0"));
|
||||
final PyPackage release = new PyPackage("foo", "2.20.3", null, Collections.emptyList());
|
||||
final PyPackage pre = new PyPackage("foo", "2.20.3a1", null, Collections.emptyList());
|
||||
final PyPackage post = new PyPackage("foo", "2.20.3.post1", null, Collections.emptyList());
|
||||
@@ -2347,10 +2349,21 @@ public class PyRequirementTest extends PyTestCase {
|
||||
assertEquals(dev, requirement.match(Collections.singletonList(dev)));
|
||||
assertEquals(localVersion, requirement.match(Collections.singletonList(localVersion)));
|
||||
|
||||
final PyRequirement moreModernRequirement = PyRequirement.fromLine("foo~=2.21.0");
|
||||
final PyRequirement moreModernRequirement = fix(PyRequirement.fromLine("foo~=2.21.0"));
|
||||
assertNull(moreModernRequirement.match(Arrays.asList(release, pre, post, dev, localVersion)));
|
||||
}
|
||||
|
||||
// PY-27076
|
||||
public void testMatchingAsteriskAndCompatibleWithTwoTrailingZeros() {
|
||||
final PyRequirement requirement1 = fix(PyRequirement.fromLine("social-auth-app-django==2.0.*"));
|
||||
final PyRequirement requirement2 = fix(PyRequirement.fromLine("social-auth-app-django~=2.0.0"));
|
||||
|
||||
final PyPackage pkg = new PyPackage("social-auth-app-django", "2.0.0", null, Collections.emptyList());
|
||||
|
||||
assertEquals(pkg, requirement1.match(Collections.singletonList(pkg)));
|
||||
assertEquals(pkg, requirement2.match(Collections.singletonList(pkg)));
|
||||
}
|
||||
|
||||
// OPTIONS
|
||||
public void testOptions() {
|
||||
assertEmpty(
|
||||
|
||||
Reference in New Issue
Block a user