Generally, there are two ways of adding new library:
To support new JVM
library and make it available via %use
magic command you need to create a library descriptor for it.
Check libraries directory to see examples of library descriptors.
Library descriptor is a <libName>.json
file with the following fields:
properties
: a dictionary of properties that are used within library descriptordescription
: a short library description which is used for generating libraries list in READMElink
: a link to library homepage. This link will be displayed in:help
commandminKernelVersion
: a minimal version of Kotlin kernel which may be used with this descriptorrepositories
: a list of maven or ivy repositories to search for dependenciesdependencies
: a list of library dependenciesimports
: a list of default imports for libraryinit
: a list of code snippets to be executed when library is includedinitCell
: a list of code snippets to be executed before execution of any cellshutdown
: a list of code snippets to be executed on kernel shutdown. Any cleanup code goes hererenderers
: a mapping from fully qualified names of types to be rendered to the Kotlin expression returning output value. Source object is referenced as$it
resources
: a list of JS/CSS resources. See this descriptor for example
*All fields are optional
For the most relevant specification see org.jetbrains.kotlinx.jupyter.libraries.LibraryDescriptor
class.
Name of the file should have the <name>.json
format where <name>
is an argument for '%use' command
Library properties can be used in any parts of library descriptor as $property
To register new library descriptor:
- For private usage - create it anywhere on your computer and reference it using file syntax.
- Alternative way for private usage - create descriptor in
.jupyter_kotlin/libraries
folder and reference it using "default" syntax - For sharing with community - commit it to libraries directory and create pull request.
If you are maintaining some library and want to update your library descriptor, create pull request with your update.
After your request is accepted, new version of your library will be available to all Kotlin Jupyter users
immediately on next kernel startup (no kernel update is needed) - but only if they use %useLatestDescriptors
magic.
If not, kernel update is needed.
You may also add a Kotlin kernel integration to your library using a Gradle plugin.
In the following code snippets <jupyterApiVersion>
is one of the published versions from the link above.
It is encouraged to use the latest stable version.
First, add the plugin dependency into your buildscript.
For build.gradle
:
plugins {
id "org.jetbrains.kotlin.jupyter.api" version "<jupyterApiVersion>"
}
For build.gradle.kts
:
plugins {
kotlin("jupyter.api") version "<jupyterApiVersion>"
}
This plugin adds dependencies to api and annotations ("scanner") artifacts to your project. You may turn off the auto-including of these artifacts by specifying following Gradle properties:
kotlin.jupyter.add.api
tofalse
.kotlin.jupyter.add.scanner
tofalse
.
Add these dependencies manually using kotlinJupyter
extension:
kotlinJupyter {
addApiDependency("<version>")
addScannerDependency("<version>")
}
Finally, implement org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinitionProducer
or
org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinition
and mark implementation with
JupyterLibrary
annotation:
package org.my.lib
import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary
import org.jetbrains.kotlinx.jupyter.api.*
import org.jetbrains.kotlinx.jupyter.api.libraries.*
@JupyterLibrary
internal class Integration : JupyterIntegration() {
override fun Builder.onLoaded() {
render<MyClass> { HTML(it.toHTML()) }
import("org.my.lib.*")
import("org.my.lib.io.*")
}
}
For more complicated example see integration of dataframe library.
For a further information see docs for:
org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinitionProducer
org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinition
You may want not to use annotation processing for implementations detection. Then you may refer your implementations right in your buildscript. Note that no checking for existence will be performed in this case.
The following example shows how to refer aforementioned Integration
class in your buildscript.
Obviously, in this case you shouldn't mark it with JupyterLibrary
annotation.
For build.gradle
:
processJupyterApiResources {
libraryProducers = ["org.my.lib.Integration"]
}
For build.gradle.kts
:
tasks.processJupyterApiResources {
libraryProducers = listOf("org.my.lib.Integration")
}
If you don't use Gradle as a build system, there is an alternative way.
First, add org.jetbrains.kotlinx:kotlin-jupyter-api:<jupyterApiVersion>
as
a compile dependency. See configuration instructions for different build systems
here
Then add one or more integration classes. They may be derived from
LibraryDefinitionProducer
or from LibraryDefinition
as described above.
Note that you don't need @JupyterLibrary
annotation in this scenario.
Finally, add file META-INF/kotlin-jupyter-libraries/libraries.json
to the JAR
resources. This file should contain FQNs of all integration classes in the JSON form:
{
"definitions":[],
"producers": [
{ "fqn" : "org.jetbrains.kotlinx.jupyter.example.GettingStartedIntegration" }
]
}
Classes derived from LibraryDefinition
should be added to the definitions
array.
Classes derived from LibraryDefinitionProducer
should be added to the producers
array.