Skip to content

Commit f94b252

Browse files
committed
adding allRecursively again, docs and cleaning
1 parent efb8a04 commit f94b252

File tree

14 files changed

+504
-225
lines changed

14 files changed

+504
-225
lines changed

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/ColumnsSelectionDsl.kt

Lines changed: 277 additions & 54 deletions
Large diffs are not rendered by default.

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/TypeConversions.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ public fun <T> DataColumn<T>.castToNullable(): DataColumn<T?> = cast()
9595

9696
public fun <T> ColumnReference<T>.castToNullable(): ColumnReference<T?> = cast()
9797

98+
public fun AnyCol.setNullable(nullable: Boolean): AnyCol {
99+
return if (nullable) {
100+
this.castToNullable()
101+
} else {
102+
this.castToNotNullable()
103+
}
104+
}
105+
98106
// region to array
99107

100108
public inline fun <reified T> DataColumn<T>.toTypedArray(): Array<T> = toList().toTypedArray()

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/cast.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@file:Suppress("UNCHECKED_CAST")
2+
13
package org.jetbrains.kotlinx.dataframe.api
24

35
import org.jetbrains.kotlinx.dataframe.AnyCol
@@ -15,6 +17,8 @@ import org.jetbrains.kotlinx.dataframe.columns.FrameColumn
1517
import org.jetbrains.kotlinx.dataframe.columns.SingleColumn
1618
import org.jetbrains.kotlinx.dataframe.columns.ValueColumn
1719
import org.jetbrains.kotlinx.dataframe.impl.api.convertToImpl
20+
import org.jetbrains.kotlinx.dataframe.impl.columns.TransformableColumnSet
21+
import org.jetbrains.kotlinx.dataframe.impl.columns.TransformableSingleColumn
1822
import kotlin.reflect.typeOf
1923

2024
public fun <T> AnyFrame.cast(): DataFrame<T> = this as DataFrame<T>
@@ -44,6 +48,10 @@ public fun <T> ColumnAccessor<*>.cast(): ColumnAccessor<T> = this as ColumnAcces
4448

4549
public fun <C> ColumnSet<*>.cast(): ColumnSet<C> = this as ColumnSet<C>
4650

51+
public fun <C> TransformableColumnSet<*>.cast(): TransformableColumnSet<C> = this as TransformableColumnSet<C>
52+
4753
public fun <C> ColumnReference<*>.cast(): ColumnReference<C> = this as ColumnReference<C>
4854

4955
public fun <C> SingleColumn<*>.cast(): SingleColumn<C> = this as SingleColumn<C>
56+
57+
public fun <C> TransformableSingleColumn<*>.cast(): TransformableSingleColumn<C> = this as TransformableSingleColumn<C>

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/convert.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import java.time.LocalTime
3636
import java.util.*
3737
import kotlin.reflect.KProperty
3838
import kotlin.reflect.KType
39+
import kotlin.reflect.full.isSubtypeOf
40+
import kotlin.reflect.full.withNullability
3941
import kotlin.reflect.typeOf
4042

4143
public fun <T, C> DataFrame<T>.convert(columns: ColumnsSelector<T, C>): Convert<T, C> =
@@ -103,8 +105,9 @@ public fun <T, C> Convert<T, C>.to(columnConverter: DataFrame<T>.(DataColumn<C>)
103105

104106
public inline fun <reified C> AnyCol.convertTo(): DataColumn<C> = convertTo(typeOf<C>()) as DataColumn<C>
105107
public fun AnyCol.convertTo(newType: KType): AnyCol {
106-
if (this.type() == typeOf<String>() && newType == typeOf<Double>()) return (this as DataColumn<String>).convertToDouble()
107-
if (this.type() == typeOf<String?>() && newType == typeOf<Double?>()) return (this as DataColumn<String?>).convertToDouble()
108+
if (this.type().withNullability(true).isSubtypeOf(typeOf<String?>()) && newType.withNullability(true) == typeOf<Double?>()) {
109+
return (this as DataColumn<String?>).convertToDouble().setNullable(newType.isMarkedNullable)
110+
}
108111
return convertToTypeImpl(newType)
109112
}
110113

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/columns/SingleColumn.kt

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package org.jetbrains.kotlinx.dataframe.columns
33
import org.jetbrains.kotlinx.dataframe.DataColumn
44
import org.jetbrains.kotlinx.dataframe.api.isColumnGroup
55
import org.jetbrains.kotlinx.dataframe.impl.columns.*
6-
import kotlin.contracts.ExperimentalContracts
7-
import kotlin.contracts.contract
86

97
/**
108
* Entity that can be [resolved][resolveSingle] into [DataColumn].
@@ -23,13 +21,10 @@ public interface SingleColumn<out C> : ColumnSet<C> {
2321
public fun resolveSingle(context: ColumnResolutionContext): ColumnWithPath<C>?
2422
}
2523

26-
@OptIn(ExperimentalContracts::class)
27-
public fun ColumnSet<*>.isSingleColumn(): Boolean {
28-
contract {
29-
returns(true) implies (this@isSingleColumn is SingleColumn<*>)
30-
}
31-
return this is SingleColumn<*>
32-
}
24+
public fun ColumnSet<*>.isSingleColumn(): Boolean = this is SingleColumn<*>
3325

34-
public fun ColumnSet<*>.isSingleColumnGroup(cols: List<ColumnWithPath<*>>): Boolean =
26+
/**
27+
* Returns true if [this] is a [SingleColumn] and [cols] consists of a single column group.
28+
*/
29+
public fun ColumnSet<*>.isSingleColumnWithGroup(cols: List<ColumnWithPath<*>>): Boolean =
3530
isSingleColumn() && cols.singleOrNull()?.isColumnGroup() == true

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/columns/Recursively.kt

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.jetbrains.kotlinx.dataframe.impl.columns
22

3+
import org.jetbrains.kotlinx.dataframe.api.allInternal
34
import org.jetbrains.kotlinx.dataframe.api.isColumnGroup
45
import org.jetbrains.kotlinx.dataframe.columns.*
56
import org.jetbrains.kotlinx.dataframe.impl.columns.tree.flattenRecursively
@@ -46,7 +47,7 @@ private class RecursivelyTransformer(
4647
)
4748

4849
override fun transformSingle(singleColumn: SingleColumn<*>): ColumnSet<*> =
49-
singleColumn.flattenRecursivelySingle(
50+
singleColumn.flattenRecursively(
5051
includeGroups = includeGroups,
5152
includeTopLevel = includeTopLevel,
5253
)
@@ -55,14 +56,7 @@ private class RecursivelyTransformer(
5556
internal fun ColumnSet<*>.flattenRecursively(
5657
includeGroups: Boolean = true,
5758
includeTopLevel: Boolean = true,
58-
): ColumnSet<*> = transform { list ->
59-
val cols =
60-
if (isSingleColumnGroup(list)) {
61-
list.single().children()
62-
} else {
63-
list
64-
}
65-
59+
): ColumnSet<*> = allInternal().transform { cols ->
6660
if (includeTopLevel) {
6761
cols.flattenRecursively()
6862
} else {
@@ -72,22 +66,10 @@ internal fun ColumnSet<*>.flattenRecursively(
7266
}.filter { includeGroups || !it.isColumnGroup() }
7367
}
7468

75-
internal fun SingleColumn<*>.flattenRecursivelySingle(
69+
internal fun SingleColumn<*>.flattenRecursively(
7670
includeGroups: Boolean = true,
7771
includeTopLevel: Boolean = true,
78-
): ColumnSet<*> = transformSingle {
79-
val cols =
80-
if (isSingleColumnGroup(listOf(it))) {
81-
it.children()
82-
} else {
83-
listOf(it)
84-
}
85-
86-
if (includeTopLevel) {
87-
cols.flattenRecursively()
88-
} else {
89-
cols
90-
.filter { it.isColumnGroup() }
91-
.flatMap { it.children().flattenRecursively() }
92-
}.filter { includeGroups || !it.isColumnGroup() }
93-
}
72+
): ColumnSet<*> = (this as ColumnSet<*>).flattenRecursively(
73+
includeGroups = includeGroups,
74+
includeTopLevel = includeTopLevel,
75+
)

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/recursively.kt

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,6 @@ class Recursively : TestBase() {
5555
).shouldAllBeEqual()
5656
}
5757

58-
@Test
59-
fun `get at`() {
60-
// dfGroup.getColumnsWithPaths { it[0..3].recursively() }.print()
61-
dfGroup.getColumnsWithPaths { all().recursively()[0..3] }.print()
62-
}
63-
6458
@Test
6559
fun `children`() {
6660
dfGroup.getColumnsWithPaths { children().recursively() }.print()
@@ -78,19 +72,17 @@ class Recursively : TestBase() {
7872
// cols { it.name in listOf("name", "firstName") }.recursively()
7973
// .last().recursively()
8074
// }
81-
// }
82-
83-
// @Test
84-
// fun `recursively`() {
85-
// dfGroup.getColumnsWithPaths { recursively() }.sortedBy { it.name } shouldBe recursivelyGoal
86-
// dfGroup.getColumnsWithPaths { rec(includeGroups = false) }.sortedBy { it.name } shouldBe recursivelyNoGroups
8775
// }
8876

8977
@Test
9078
fun `all recursively`() {
9179
dfGroup.getColumnsWithPaths { all().recursively() }.sortedBy { it.name } shouldBe recursivelyGoal
9280
dfGroup.getColumnsWithPaths { all().rec(includeGroups = false) }
9381
.sortedBy { it.name } shouldBe recursivelyNoGroups
82+
83+
dfGroup.getColumnsWithPaths { allRecursively() }.sortedBy { it.name } shouldBe recursivelyGoal
84+
dfGroup.getColumnsWithPaths { allRec(includeGroups = false) }
85+
.sortedBy { it.name } shouldBe recursivelyNoGroups
9486
}
9587

9688
@Test
@@ -112,21 +104,20 @@ class Recursively : TestBase() {
112104
dfGroup.getColumnsWithPaths { all().all().recursively() }.sortedBy { it.name } shouldBe recursivelyGoal
113105
dfGroup.getColumnsWithPaths { all().all().rec(includeGroups = false) }
114106
.sortedBy { it.name } shouldBe recursivelyNoGroups
107+
108+
dfGroup.getColumnsWithPaths { all().allRecursively() }.sortedBy { it.name } shouldBe recursivelyGoal
109+
dfGroup.getColumnsWithPaths { all().allRec(includeGroups = false) }
110+
.sortedBy { it.name } shouldBe recursivelyNoGroups
115111
}
116112

117113
@Test
118114
fun `cols allRecursively`() {
119115
dfGroup.getColumnsWithPaths { cols().all().recursively() }.sortedBy { it.name } shouldBe recursivelyGoal
120116
dfGroup.getColumnsWithPaths { cols().all().rec(includeGroups = false) }
121117
.sortedBy { it.name } shouldBe recursivelyNoGroups
122-
}
123118

124-
// @Test
125-
// fun `accessor recursively`() {
126-
// listOf(
127-
// dfGroup.getColumnsWithPaths { name.recursively() }.sortedBy { it.name }.map { it.name to it.path },
128-
// dfGroup.getColumnsWithPaths { it["name"].recursively() }.sortedBy { it.name }.map { it.name to it.path },
129-
// dfGroup.getColumnsWithPaths { name.dfs { true } }.sortedBy { it.name }.map { it.name to it.path },
130-
// ).shouldAllBeEqual()
131-
// }
119+
dfGroup.getColumnsWithPaths { cols().allRecursively() }.sortedBy { it.name } shouldBe recursivelyGoal
120+
dfGroup.getColumnsWithPaths { cols().allRec(includeGroups = false) }
121+
.sortedBy { it.name } shouldBe recursivelyNoGroups
122+
}
132123
}

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/ParserTests.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,14 @@ class ParserTests {
132132
fun `converting String to Double in different locales`() {
133133
val currentLocale = Locale.getDefault()
134134
try {
135-
// Test 36 behaviour combinations:
135+
// Test 45 behaviour combinations:
136136

137137
// 3 source columns
138138
val columnDot = columnOf("12.345", "67.890")
139139
val columnComma = columnOf("12,345", "67,890")
140140
val columnMixed = columnOf("12.345", "67,890")
141141
// *
142-
// (3 locales as converting parameter + original converting)
142+
// (3 locales as converting parameter + original converting + original converting to nullable)
143143
val parsingLocaleNotDefined: Locale? = null
144144
val parsingLocaleUsesDot: Locale = Locale.forLanguageTag("en-US")
145145
val parsingLocaleUsesComma: Locale = Locale.forLanguageTag("ru-RU")
@@ -152,6 +152,10 @@ class ParserTests {
152152
columnComma.convertTo<Double>().shouldBe(columnOf(12345.0, 67890.0))
153153
columnMixed.convertTo<Double>().shouldBe(columnOf(12.345, 67890.0))
154154

155+
columnDot.convertTo<Double?>().shouldBe(columnOf(12.345, 67.89))
156+
columnComma.convertTo<Double?>().shouldBe(columnOf(12345.0, 67890.0))
157+
columnMixed.convertTo<Double?>().shouldBe(columnOf(12.345, 67890.0))
158+
155159
columnDot.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12.345, 67.89))
156160
columnComma.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12345.0, 67890.0))
157161
columnMixed.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12.345, 67890.0))
@@ -170,6 +174,10 @@ class ParserTests {
170174
columnComma.convertTo<Double>().shouldBe(columnOf(12345.0, 67890.0))
171175
columnMixed.convertTo<Double>().shouldBe(columnOf(12.345, 67890.0))
172176

177+
columnDot.convertTo<Double?>().shouldBe(columnOf(12.345, 67.89))
178+
columnComma.convertTo<Double?>().shouldBe(columnOf(12345.0, 67890.0))
179+
columnMixed.convertTo<Double?>().shouldBe(columnOf(12.345, 67890.0))
180+
173181
columnDot.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12.345, 67.89))
174182
columnComma.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12345.0, 67890.0))
175183
columnMixed.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12.345, 67890.0))
@@ -188,6 +196,10 @@ class ParserTests {
188196
columnComma.convertTo<Double>().shouldBe(columnOf(12.345, 67.89))
189197
columnMixed.convertTo<Double>().shouldBe(columnOf(12.345, 67890.0))
190198

199+
columnDot.convertTo<Double?>().shouldBe(columnOf(12.345, 67.89))
200+
columnComma.convertTo<Double?>().shouldBe(columnOf(12.345, 67.89))
201+
columnMixed.convertTo<Double?>().shouldBe(columnOf(12.345, 67890.0))
202+
191203
columnDot.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12.345, 67.89))
192204
columnComma.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12.345, 67.89))
193205
columnMixed.convertToDouble(parsingLocaleNotDefined).shouldBe(columnOf(12.345, 67890.0))

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/SampleNotebooksTests.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class SampleNotebooksTests : DataFrameJupyterTest() {
109109
cleanup: () -> Unit = {},
110110
) {
111111
val fileName = if (notebookName == null) "$dir.ipynb" else "$notebookName.ipynb"
112-
doTest("$jupyterExamplesPath/$dir/$fileName", replacer, cellClause, cleanup)
112+
doTest("$notebookExamplesPath/$dir/$fileName", replacer, cellClause, cleanup)
113113
}
114114

115115
data class CodeCellData(
@@ -119,8 +119,8 @@ class SampleNotebooksTests : DataFrameJupyterTest() {
119119

120120
companion object {
121121
const val ideaExamplesPath = "../examples/idea-examples"
122-
const val jupyterExamplesPath = "../examples/jupyter-notebooks"
122+
const val notebookExamplesPath = "../examples/notebooks"
123123

124-
fun testFile(folder: String, fileName: String) = fileName to "$jupyterExamplesPath/$folder/$fileName"
124+
fun testFile(folder: String, fileName: String) = fileName to "$notebookExamplesPath/$folder/$fileName"
125125
}
126126
}

0 commit comments

Comments
 (0)