Skip to content

Commit

Permalink
Merge pull request #202 from Kotlin/jupyter-codegen-var/val
Browse files Browse the repository at this point in the history
Jupyter codegen isOpen both for var/val
  • Loading branch information
Jolanrensen authored Dec 9, 2022
2 parents b34a541 + a15e1f0 commit 6f3773c
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,18 @@ import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter
import org.jetbrains.kotlinx.dataframe.impl.codeGen.ReplCodeGeneratorImpl
import org.jetbrains.kotlinx.jupyter.api.Code
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty
import kotlin.reflect.KProperty

internal interface ReplCodeGenerator {

fun process(
df: AnyFrame,
property: KProperty<*>? = null,
isMutable: Boolean = property is KMutableProperty?,
): CodeWithConverter

fun process(
row: AnyRow,
property: KProperty<*>? = null,
isMutable: Boolean = property is KMutableProperty?,
): CodeWithConverter

fun process(markerClass: KClass<*>): Code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import org.jetbrains.kotlinx.dataframe.codeGen.MarkersExtractor
import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema
import org.jetbrains.kotlinx.jupyter.api.Code
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.KVisibility
Expand Down Expand Up @@ -45,25 +44,22 @@ internal class ReplCodeGeneratorImpl : ReplCodeGenerator {
else -> null
}

override fun process(row: AnyRow, property: KProperty<*>?, isMutable: Boolean) =
process(row.df(), property, isMutable)
override fun process(row: AnyRow, property: KProperty<*>?): CodeWithConverter = process(row.df(), property)

override fun process(df: AnyFrame, property: KProperty<*>?, isMutable: Boolean): CodeWithConverter {
override fun process(df: AnyFrame, property: KProperty<*>?): CodeWithConverter {
var targetSchema = df.schema()
var isMutable = isMutable

if (property != null) {
val wasProcessedBefore = property in registeredProperties
registeredProperties.add(property)
isMutable = property is KMutableProperty

// maybe property is already properly typed, let's do some checks
val currentMarker = getMarkerClass(property.returnType)
?.takeIf { it.findAnnotation<DataSchema>() != null }
?.let { registeredMarkers[it] ?: MarkersExtractor.get(it) }
if (currentMarker != null) {
// if property is mutable, we need to make sure that its marker type is open in order to let derived data frames be assignable to it
if (!isMutable || currentMarker.isOpen) {
// we need to make sure that the property's marker type is open in order to let derived data frames be assignable to it
if (currentMarker.isOpen) {
val columnSchema = currentMarker.schema
// for mutable properties we do strong typing only at the first processing, after that we allow its type to be more general than actual data frame type
if (wasProcessedBefore || columnSchema == targetSchema) {
Expand All @@ -79,7 +75,7 @@ internal class ReplCodeGeneratorImpl : ReplCodeGenerator {
}
}

return generate(schema = targetSchema, name = markerInterfacePrefix, isOpen = isMutable)
return generate(schema = targetSchema, name = markerInterfacePrefix, isOpen = true)
}

fun generate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class CodeGenerationTests : BaseTest() {
val generated = codeGen.process(df, ::df)
val typeName = ReplCodeGeneratorImpl.markerInterfacePrefix
val expectedDeclaration = """
@DataSchema(isOpen = false)
@DataSchema
interface $typeName
""".trimIndent() + "\n" + expectedProperties(typeName, typeName)
Expand All @@ -84,7 +84,7 @@ class CodeGenerationTests : BaseTest() {
val generated = ReplCodeGenerator.create().process(df[0], property)
val typeName = ReplCodeGeneratorImpl.markerInterfacePrefix
val expectedDeclaration = """
@DataSchema(isOpen = false)
@DataSchema
interface $typeName
""".trimIndent() + "\n" + expectedProperties(typeName, typeName)
Expand Down Expand Up @@ -118,7 +118,7 @@ class CodeGenerationTests : BaseTest() {
""".trimIndent()

val declaration2 = """
@DataSchema(isOpen = false)
@DataSchema
interface $type2
val $dfName<$type2>.age: $dataCol<$intName> @JvmName("${type2}_age") get() = this["age"] as $dataCol<$intName>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.jetbrains.kotlinx.dataframe.codeGen

import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldBeEmpty
import io.kotest.matchers.string.shouldNotBeEmpty
import org.jetbrains.dataframe.impl.codeGen.ReplCodeGenerator
import org.jetbrains.dataframe.impl.codeGen.process
import org.jetbrains.kotlinx.dataframe.ColumnsContainer
Expand Down Expand Up @@ -68,7 +68,7 @@ class ReplCodeGenTests : BaseTest() {
@Test
fun `process derived markers`() {
val repl = ReplCodeGenerator.create()
val code = repl.process(df, isMutable = true).declarations
val code = repl.process(df).declarations

val marker = ReplCodeGeneratorImpl.markerInterfacePrefix
val markerFull = Test1._DataFrameType::class.qualifiedName!!
Expand Down Expand Up @@ -100,10 +100,10 @@ class ReplCodeGenTests : BaseTest() {
code2 shouldBe ""

val df3 = typed.filter { city != null }
val code3 = repl.process(df3, isMutable = false).declarations
val code3 = repl.process(df3).declarations
val marker3 = marker + "1"
val expected3 = """
@DataSchema(isOpen = false)
@DataSchema
interface $marker3 : $markerFull
val $dfName<$marker3>.city: $dataCol<$stringName> @JvmName("${marker3}_city") get() = this["city"] as $dataCol<$stringName>
Expand All @@ -118,10 +118,10 @@ class ReplCodeGenTests : BaseTest() {
code4 shouldBe ""

val df5 = typed.filter { weight != null }
val code5 = repl.process(df5, isMutable = false).declarations
val code5 = repl.process(df5).declarations
val marker5 = marker + "2"
val expected5 = """
@DataSchema(isOpen = false)
@DataSchema
interface $marker5 : $markerFull
val $dfName<$marker5>.weight: $dataCol<$intName> @JvmName("${marker5}_weight") get() = this["weight"] as $dataCol<$intName>
Expand All @@ -144,12 +144,12 @@ class ReplCodeGenTests : BaseTest() {
repl.process<Test2._DataFrameType1>() shouldBe ""

val expected = """
@DataSchema(isOpen = false)
@DataSchema
interface ${Test2._DataFrameType2::class.simpleName!!} : ${Test2._DataFrameType::class.qualifiedName}, ${Test2._DataFrameType1::class.qualifiedName}
""".trimIndent()

val code = repl.process(typed, isMutable = false).declarations.trimIndent()
val code = repl.process(typed).declarations.trimIndent()
code shouldBe expected
}

Expand All @@ -163,7 +163,7 @@ class ReplCodeGenTests : BaseTest() {

val marker = Test2._DataFrameType2::class.simpleName!!
val expected = """
@DataSchema(isOpen = false)
@DataSchema
interface $marker : ${Test2._DataFrameType::class.qualifiedName}
val $dfName<$marker>.city: $dataCol<$stringName?> @JvmName("${marker}_city") get() = this["city"] as $dataCol<$stringName?>
Expand All @@ -176,18 +176,18 @@ class ReplCodeGenTests : BaseTest() {
val $dfRowName<$marker?>.weight: $intName? @JvmName("Nullable${marker}_weight") get() = this["weight"] as $intName?
""".trimIndent()

val code = repl.process(typed, isMutable = false).declarations.trimIndent()
val code = repl.process(typed).declarations.trimIndent()
code shouldBe expected
}

@Test
fun `process overriden property`() {
fun `process overridden property`() {
val repl = ReplCodeGenerator.create()
repl.process<Test3.A>()
repl.process<Test3.B>()
repl.process<Test3.C>()
val c = repl.process(Test3.df, Test3::df)
c.declarations.shouldBeEmpty()
c.declarations.shouldNotBeEmpty()
}

@Test
Expand Down

0 comments on commit 6f3773c

Please sign in to comment.