diff --git a/core/api/core.api b/core/api/core.api index 4784802faf..b86d791bae 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -2739,17 +2739,6 @@ public abstract interface class org/jetbrains/kotlinx/dataframe/api/KeyValueProp public abstract fun getValue ()Ljava/lang/Object; } -public final class org/jetbrains/kotlinx/dataframe/api/KeyValueProperty_ExtensionsKt { - public static final fun KeyValueProperty_key (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; - public static final fun KeyValueProperty_key (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; - public static final fun KeyValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; - public static final fun KeyValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; - public static final fun NullableKeyValueProperty_key (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; - public static final fun NullableKeyValueProperty_key (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; - public static final fun NullableKeyValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; - public static final fun NullableKeyValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; -} - public abstract interface class org/jetbrains/kotlinx/dataframe/api/LastColumnsSelectionDsl { public fun last (Lorg/jetbrains/kotlinx/dataframe/api/ColumnsSelectionDsl;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn; public fun last (Lorg/jetbrains/kotlinx/dataframe/columns/ColumnSet;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn; @@ -3466,15 +3455,15 @@ public final class org/jetbrains/kotlinx/dataframe/api/MoveKt { public static final fun under (Lorg/jetbrains/kotlinx/dataframe/api/MoveClause;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnAccessor;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; } -public final class org/jetbrains/kotlinx/dataframe/api/NameValuePair { +public final class org/jetbrains/kotlinx/dataframe/api/NameValuePair : org/jetbrains/kotlinx/dataframe/api/NameValueProperty { public fun (Ljava/lang/String;Ljava/lang/Object;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/Object; public final fun copy (Ljava/lang/String;Ljava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/NameValuePair; public static synthetic fun copy$default (Lorg/jetbrains/kotlinx/dataframe/api/NameValuePair;Ljava/lang/String;Ljava/lang/Object;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/NameValuePair; public fun equals (Ljava/lang/Object;)Z - public final fun getName ()Ljava/lang/String; - public final fun getValue ()Ljava/lang/Object; + public fun getName ()Ljava/lang/String; + public fun getValue ()Ljava/lang/Object; public fun hashCode ()I public fun toString ()Ljava/lang/String; } @@ -3490,6 +3479,37 @@ public final class org/jetbrains/kotlinx/dataframe/api/NameValuePair_ExtensionsK public static final fun NullableNameValuePair_value (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; } +public abstract interface class org/jetbrains/kotlinx/dataframe/api/NameValueProperty { + public abstract fun getName ()Ljava/lang/String; + public abstract fun getValue ()Ljava/lang/Object; +} + +public final class org/jetbrains/kotlinx/dataframe/api/NameValuePropertyKt { + public static final fun KeyValueProperty_key (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun KeyValueProperty_key (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; + public static final fun KeyValueProperty_name (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun KeyValueProperty_name (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; + public static final fun KeyValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun KeyValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; + public static final fun NullableKeyValueProperty_key (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun NullableKeyValueProperty_key (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; + public static final fun NullableKeyValueProperty_name (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun NullableKeyValueProperty_name (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; + public static final fun NullableKeyValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun NullableKeyValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; +} + +public final class org/jetbrains/kotlinx/dataframe/api/NameValueProperty_ExtensionsKt { + public static final fun NameValueProperty_name (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun NameValueProperty_name (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; + public static final fun NameValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun NameValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; + public static final fun NullableNameValueProperty_name (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun NullableNameValueProperty_name (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; + public static final fun NullableNameValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun NullableNameValueProperty_value (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; +} + public abstract interface class org/jetbrains/kotlinx/dataframe/api/NoneColumnsSelectionDsl { public fun none ()Lorg/jetbrains/kotlinx/dataframe/columns/ColumnsResolver; } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/ImportDataSchema.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/ImportDataSchema.kt index 3f7e0d576c..114e124e8d 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/ImportDataSchema.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/ImportDataSchema.kt @@ -1,7 +1,7 @@ package org.jetbrains.kotlinx.dataframe.annotations import org.jetbrains.kotlinx.dataframe.api.JsonPath -import org.jetbrains.kotlinx.dataframe.api.KeyValueProperty +import org.jetbrains.kotlinx.dataframe.api.NameValueProperty import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.columns.FrameColumn import org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers @@ -78,7 +78,7 @@ public annotation class JsonOptions( * */ public val typeClashTactic: String = TypeClashTactics.ARRAY_AND_VALUE_COLUMNS, /** - * List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * * Example: diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataRowApi.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataRowApi.kt index 70e6a9d285..67f8d62982 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataRowApi.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataRowApi.kt @@ -41,7 +41,7 @@ public inline fun AnyRow.valuesOf(): List = values().filterIsInst // region DataSchema @DataSchema @RequiredByIntellijPlugin -public data class NameValuePair(val name: String, val value: V) +public data class NameValuePair(override val name: String, override val value: V) : NameValueProperty // Without these overloads row.transpose().name or row.map { name } won't resolve public val ColumnsContainer>.name: DataColumn diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/KeyValueProperty.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/KeyValueProperty.kt deleted file mode 100644 index 56a52c2f3d..0000000000 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/KeyValueProperty.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.api - -import org.jetbrains.kotlinx.dataframe.annotations.ColumnName -import org.jetbrains.kotlinx.dataframe.annotations.DataSchema - -/** A [DataSchema] interface / class can implement this if it represents a map-like data schema (so key: value). */ -@DataSchema -public interface KeyValueProperty { - // needs to be explicitly overridden in @DataSchema interface, otherwise extension functions won't generate (TODO) - public val key: String - - // needs to be explicitly overridden in @DataSchema interface, otherwise type will be read as `T` and extensions won't generate (TODO) - @ColumnName("value") - public val `value`: T -} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/NameValueProperty.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/NameValueProperty.kt new file mode 100644 index 0000000000..53724a35df --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/NameValueProperty.kt @@ -0,0 +1,117 @@ +@file:Suppress("UNCHECKED_CAST", "DEPRECATION") + +package org.jetbrains.kotlinx.dataframe.api + +import org.jetbrains.kotlinx.dataframe.ColumnsScope +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.DataRow +import org.jetbrains.kotlinx.dataframe.annotations.ColumnName +import org.jetbrains.kotlinx.dataframe.annotations.DataSchema +import org.jetbrains.kotlinx.dataframe.util.KEY_VALUE_PROPERTY +import org.jetbrains.kotlinx.dataframe.util.KEY_VALUE_PROPERTY_KEY + +/** A [DataSchema] interface / class can implement this if it represents a map-like data schema (so name: value). */ +@DataSchema +public interface NameValueProperty { + // needs to be explicitly overridden in @DataSchema interface, otherwise extension functions won't generate (TODO) + public val name: String + + // needs to be explicitly overridden in @DataSchema interface, otherwise type will be read as `T` and extensions won't generate (TODO) + @ColumnName("value") + public val `value`: T +} + +// region Deprecated + +/** A [DataSchema] interface / class can implement this if it represents a map-like data schema (so key: value). */ +@Deprecated(KEY_VALUE_PROPERTY, ReplaceWith("NameValueProperty")) +public interface KeyValueProperty { + // needs to be explicitly overridden in @DataSchema interface, otherwise extension functions won't generate (TODO) + public val key: String + + // needs to be explicitly overridden in @DataSchema interface, otherwise type will be read as `T` and extensions won't generate (TODO) + @ColumnName("value") + public val `value`: T +} + +@Deprecated(KEY_VALUE_PROPERTY_KEY, ReplaceWith("name")) +public val ColumnsScope>.key: DataColumn + @JvmName("KeyValueProperty_key") + get() = this["key"].cast() + +@Deprecated(KEY_VALUE_PROPERTY_KEY, ReplaceWith("name")) +public val ColumnsScope?>.key: DataColumn + @JvmName("NullableKeyValueProperty_key") + get() = this["key"].cast() + +@Deprecated(KEY_VALUE_PROPERTY_KEY, ReplaceWith("name")) +public val DataRow>.key: String + @JvmName("KeyValueProperty_key") + get() = this["key"] as String + +@Deprecated(KEY_VALUE_PROPERTY_KEY, ReplaceWith("name")) +public val DataRow?>.key: String? + @JvmName("NullableKeyValueProperty_key") + get() = this["key"] as String? + +/** + * Accesses the 'key' column of this [KeyValueProperty][KeyValueProperty] + * [ColumnsContainer][org.jetbrains.kotlinx.dataframe.ColumnsContainer]. + * + * This is a temporary, future-proof, extension property in preparation of the migration from [KeyValueProperty] + * to [NameValueProperty]. + */ +public val ColumnsScope>.name: DataColumn + @JvmName("KeyValueProperty_name") + get() = key + +/** + * Accesses the 'key' column of this [KeyValueProperty][KeyValueProperty] + * [ColumnsContainer][org.jetbrains.kotlinx.dataframe.ColumnsContainer]. + * + * This is a temporary, future-proof, extension property in preparation of the migration from [KeyValueProperty] + * to [NameValueProperty]. + */ +public val ColumnsScope?>.name: DataColumn + @JvmName("NullableKeyValueProperty_name") + get() = key + +/** + * Accesses the 'key' value of this [KeyValueProperty][KeyValueProperty] + * [DataRow][DataRow]. + * + * This is a temporary, future-proof, extension property in preparation of the migration from [KeyValueProperty] + * to [NameValueProperty]. + */ +public val DataRow>.name: String + @JvmName("KeyValueProperty_name") + get() = key + +/** + * Accesses the 'key' value of this [KeyValueProperty][KeyValueProperty] + * [DataRow][DataRow]. + * + * This is a temporary, future-proof, extension property in preparation of the migration from [KeyValueProperty] + * to [NameValueProperty]. + */ +public val DataRow?>.name: String? + @JvmName("NullableKeyValueProperty_name") + get() = key + +public val ColumnsScope>.value: DataColumn + @JvmName("KeyValueProperty_value") + get() = this["value"].cast() + +public val ColumnsScope?>.value: DataColumn + @JvmName("NullableKeyValueProperty_value") + get() = this["value"].cast() + +public val DataRow>.value: T + @JvmName("KeyValueProperty_value") + get() = this["value"] as T + +public val DataRow?>.value: T? + @JvmName("NullableKeyValueProperty_value") + get() = this["value"] as T? + +// endregion diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt index 7f32155553..86173d6c66 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt @@ -263,6 +263,10 @@ internal const val COPY_REPLACE = "columns().toDataFrame().cast()" internal const val LISTS_TO_DATAFRAME_MIGRATION = "Function moved from io to api package, and a new `header` parameter is introduced. $MESSAGE_1_1" +internal const val KEY_VALUE_PROPERTY = "Deprecated in favor of NameValueProperty. $MESSAGE_1_1" +internal const val KEY_VALUE_PROPERTY_KEY = + "This column will be renamed to 'name' when KeyValueProperty will be replaced with NameValueProperty. $MESSAGE_1_1" + // endregion // region keep across releases diff --git a/dataframe-json/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/io/readJson.kt b/dataframe-json/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/io/readJson.kt index 775481c337..3b528194f1 100644 --- a/dataframe-json/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/io/readJson.kt +++ b/dataframe-json/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/io/readJson.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.api.JsonPath -import org.jetbrains.kotlinx.dataframe.api.KeyValueProperty +import org.jetbrains.kotlinx.dataframe.api.NameValueProperty import org.jetbrains.kotlinx.dataframe.api.cast import org.jetbrains.kotlinx.dataframe.api.chunked import org.jetbrains.kotlinx.dataframe.api.columnOf @@ -67,7 +67,7 @@ private enum class AnyColType { OBJECTS, } -internal interface AnyKeyValueProperty : KeyValueProperty { +internal interface AnyNameValueProperty : NameValueProperty { override val value: Any? } @@ -122,7 +122,7 @@ internal fun readJsonImpl( * * @param records List of json elements to be converted to a [DataFrame]. * @param unifyNumbers Whether to [unify the numbers that are read][UnifyingNumbers]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param header Optional list of column names. If given, [records] will be read like an object with [header] being the keys. * @return [DataFrame] from the given [records]. @@ -340,22 +340,22 @@ internal fun fromJsonListAnyColumns( valueTypes += valueType dataFrameOf( - columnOf(*map.keys.toTypedArray()).named(KeyValueProperty<*>::key.name), + columnOf(*map.keys.toTypedArray()).named(NameValueProperty<*>::name.name), createColumnGuessingType( values = map.values, suggestedType = TypeSuggestion.Use(valueType), unifyNumbers = unifyNumbers, - ).named(KeyValueProperty<*>::value.name), + ).named(NameValueProperty<*>::value.name), ) } - is JsonNull, null -> DataFrame.emptyOf() + is JsonNull, null -> DataFrame.emptyOf() else -> error("Expected JsonObject, got $record") } } - val valueColumns = dataFrames.map { it[KeyValueProperty<*>::value.name] } + val valueColumns = dataFrames.map { it[NameValueProperty<*>::value.name] } val valueColumnSchema = when { // in these cases we can safely combine the columns to get a single column schema valueColumns.all { it is ColumnGroup<*> } || valueColumns.all { it is FrameColumn<*> } -> @@ -373,8 +373,8 @@ internal fun fromJsonListAnyColumns( schema = lazy { DataFrameSchemaImpl( columns = mapOf( - KeyValueProperty<*>::key.name to ColumnSchema.Value(typeOf()), - KeyValueProperty<*>::value.name to valueColumnSchema, + NameValueProperty<*>::name.name to ColumnSchema.Value(typeOf()), + NameValueProperty<*>::value.name to valueColumnSchema, ), ) }, @@ -443,7 +443,7 @@ private fun AnyFrame.isSingleUnnamedColumn() = columnsCount() == 1 && getColumn( * * @param records List of json elements to be converted to a [DataFrame]. * @param unifyNumbers Whether to [unify the numbers that are read][UnifyingNumbers]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param header Optional list of column names. If given, [records] will be read like an object with [header] being the keys. * @return [DataFrame] from the given [records]. @@ -527,16 +527,16 @@ internal fun fromJsonListArrayAndValueColumns( .commonType() dataFrameOf( - columnOf(*map.keys.toTypedArray()).named(KeyValueProperty<*>::key.name), + columnOf(*map.keys.toTypedArray()).named(NameValueProperty<*>::name.name), createColumnGuessingType( values = map.values, suggestedType = TypeSuggestion.Use(valueType), unifyNumbers = unifyNumbers, - ).named(KeyValueProperty<*>::value.name), + ).named(NameValueProperty<*>::value.name), ) } - is JsonNull, null -> DataFrame.emptyOf() + is JsonNull, null -> DataFrame.emptyOf() else -> error("Expected JsonObject, got $record") } diff --git a/dataframe-json/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/json.kt b/dataframe-json/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/json.kt index a6acaeab3a..4cb4e5a3ec 100644 --- a/dataframe-json/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/json.kt +++ b/dataframe-json/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/json.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.api.FormattedFrame import org.jetbrains.kotlinx.dataframe.api.JsonPath -import org.jetbrains.kotlinx.dataframe.api.KeyValueProperty +import org.jetbrains.kotlinx.dataframe.api.NameValueProperty import org.jetbrains.kotlinx.dataframe.api.single import org.jetbrains.kotlinx.dataframe.codeGen.AbstractDefaultReadMethod import org.jetbrains.kotlinx.dataframe.codeGen.DefaultReadDfMethod @@ -132,7 +132,7 @@ internal const val VALUE_COLUMN_NAME: String = "value" /** * @param file Where to fetch the Json as [InputStream] to be converted to a [DataFrame]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, the file will be read like an object with [header] being the keys. @@ -149,7 +149,7 @@ public fun DataFrame.Companion.readJson( /** * @param file Where to fetch the Json as [InputStream] to be converted to a [DataRow]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, the file will be read like an object with [header] being the keys. @@ -166,7 +166,7 @@ public fun DataRow.Companion.readJson( /** * @param path URL or file path from where to fetch the Json as [InputStream] to be converted to a [DataFrame]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, the stream will be read like an object with [header] being the keys. @@ -183,7 +183,7 @@ public fun DataFrame.Companion.readJson( /** * @param path URL or file path from where to fetch the Json as [InputStream] to be converted to a [DataRow]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, the stream will be read like an object with [header] being the keys. @@ -200,7 +200,7 @@ public fun DataRow.Companion.readJson( /** * @param url Where to fetch the Json as [InputStream] to be converted to a [DataFrame]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, the stream will be read like an object with [header] being the keys. @@ -217,7 +217,7 @@ public fun DataFrame.Companion.readJson( /** * @param url Where to fetch the Json as [InputStream] to be converted to a [DataRow]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, the stream will be read like an object with [header] being the keys. @@ -234,7 +234,7 @@ public fun DataRow.Companion.readJson( /** * @param stream Json as [InputStream] to be converted to a [DataFrame]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, [stream] will be read like an object with [header] being the keys. @@ -253,7 +253,7 @@ public fun DataFrame.Companion.readJson( /** * @param stream Json as [InputStream] to be converted to a [DataRow]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, [stream] will be read like an object with [header] being the keys. @@ -270,7 +270,7 @@ public fun DataRow.Companion.readJson( /** * @param text Json as [String] to be converted to a [DataFrame]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, [text] will be read like an object with [header] being the keys. @@ -287,7 +287,7 @@ public fun DataFrame.Companion.readJsonStr( /** * @param text Json as [String] to be converted to a [DataRow]. - * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[KeyValueProperty]> + * @param keyValuePaths List of [JsonPath]s where instead of a [ColumnGroup], a [FrameColumn]<[NameValueProperty]> * will be created. * @param typeClashTactic How to handle type clashes when reading a JSON file. * @param header Optional list of column names. If given, [text] will be read like an object with [header] being the keys. diff --git a/dataframe-json/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/JsonTests.kt b/dataframe-json/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/JsonTests.kt index f27892199d..0cfe218251 100644 --- a/dataframe-json/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/JsonTests.kt +++ b/dataframe-json/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/JsonTests.kt @@ -861,12 +861,12 @@ class JsonTests { it["a"][1].let { it as AnyFrame }.alsoDebug() } // ⌌------------------------------⌍ -// | | a:[key:String, value:Any?]| +// | | a:[name:String, value:Any?]| // |--|---------------------------| -// | 0| [1 x 2] { key:b, value:1 }| -// | 1| [3 x 2]| -> { key:c, value:2 } -// | 2| [0 x 2]| { key:d, value:null } -// | 3| [0 x 2]| { key:b, value:[1,2,3] } +// | 0| [1 x 2] { name:b, value:1 }| +// | 1| [3 x 2]| -> { name:c, value:2 } +// | 2| [0 x 2]| { name:d, value:null } +// | 3| [0 x 2]| { name:b, value:[1,2,3] } // | 4| [0 x 2]| // | 5| [0 x 2]| // ⌎------------------------------⌏ @@ -880,7 +880,7 @@ class JsonTests { it[0].let { it.columnsCount() shouldBe 2 it.rowsCount() shouldBe 1 - it["key"].let { + it["name"].let { it.type() shouldBe typeOf() it[0] shouldBe "b" } @@ -892,7 +892,7 @@ class JsonTests { it[1].let { it.columnsCount() shouldBe 2 it.rowsCount() shouldBe 3 - it["key"].let { + it["name"].let { it.type() shouldBe typeOf() it[0] shouldBe "c" it[1] shouldBe "d" @@ -907,7 +907,7 @@ class JsonTests { it.columnsCount() shouldBe 2 it.rowsCount() shouldBe 0 - it["key"].type() shouldBe typeOf() + it["name"].type() shouldBe typeOf() it["value"].type() shouldBeIn listOf(typeOf(), typeOf()) // no data, so Any(?) ValueColumn } } @@ -974,12 +974,12 @@ class JsonTests { } // ⌌------------------------------⌍ -// | | a:[key:String, value:Any?]| +// | | a:[name:String, value:Any?]| // |--|---------------------------| -// | 0| [1 x 2] { key:b, value:1 }| -// | 1| [3 x 2]| -> { key:c, value:2 } -// | 2| [0 x 2]| { key:d, value:null } -// | 3| [0 x 2]| { key:b, value:[1,2,3] } +// | 0| [1 x 2] { name:b, value:1 }| +// | 1| [3 x 2]| -> { name:c, value:2 } +// | 2| [0 x 2]| { name:d, value:null } +// | 3| [0 x 2]| { name:b, value:[1,2,3] } // | 4| [0 x 2]| // | 5| [0 x 2]| // ⌎------------------------------⌏ @@ -992,7 +992,7 @@ class JsonTests { it[0].let { it.columnsCount() shouldBe 2 it.rowsCount() shouldBe 1 - it["key"].let { + it["name"].let { it.type() shouldBe typeOf() it[0] shouldBe "b" } @@ -1004,7 +1004,7 @@ class JsonTests { it[1].let { it.columnsCount() shouldBe 2 it.rowsCount() shouldBe 3 - it["key"].let { + it["name"].let { it.type() shouldBe typeOf() it[0] shouldBe "c" it[1] shouldBe "d" @@ -1020,7 +1020,7 @@ class JsonTests { it.columnsCount() shouldBe 2 it.rowsCount() shouldBe 0 - it["key"].type() shouldBe typeOf() + it["name"].type() shouldBe typeOf() it["value"].type() shouldBeIn listOf(typeOf(), typeOf()) // no data, so Any(?) ValueColumn } } diff --git a/dataframe-openapi-generator/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/OpenApiMarker.kt b/dataframe-openapi-generator/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/OpenApiMarker.kt index 8f858ddc9c..09d854d69b 100644 --- a/dataframe-openapi-generator/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/OpenApiMarker.kt +++ b/dataframe-openapi-generator/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/OpenApiMarker.kt @@ -193,8 +193,8 @@ internal sealed class OpenApiMarker private constructor( ), generatedFieldOf( overrides = true, - fieldName = ValidFieldName.of(AdditionalProperty<*>::key.name), - columnName = AdditionalProperty<*>::key.name, + fieldName = ValidFieldName.of(AdditionalProperty<*>::name.name), + columnName = AdditionalProperty<*>::name.name, fieldType = FieldType.ValueFieldType(String::class.qualifiedName!!), ), ), diff --git a/dataframe-openapi-generator/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/getMarker.kt b/dataframe-openapi-generator/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/getMarker.kt index d03289450b..ab15d41f06 100644 --- a/dataframe-openapi-generator/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/getMarker.kt +++ b/dataframe-openapi-generator/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/getMarker.kt @@ -11,8 +11,8 @@ internal fun AdditionalProperty.Companion.getMarker(typeArguments: List) isOpen = false, fields = listOf( generatedFieldOf( - fieldName = ValidFieldName.of(AdditionalProperty<*>::key.name), - columnName = AdditionalProperty<*>::key.name, + fieldName = ValidFieldName.of(AdditionalProperty<*>::name.name), + columnName = AdditionalProperty<*>::name.name, overrides = false, fieldType = FieldType.ValueFieldType(String::class.qualifiedName!!), ), diff --git a/dataframe-openapi-generator/src/test/kotlin/OpenApiTests.kt b/dataframe-openapi-generator/src/test/kotlin/OpenApiTests.kt index e66af5a9e3..9cc1e4ce55 100644 --- a/dataframe-openapi-generator/src/test/kotlin/OpenApiTests.kt +++ b/dataframe-openapi-generator/src/test/kotlin/OpenApiTests.kt @@ -736,7 +736,7 @@ class OpenApiTests : JupyterReplTestCase() { interface ObjectWithAdditionalProperties : org.jetbrains.kotlinx.dataframe.io.AdditionalProperty { @ColumnName("value") override val `value`: kotlin.String - override val key: kotlin.String + override val name: kotlin.String public companion object { public val keyValuePaths: kotlin.collections.List get() = listOf(JsonPath(""${'"'}${'$'}""${'"'})) @@ -769,7 +769,7 @@ class OpenApiTests : JupyterReplTestCase() { interface ObjectWithAdditional2 : org.jetbrains.kotlinx.dataframe.io.AdditionalProperty { @ColumnName("value") override val `value`: kotlin.Any - override val key: kotlin.String + override val name: kotlin.String public companion object { public val keyValuePaths: kotlin.collections.List get() = listOf(JsonPath(""${'"'}${'$'}""${'"'})) @@ -802,7 +802,7 @@ class OpenApiTests : JupyterReplTestCase() { interface ObjectWithAdditional3 : org.jetbrains.kotlinx.dataframe.io.AdditionalProperty { @ColumnName("value") override val `value`: kotlin.Any? - override val key: kotlin.String + override val name: kotlin.String public companion object { public val keyValuePaths: kotlin.collections.List get() = listOf(JsonPath(""${'"'}${'$'}""${'"'})) @@ -916,7 +916,7 @@ class OpenApiTests : JupyterReplTestCase() { interface ObjectWithAdditional : org.jetbrains.kotlinx.dataframe.io.AdditionalProperty { @ColumnName("value") override val `value`: kotlin.Int - override val key: kotlin.String + override val name: kotlin.String public companion object { public val keyValuePaths: kotlin.collections.List get() = listOf(JsonPath(""${'"'}${'$'}""${'"'})) diff --git a/dataframe-openapi/api/dataframe-openapi.api b/dataframe-openapi/api/dataframe-openapi.api index c0c767e214..7943114284 100644 --- a/dataframe-openapi/api/dataframe-openapi.api +++ b/dataframe-openapi/api/dataframe-openapi.api @@ -1,12 +1,20 @@ -public abstract interface class org/jetbrains/kotlinx/dataframe/io/AdditionalProperty : org/jetbrains/kotlinx/dataframe/api/KeyValueProperty { +public abstract interface class org/jetbrains/kotlinx/dataframe/io/AdditionalProperty : org/jetbrains/kotlinx/dataframe/api/NameValueProperty { public static final field Companion Lorg/jetbrains/kotlinx/dataframe/io/AdditionalProperty$Companion; - public abstract fun getKey ()Ljava/lang/String; + public abstract fun getName ()Ljava/lang/String; public abstract fun getValue ()Ljava/lang/Object; } public final class org/jetbrains/kotlinx/dataframe/io/AdditionalProperty$Companion { } +public final class org/jetbrains/kotlinx/dataframe/io/AdditionalPropertyKt { + public static final fun AdditionalProperty_key (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun AdditionalProperty_key (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; + public static final fun NullableAdditionalProperty_key (Lorg/jetbrains/kotlinx/dataframe/ColumnsScope;)Lorg/jetbrains/kotlinx/dataframe/DataColumn; + public static final fun NullableAdditionalProperty_key (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/String; + public static final fun getKey (Lorg/jetbrains/kotlinx/dataframe/io/AdditionalProperty;)Ljava/lang/String; +} + public final class org/jetbrains/kotlinx/dataframe/io/ConvertDataRowsWithOpenApiKt { public static final fun convertDataRowsWithOpenApi (Lorg/jetbrains/kotlinx/dataframe/api/ConvertSchemaDsl;)V } diff --git a/dataframe-openapi/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/AdditionalProperty.kt b/dataframe-openapi/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/AdditionalProperty.kt index 297c57c01a..dc0fea0bda 100644 --- a/dataframe-openapi/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/AdditionalProperty.kt +++ b/dataframe-openapi/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/AdditionalProperty.kt @@ -1,19 +1,49 @@ package org.jetbrains.kotlinx.dataframe.io +import org.jetbrains.kotlinx.dataframe.ColumnsScope +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.annotations.DataSchema -import org.jetbrains.kotlinx.dataframe.api.KeyValueProperty +import org.jetbrains.kotlinx.dataframe.api.NameValueProperty +import org.jetbrains.kotlinx.dataframe.api.cast /** - * A [DataSchema] interface can implement this if it represents a map-like data schema (so key: value). + * A [DataSchema] interface can implement this if it represents a map-like data schema (so name: value). * Used in OpenAPI to represent objects with 'just' additionalProperties of a certain type. */ -public interface AdditionalProperty : KeyValueProperty { +public interface AdditionalProperty : NameValueProperty { /** Key of the property. */ - override val key: String + override val name: String /** Value of the property. */ override val value: T public companion object } + +private const val DEPRECATION_MESSAGE = "'key' has been renamed to 'name'." + +@Deprecated(DEPRECATION_MESSAGE, ReplaceWith("name")) +public val ColumnsScope>.key: DataColumn + @JvmName("AdditionalProperty_key") + get() = get("name").cast() + +@Deprecated(DEPRECATION_MESSAGE, ReplaceWith("name")) +public val ColumnsScope?>.key: DataColumn + @JvmName("NullableAdditionalProperty_key") + get() = get("name").cast() + +@Deprecated(DEPRECATION_MESSAGE, ReplaceWith("name")) +public val DataRow>.key: String + @JvmName("AdditionalProperty_key") + get() = get("name") as String + +@Deprecated(DEPRECATION_MESSAGE, ReplaceWith("name")) +public val DataRow?>.key: String? + @JvmName("NullableAdditionalProperty_key") + get() = get("name") as String? + +@Deprecated(DEPRECATION_MESSAGE, ReplaceWith("name")) +public val AdditionalProperty<*>.key: String + get() = name diff --git a/docs/StardustDocs/topics/read.md b/docs/StardustDocs/topics/read.md index 391b62cad8..afdf95d3b4 100644 --- a/docs/StardustDocs/topics/read.md +++ b/docs/StardustDocs/topics/read.md @@ -487,27 +487,27 @@ This can be the difference between: and ```text -⌌------------------------------------------------------------------------------------------------------⌍ -| | dogs:[key:String, value:{age:Int, breed:String}]| cats:[key:String, value:{age:Int, breed:String}]| -|--|-------------------------------------------------|-------------------------------------------------| -| 0| [7 x 2]| [6 x 2]| -⌎------------------------------------------------------------------------------------------------------⌏ +⌌--------------------------------------------------------------------------------------------------------⌍ +| | dogs:[name:String, value:{age:Int, breed:String}]| cats:[name:String, value:{age:Int, breed:String}]| +|--|--------------------------------------------------|--------------------------------------------------| +| 0| [7 x 2]| [6 x 2]| +⌎--------------------------------------------------------------------------------------------------------⌏ ``` with dogs looking like ```text -⌌-------------------------------------------------⌍ -| | key:String| value:{age:Int, breed:String}| -|--|-----------|----------------------------------| -| 0| fido| { age:3, breed:poodle }| -| 1| spot| { age:5, breed:labrador }| -| 2| rex| { age:2, breed:golden retriever }| -| 3| lucky| { age:1, breed:poodle }| -| 4| rover| { age:3, breed:labrador }| -| 5| max| { age:2, breed:golden retriever }| -| 6| buster| { age:1, breed:poodle }| -⌎-------------------------------------------------⌏ +⌌--------------------------------------------------⌍ +| | name:String| value:{age:Int, breed:String}| +|--|------------|----------------------------------| +| 0| fido| { age:3, breed:poodle }| +| 1| spot| { age:5, breed:labrador }| +| 2| rex| { age:2, breed:golden retriever }| +| 3| lucky| { age:1, breed:poodle }| +| 4| rover| { age:3, breed:labrador }| +| 5| max| { age:2, breed:golden retriever }| +| 6| buster| { age:1, breed:poodle }| +⌎--------------------------------------------------⌏ ``` (The results are wrapped in a [`FrameColumn`](DataColumn.md#framecolumn) instead of a `ColumnGroup` since lengths between "cats" and "dogs" can vary, diff --git a/examples/notebooks/dev/json/KeyValueAndOpenApi.ipynb b/examples/notebooks/dev/json/KeyValueAndOpenApi.ipynb index d84465347e..2bfd9ba6de 100644 --- a/examples/notebooks/dev/json/KeyValueAndOpenApi.ipynb +++ b/examples/notebooks/dev/json/KeyValueAndOpenApi.ipynb @@ -925,8 +925,8 @@ { "cell_type": "markdown", "source": [ - "Key/value objects are wrapped in a dataframe (to have a working hierarchy).\n", - "Since we convert the top-level object to key/value we need to unpack it to see the result." + "Key/value (or rather \"name/value\") objects are wrapped in a dataframe (to have a working hierarchy).\n", + "Since we convert the top-level object to name/value we need to unpack it to see the result." ], "metadata": { "collapsed": false @@ -2322,7 +2322,8 @@ ] }, "metadata": {}, - "output_type": "display_data" + "output_type": "display_data", + "jetTransient": {} } ], "execution_count": 4 @@ -3750,9 +3751,7 @@ }, { "cell_type": "markdown", - "source": [ - "As you can see, we've successfully read and converted the JSON to the correct types (including key/values and correct nullability!) using a foolproof method. Go ahead and explore the data a bit more if you feel like it!" - ], + "source": "As you can see, we've successfully read and converted the JSON to the correct types (including name/values and correct nullability!) using a foolproof method. Go ahead and explore the data a bit more if you feel like it!", "metadata": { "collapsed": false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d6a7a4cf1c..8e1e3a550d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ libsPublisher = "2.2.0-dev-61" # "Bootstrap" version of the dataframe, used in the build itself to generate @DataSchema APIs, # dogfood Gradle / KSP plugins in tests and idea-examples modules -dataframe = "1.0.0-dev-8314" +dataframe = "1.0.0-dev-8808" korro = "0.1.6" binaryCompatibilityValidator = "0.17.0"