Skip to content

Commit d2edb45

Browse files
authored
Rewrite logic with system paths and imports in python (#1578)
1 parent 52acdb2 commit d2edb45

File tree

6 files changed

+62
-25
lines changed

6 files changed

+62
-25
lines changed

utbot-intellij-python/src/main/kotlin/org/utbot/intellij/plugin/language/python/PythonDialogProcessor.kt

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.intellij.openapi.roots.ProjectFileIndex
1212
import com.intellij.openapi.ui.Messages
1313
import com.intellij.openapi.vfs.VfsUtil
1414
import com.intellij.openapi.vfs.VfsUtilCore
15+
import com.intellij.openapi.vfs.VirtualFile
1516
import com.intellij.psi.PsiDirectory
1617
import com.intellij.psi.PsiFileFactory
1718
import com.jetbrains.python.psi.PyClass
@@ -36,7 +37,6 @@ import org.utbot.python.framework.codegen.PythonCgLanguageAssistant
3637
import org.utbot.python.utils.RequirementsUtils.installRequirements
3738
import org.utbot.python.utils.RequirementsUtils.requirements
3839
import org.utbot.python.utils.camelToSnakeCase
39-
import java.io.File
4040
import java.nio.file.Path
4141
import java.nio.file.Paths
4242
import kotlin.io.path.Path
@@ -285,43 +285,66 @@ fun getPyCodeFromPyFile(file: PyFile, pythonModule: String): PythonCode? {
285285
return getFromString(content, file.virtualFile.path, pythonModule = pythonModule)
286286
}
287287

288+
/*
289+
* Returns set of sys paths and tested file import path
290+
*/
288291
fun getDirectoriesForSysPath(
289292
srcModule: Module,
290293
file: PyFile
291294
): Pair<Set<String>, String> {
292295
val sources = ModuleRootManager.getInstance(srcModule).getSourceRoots(false).toMutableList()
293296
val ancestor = ProjectFileIndex.getInstance(file.project).getContentRootForFile(file.virtualFile)
294-
if (ancestor != null && !sources.contains(ancestor))
297+
if (ancestor != null)
295298
sources.add(ancestor)
296299

297300
// Collect sys.path directories with imported modules
301+
val importedPaths = emptyList<VirtualFile>().toMutableList()
302+
303+
// 1. import <module>
298304
file.importTargets.forEach { importTarget ->
299305
importTarget.multiResolve().forEach {
300306
val element = it.element
301307
if (element != null) {
302308
val directory = element.parent
303309
if (directory is PsiDirectory) {
304-
if (sources.any { source ->
305-
val sourcePath = source.canonicalPath
306-
if (source.isDirectory && sourcePath != null) {
307-
directory.virtualFile.canonicalPath?.startsWith(sourcePath) ?: false
308-
} else {
309-
false
310-
}
311-
}) {
312-
sources.add(directory.virtualFile)
313-
}
310+
importedPaths.add(directory.virtualFile)
314311
}
315312
}
316313
}
317314
}
318315

319-
var importPath = ancestor?.let { VfsUtil.getParentDir(VfsUtilCore.getRelativeLocation(file.virtualFile, it)) } ?: ""
320-
if (importPath != "")
321-
importPath += "."
316+
// 2. from <module> import ...
317+
file.fromImports.forEach { importTarget ->
318+
importTarget.resolveImportSourceCandidates().forEach {
319+
val directory = it.parent
320+
if (directory is PsiDirectory ) {
321+
importedPaths.add(directory.virtualFile)
322+
}
323+
}
324+
}
325+
326+
// Select modules only from this project
327+
importedPaths.forEach {
328+
if (it.isProjectSubmodule(ancestor)) {
329+
sources.add(it)
330+
}
331+
}
332+
333+
val fileName = file.name.removeSuffix(".py")
334+
val importPath = ancestor?.let {
335+
VfsUtil.getParentDir(
336+
VfsUtilCore.getRelativeLocation(file.virtualFile, it)
337+
)
338+
} ?: ""
339+
val importStringPath = listOf(
340+
importPath.toPath().joinToString("."),
341+
fileName
342+
)
343+
.filterNot { it.isEmpty() }
344+
.joinToString(".")
322345

323346
return Pair(
324-
sources.map { it.path.replace("\\", "\\\\") }.toSet(),
325-
"${importPath}${file.name}".removeSuffix(".py").toPath().joinToString(".").replace("/", File.separator)
347+
sources.map { it.path }.toSet(),
348+
importStringPath
326349
)
327350
}

utbot-intellij-python/src/main/kotlin/org/utbot/intellij/plugin/language/python/Utils.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package org.utbot.intellij.plugin.language.python
22

33
import com.intellij.openapi.project.Project
44
import com.intellij.openapi.roots.ProjectFileIndex
5+
import com.intellij.openapi.vfs.VfsUtil
56
import com.intellij.openapi.vfs.VirtualFile
67
import com.intellij.psi.PsiElement
78
import org.utbot.python.utils.RequirementsUtils
@@ -30,6 +31,10 @@ fun generateRandomString(length: Int): String {
3031
.joinToString("")
3132
}
3233

34+
fun VirtualFile.isProjectSubmodule(ancestor: VirtualFile?): Boolean {
35+
return VfsUtil.isUnder(this, setOf(ancestor).toMutableSet())
36+
}
37+
3338
fun checkModuleIsInstalled(pythonPath: String, moduleName: String): Boolean {
3439
return RequirementsUtils.requirementsAreInstalled(pythonPath, listOf(moduleName))
35-
}
40+
}

utbot-python/src/main/kotlin/org/utbot/python/PythonEvaluation.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ fun startEvaluationProcess(input: EvaluationInput): EvaluationProcess {
7373
input.directoriesForSysPath,
7474
input.moduleToImport,
7575
input.additionalModulesToImport,
76-
fileForOutput.path.replace("\\", "\\\\"),
77-
coverageDatabasePath.absolutePath.replace("\\", "\\\\")
76+
fileForOutput.path,
77+
coverageDatabasePath.path,
7878
)
7979
val fileWithCode = TemporaryFileManager.createTemporaryFile(
8080
runCode,

utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/PythonCodeGenerator.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import org.utbot.python.framework.codegen.model.constructor.visitor.CgPythonRend
3333
import org.utbot.python.framework.codegen.model.tree.CgPythonDict
3434
import org.utbot.python.framework.codegen.model.tree.CgPythonFunctionCall
3535
import org.utbot.python.framework.codegen.model.tree.CgPythonList
36+
import org.utbot.python.framework.codegen.toPythonRawString
3637

3738
class PythonCodeGenerator(
3839
classUnderTest: ClassId,
@@ -128,9 +129,9 @@ class PythonCodeGenerator(
128129
arguments.associateBy { argument -> CgLiteral(pythonStrClassId, "'${argument.name}'") }
129130
)
130131

131-
val fullpath = CgLiteral(pythonStrClassId, "'${method.moduleFilename.replace("\\", "\\\\")}'")
132-
val outputPath = CgLiteral(pythonStrClassId, "'$fileForOutputName'")
133-
val databasePath = CgLiteral(pythonStrClassId, "'$coverageDatabasePath'")
132+
val fullpath = CgLiteral(pythonStrClassId, method.moduleFilename.toPythonRawString())
133+
val outputPath = CgLiteral(pythonStrClassId, fileForOutputName.toPythonRawString())
134+
val databasePath = CgLiteral(pythonStrClassId, coverageDatabasePath.toPythonRawString())
134135

135136
val executorCall = CgPythonFunctionCall(
136137
pythonNoneClassId,

utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/visitor/CgPythonRenderer.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import org.utbot.python.framework.api.python.PythonClassId
6363
import org.utbot.python.framework.api.python.pythonBuiltinsModuleName
6464
import org.utbot.python.framework.api.python.util.pythonAnyClassId
6565
import org.utbot.python.framework.codegen.model.tree.*
66+
import org.utbot.python.framework.codegen.toPythonRawString
6667

6768
internal class CgPythonRenderer(
6869
context: CgRendererContext,
@@ -291,7 +292,7 @@ internal class CgPythonRenderer(
291292

292293
fun renderPythonImport(pythonImport: PythonImport) {
293294
if (pythonImport is PythonSysPathImport) {
294-
println("sys.path.append('${pythonImport.sysPath}')")
295+
println("sys.path.append(${pythonImport.sysPath.toPythonRawString()})")
295296
} else if (pythonImport.moduleName == null) {
296297
println("import ${pythonImport.importName}")
297298
} else {
@@ -541,4 +542,5 @@ internal class CgPythonRenderer(
541542
.replace("'", "\\'")
542543
.replace("\\f", "\\u000C")
543544
.replace("\\xxx", "\\\u0058\u0058\u0058")
544-
}
545+
}
546+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.utbot.python.framework.codegen
2+
3+
4+
fun String.toPythonRawString(): String {
5+
return "r'${this}'"
6+
}

0 commit comments

Comments
 (0)