@@ -19,6 +19,7 @@ import org.utbot.python.framework.api.python.util.pythonStrClassId
1919import org.utbot.python.framework.api.python.util.pythonTupleClassId
2020import org.utbot.python.fuzzing.FuzzedUtType
2121import org.utbot.python.fuzzing.FuzzedUtType.Companion.activateAny
22+ import org.utbot.python.fuzzing.FuzzedUtType.Companion.activateAnyIf
2223import org.utbot.python.fuzzing.FuzzedUtType.Companion.toFuzzed
2324import org.utbot.python.fuzzing.PythonFuzzedValue
2425import org.utbot.python.fuzzing.PythonMethodDescription
@@ -34,6 +35,7 @@ import org.utbot.python.newtyping.PythonCallableTypeDescription
3435import org.utbot.python.newtyping.PythonCompositeTypeDescription
3536import org.utbot.python.newtyping.PythonDefinition
3637import org.utbot.python.newtyping.general.FunctionType
38+ import org.utbot.python.newtyping.general.getBoundedParameters
3739import org.utbot.python.newtyping.getPythonAttributeByName
3840import org.utbot.python.newtyping.getPythonAttributes
3941import org.utbot.python.newtyping.pythonDescription
@@ -66,16 +68,18 @@ object ReduceValueProvider : PythonValueProvider {
6668
6769 override fun generate (description : PythonMethodDescription , type : FuzzedUtType ) = sequence {
6870 val fields = findFields(description, type)
69- findConstructors(description, type)
71+ val modifications = emptyList<Routine .Call <FuzzedUtType , PythonFuzzedValue >>().toMutableList()
72+ modifications.addAll(fields.map { field ->
73+ Routine .Call (listOf (field.type).toFuzzed().activateAnyIf(type)) { instance, arguments ->
74+ val obj = instance.tree as PythonTree .ReduceNode
75+ obj.state[field.meta.name] = arguments.first().tree
76+ }
77+ })
78+
79+ val (constructors, newType) = findConstructors(description, type)
80+ constructors
7081 .forEach {
71- val modifications = emptyList<Routine .Call <FuzzedUtType , PythonFuzzedValue >>().toMutableList()
72- modifications.addAll(fields.map { field ->
73- Routine .Call (listOf (field.type).toFuzzed().activateAny()) { instance, arguments ->
74- val obj = instance.tree as PythonTree .ReduceNode
75- obj.state[field.meta.name] = arguments.first().tree
76- }
77- })
78- yieldAll(callConstructors(type, it, modifications.asSequence(), description))
82+ yieldAll(callConstructors(newType, it, modifications.asSequence(), description))
7983 }
8084 }
8185
@@ -90,25 +94,66 @@ object ReduceValueProvider : PythonValueProvider {
9094 }
9195 }
9296
93- private fun findConstructors (description : PythonMethodDescription , type : FuzzedUtType ): List <PythonDefinition > {
97+ /*
98+ * 1. Annotated __init__ without functional arguments and mro(__init__) <= mro(__new__) -> listOf(__init__)
99+ * 2. Not 1 and annotated __new__ without functional arguments -> listOf(__new__)
100+ * 3. Not 1 and not 2 and __init__ without tp.Any -> listOf(__init__)
101+ * 4. Not 1 and not 2 and not 3 and type is not generic -> listOf(__init__, __new__) + activateAny
102+ * 5. emptyList()
103+ */
104+ private fun findConstructors (description : PythonMethodDescription , type : FuzzedUtType ): Pair <List <PythonDefinition >, FuzzedUtType> {
94105 val initMethodName = " __init__"
95106 val newMethodName = " __new__"
96107 val typeDescr = type.utType.pythonDescription()
97108 return if (typeDescr is PythonCompositeTypeDescription ) {
98109 val mro = typeDescr.mro(description.pythonTypeStorage, type.utType)
99110 val initParent = mro.indexOfFirst { p -> p.getPythonAttributes().any { it.meta.name == initMethodName } }
100111 val newParent = mro.indexOfFirst { p -> p.getPythonAttributes().any { it.meta.name == newMethodName } }
101- val initMethods = type.utType.getPythonAttributeByName(description.pythonTypeStorage, initMethodName)
102- val newMethods = type.utType.getPythonAttributeByName(description.pythonTypeStorage, newMethodName)
103- if (initParent <= newParent && initMethods != null ) {
104- listOf (initMethods)
105- } else if (newMethods != null ) {
106- listOf (newMethods)
112+ val initMethod = type.utType.getPythonAttributeByName(description.pythonTypeStorage, initMethodName)
113+ val newMethod = type.utType.getPythonAttributeByName(description.pythonTypeStorage, newMethodName)
114+
115+ val initWithoutCallable = initMethod?.isCallable(description.pythonTypeStorage) ? : false
116+ val newWithoutCallable = newMethod?.isCallable(description.pythonTypeStorage) ? : false
117+
118+ val initWithoutAny = (initMethod?.type as ? FunctionType )?.arguments?.drop(1 )?.all { ! it.isAny() } ? : false
119+ val newWithoutAny = (initMethod?.type as ? FunctionType )?.arguments?.drop(1 )?.all { ! it.isAny() } ? : false
120+
121+ val isGeneric = type.utType.getBoundedParameters().isNotEmpty()
122+
123+ if (initParent <= newParent && initMethod != null && initWithoutCallable && initWithoutAny) {
124+ listOf (initMethod) to type
125+ } else if (newMethod != null && newWithoutCallable && newWithoutAny) {
126+ listOf (newMethod) to type
127+ } else if (initMethod != null && initWithoutAny) {
128+ listOf (initMethod) to type
129+ } else if (! isGeneric) {
130+ listOfNotNull(initMethod, newMethod) to type.activateAny()
107131 } else {
108- emptyList() // probably not reachable (because of class object)
132+ emptyList< PythonDefinition > () to type
109133 }
110134 } else {
111- emptyList()
135+ emptyList<PythonDefinition >() to type
136+ }
137+ }
138+
139+ private fun callConstructors (
140+ type : FuzzedUtType ,
141+ constructor : PythonDefinition ,
142+ modifications : Sequence <Routine .Call <FuzzedUtType , PythonFuzzedValue >>,
143+ description : PythonMethodDescription ,
144+ ): Sequence <Seed .Recursive <FuzzedUtType , PythonFuzzedValue >> = sequence {
145+ val constructors = emptyList<FunctionType >().toMutableList()
146+ if (constructor .type.pythonTypeName() == " Overload" ) {
147+ constructor .type.parameters.forEach {
148+ if (it is FunctionType ) {
149+ constructors.add(it)
150+ }
151+ }
152+ } else {
153+ constructors.add(constructor .type as FunctionType )
154+ }
155+ constructors.forEach {
156+ yield (constructObject(type, it, modifications, description))
112157 }
113158 }
114159
@@ -154,7 +199,7 @@ object ReduceValueProvider : PythonValueProvider {
154199 val newMethodArgs = (newMethod?.type as FunctionType ? )?.arguments
155200 return if (newMethodArgs != null && newMethodArgs.size == 1 ) {
156201 val classId = PythonClassId (type.pythonModuleName(), type.pythonName())
157- Routine .Create (newMethodArgs.toFuzzed().activateAny( )) { v ->
202+ Routine .Create (newMethodArgs.toFuzzed().activateAnyIf(type )) { _ ->
158203 PythonFuzzedValue (
159204 PythonTree .ReduceNode (
160205 classId,
@@ -182,7 +227,7 @@ object ReduceValueProvider : PythonValueProvider {
182227 val positionalArgs = typeDescription.argumentKinds.count { it == PythonCallableTypeDescription .ArgKind .ARG_POS }
183228 val arguments = constructorFunction.arguments.take(positionalArgs)
184229 val nonSelfArgs = arguments.drop(1 )
185- return Routine .Create (nonSelfArgs.toFuzzed()) { v ->
230+ return Routine .Create (nonSelfArgs.toFuzzed().activateAnyIf(type) ) { v ->
186231 PythonFuzzedValue (
187232 PythonTree .ReduceNode (
188233 PythonClassId (type.pythonModuleName(), type.pythonName()),
@@ -195,26 +240,4 @@ object ReduceValueProvider : PythonValueProvider {
195240 }
196241 }
197242
198-
199-
200- private fun callConstructors (
201- type : FuzzedUtType ,
202- constructor : PythonDefinition ,
203- modifications : Sequence <Routine .Call <FuzzedUtType , PythonFuzzedValue >>,
204- description : PythonMethodDescription ,
205- ): Sequence <Seed .Recursive <FuzzedUtType , PythonFuzzedValue >> = sequence {
206- val constructors = emptyList<FunctionType >().toMutableList()
207- if (constructor .type.pythonTypeName() == " Overload" ) {
208- constructor .type.parameters.forEach {
209- if (it is FunctionType ) {
210- constructors.add(it)
211- }
212- }
213- } else {
214- constructors.add(constructor .type as FunctionType )
215- }
216- constructors.forEach {
217- yield (constructObject(type, it, modifications, description))
218- }
219- }
220243}
0 commit comments