Skip to content

Commit 716c974

Browse files
authored
Python type hints in a separate module (#2510)
1 parent 2dc9600 commit 716c974

File tree

105 files changed

+2315
-786
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+2315
-786
lines changed

settings.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ if (pythonIde.split(",").contains(ideType)) {
6565
include("utbot-cli-python")
6666
include("utbot-intellij-python")
6767
include("utbot-python-parser")
68+
include("utbot-python-types")
6869
}
6970

7071
include("utbot-spring-sample")
@@ -85,4 +86,3 @@ if (projectType == ultimateEdition) {
8586
}
8687

8788
include("utbot-light")
88-

utbot-python-types/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist/

utbot-python-types/build.gradle.kts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
val kotlinLoggingVersion: String? by rootProject
2+
3+
dependencies {
4+
implementation("com.squareup.moshi:moshi:1.11.0")
5+
implementation("com.squareup.moshi:moshi-kotlin:1.11.0")
6+
implementation("com.squareup.moshi:moshi-adapters:1.11.0")
7+
implementation(group = "io.github.microutils", name = "kotlin-logging", version = kotlinLoggingVersion)
8+
}
9+
10+
val utbotMypyRunnerVersion = File(project.projectDir, "src/main/resources/utbot_mypy_runner_version").readText()
11+
// these two properties --- from GRADLE_USER_HOME/gradle.properties
12+
val pypiToken: String? by project
13+
val pythonInterpreter: String? by project
14+
val utbotMypyRunnerPath = File(project.projectDir, "src/main/python/utbot_mypy_runner")
15+
val localMypyPath = File(utbotMypyRunnerPath, "dist")
16+
17+
tasks.register("cleanDist") {
18+
group = "python"
19+
delete(localMypyPath.canonicalPath)
20+
}
21+
22+
val setMypyRunnerVersion =
23+
if (pythonInterpreter != null)
24+
tasks.register<Exec>("setVersion") {
25+
group = "python"
26+
workingDir = utbotMypyRunnerPath
27+
commandLine(pythonInterpreter, "-m", "poetry", "version", utbotMypyRunnerVersion)
28+
} else {
29+
null
30+
}
31+
32+
val buildMypyRunner =
33+
if (pythonInterpreter != null) {
34+
tasks.register<Exec>("buildUtbotMypyRunner") {
35+
dependsOn(setMypyRunnerVersion!!)
36+
group = "python"
37+
workingDir = utbotMypyRunnerPath
38+
commandLine(pythonInterpreter, "-m", "poetry", "build")
39+
}
40+
} else {
41+
null
42+
}
43+
44+
if (pythonInterpreter != null && pypiToken != null) {
45+
tasks.register<Exec>("publishUtbotMypyRunner") {
46+
dependsOn(buildMypyRunner!!)
47+
group = "python"
48+
workingDir = utbotMypyRunnerPath
49+
commandLine(
50+
pythonInterpreter,
51+
"-m",
52+
"poetry",
53+
"publish",
54+
"-u",
55+
"__token__",
56+
"-p",
57+
pypiToken
58+
)
59+
}
60+
}
61+
62+
val installMypyRunner =
63+
if (pythonInterpreter != null) {
64+
tasks.register<Exec>("installUtbotMypyRunner") {
65+
dependsOn(buildMypyRunner!!)
66+
group = "python"
67+
environment("PIP_FIND_LINKS" to localMypyPath.canonicalPath)
68+
commandLine(
69+
pythonInterpreter,
70+
"-m",
71+
"pip",
72+
"install",
73+
"utbot_mypy_runner==$utbotMypyRunnerVersion"
74+
)
75+
}
76+
} else {
77+
null
78+
}
79+
80+
val samplesDir = File(project.projectDir, "src/test/resources/samples")
81+
val buildDir = File(project.buildDir, "samples_builds")
82+
val jsonDir = File(project.projectDir, "src/test/resources")
83+
84+
fun getParamsForSample(sampleName: String): List<String> =
85+
listOf(
86+
File(samplesDir, "$sampleName.py").canonicalPath,
87+
sampleName,
88+
buildDir.canonicalPath,
89+
File(jsonDir, "$sampleName.json").canonicalPath
90+
)
91+
92+
val samplesInfo = listOf(
93+
getParamsForSample("annotation_tests"),
94+
getParamsForSample("boruvka"),
95+
getParamsForSample("import_test"),
96+
getParamsForSample("subtypes"),
97+
)
98+
99+
if (pythonInterpreter != null) {
100+
val subtasks = samplesInfo.mapIndexed { index, params ->
101+
tasks.register<JavaExec>("regenerateJsonForTests_$index") {
102+
dependsOn(installMypyRunner!!)
103+
group = "python_subtasks"
104+
classpath = sourceSets.test.get().runtimeClasspath
105+
args = listOf(pythonInterpreter) + params
106+
mainClass.set("org.utbot.python.newtyping.samples.GenerateMypyInfoBuildKt")
107+
}
108+
}
109+
110+
tasks.register("regenerateJsonForTests") {
111+
subtasks.forEach { dependsOn(it) }
112+
group = "python"
113+
}
114+
}

utbot-python/src/main/kotlin/org/utbot/python/newtyping/PythonDefinition.kt renamed to utbot-python-types/src/main/kotlin/org/utbot/python/newtyping/PythonDefinition.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package org.utbot.python.newtyping
22

33
import org.utbot.python.newtyping.general.FunctionType
4-
import org.utbot.python.newtyping.general.Type
4+
import org.utbot.python.newtyping.general.UtType
55

6-
open class PythonDefinition(open val meta: PythonDefinitionDescription, open val type: Type) {
6+
open class PythonDefinition(open val meta: PythonDefinitionDescription, open val type: UtType) {
77
override fun toString(): String =
88
"${meta.name}: ${type.pythonTypeRepresentation()}"
99
}

utbot-python/src/main/kotlin/org/utbot/python/newtyping/PythonType.kt renamed to utbot-python-types/src/main/kotlin/org/utbot/python/newtyping/PythonType.kt

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import org.utbot.python.newtyping.general.Name
55
import org.utbot.python.newtyping.utils.isRequired
66

77
sealed class PythonTypeDescription(name: Name) : TypeMetaDataWithName(name) {
8-
open fun castToCompatibleTypeApi(type: Type): Type = type
9-
open fun getNamedMembers(type: Type): List<PythonDefinition> = emptyList() // direct members (without inheritance)
10-
open fun getAnnotationParameters(type: Type): List<Type> = emptyList()
11-
open fun getMemberByName(storage: PythonTypeStorage, type: Type, name: String): PythonDefinition? =
8+
open fun castToCompatibleTypeApi(type: UtType): UtType = type
9+
open fun getNamedMembers(type: UtType): List<PythonDefinition> = emptyList() // direct members (without inheritance)
10+
open fun getAnnotationParameters(type: UtType): List<UtType> = emptyList()
11+
open fun getMemberByName(storage: PythonTypeHintsStorage, type: UtType, name: String): PythonDefinition? =
1212
// overridden for some types
1313
getNamedMembers(type).find { it.meta.name == name }
14-
open fun createTypeWithNewAnnotationParameters(like: Type, newParams: List<Type>): Type = // overriden for Callable
14+
open fun createTypeWithNewAnnotationParameters(like: UtType, newParams: List<UtType>): UtType = // overriden for Callable
1515
DefaultSubstitutionProvider.substituteAll(like.getOrigin(), newParams)
16-
open fun getTypeRepresentation(type: Type): String { // overriden for Callable
16+
open fun getTypeRepresentation(type: UtType): String { // overriden for Callable
1717
if (name.prefix == listOf("builtins") && name.name == "tuple") {
1818
return "${getTypeName()}[${type.parameters.first().pythonTypeRepresentation()}, ...]"
1919
}
@@ -35,7 +35,7 @@ sealed class PythonTypeDescription(name: Name) : TypeMetaDataWithName(name) {
3535
fun getName(): String {
3636
return name.name
3737
}
38-
fun getModules(type: Type): Set<String> {
38+
fun getModules(type: UtType): Set<String> {
3939
val cur = if (name.prefix.isNotEmpty())
4040
setOf(name.prefix.joinToString(separator = "."))
4141
else
@@ -50,12 +50,12 @@ sealed class PythonCompositeTypeDescription(
5050
name: Name,
5151
private val memberDescriptions: List<PythonDefinitionDescription>
5252
): PythonTypeDescription(name) {
53-
override fun castToCompatibleTypeApi(type: Type): CompositeType {
53+
override fun castToCompatibleTypeApi(type: UtType): CompositeType {
5454
return type as? CompositeType
5555
?: error("Got unexpected type PythonCompositeTypeDescription: $type")
5656
}
5757

58-
override fun getNamedMembers(type: Type): List<PythonDefinition> {
58+
override fun getNamedMembers(type: UtType): List<PythonDefinition> {
5959
val compositeType = castToCompatibleTypeApi(type)
6060
assert(compositeType.members.size == memberDescriptions.size)
6161
return (memberDescriptions zip compositeType.members).map { (descr, typ) ->
@@ -66,8 +66,8 @@ sealed class PythonCompositeTypeDescription(
6666
}
6767
}
6868

69-
override fun getAnnotationParameters(type: Type): List<Type> = type.parameters
70-
fun mro(storage: PythonTypeStorage, type: Type): List<Type> {
69+
override fun getAnnotationParameters(type: UtType): List<UtType> = type.parameters
70+
fun mro(storage: PythonTypeHintsStorage, type: UtType): List<UtType> {
7171
val compositeType = castToCompatibleTypeApi(type)
7272
var bases = compositeType.supertypes
7373
if (bases.isEmpty() && !type.isPythonObjectType())
@@ -82,7 +82,7 @@ sealed class PythonCompositeTypeDescription(
8282
linBases.removeIf { it.isEmpty() }
8383
if (linBases.isEmpty())
8484
break
85-
lateinit var addAtThisIteration: Type
85+
lateinit var addAtThisIteration: UtType
8686
for (seq in linBases) {
8787
val head = seq.first()
8888
val isContainedSomewhereElse = linBases.any {
@@ -102,7 +102,7 @@ sealed class PythonCompositeTypeDescription(
102102
return result
103103
}
104104

105-
override fun getMemberByName(storage: PythonTypeStorage, type: Type, name: String): PythonDefinition? {
105+
override fun getMemberByName(storage: PythonTypeHintsStorage, type: UtType, name: String): PythonDefinition? {
106106
for (parent in mro(storage, type)) {
107107
val cur = parent.getPythonAttributes().find { it.meta.name == name }
108108
if (cur != null)
@@ -119,7 +119,7 @@ class PythonTypeVarDescription(
119119
val variance: Variance,
120120
val parameterKind: ParameterKind
121121
) : PythonTypeDescription(name) {
122-
override fun castToCompatibleTypeApi(type: Type): TypeParameter {
122+
override fun castToCompatibleTypeApi(type: UtType): TypeParameter {
123123
return type as? TypeParameter
124124
?: error("Got unexpected type PythonTypeVarDescription: $type")
125125
}
@@ -154,17 +154,17 @@ class PythonCallableTypeDescription(
154154
val argumentNames: List<String?> // like in mypy's CallableType: https://github.com/python/mypy/blob/master/mypy/types.py#L1672
155155
): PythonTypeDescription(pythonCallableName) {
156156
val numberOfArguments = argumentKinds.size
157-
override fun castToCompatibleTypeApi(type: Type): FunctionType {
157+
override fun castToCompatibleTypeApi(type: UtType): FunctionType {
158158
return type as? FunctionType
159159
?: error("Got unexpected type PythonCallableTypeDescription: $type")
160160
}
161161

162-
override fun getNamedMembers(type: Type): List<PythonDefinition> {
162+
override fun getNamedMembers(type: UtType): List<PythonDefinition> {
163163
val functionType = castToCompatibleTypeApi(type)
164164
return listOf(PythonDefinition(PythonVariableDescription("__call__"), functionType))
165165
}
166166

167-
override fun getAnnotationParameters(type: Type): List<Type> {
167+
override fun getAnnotationParameters(type: UtType): List<UtType> {
168168
val functionType = castToCompatibleTypeApi(type)
169169
return functionType.arguments + listOf(functionType.returnValue)
170170
}
@@ -178,7 +178,7 @@ class PythonCallableTypeDescription(
178178
ARG_NAMED_OPT
179179
}
180180

181-
override fun createTypeWithNewAnnotationParameters(like: Type, newParams: List<Type>): Type {
181+
override fun createTypeWithNewAnnotationParameters(like: UtType, newParams: List<UtType>): UtType {
182182
val args = newParams.dropLast(1)
183183
val returnValue = newParams.last()
184184
return createPythonCallableType(
@@ -200,15 +200,15 @@ class PythonCallableTypeDescription(
200200
}
201201
}
202202

203-
override fun getTypeRepresentation(type: Type): String {
203+
override fun getTypeRepresentation(type: UtType): String {
204204
val functionType = castToCompatibleTypeApi(type)
205205
val root = name.prefix.joinToString(".") + "." + name.name
206206
return "$root[[${
207207
functionType.arguments.joinToString(separator = ", ") { it.pythonTypeRepresentation() }
208208
}], ${functionType.returnValue.pythonTypeRepresentation()}]"
209209
}
210210

211-
fun removeNonPositionalArgs(type: Type): FunctionType {
211+
fun removeNonPositionalArgs(type: UtType): FunctionType {
212212
val functionType = castToCompatibleTypeApi(type)
213213
val argsCount = argumentKinds.count { it == ArgKind.ARG_POS }
214214
return createPythonCallableType(
@@ -228,7 +228,7 @@ class PythonCallableTypeDescription(
228228
}
229229
}
230230

231-
fun removeNotRequiredArgs(type: Type): FunctionType {
231+
fun removeNotRequiredArgs(type: UtType): FunctionType {
232232
val functionType = castToCompatibleTypeApi(type)
233233
return createPythonCallableType(
234234
functionType.parameters.size,
@@ -250,7 +250,7 @@ class PythonCallableTypeDescription(
250250

251251
// Special Python annotations
252252
object PythonAnyTypeDescription : PythonSpecialAnnotation(pythonAnyName) {
253-
override fun getMemberByName(storage: PythonTypeStorage, type: Type, name: String): PythonDefinition {
253+
override fun getMemberByName(storage: PythonTypeHintsStorage, type: UtType, name: String): PythonDefinition {
254254
return PythonDefinition(PythonVariableDescription(name), pythonAnyType)
255255
}
256256
}
@@ -260,7 +260,7 @@ object PythonNoneTypeDescription : PythonSpecialAnnotation(pythonNoneName) {
260260
}
261261

262262
object PythonUnionTypeDescription : PythonSpecialAnnotation(pythonUnionName) {
263-
override fun getMemberByName(storage: PythonTypeStorage, type: Type, name: String): PythonDefinition? {
263+
override fun getMemberByName(storage: PythonTypeHintsStorage, type: UtType, name: String): PythonDefinition? {
264264
val children = type.parameters.mapNotNull {
265265
it.getPythonAttributeByName(storage, name)?.type
266266
}
@@ -273,28 +273,28 @@ object PythonUnionTypeDescription : PythonSpecialAnnotation(pythonUnionName) {
273273
)
274274
}
275275

276-
override fun getAnnotationParameters(type: Type): List<Type> = type.parameters
276+
override fun getAnnotationParameters(type: UtType): List<UtType> = type.parameters
277277
}
278278

279279
object PythonOverloadTypeDescription : PythonSpecialAnnotation(overloadName) {
280-
override fun getAnnotationParameters(type: Type): List<Type> = type.parameters
281-
override fun getNamedMembers(type: Type): List<PythonDefinition> {
280+
override fun getAnnotationParameters(type: UtType): List<UtType> = type.parameters
281+
override fun getNamedMembers(type: UtType): List<PythonDefinition> {
282282
return listOf(PythonDefinition(PythonVariableDescription("__call__"), type))
283283
}
284284
}
285285

286286
object PythonTypeAliasDescription : PythonSpecialAnnotation(pythonTypeAliasName) {
287-
override fun castToCompatibleTypeApi(type: Type): CompositeType {
287+
override fun castToCompatibleTypeApi(type: UtType): CompositeType {
288288
return type as? CompositeType ?: error("Got unexpected type for PythonTypeAliasDescription: $type")
289289
}
290-
fun getInterior(type: Type): Type {
290+
fun getInterior(type: UtType): UtType {
291291
val casted = castToCompatibleTypeApi(type)
292292
return casted.members.first()
293293
}
294294
}
295295

296296
object PythonTupleTypeDescription : PythonSpecialAnnotation(pythonTupleName) {
297-
override fun getAnnotationParameters(type: Type): List<Type> = castToCompatibleTypeApi(type).parameters
297+
override fun getAnnotationParameters(type: UtType): List<UtType> = castToCompatibleTypeApi(type).parameters
298298
// TODO: getMemberByName and/or getNamedMembers
299299
}
300300

@@ -306,13 +306,13 @@ private fun initTypeVar(param: TypeParameter) {
306306
)
307307
}
308308

309-
private fun substituteMembers(origin: Type, members: List<Type>): Type =
309+
private fun substituteMembers(origin: UtType, members: List<UtType>): UtType =
310310
DefaultSubstitutionProvider.substitute(
311311
origin,
312312
(origin.parameters.map { it as TypeParameter } zip members).associate { it }
313313
)
314314

315-
fun createTypeWithMembers(description: PythonTypeDescription, members: List<Type>): Type {
315+
fun createTypeWithMembers(description: PythonTypeDescription, members: List<UtType>): UtType {
316316
val origin = TypeCreator.create(members.size, description) {
317317
it.parameters.forEach(::initTypeVar)
318318
}

0 commit comments

Comments
 (0)