diff --git a/utbot-python/samples/samples/collections/recursive.py b/utbot-python/samples/samples/collections/recursive.py new file mode 100644 index 0000000000..5d2026f111 --- /dev/null +++ b/utbot-python/samples/samples/collections/recursive.py @@ -0,0 +1,19 @@ +import typing + + +def make_recursive_list(x: int): + xs = [1, 2] + xs.append(xs) + xs.append(x) + return xs + + +def make_recursive_dict(x: int, y: int): + d = {1: 2} + d[x] = d + d[y] = x + return d + + +if __name__ == '__main__': + make_recursive_dict(3, 4) \ No newline at end of file diff --git a/utbot-python/samples/samples/primitives/regex.py b/utbot-python/samples/samples/primitives/regex.py index acee35cc7b..04e4592358 100644 --- a/utbot-python/samples/samples/primitives/regex.py +++ b/utbot-python/samples/samples/primitives/regex.py @@ -6,3 +6,10 @@ def check_regex(string: str) -> bool: if re.match(pattern, string): return True return False + + +def create_pattern(string: str): + if len(string) > 10: + return re.compile(rf"{string}") + else: + return re.compile(string) diff --git a/utbot-python/samples/samples/primitives/str_example.py b/utbot-python/samples/samples/primitives/str_example.py index 834f5ca477..e9e0a8d3c8 100644 --- a/utbot-python/samples/samples/primitives/str_example.py +++ b/utbot-python/samples/samples/primitives/str_example.py @@ -48,4 +48,12 @@ def starts_with(s: str): def join_str(strings: typing.List[str]): - return "--".join(strings) \ No newline at end of file + return "--".join(strings) + + +def separated_str(x: int): + if x == 1: + return r"fjalsdk\\nfjlask" + if 1 < x < 100: + return "fjalsd\n" * x + return x diff --git a/utbot-python/samples/test_configuration.json b/utbot-python/samples/test_configuration.json index 1746e07ba0..91dce2d34c 100644 --- a/utbot-python/samples/test_configuration.json +++ b/utbot-python/samples/test_configuration.json @@ -167,6 +167,17 @@ } ] }, + { + "name": "recursive", + "groups": [ + { + "classes": null, + "methods": null, + "timeout": 30, + "coverage": 100 + } + ] + }, { "name": "sets", "groups": [ @@ -433,7 +444,7 @@ { "classes": null, "methods": null, - "timeout": 40, + "timeout": 50, "coverage": 100 } ] @@ -445,7 +456,7 @@ "classes": null, "methods": null, "timeout": 160, - "coverage": 100 + "coverage": 110 } ] } diff --git a/utbot-python/src/main/kotlin/org/utbot/python/evaluation/serialiation/PythonObjectParser.kt b/utbot-python/src/main/kotlin/org/utbot/python/evaluation/serialiation/PythonObjectParser.kt index 002ebeed0e..5210ad173d 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/evaluation/serialiation/PythonObjectParser.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/evaluation/serialiation/PythonObjectParser.kt @@ -32,6 +32,10 @@ object PythonObjectParser { class MemoryDump( private val objects: MutableMap ) { + fun contains(id: String): Boolean { + return objects.containsKey(id) + } + fun getById(id: String): MemoryObject { return objects[id]!! } @@ -41,7 +45,7 @@ class MemoryDump( } } -class TypeInfo( +data class TypeInfo( val module: String, val kind: String, ) { @@ -88,65 +92,69 @@ class ReduceMemoryObject( val dictitems: String ) : MemoryObject(id, typeinfo, comparable) -fun PythonTree.PythonTreeNode.toMemoryObject(memoryDump: MemoryDump): String { +fun PythonTree.PythonTreeNode.toMemoryObject(memoryDump: MemoryDump, reload: Boolean = false): String { + val id = this.id.toString() + if (memoryDump.contains(id) && !reload) return id + + val typeinfo = TypeInfo(this.type.moduleName, this.type.typeName) val obj = when (this) { is PythonTree.PrimitiveNode -> { ReprMemoryObject( - this.id.toString(), - TypeInfo(this.type.moduleName, this.type.typeName), + id, + typeinfo, this.comparable, - this.repr + this.repr.replace("\n", "\\\n").replace("\r", "\\\r") ) } is PythonTree.ListNode -> { + val draft = ListMemoryObject(id, typeinfo, this.comparable, emptyList()) + memoryDump.addObject(draft) + val items = this.items.entries - .sortedBy { it.key } .map { it.value.toMemoryObject(memoryDump) } - ListMemoryObject( - this.id.toString(), - TypeInfo(this.type.moduleName, this.type.typeName), - this.comparable, - items - ) + ListMemoryObject(id, typeinfo, this.comparable, items) } is PythonTree.TupleNode -> { val items = this.items.entries - .sortedBy { it.key } .map { it.value.toMemoryObject(memoryDump) } - ListMemoryObject( - this.id.toString(), - TypeInfo(this.type.moduleName, this.type.typeName), - this.comparable, - items - ) + ListMemoryObject(id, typeinfo, this.comparable, items) } is PythonTree.SetNode -> { val items = this.items.map { it.toMemoryObject(memoryDump) } - ListMemoryObject( - this.id.toString(), - TypeInfo(this.type.moduleName, this.type.typeName), - this.comparable, - items - ) + ListMemoryObject(id, typeinfo, this.comparable, items) } is PythonTree.DictNode -> { + val draft = DictMemoryObject(id, typeinfo, this.comparable, emptyMap()) + memoryDump.addObject(draft) + val items = this.items.entries .associate { it.key.toMemoryObject(memoryDump) to it.value.toMemoryObject(memoryDump) } - DictMemoryObject( - this.id.toString(), - TypeInfo(this.type.moduleName, this.type.typeName), - this.comparable, - items - ) + DictMemoryObject(id, typeinfo, this.comparable, items) } is PythonTree.ReduceNode -> { + val argsIds = PythonTree.ListNode(this.args.withIndex().associate { it.index to it.value }.toMutableMap()) + val draft = ReduceMemoryObject( + id, + typeinfo, + this.comparable, + TypeInfo( + this.constructor.moduleName, + this.constructor.typeName, + ), + argsIds.toMemoryObject(memoryDump), + "", + "", + "", + ) + memoryDump.addObject(draft) + val stateObjId = if (this.customState) { this.state["state"]!! } else { @@ -154,16 +162,12 @@ fun PythonTree.PythonTreeNode.toMemoryObject(memoryDump: MemoryDump): String { PythonTree.fromString(it.key) to it.value }.toMutableMap()) } - val argsIds = PythonTree.ListNode(this.args.withIndex().associate { it.index to it.value }.toMutableMap()) val listItemsIds = PythonTree.ListNode(this.listitems.withIndex().associate { it.index to it.value }.toMutableMap()) val dictItemsIds = PythonTree.DictNode(this.dictitems.toMutableMap()) ReduceMemoryObject( - this.id.toString(), - TypeInfo( - this.type.moduleName, - this.type.typeName, - ), + id, + typeinfo, this.comparable, TypeInfo( this.constructor.moduleName, @@ -200,33 +204,36 @@ fun MemoryObject.toPythonTree( } is DictMemoryObject -> { - PythonTree.DictNode( + val draft = PythonTree.DictNode( id, - items.entries.associate { - memoryDump.getById(it.key).toPythonTree(memoryDump, visited) to - memoryDump.getById(it.value).toPythonTree(memoryDump, visited) - }.toMutableMap() + mutableMapOf() ) + visited[this.id] = draft + items.entries.map { + draft.items[memoryDump.getById(it.key).toPythonTree(memoryDump, visited)] = + memoryDump.getById(it.value).toPythonTree(memoryDump, visited) + } + draft } is ListMemoryObject -> { - val elementsMap = items.withIndex().associate { - it.index to - memoryDump.getById(it.value).toPythonTree(memoryDump, visited) - }.toMutableMap() - when (this.qualname) { - "builtins.tuple" -> { - PythonTree.TupleNode(this.id.toLong(), elementsMap) - } - - "builtins.set" -> { - PythonTree.SetNode(this.id.toLong(), elementsMap.values.toMutableSet()) - } + val draft = when (this.qualname) { + "builtins.tuple" -> PythonTree.TupleNode(id, mutableMapOf()) + "builtins.set" -> PythonTree.SetNode(id, mutableSetOf()) + else -> PythonTree.ListNode(id, mutableMapOf()) + } + visited[this.id] = draft - else -> { - PythonTree.ListNode(this.id.toLong(), elementsMap) + items.mapIndexed { index, valueId -> + val value = memoryDump.getById(valueId).toPythonTree(memoryDump, visited) + when (draft) { + is PythonTree.TupleNode -> draft.items[index] = value + is PythonTree.SetNode -> draft.items.add(value) + is PythonTree.ListNode -> draft.items[index] = value + else -> {} } } + draft } is ReduceMemoryObject -> { diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonTree.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonTree.kt index 37238b91af..6c1afceaf9 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonTree.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/PythonTree.kt @@ -53,6 +53,10 @@ object PythonTree { open val children: List = emptyList() + fun isRecursive(): Boolean { + return isRecursiveObject(this) + } + override fun toString(): String { return type.name + children.toString() } diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/util/PythonIdUtils.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/util/PythonIdUtils.kt index 5564841403..5cd07a09f5 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/util/PythonIdUtils.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/api/python/util/PythonIdUtils.kt @@ -20,3 +20,4 @@ val pythonSetClassId = PythonClassId("builtins.set") val pythonBytearrayClassId = PythonClassId("builtins.bytearray") val pythonBytesClassId = PythonClassId("builtins.bytes") val pythonExceptionClassId = PythonClassId("builtins.Exception") +val pythonRePatternClassId = PythonClassId("re.Pattern") diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgMethodConstructor.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgMethodConstructor.kt index 88ef4feb91..b4a7863fc8 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgMethodConstructor.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgMethodConstructor.kt @@ -288,7 +288,7 @@ class PythonCgMethodConstructor(context: CgContext) : CgMethodConstructor(contex emptyLineIfNeeded() if (elementsHaveSameStructure) { val index = newVar(pythonNoneClassId, keyName) { - CgLiteral(pythonNoneClassId, "None") + CgPythonRepr(pythonNoneClassId, "None") } forEachLoop { innerBlock { @@ -341,6 +341,12 @@ class PythonCgMethodConstructor(context: CgContext) : CgMethodConstructor(contex depth: Int = maxDepth, useExpectedAsValue: Boolean = false ) { + if (!expectedNode.comparable && expectedNode.isRecursive()) { + emptyLineIfNeeded() + comment("Cannot compare recursive objects") // TODO: add special function for recursive comparison + assertIsInstance(expected, actual) + return + } if (expectedNode.comparable || depth == 0) { val expectedValue = if (useExpectedAsValue) { expected diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgVariableConstructor.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgVariableConstructor.kt index 7410ea4fab..dd2329f73c 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgVariableConstructor.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/tree/PythonCgVariableConstructor.kt @@ -2,7 +2,6 @@ package org.utbot.python.framework.codegen.model.constructor.tree import org.utbot.framework.codegen.domain.context.CgContext import org.utbot.framework.codegen.domain.models.CgConstructorCall -import org.utbot.framework.codegen.domain.models.CgLiteral import org.utbot.framework.codegen.domain.models.CgMethodCall import org.utbot.framework.codegen.domain.models.CgStatement import org.utbot.framework.codegen.domain.models.CgValue @@ -13,9 +12,10 @@ import org.utbot.framework.plugin.api.FieldId import org.utbot.framework.plugin.api.UtModel import org.utbot.python.framework.api.python.* import org.utbot.python.framework.api.python.util.comparePythonTree +import org.utbot.python.framework.api.python.util.pythonDictClassId +import org.utbot.python.framework.api.python.util.pythonListClassId import org.utbot.python.framework.api.python.util.pythonNoneClassId import org.utbot.python.framework.codegen.PythonCgLanguageAssistant -import org.utbot.python.framework.codegen.model.constructor.util.dropBuiltins import org.utbot.python.framework.codegen.model.tree.* class PythonCgVariableConstructor(cgContext: CgContext) : CgVariableConstructor(cgContext) { @@ -35,15 +35,30 @@ class PythonCgVariableConstructor(cgContext: CgContext) : CgVariableConstructor( } } - private fun pythonBuildObject(objectNode: PythonTree.PythonTreeNode, baseName: String? = null): Pair> { + private fun pythonBuildObject(objectNode: PythonTree.PythonTreeNode, baseName: String? = null, depth: Int = 6): Pair> { + val id = objectNode.id + val assistant = (context.cgLanguageAssistant as PythonCgLanguageAssistant) return when (objectNode) { is PythonTree.PrimitiveNode -> { - Pair(CgLiteral(objectNode.type, objectNode.repr), emptyList()) + Pair(CgPythonRepr(objectNode.type, objectNode.repr), emptyList()) } is PythonTree.ListNode -> { - val items = objectNode.items.values.map { pythonBuildObject(it) } - Pair(CgPythonList(items.map {it.first}), items.flatMap { it.second }) + if (PythonTree.isRecursiveObject(objectNode)) { + val obj = PythonTree.ReduceNode( + id, + pythonListClassId, + PythonClassId("builtins.list"), + emptyList(), + mutableMapOf(), + objectNode.items.values.toList(), + emptyMap(), + ) + pythonBuildObject(obj) + } else { + val items = objectNode.items.values.map { pythonBuildObject(it) } + Pair(CgPythonList(items.map { it.first }), items.flatMap { it.second }) + } } is PythonTree.TupleNode -> { @@ -57,21 +72,32 @@ class PythonCgVariableConstructor(cgContext: CgContext) : CgVariableConstructor( } is PythonTree.DictNode -> { - val keys = objectNode.items.keys.map { pythonBuildObject(it) } - val values = objectNode.items.values.map { pythonBuildObject(it) } - Pair( - CgPythonDict( - keys.zip(values).associate { (key, value) -> - key.first to value.first - } - ), - keys.flatMap { it.second } + values.flatMap { it.second } - ) + if (PythonTree.isRecursiveObject(objectNode)) { + val obj = PythonTree.ReduceNode( + id, + pythonDictClassId, + PythonClassId("builtins.dict"), + emptyList(), + mutableMapOf(), + emptyList(), + objectNode.items, + ) + pythonBuildObject(obj) + } else { + val keys = objectNode.items.keys.map { pythonBuildObject(it) } + val values = objectNode.items.values.map { pythonBuildObject(it) } + Pair( + CgPythonDict( + keys.zip(values).associate { (key, value) -> + key.first to value.first + } + ), + keys.flatMap { it.second } + values.flatMap { it.second } + ) + } } is PythonTree.ReduceNode -> { - val id = objectNode.id - val assistant = (context.cgLanguageAssistant as PythonCgLanguageAssistant) if (assistant.memoryObjects.containsKey(id)) { val tree = assistant.memoryObjectsModels[id] val savedObj = assistant.memoryObjects[id] @@ -92,8 +118,8 @@ class PythonCgVariableConstructor(cgContext: CgContext) : CgVariableConstructor( constructorCall } - (context.cgLanguageAssistant as PythonCgLanguageAssistant).memoryObjects[id] = obj - (context.cgLanguageAssistant as PythonCgLanguageAssistant).memoryObjectsModels[id] = objectNode + assistant.memoryObjects[id] = obj + assistant.memoryObjectsModels[id] = objectNode val state = objectNode.state.map { (key, value) -> key to getOrCreateVariable(PythonTreeModel(value, value.type)) diff --git a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/visitor/CgPythonRenderer.kt b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/visitor/CgPythonRenderer.kt index 5c91f5389d..2e1ac560c2 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/visitor/CgPythonRenderer.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/framework/codegen/model/constructor/visitor/CgPythonRenderer.kt @@ -505,7 +505,18 @@ internal class CgPythonRenderer( } override fun visit(element: CgPythonRepr) { - print(element.content.dropBuiltins()) + val content = element.content.dropBuiltins() + if (content.startsWith("\"") && content.endsWith("\"")) { + val realContent = content.slice(1 until content.length - 1) + if (realContent.startsWith("r\\\"") && realContent.endsWith("\\\"")) { // raw string + val innerContent = realContent.slice(5 until realContent.length - 4) + print("r\"${innerContent.replace("\r", "\\r").replace("\n", "\\n")}\"") + } else { + print("\"${realContent.replace("\r", "\\r").replace("\n", "\\n")}\"") + } + } else { + print(content.dropBuiltins()) + } } override fun visit(element: CgPythonIndex) { diff --git a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/PythonApi.kt b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/PythonApi.kt index e3b7b1931c..9d32164be0 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/PythonApi.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/PythonApi.kt @@ -70,6 +70,7 @@ fun pythonDefaultValueProviders(typeStorage: PythonTypeStorage) = listOf( BytesValueProvider, BytearrayValueProvider, ReduceValueProvider, + RePatternValueProvider, ConstantValueProvider, TypeAliasValueProvider, SubtypeValueProvider(typeStorage) diff --git a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/RePatternValueProvider.kt b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/RePatternValueProvider.kt new file mode 100644 index 0000000000..2d7d7054a4 --- /dev/null +++ b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/RePatternValueProvider.kt @@ -0,0 +1,56 @@ +package org.utbot.python.fuzzing.provider + +import org.utbot.fuzzing.Routine +import org.utbot.fuzzing.Seed +import org.utbot.fuzzing.ValueProvider +import org.utbot.fuzzing.seeds.Bool +import org.utbot.fuzzing.seeds.KnownValue +import org.utbot.python.framework.api.python.PythonClassId +import org.utbot.python.framework.api.python.PythonTree +import org.utbot.python.framework.api.python.util.pythonBoolClassId +import org.utbot.python.framework.api.python.util.pythonRePatternClassId +import org.utbot.python.framework.api.python.util.toPythonRepr +import org.utbot.python.fuzzing.PythonFuzzedValue +import org.utbot.python.fuzzing.PythonMethodDescription +import org.utbot.python.fuzzing.provider.utils.generateSummary +import org.utbot.python.fuzzing.provider.utils.isAny +import org.utbot.python.fuzzing.provider.utils.makeRawString +import org.utbot.python.fuzzing.provider.utils.transformRawString +import org.utbot.python.newtyping.general.Type +import org.utbot.python.newtyping.pythonTypeName + +object RePatternValueProvider : ValueProvider{ + override fun accept(type: Type): Boolean { + return type.pythonTypeName() == pythonRePatternClassId.canonicalName + } + + override fun generate(description: PythonMethodDescription, type: Type) = sequence { + yield(Seed.Recursive( + construct = Routine.Create( + listOf( + description.pythonTypeStorage.pythonStr, + ) + ) { v -> + val value = v.first().tree as PythonTree.PrimitiveNode + val rawValue = value.repr.toPythonRepr().makeRawString() + PythonFuzzedValue( + PythonTree.ReduceNode( + pythonRePatternClassId, + PythonClassId("re.compile"), + listOf(PythonTree.fromString(rawValue)) + ), + "%var% = re.compile(${rawValue})" + ) + }, + empty = Routine.Empty { + PythonFuzzedValue( + PythonTree.PrimitiveNode( + pythonRePatternClassId, + "re.compile('')" + ), + "%var% = re.compile('')" + ) + } + )) + } +} \ No newline at end of file diff --git a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/ReduceValueProvider.kt b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/ReduceValueProvider.kt index 4e0c8831af..e9bae290ee 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/ReduceValueProvider.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/ReduceValueProvider.kt @@ -8,13 +8,19 @@ import org.utbot.python.framework.api.python.PythonTree import org.utbot.python.framework.api.python.util.* import org.utbot.python.fuzzing.PythonFuzzedValue import org.utbot.python.fuzzing.PythonMethodDescription +import org.utbot.python.fuzzing.provider.utils.isCallable import org.utbot.python.fuzzing.provider.utils.isConcreteType +import org.utbot.python.fuzzing.provider.utils.isMagic +import org.utbot.python.fuzzing.provider.utils.isPrivate +import org.utbot.python.fuzzing.provider.utils.isProperty +import org.utbot.python.fuzzing.provider.utils.isProtected import org.utbot.python.newtyping.* import org.utbot.python.newtyping.general.FunctionType import org.utbot.python.newtyping.general.Type object ReduceValueProvider : ValueProvider { private val unsupportedTypes = listOf( + pythonRePatternClassId.canonicalName, pythonListClassId.canonicalName, pythonSetClassId.canonicalName, pythonTupleClassId.canonicalName, @@ -35,11 +41,36 @@ object ReduceValueProvider : ValueProvider>().toMutableList() + modifications.addAll(fields.map { field -> + Routine.Call(listOf(field.type)) { instance, arguments -> + val obj = instance.tree as PythonTree.ReduceNode + obj.state[field.meta.name] = arguments.first().tree + } + }) + yieldAll(callConstructors(type, it, modifications.asSequence())) + } + } + + private fun findFields(description: PythonMethodDescription, type: Type): List { + // TODO: here we need to use same as .getPythonAttributeByName but without name + // TODO: now we do not have fields from parents + // TODO: here we should use only attributes from __slots__ + return type.getPythonAttributes().filter { attr -> + !attr.isMagic() && !attr.isProtected() && !attr.isPrivate() && !attr.isProperty() && !attr.isCallable( + description.pythonTypeStorage + ) + } + } + + private fun findConstructors(description: PythonMethodDescription, type: Type): List { val initMethodName = "__init__" val newMethodName = "__new__" val typeDescr = type.pythonDescription() - val constructors = - if (typeDescr is PythonCompositeTypeDescription) { + return if (typeDescr is PythonCompositeTypeDescription) { val mro = typeDescr.mro(description.pythonTypeStorage, type) val initParent = mro.indexOfFirst { p -> p.getPythonAttributes().any { it.meta.name == initMethodName } } val newParent = mro.indexOfFirst { p -> p.getPythonAttributes().any { it.meta.name == newMethodName } } @@ -55,29 +86,6 @@ object ReduceValueProvider : ValueProvider - !(attr.meta.name.startsWith("__") && attr.meta.name.endsWith("__") && attr.meta.name.length >= 4) && - (attr.meta as? PythonVariableDescription)?.isProperty != true && attr.type.getPythonAttributeByName( - description.pythonTypeStorage, - "__call__" - ) == null - } - - val modifications = emptyList>().toMutableList() - modifications.addAll(fields.map { field -> - Routine.Call(listOf(field.type)) { instance, arguments -> - val obj = instance.tree as PythonTree.ReduceNode - obj.state[field.meta.name] = arguments.first().tree - } - }) - yieldAll(callConstructors(type, it, modifications.asSequence())) - } } private fun constructObject( diff --git a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/utils/ProviderUtils.kt b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/utils/ProviderUtils.kt index 80513fed77..024a8f614e 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/utils/ProviderUtils.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/utils/ProviderUtils.kt @@ -6,8 +6,12 @@ import org.utbot.python.fuzzing.PythonFuzzedValue import org.utbot.python.fuzzing.PythonMethodDescription import org.utbot.python.newtyping.PythonAnyTypeDescription import org.utbot.python.newtyping.PythonConcreteCompositeTypeDescription +import org.utbot.python.newtyping.PythonDefinition import org.utbot.python.newtyping.PythonSubtypeChecker +import org.utbot.python.newtyping.PythonTypeStorage +import org.utbot.python.newtyping.PythonVariableDescription import org.utbot.python.newtyping.general.Type +import org.utbot.python.newtyping.getPythonAttributeByName fun Type.isAny(): Boolean { return meta is PythonAnyTypeDescription @@ -25,4 +29,26 @@ fun getSuitableConstantsFromCode(description: PythonMethodDescription, type: Typ fun isConcreteType(type: Type): Boolean { return (type.meta as? PythonConcreteCompositeTypeDescription)?.isAbstract == false +} + +fun PythonDefinition.isProtected(): Boolean { + val name = this.meta.name + return name.startsWith("_") && !this.isMagic() +} + +fun PythonDefinition.isPrivate(): Boolean { + val name = this.meta.name + return name.startsWith("__") && !this.isMagic() +} + +fun PythonDefinition.isMagic(): Boolean { + return this.meta.name.startsWith("__") && this.meta.name.endsWith("__") && this.meta.name.length >= 4 +} + +fun PythonDefinition.isProperty(): Boolean { + return (this.meta as? PythonVariableDescription)?.isProperty == true +} + +fun PythonDefinition.isCallable(typeStorage: PythonTypeStorage): Boolean { + return this.type.getPythonAttributeByName(typeStorage, "__call__") != null } \ No newline at end of file diff --git a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/utils/StringUtils.kt b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/utils/StringUtils.kt index 3704508226..2d413a1ceb 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/utils/StringUtils.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/fuzzing/provider/utils/StringUtils.kt @@ -29,6 +29,14 @@ fun String.transformRawString(): String { } } +fun String.makeRawString(): String { + return if (this.isRawString()) { + this + } else { + "r${this}" + } +} + fun String.isRawString(): Boolean { val rawStringWithDoubleQuotationMarks = this.startsWith("r\"") && this.endsWith("\"") val rawStringWithOneQuotationMarks = this.startsWith("r'") && this.endsWith("'") diff --git a/utbot-python/src/main/kotlin/org/utbot/python/newtyping/general/Type.kt b/utbot-python/src/main/kotlin/org/utbot/python/newtyping/general/Type.kt index 74b202d2fc..4734d6f57f 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/newtyping/general/Type.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/newtyping/general/Type.kt @@ -24,7 +24,11 @@ interface CompositeType: Type { } open class TypeMetaData -open class TypeMetaDataWithName(val name: Name): TypeMetaData() +open class TypeMetaDataWithName(val name: Name): TypeMetaData() { + override fun toString(): String { + return name.toString() + } +} class TypeParameter(val definedAt: Type): Type { // tricky case with cyclic dependency; constraints may be changed after substitution diff --git a/utbot-python/src/main/kotlin/org/utbot/python/utils/RequirementsUtils.kt b/utbot-python/src/main/kotlin/org/utbot/python/utils/RequirementsUtils.kt index 008439aa7f..e9f4720172 100644 --- a/utbot-python/src/main/kotlin/org/utbot/python/utils/RequirementsUtils.kt +++ b/utbot-python/src/main/kotlin/org/utbot/python/utils/RequirementsUtils.kt @@ -3,7 +3,7 @@ package org.utbot.python.utils object RequirementsUtils { val requirements: List = listOf( "mypy==1.0.0", - "utbot-executor==1.4.32", + "utbot-executor==1.4.36", "utbot-mypy-runner==0.2.11", )