Fix naming conventions in names

This commit is contained in:
Alexander Nozik 2023-01-08 11:03:58 +03:00
parent 4117a05df4
commit e41fdfc086
Signed by: altavir
GPG Key ID: B10A55DCC7B9AEBB
16 changed files with 72 additions and 33 deletions

View File

@ -26,6 +26,7 @@
- Separate interfaces for `IOReader` and `IOWriter`
### Deprecated
- Context.fetch -> Context.request
### Removed

View File

@ -11,6 +11,8 @@ public abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plu
private var _context: Context? = null
private val dependencies = HashMap<PluginFactory<*>, Meta>()
override val isAttached: Boolean = _context != null
override val context: Context
get() = _context ?: error("Plugin $tag is not attached")
@ -27,7 +29,10 @@ public abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plu
/**
* Register plugin dependency and return a delegate which provides lazily initialized reference to dependent plugin
*/
protected fun <P : Plugin> require(factory: PluginFactory<P>, meta: Meta = Meta.EMPTY): ReadOnlyProperty<AbstractPlugin, P> {
protected fun <P : Plugin> require(
factory: PluginFactory<P>,
meta: Meta = Meta.EMPTY,
): ReadOnlyProperty<AbstractPlugin, P> {
dependencies[factory] = meta
return PluginDependencyDelegate(factory.type)
}
@ -37,6 +42,7 @@ public fun <T : Named> Collection<T>.toMap(): Map<Name, T> = associate { it.name
private class PluginDependencyDelegate<P : Plugin>(val type: KClass<out P>) : ReadOnlyProperty<AbstractPlugin, P> {
override fun getValue(thisRef: AbstractPlugin, property: KProperty<*>): P {
if (!thisRef.isAttached) error("Plugin dependency must not be called eagerly during initialization.")
return thisRef.context.plugins[type] ?: error("Plugin with type $type not found")
}
}

View File

@ -53,6 +53,8 @@ public interface Plugin : Named, ContextAware, Provider, MetaRepr {
*/
public fun detach()
public val isAttached: Boolean
override fun toMeta(): Meta = Meta {
"context" put context.name.toString()
"type" to this::class.simpleName

View File

@ -13,7 +13,7 @@ import kotlin.reflect.KClass
*/
public class PluginManager internal constructor(
override val context: Context,
private val plugins: Set<Plugin>
private val plugins: Set<Plugin>,
) : ContextAware, Iterable<Plugin> {
init {
@ -81,12 +81,16 @@ public class PluginManager internal constructor(
* Fetch a plugin with given meta from the context. If the plugin (with given meta) is already registered, it is returned.
* Otherwise, new child context with the plugin is created. In the later case the context could be retrieved from the plugin.
*/
public inline fun <reified T : Plugin> Context.fetch(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T {
public inline fun <reified T : Plugin> Context.request(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T {
val existing = plugins[factory]
return if (existing != null && existing.meta == meta) existing
else {
buildContext(name = this@fetch.name + factory.tag.name) {
buildContext(name = this@request.name + factory.tag.name) {
plugin(factory, meta)
}.plugins[factory]!!
}
}
}
@Deprecated("Replace with request", ReplaceWith("request(factory, meta)"))
public inline fun <reified T : Plugin> Context.fetch(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
request(factory, meta)

View File

@ -1,7 +1,7 @@
package space.kscience.dataforge.context
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.appendLeft
import space.kscience.dataforge.names.appendFirst
import kotlin.test.Test
import kotlin.test.assertEquals
@ -26,7 +26,7 @@ class ContextTest {
val members = context.gather<Name>("test")
assertEquals(3, members.count())
members.forEach {
assertEquals(it.key, it.value.appendLeft("test"))
assertEquals(it.key, it.value.appendFirst("test"))
}
}

View File

@ -73,7 +73,7 @@ private class LazyData<T : Any>(
override val type: KType,
override val meta: Meta = Meta.EMPTY,
additionalContext: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(),
dependencies: Collection<Goal<*>> = emptyList(),
block: suspend () -> T,
) : Data<T>, LazyGoal<T>(additionalContext, dependencies, block)
@ -93,7 +93,7 @@ public fun <T : Any> Data(
type: KType,
meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(),
dependencies: Collection<Goal<*>> = emptyList(),
block: suspend () -> T,
): Data<T> = LazyData(type, meta, context, dependencies, block)
@ -102,6 +102,6 @@ public fun <T : Any> Data(
public inline fun <reified T : Any> Data(
meta: Meta = Meta.EMPTY,
context: CoroutineContext = EmptyCoroutineContext,
dependencies: Collection<Data<*>> = emptyList(),
dependencies: Collection<Goal<*>> = emptyList(),
noinline block: suspend () -> T,
): Data<T> = Data(typeOf<T>(), meta, context, dependencies, block)

View File

@ -67,7 +67,7 @@ public fun <T : Any> DataSet<T>.withNamePrefix(prefix: Name): DataSet<T> = if (p
}
override fun get(name: Name): Data<T>? =
name.removeHeadOrNull(name)?.let { this@withNamePrefix.get(it) }
name.removeFirstOrNull(name)?.let { this@withNamePrefix.get(it) }
override val updates: Flow<Name> get() = this@withNamePrefix.updates.map { prefix + it }
}
@ -87,7 +87,7 @@ public fun <T : Any> DataSet<T>.branch(branchName: Name): DataSet<T> = if (branc
override fun iterator(): Iterator<NamedData<T>> = iterator {
for (d in this@branch) {
d.name.removeHeadOrNull(branchName)?.let { name ->
d.name.removeFirstOrNull(branchName)?.let { name ->
yield(d.data.named(name))
}
}
@ -95,7 +95,7 @@ public fun <T : Any> DataSet<T>.branch(branchName: Name): DataSet<T> = if (branc
override fun get(name: Name): Data<T>? = this@branch.get(branchName + name)
override val updates: Flow<Name> get() = this@branch.updates.mapNotNull { it.removeHeadOrNull(branchName) }
override val updates: Flow<Name> get() = this@branch.updates.mapNotNull { it.removeFirstOrNull(branchName) }
}
public fun <T : Any> DataSet<T>.branch(branchName: String): DataSet<T> = this@branch.branch(branchName.parseAsName())

View File

@ -36,6 +36,8 @@ public interface Envelope {
public class SimpleEnvelope(override val meta: Meta, override val data: Binary?) : Envelope
public fun Envelope(meta: Meta, data: Binary?): Envelope = SimpleEnvelope(meta, data)
/**
* The purpose of the envelope
*

View File

@ -7,8 +7,11 @@ import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.string
import space.kscience.dataforge.misc.DFInternal
import space.kscience.dataforge.names.Name
import kotlin.reflect.KClass
import kotlin.reflect.KType
import kotlin.reflect.typeOf
public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
override val tag: PluginTag get() = Companion.tag
@ -17,15 +20,15 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
context.gather<IOFormatFactory<*>>(IO_FORMAT_TYPE).values
}
public fun <T : Any> resolveIOFormat(item: Meta, type: KClass<out T>): IOFormat<T>? {
val key = item.string ?: item[IOFormatFactory.NAME_KEY]?.string ?: error("Format name not defined")
val name = Name.parse(key)
return ioFormatFactories.find { it.name == name }?.let {
@Suppress("UNCHECKED_CAST")
if (it.type != type) error("Format type ${it.type} is not the same as requested type $type")
else it.build(context, item[IOFormatFactory.META_KEY] ?: Meta.EMPTY) as IOFormat<T>
}
}
@Suppress("UNCHECKED_CAST")
@DFInternal
public fun <T : Any> resolveIOFormat(type: KType, meta: Meta): IOFormat<T>? =
ioFormatFactories.singleOrNull { it.type == type }?.build(context, meta) as? IOFormat<T>
@OptIn(DFInternal::class)
public inline fun <reified T : Any> resolveIOFormat(meta: Meta = Meta.EMPTY): IOFormat<T>? =
resolveIOFormat(typeOf<T>(), meta)
public val metaFormatFactories: Collection<MetaFormatFactory> by lazy {
context.gather<MetaFormatFactory>(META_FORMAT_TYPE).values
@ -79,7 +82,7 @@ internal val ioContext = Context("IO") {
public val Context.io: IOPlugin
get() = if (this == Global) {
ioContext.fetch(IOPlugin)
ioContext.request(IOPlugin)
} else {
fetch(IOPlugin)
request(IOPlugin)
}

View File

@ -25,7 +25,7 @@ private class ObservableMetaWrapper(
listeners.add(
MetaListener(Pair(owner, absoluteName)) { name ->
if (name.startsWith(absoluteName)) {
(this[absoluteName] ?: Meta.EMPTY).callback(name.removeHeadOrNull(absoluteName)!!)
(this[absoluteName] ?: Meta.EMPTY).callback(name.removeFirstOrNull(absoluteName)!!)
}
}
)

View File

@ -96,7 +96,7 @@ public open class Scheme : Described, MetaRepr, MutableMetaProvider, Configurabl
override fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) {
listeners.add(MetaListener(owner) { changedName ->
if (changedName.startsWith(pathName)) {
this@Scheme.meta.callback(changedName.removeHeadOrNull(pathName)!!)
this@Scheme.meta.callback(changedName.removeFirstOrNull(pathName)!!)
}
})
}

View File

@ -159,8 +159,14 @@ public operator fun Name.plus(other: String): Name = this + Name.parse(other)
public operator fun Name.plus(other: NameToken): Name = Name(tokens + other)
@Deprecated(
"Use appendFirst instead",
ReplaceWith("appendFirst(other)")
)
public fun Name.appendLeft(other: String): Name = NameToken(other) + this
public fun Name.appendFirst(other: String): Name = NameToken(other) + this
public fun NameToken.asName(): Name = Name(listOf(this))
public fun Name.isEmpty(): Boolean = this.length == 0
@ -202,12 +208,26 @@ public fun Name.endsWith(name: Name): Boolean =
/**
* if [this] starts with given [head] name, returns the reminder of the name (could be empty). Otherwise, returns null
*/
@Deprecated(
"Use removeFirstOrNull instead",
ReplaceWith("removeFirstOrNull(head)")
)
public fun Name.removeHeadOrNull(head: Name): Name? = if (startsWith(head)) {
Name(tokens.subList(head.length, length))
} else {
null
}
/**
* if [this] starts with given [first] name, returns the reminder of the name (could be empty). Otherwise, returns null
*/
public fun Name.removeFirstOrNull(first: Name): Name? = if (startsWith(first)) {
Name(tokens.subList(first.length, length))
} else {
null
}
@ThreadLocal
private val nameCache = HashMap<String, Name>()

View File

@ -25,7 +25,7 @@ public interface Task<out T : Any> : Described {
/**
* A task identification string used to compare tasks and check task body for change
*/
public val fingerprint: String get() = hashCode().toString()
public val fingerprint: String get() = hashCode().toString(radix = 16)
/**
* Compute a [TaskResult] using given meta. In general, the result is lazy and represents both computation model

View File

@ -42,6 +42,6 @@ private class TaskDataImpl<out T : Any>(
// }
}
public fun <T : Any> Workspace.wrapData(data: Data<T>, name: Name, taskName: Name, stageMeta: Meta): TaskData<T> =
TaskDataImpl(this, data, name, taskName, stageMeta)
public fun <T : Any> Workspace.wrapData(data: Data<T>, name: Name, taskName: Name, taskMeta: Meta): TaskData<T> =
TaskDataImpl(this, data, name, taskName, taskMeta)

View File

@ -25,14 +25,15 @@ public interface TaskResult<out T : Any> : DataSet<T> {
public val taskMeta: Meta
override fun iterator(): Iterator<TaskData<T>>
override fun get(name: Name): TaskData<T>?
}
private class TaskResultImpl<out T : Any>(
override val workspace: Workspace,
val dataSet: DataSet<T>,
override val taskName: Name,
override val taskMeta: Meta,
val dataSet: DataSet<T>,
) : TaskResult<T>, DataSet<T> by dataSet {
override fun iterator(): Iterator<TaskData<T>> = iterator {
@ -41,7 +42,7 @@ private class TaskResultImpl<out T : Any>(
}
}
override fun get(name: Name): TaskData<T>? = dataSet.get(name)?.let {
override fun get(name: Name): TaskData<T>? = dataSet[name]?.let {
workspace.wrapData(it, name, taskName, taskMeta)
}
}
@ -50,4 +51,4 @@ private class TaskResultImpl<out T : Any>(
* Wrap data into [TaskResult]
*/
public fun <T : Any> Workspace.wrapResult(dataSet: DataSet<T>, taskName: Name, taskMeta: Meta): TaskResult<T> =
TaskResultImpl(this, dataSet, taskName, taskMeta)
TaskResultImpl(this, taskName, taskMeta, dataSet)

View File

@ -5,4 +5,4 @@ kotlin.code.style=official
kotlin.mpp.stability.nowarn=true
kotlin.incremental.js.ir=true
toolsVersion=0.13.0-kotlin-1.7.20-Beta
toolsVersion=0.13.3-kotlin-1.7.20