Skip to content

Commit fe50298

Browse files
Add support for set container; make standard Arrays have values descriptors right away, not through 'size' and 'data' fields
1 parent 476a883 commit fe50298

File tree

3 files changed

+132
-25
lines changed

3 files changed

+132
-25
lines changed

src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ class ReplForJupyterImpl(
453453
notebook.updateVariablesState(internalEvaluator)
454454
// printVars()
455455
// printUsagesInfo(jupyterId, cellVariables[jupyterId - 1])
456-
val serializedData = variablesSerializer.serializeVariables(jupyterId - 1, notebook.variablesState)
456+
val serializedData = variablesSerializer.serializeVariables(jupyterId - 1, notebook.variablesState, notebook.unchangedVariables())
457457

458458

459459
val variablesStateUpdate = notebook.variablesState.mapValues { "" }

src/main/kotlin/org/jetbrains/kotlinx/jupyter/serializationUtils.kt

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,17 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
117117
} catch (ex: Exception) {null}
118118
val serializedVersion = SerializedVariablesState(simpleTypeName, getProperString(value), true)
119119
val descriptors = serializedVersion.fieldDescriptor
120+
121+
// only for set case
122+
if (simpleTypeName == "Set" && kProperties == null) {
123+
value as Set<*>
124+
val size = value.size
125+
descriptors["size"] = createSerializeVariableState(
126+
"size", "Int", size
127+
).serializedVariablesState
128+
descriptors.addDescriptor(value, "data")
129+
}
130+
120131
if (isDescriptorsNeeded) {
121132
kProperties?.forEach { prop ->
122133
val name = prop.name
@@ -206,7 +217,8 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
206217
Float::class.java,
207218
Double::class.java,
208219
Char::class.java,
209-
Boolean::class.java
220+
Boolean::class.java,
221+
String::class.java
210222
)
211223

212224
/**
@@ -219,9 +231,9 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
219231
/**
220232
* Cache for not recomputing unchanged variables
221233
*/
222-
val serializedVariablesCache: MutableMap<String, SerializedVariablesState> = mutableMapOf()
234+
private val serializedVariablesCache: MutableMap<String, SerializedVariablesState> = mutableMapOf()
223235

224-
fun serializeVariables(cellId: Int, variablesState: Map<String, VariableState>): Map<String, SerializedVariablesState> {
236+
fun serializeVariables(cellId: Int, variablesState: Map<String, VariableState>, unchangedVariables: Set<String>): Map<String, SerializedVariablesState> {
225237
if (!isSerializationActive) return emptyMap()
226238

227239
if (seenObjectsPerCell.containsKey(cellId)) {
@@ -231,7 +243,12 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
231243
return emptyMap()
232244
}
233245
currentSerializeCount = 0
234-
return variablesState.mapValues { serializeVariableState(cellId, it.key, it.value) }
246+
247+
val neededEntries = variablesState.filterKeys { unchangedVariables.contains(it) }
248+
249+
val serializedData = neededEntries.mapValues { serializeVariableState(cellId, it.key, it.value) }
250+
serializedVariablesCache.putAll(serializedData)
251+
return serializedVariablesCache
235252
}
236253

237254
fun doIncrementalSerialization(cellId: Int, propertyName: String, serializedVariablesState: SerializedVariablesState): SerializedVariablesState {
@@ -307,6 +324,7 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
307324
}
308325
iterateThroughContainerMembers(cellId, value.objectInstance, serializedVersion.fieldDescriptor, currentCellDescriptors.processedSerializedVarsToJavaProperties[serializedVersion])
309326
}
327+
310328
return processedData.serializedVariablesState
311329
}
312330

@@ -318,7 +336,19 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
318336
kProperties: KPropertiesData? = null,
319337
currentDepth: Int = 0
320338
) {
321-
if ((properties == null && kProperties == null) || callInstance == null || currentDepth >= serializationDepth) return
339+
fun iterateAndStoreValues(callInstance: Any, descriptorsState: MutableMap<String, SerializedVariablesState?>) {
340+
if (callInstance is Collection<*>) {
341+
callInstance.forEach {
342+
descriptorsState.addDescriptor(it)
343+
}
344+
} else if (callInstance is Array<*>) {
345+
callInstance.forEach {
346+
descriptorsState.addDescriptor(it)
347+
}
348+
}
349+
}
350+
351+
if ((properties == null && kProperties == null && callInstance !is Set<*>) || callInstance == null || currentDepth >= serializationDepth) return
322352

323353
val serializedIteration = mutableMapOf<String, ProcessedSerializedVarsState>()
324354

@@ -353,6 +383,17 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
353383
val isArrayType = checkForPossibleArray(callInstance)
354384
computedDescriptorsPerCell[cellId]!!.instancesPerState += instancesPerState
355385

386+
if (descriptor.size == 2 && descriptor.containsKey("data")) {
387+
val listData = descriptor["data"]?.fieldDescriptor ?: return
388+
if (descriptor.containsKey("size") && descriptor["size"]?.value == "null") {
389+
descriptor.remove("size")
390+
descriptor.remove("data")
391+
iterateAndStoreValues(callInstance, descriptor)
392+
} else {
393+
iterateAndStoreValues(callInstance, listData)
394+
}
395+
}
396+
356397
serializedIteration.forEach {
357398
val serializedVariablesState = it.value.serializedVariablesState
358399
val name = it.key
@@ -379,7 +420,7 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
379420
)
380421
}
381422
}
382-
423+
/*
383424
if (descriptor.size == 2 && descriptor.containsKey("data")) {
384425
val listData = descriptor["data"]?.fieldDescriptor ?: return
385426
if (callInstance is Collection<*>) {
@@ -391,7 +432,7 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
391432
listData.addDescriptor(it)
392433
}
393434
}
394-
}
435+
}*/
395436
}
396437

397438
/**
@@ -480,7 +521,7 @@ class VariablesSerializer(private val serializationDepth: Int = 2, private val s
480521
}
481522

482523
val isContainer = if (membersProperties != null) (
483-
!primitiveWrappersSet.contains(javaClass) && membersProperties.isNotEmpty() || value::class.java.isArray || (javaClass.isMemberClass)
524+
!primitiveWrappersSet.contains(javaClass) && membersProperties.isNotEmpty() || value is Set<*> || value::class.java.isArray || javaClass.isMemberClass
484525
) else false
485526
val type = if (value != null && value::class.java.isArray) {
486527
"Array"

src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/repl/ReplTests.kt

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -639,18 +639,23 @@ class ReplVarsTest : AbstractSingleReplTest() {
639639
"""
640640
val x = 124
641641
private var f = "abcd"
642-
""".trimIndent()
642+
""".trimIndent(),
643+
jupyterId = 1
643644
)
644645
val state = repl.notebook.cellVariables
645646
assertTrue(state.isNotEmpty())
647+
648+
// f is not accessible from here
646649
eval(
647650
"""
648651
private var z = 1
649652
z += x
650-
""".trimIndent()
653+
""".trimIndent(),
654+
jupyterId = 1
651655
)
652656
assertTrue(state.isNotEmpty())
653657

658+
// TODO discuss if we really want this
654659
val setOfCell = setOf("z", "f", "x")
655660
assertTrue(state.containsValue(setOfCell))
656661
}
@@ -817,6 +822,7 @@ class ReplVarsSerializationTest : AbstractSingleReplTest() {
817822

818823
val serializer = repl.variablesSerializer
819824
val newData = serializer.doIncrementalSerialization(0, "data", actualContainer)
825+
val a = 1
820826
}
821827

822828
@Test
@@ -900,13 +906,7 @@ class ReplVarsSerializationTest : AbstractSingleReplTest() {
900906
val serializer = repl.variablesSerializer
901907

902908
val newData = serializer.doIncrementalSerialization(0, listData.fieldDescriptor.entries.first().key, actualContainer)
903-
var receivedDescriptor = newData.fieldDescriptor
904-
assertEquals(2, receivedDescriptor.size)
905-
assertTrue(receivedDescriptor.containsKey("size"))
906-
907-
val innerList = receivedDescriptor.entries.last().value!!
908-
assertTrue(innerList.isContainer)
909-
receivedDescriptor = innerList.fieldDescriptor
909+
val receivedDescriptor = newData.fieldDescriptor
910910
assertEquals(4, receivedDescriptor.size)
911911

912912
var values = 1
@@ -954,13 +954,61 @@ class ReplVarsSerializationTest : AbstractSingleReplTest() {
954954
assertEquals(3, newDescriptor["data"]!!.fieldDescriptor.size)
955955
val ansSet = mutableSetOf("a", "b", "c")
956956
newDescriptor["data"]!!.fieldDescriptor.forEach { (_, state) ->
957-
assertTrue(state!!.isContainer)
957+
assertFalse(state!!.isContainer)
958958
assertTrue(ansSet.contains(state.value))
959959
ansSet.remove(state.value)
960960
}
961961
assertTrue(ansSet.isEmpty())
962962
}
963963

964+
965+
@Test
966+
fun testSetContainer() {
967+
var res = eval(
968+
"""
969+
val x = setOf("a", "b", "cc", "c")
970+
""".trimIndent(),
971+
jupyterId = 1
972+
)
973+
var varsData = res.metadata.evaluatedVariablesState
974+
assertEquals(1, varsData.size)
975+
assertTrue(varsData.containsKey("x"))
976+
977+
var setData = varsData["x"]!!
978+
assertTrue(setData.isContainer)
979+
assertEquals(2, setData.fieldDescriptor.size)
980+
var setDescriptors = setData.fieldDescriptor
981+
assertEquals("4", setDescriptors["size"]!!.value)
982+
assertTrue(setDescriptors["data"]!!.isContainer)
983+
assertEquals(4, setDescriptors["data"]!!.fieldDescriptor.size)
984+
assertEquals("a", setDescriptors["data"]!!.fieldDescriptor["a"]!!.value)
985+
assertTrue(setDescriptors["data"]!!.fieldDescriptor.containsKey("b"))
986+
assertTrue(setDescriptors["data"]!!.fieldDescriptor.containsKey("cc"))
987+
assertTrue(setDescriptors["data"]!!.fieldDescriptor.containsKey("c"))
988+
989+
res = eval(
990+
"""
991+
val c = mutableSetOf("a", "b", "cc", "c")
992+
""".trimIndent(),
993+
jupyterId = 2
994+
)
995+
varsData = res.metadata.evaluatedVariablesState
996+
assertEquals(2, varsData.size)
997+
assertTrue(varsData.containsKey("c"))
998+
999+
setData = varsData["c"]!!
1000+
assertTrue(setData.isContainer)
1001+
assertEquals(2, setData.fieldDescriptor.size)
1002+
setDescriptors = setData.fieldDescriptor
1003+
assertEquals("4", setDescriptors["size"]!!.value)
1004+
assertTrue(setDescriptors["data"]!!.isContainer)
1005+
assertEquals(4, setDescriptors["data"]!!.fieldDescriptor.size)
1006+
assertEquals("a", setDescriptors["data"]!!.fieldDescriptor["a"]!!.value)
1007+
assertTrue(setDescriptors["data"]!!.fieldDescriptor.containsKey("b"))
1008+
assertTrue(setDescriptors["data"]!!.fieldDescriptor.containsKey("cc"))
1009+
assertTrue(setDescriptors["data"]!!.fieldDescriptor.containsKey("c"))
1010+
}
1011+
9641012
@Test
9651013
fun testSerializationMessage() {
9661014
val res = eval(
@@ -983,9 +1031,7 @@ class ReplVarsSerializationTest : AbstractSingleReplTest() {
9831031

9841032
val innerList = data.entries.last().value
9851033
assertTrue(innerList.isContainer)
986-
var receivedDescriptor = innerList.fieldDescriptor
987-
assertEquals(2, receivedDescriptor.size)
988-
receivedDescriptor = receivedDescriptor.entries.last().value!!.fieldDescriptor
1034+
val receivedDescriptor = innerList.fieldDescriptor
9891035

9901036
assertEquals(4, receivedDescriptor.size)
9911037
var values = 1
@@ -1005,9 +1051,8 @@ class ReplVarsSerializationTest : AbstractSingleReplTest() {
10051051

10061052
val innerList = data.entries.last().value
10071053
assertTrue(innerList.isContainer)
1008-
var receivedDescriptor = innerList.fieldDescriptor
1009-
assertEquals(2, receivedDescriptor.size)
1010-
receivedDescriptor = receivedDescriptor.entries.last().value!!.fieldDescriptor
1054+
val receivedDescriptor = innerList.fieldDescriptor
1055+
10111056

10121057
assertEquals(4, receivedDescriptor.size)
10131058
var values = 1
@@ -1058,5 +1103,26 @@ class ReplVarsSerializationTest : AbstractSingleReplTest() {
10581103
)
10591104
assertTrue(state.isNotEmpty())
10601105
assertEquals(state, setOfPrevCell)
1106+
1107+
1108+
eval(
1109+
"""
1110+
private val x = 341
1111+
protected val z = "abcd"
1112+
""".trimIndent(),
1113+
jupyterId = 1
1114+
)
1115+
assertTrue(state.isEmpty())
1116+
1117+
eval(
1118+
"""
1119+
private val x = "abcd"
1120+
var f = 47
1121+
internal val z = 47
1122+
""".trimIndent(),
1123+
jupyterId = 1
1124+
)
1125+
assertTrue(state.isNotEmpty())
1126+
assertEquals(setOfPrevCell, state)
10611127
}
10621128
}

0 commit comments

Comments
 (0)