WIP full data refactor

This commit is contained in:
Alexander Nozik 2021-01-10 18:18:34 +03:00
parent 23fae9794f
commit b916a038f7
11 changed files with 35 additions and 56 deletions

View File

@ -44,7 +44,7 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr {
/** /**
* An empty data containing only meta * An empty data containing only meta
*/ */
public fun empty(meta: Meta): Data<Nothing> = object : Data<Nothing> { public fun <T> empty(meta: Meta): Data<Nothing> = object : Data<Nothing> {
override val type: KClass<out Nothing> = Nothing::class override val type: KClass<out Nothing> = Nothing::class
override val meta: Meta = meta override val meta: Meta = meta
override val dependencies: Collection<Goal<*>> = emptyList() override val dependencies: Collection<Goal<*>> = emptyList()

View File

@ -67,6 +67,8 @@ public interface DataTree<out T : Any> : DataSet<T> {
} }
} }
public suspend fun <T: Any> DataSet<T>.getData(name: String): Data<T>? = getData(name.toName())
/** /**
* Get a [DataTreeItem] with given [name] or null if the item does not exist * Get a [DataTreeItem] with given [name] or null if the item does not exist
*/ */
@ -97,10 +99,10 @@ public fun <T : Any> DataTree<T>.itemFlow(): Flow<Pair<Name, DataTreeItem<T>>> =
* Get a branch of this [DataTree] with a given [branchName]. * Get a branch of this [DataTree] with a given [branchName].
* The difference from similar method for [DataSet] is that internal logic is more simple and the return value is a [DataTree] * The difference from similar method for [DataSet] is that internal logic is more simple and the return value is a [DataTree]
*/ */
public operator fun <T : Any> DataTree<T>.get(branchName: Name): DataTree<T> = object : DataTree<T> { public fun <T : Any> DataTree<T>.branch(branchName: Name): DataTree<T> = object : DataTree<T> {
override val dataType: KClass<out T> get() = this@get.dataType override val dataType: KClass<out T> get() = this@branch.dataType
override val updates: Flow<Name> = this@get.updates.mapNotNull { it.removeHeadOrNull(branchName) } override val updates: Flow<Name> = this@branch.updates.mapNotNull { it.removeHeadOrNull(branchName) }
override suspend fun items(): Map<NameToken, DataTreeItem<T>> = getItem(branchName).tree?.items() ?: emptyMap() override suspend fun items(): Map<NameToken, DataTreeItem<T>> = getItem(branchName).tree?.items() ?: emptyMap()
} }

View File

@ -154,6 +154,3 @@ public suspend fun <T : Any> DataSet<T>.toMutableTree(
set(it, getData(it)) set(it, getData(it))
}.launchIn(scope) }.launchIn(scope)
} }
public fun <T : Any> MutableDataTree<T>.get(branchName: Name): MutableDataTree<T> =
(this as DataTree<T>).get(branchName) as MutableDataTree<T>

View File

@ -51,22 +51,22 @@ else object : DataSet<T> {
/** /**
* Get a subset of data starting with a given [branchName] * Get a subset of data starting with a given [branchName]
*/ */
public operator fun <T : Any> DataSet<T>.get(branchName: Name): DataSet<T> = if (branchName.isEmpty()) this public fun <T : Any> DataSet<T>.branch(branchName: Name): DataSet<T> = if (branchName.isEmpty()) this
else object : DataSet<T> { else object : DataSet<T> {
override val dataType: KClass<out T> get() = this@get.dataType override val dataType: KClass<out T> get() = this@branch.dataType
override fun flow(): Flow<NamedData<T>> = this@get.flow().mapNotNull { override fun flow(): Flow<NamedData<T>> = this@branch.flow().mapNotNull {
it.name.removeHeadOrNull(branchName)?.let { name -> it.name.removeHeadOrNull(branchName)?.let { name ->
it.data.named(name) it.data.named(name)
} }
} }
override suspend fun getData(name: Name): Data<T>? = this@get.getData(branchName + name) override suspend fun getData(name: Name): Data<T>? = this@branch.getData(branchName + name)
override val updates: Flow<Name> get() = this@get.updates.mapNotNull { it.removeHeadOrNull(branchName) } override val updates: Flow<Name> get() = this@branch.updates.mapNotNull { it.removeHeadOrNull(branchName) }
} }
public operator fun <T : Any> DataSet<T>.get(branchName: String): DataSet<T> = this@get.get(branchName.toName()) public fun <T : Any> DataSet<T>.branch(branchName: String): DataSet<T> = this@branch.branch(branchName.toName())
@DFExperimental @DFExperimental
public suspend fun <T : Any> DataSet<T>.rootData(): Data<T>? = getData(Name.EMPTY) public suspend fun <T : Any> DataSet<T>.rootData(): Data<T>? = getData(Name.EMPTY)

View File

@ -27,8 +27,8 @@ internal class DataTreeBuilderTest{
} }
assertTrue { node["update.a"] != null } assertTrue { node.branch("update.a") != null }
assertTrue { node["primary.a"] != null } assertTrue { node.branch("primary.a") != null }
} }
} }

View File

@ -57,7 +57,7 @@ public class TaskBuilder<R : Any>(private val name: Name, public val type: KClas
) { ) {
dataTransforms += { context, model, data -> dataTransforms += { context, model, data ->
val env = TaskEnv(Name.EMPTY, model.meta, context, data) val env = TaskEnv(Name.EMPTY, model.meta, context, data)
val startData = data.get(from) val startData = data.branch(from)
env.block(startData).withNamePrefix(to) env.block(startData).withNamePrefix(to)
} }
} }

View File

@ -3,10 +3,8 @@ package hep.dataforge.workspace
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.context.ContextBuilder import hep.dataforge.context.ContextBuilder
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.data.DataTree
import hep.dataforge.data.MutableDataTree import hep.dataforge.data.MutableDataTree
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.toName import hep.dataforge.names.toName
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -28,19 +26,11 @@ public fun WorkspaceBuilder.context(name: String = "WORKSPACE", block: ContextBu
context = ContextBuilder(parentContext, name).apply(block).build() context = ContextBuilder(parentContext, name).apply(block).build()
} }
public inline fun <reified T : Any> WorkspaceBuilder.data( public inline fun WorkspaceBuilder.data(
name: Name = Name.EMPTY,
noinline block: MutableDataTree<T>.() -> Unit,
): DataTree<T> {
TODO()
//data.branch(name).apply(block)
}
@JvmName("rawData")
public fun WorkspaceBuilder.data(
name: Name = Name.EMPTY,
block: MutableDataTree<Any>.() -> Unit, block: MutableDataTree<Any>.() -> Unit,
): DataTree<Any> = data<Any>(name, block) ): Unit{
data.apply(block)
}
public fun WorkspaceBuilder.target(name: String, block: MetaBuilder.() -> Unit) { public fun WorkspaceBuilder.target(name: String, block: MetaBuilder.() -> Unit) {

View File

@ -1,9 +0,0 @@
package hep.dataforge.workspace
import hep.dataforge.data.DataSet
import hep.dataforge.meta.MetaBuilder
import kotlinx.coroutines.runBlocking
public fun Workspace.runBlocking(task: String, block: MetaBuilder.() -> Unit = {}): DataSet<Any> = runBlocking{
run(task, block)
}

View File

@ -13,7 +13,7 @@ import kotlin.reflect.KClass
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
public fun <T : Any> DataSet<T>.first(): NamedData<T>? = runBlocking { flow().firstOrNull() } fun <T : Any> DataSet<T>.first(): NamedData<T>? = runBlocking { flow().firstOrNull() }
class DataPropagationTestPlugin : WorkspacePlugin() { class DataPropagationTestPlugin : WorkspacePlugin() {
override val tag: PluginTag = Companion.tag override val tag: PluginTag = Companion.tag

View File

@ -67,8 +67,10 @@ class FileDataTest {
} }
println(dir.toUri().toString()) println(dir.toUri().toString())
val reconstructed = readDataDirectory(dir,StringFormatResolver) val reconstructed = readDataDirectory(dir,StringFormatResolver)
assertEquals(dataNode["dir.a"].data?.meta, reconstructed["dir.a"].data?.meta) runBlocking {
assertEquals(dataNode["b"]?.data?.value(), reconstructed["b"]?.data?.value()) assertEquals(dataNode.getData("dir.a")?.meta, reconstructed.getData("dir.a")?.meta)
assertEquals(dataNode.getData("b")?.value(), reconstructed.getData("b")?.value())
}
} }
} }
@ -83,8 +85,10 @@ class FileDataTest {
} }
println(zip.toUri().toString()) println(zip.toUri().toString())
val reconstructed = readDataDirectory(zip, StringFormatResolver) val reconstructed = readDataDirectory(zip, StringFormatResolver)
assertEquals(dataNode["dir.a"].data?.meta, reconstructed["dir.a"].data?.meta) runBlocking {
assertEquals(dataNode["b"]?.data?.value(), reconstructed["b"]?.data?.value()) assertEquals(dataNode.getData("dir.a")?.meta, reconstructed.getData("dir.a")?.meta)
assertEquals(dataNode.getData("b")?.value(), reconstructed.getData("b")?.value())
}
} }
} }
} }

View File

@ -6,6 +6,7 @@ import hep.dataforge.meta.*
import hep.dataforge.names.plus import hep.dataforge.names.plus
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Timeout
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -21,15 +22,8 @@ public inline fun <reified P : Plugin> P.toFactory(): PluginFactory<P> = object
override val type: KClass<out P> = P::class override val type: KClass<out P> = P::class
} }
public fun DataTree<*>.toMeta(): Meta = Meta { public fun Workspace.runBlocking(task: String, block: MetaBuilder.() -> Unit = {}): DataSet<Any> = runBlocking{
"type" put (dataType.simpleName ?: "undefined") run(task, block)
"items" put {
runBlocking {
flow().collect {
it.name.toString() put it.data.meta
}
}
}
} }
@ -89,8 +83,8 @@ class SimpleWorkspaceTest {
val linearDep = dependsOn(linear, placement = DataPlacement.into("linear")) val linearDep = dependsOn(linear, placement = DataPlacement.into("linear"))
} }
transform<Int> { data -> transform<Int> { data ->
val squareNode = data["square"].filterIsInstance<Int>() //squareDep() val squareNode = data.branch("square").filterIsInstance<Int>() //squareDep()
val linearNode = data["linear"].filterIsInstance<Int>() //linearDep() val linearNode = data.branch("linear").filterIsInstance<Int>() //linearDep()
DataTree.dynamic<Int>(context) { DataTree.dynamic<Int>(context) {
squareNode.flow().collect { squareNode.flow().collect {
val newData: Data<Int> = Data { val newData: Data<Int> = Data {
@ -163,6 +157,7 @@ class SimpleWorkspaceTest {
} }
@Test @Test
@Timeout(400)
fun testMetaPropagation() { fun testMetaPropagation() {
val node = workspace.runBlocking("sum") { "testFlag" put true } val node = workspace.runBlocking("sum") { "testFlag" put true }
val res = node.first()?.value() val res = node.first()?.value()