Skip to content

Commit

Permalink
SONARPY-2326 Treat Python 3.13 as if was Python 3.11 when deserializi…
Browse files Browse the repository at this point in the history
…ng typeshed
  • Loading branch information
Seppli11 committed Nov 15, 2024
1 parent a4ab254 commit e7df9ae
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ public static boolean areSourcePythonVersionsGreaterOrEqualThan(Set<Version> sou
.allMatch(version -> version.compare(required.major(), required.minor()) >= 0);
}

/**
* @return the set of versions which are supported but not serialized due to SONARPY-1522
*/
public static Set<Version> getNotSerializedVersions() {
return EnumSet.of(V_312, V_313);
}

private static void logErrorMessage(String propertyValue) {
LOG.warn(
"Error while parsing value of parameter '{}' ({}). Versions must be specified as MAJOR_VERSION.MINOR_VERSION (e.g. \"3.7, 3.8\")",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ static boolean isValidForPythonVersion(List<String> validForPythonVersions, Set<
return true;
}
// TODO: SONARPY-1522 - remove this workaround when we will have all the stubs for Python 3.12.
if (supportedPythonVersions.stream().allMatch(PythonVersionUtils.Version.V_312.serializedValue()::equals)
&& validForPythonVersions.contains(PythonVersionUtils.Version.V_311.serializedValue())) {
Set<String> notSerializedVersions =
PythonVersionUtils.getNotSerializedVersions().stream().map(PythonVersionUtils.Version::serializedValue).collect(Collectors.toSet());
if (notSerializedVersions.containsAll(supportedPythonVersions)
&& validForPythonVersions.contains(PythonVersionUtils.Version.V_311.serializedValue())) {
return true;
}
HashSet<String> intersection = new HashSet<>(validForPythonVersions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,9 @@ public static boolean isValidForProjectPythonVersion(List<String> validForPython
return true;
}
// TODO: SONARPY-1522 - remove this workaround when we will have all the stubs for Python 3.12.
if (supportedPythonVersions.stream().allMatch(PythonVersionUtils.Version.V_312.serializedValue()::equals)
&& validForPythonVersions.contains(PythonVersionUtils.Version.V_311.serializedValue())) {
Set<String> notSerializedVersions = PythonVersionUtils.getNotSerializedVersions().stream().map(PythonVersionUtils.Version::serializedValue).collect(Collectors.toSet());
if (notSerializedVersions.containsAll(supportedPythonVersions)
&& validForPythonVersions.contains(PythonVersionUtils.Version.V_311.serializedValue())) {
return true;
}
HashSet<String> intersection = new HashSet<>(validForPythonVersions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@
*/
package org.sonar.python.semantic.v2.typeshed;

import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.plugins.python.api.ProjectPythonVersion;
import org.sonar.plugins.python.api.PythonVersionUtils;
import org.sonar.python.index.AmbiguousDescriptor;
import org.sonar.python.index.Descriptor;
import org.sonar.python.index.FunctionDescriptor;
Expand Down Expand Up @@ -98,6 +104,84 @@ void test() {
.containsOnly(true, true);
}

static Stream<Arguments> versionsToTest() {
return Stream.of(
Arguments.of(PythonVersionUtils.Version.V_312),
Arguments.of(PythonVersionUtils.Version.V_313)
);
}

@ParameterizedTest
@MethodSource("versionsToTest")
void validForPythonVersionsTest(PythonVersionUtils.Version version) {
var functionConverter = new FunctionSymbolToDescriptorConverter();
var variableConverter = new VarSymbolToDescriptorConverter();
var overloadedFunctionConverter = new OverloadedFunctionSymbolToDescriptorConverter(functionConverter);
var converter = new ClassSymbolToDescriptorConverter(variableConverter, functionConverter, overloadedFunctionConverter, Set.of(version.serializedValue()));

var symbol = SymbolsProtos.ClassSymbol.newBuilder()
.setName("MyClass")
.addAttributes(SymbolsProtos.VarSymbol.newBuilder()
.setName("v1")
.addValidFor("311")
.build())
.addAttributes(SymbolsProtos.VarSymbol.newBuilder()
.setName("v2")
.addValidFor("39")
.build())
.addMethods(SymbolsProtos.FunctionSymbol.newBuilder()
.setName("foo1")
.addValidFor("311")
.build())
.addMethods(SymbolsProtos.FunctionSymbol.newBuilder()
.setName("foo2")
.addValidFor("39")
.build())
.addOverloadedMethods(SymbolsProtos.OverloadedFunctionSymbol.newBuilder()
.setName("overloaded_foo1")
.addValidFor("311")
.setFullname("module.MyClass.overloaded_foo1")
.addDefinitions(SymbolsProtos.FunctionSymbol.newBuilder()
.setName("overloaded_foo1")
.addValidFor("311")
.build())
.addDefinitions(SymbolsProtos.FunctionSymbol.newBuilder()
.setName("overloaded_foo1")
.addValidFor("311")
.build())
.build())
.addOverloadedMethods(SymbolsProtos.OverloadedFunctionSymbol.newBuilder()
.setName("overloaded_foo2")
.addValidFor("39")
.setFullname("module.MyClass.overloaded_foo2")
.addDefinitions(SymbolsProtos.FunctionSymbol.newBuilder()
.setName("overloaded_foo2")
.addValidFor("39")
.build())
.addDefinitions(SymbolsProtos.FunctionSymbol.newBuilder()
.setName("overloaded_foo2")
.addValidFor("39")
.build())
.build())
.build();

var descriptor = converter.convert(symbol);

Assertions.assertThat(descriptor.members()).hasSize(3);

var membersByName = descriptor.members()
.stream()
.collect(Collectors.toMap(Descriptor::name, Function.identity()));

Assertions.assertThat(membersByName).hasSize(3);
Assertions.assertThat(membersByName.get("v1")).isInstanceOf(VariableDescriptor.class);
Assertions.assertThat(membersByName.get("v2")).isNull();
Assertions.assertThat(membersByName.get("foo1")).isInstanceOf(FunctionDescriptor.class);
Assertions.assertThat(membersByName.get("foo2")).isNull();
Assertions.assertThat(membersByName.get("overloaded_foo1")).isInstanceOf(AmbiguousDescriptor.class);
Assertions.assertThat(membersByName.get("overloaded_foo2")).isNull();
}

@Test
void builtinsTest() {
var functionConverter = new FunctionSymbolToDescriptorConverter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@
package org.sonar.python.semantic.v2.typeshed;

import java.util.Set;
import java.util.stream.Stream;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.plugins.python.api.PythonVersionUtils;
import org.sonar.python.index.AmbiguousDescriptor;
import org.sonar.python.index.ClassDescriptor;
Expand All @@ -30,7 +34,6 @@
import org.sonar.python.types.protobuf.SymbolsProtos;

class ModuleSymbolToDescriptorConverterTest {

@Test
void test() {
var converter = new ModuleSymbolToDescriptorConverter(PythonVersionUtils.allVersions());
Expand Down Expand Up @@ -90,9 +93,18 @@ void nullSymbolTest() {
Assertions.assertThat(descriptor).isNull();
}

@Test
void validForPythonVersionsTest() {
var converter = new ModuleSymbolToDescriptorConverter(Set.of(PythonVersionUtils.Version.V_312));

static Stream<Arguments> versionsToTest() {
return Stream.of(
Arguments.of(PythonVersionUtils.Version.V_312),
Arguments.of(PythonVersionUtils.Version.V_313)
);
}

@ParameterizedTest
@MethodSource("versionsToTest")
void validForPythonVersionsTest(PythonVersionUtils.Version requestedVersion) {
var converter = new ModuleSymbolToDescriptorConverter(Set.of(requestedVersion));
var symbol = SymbolsProtos.ModuleSymbol.newBuilder()
.setFullyQualifiedName("module")
.addVars(SymbolsProtos.VarSymbol.newBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,10 @@ void pythonVersions() {
intSymbol = TypeShed.typeShedClass("int");
assertThat(intSymbol.resolveMember("bit_count")).isNotEmpty();

setPythonVersions(PythonVersionUtils.fromString("3.13"));
intSymbol = TypeShed.typeShedClass("int");
assertThat(intSymbol.resolveMember("bit_count")).isNotEmpty();

setPythonVersions(PythonVersionUtils.allVersions());
}

Expand Down

0 comments on commit e7df9ae

Please sign in to comment.