Skip to content

Commit

Permalink
Add jupyter integration for lets-plot-kotlin and lets-plot-kotlin-geo…
Browse files Browse the repository at this point in the history
…tools (#258)

* Agg jupyter integration for lets-plot-kotlin and lets-plot-kotlin-geotools

* Extract integrations to separate modules and artifacts with all LP/LPK implementations; extract spec serialization to util module

* little code clean up

* rename util to json & remove lets-plot mention

* move serialization version
  • Loading branch information
AndreiKingsley authored Nov 4, 2024
1 parent 11fd59b commit c81d496
Show file tree
Hide file tree
Showing 21 changed files with 836 additions and 0 deletions.
5 changes: 5 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ plugins {
id("io.codearte.nexus-staging") apply false

id("io.github.gradle-nexus.publish-plugin")

// Add the KSP plugin before the Jupyter API to avoid ksp versions incompatibility.
// May be removed when using further versions of the jupyter api
id("com.google.devtools.ksp") apply false
kotlin("jupyter.api") apply false
}

val localProps = Properties()
Expand Down
7 changes: 7 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,24 @@ kotlin.code.style=official
kotlin.daemon.jvmargs=-Xmx2048M
kotlin.jvm.target.validation.mode=error

# Jupyter API
kotlin.jupyter.add.scanner=false

# Versions
kotlin.version=1.9.25
datetime.version=0.3.2
kotlinLogging.version=2.0.5
slf4j.version=1.7.32
assertj.version=3.26.3
serialization.version=1.7.3

dokka.version=1.9.20
nexusStaging.version=0.30.0
nexusPublish.version=1.3.0

ksp.version=1.9.25-1.0.20
jupyterApi.version=0.12.0-313

# Also update JS version in <home>/demo/js-frontend-app/src/main/resources/index.html
letsPlot.version=4.5.1

Expand Down
19 changes: 19 additions & 0 deletions plot-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,22 @@ tasks {
// print("${project.name}: ${uri(project.localMavenRepository)}")
//}

// Provide jvm resources to jupyter module
// https://youtrack.jetbrains.com/issue/KTIJ-16582/Consumer-Kotlin-JVM-library-cannot-access-a-Kotlin-Multiplatform-JVM-target-resources-in-multi-module-Gradle-project
tasks {
val jvmProcessResources by getting
val fixMissingResources by creating(Copy::class) {
dependsOn(jvmProcessResources)
from(layout.buildDirectory.dir("processedResources/jvm/main"))
into(layout.buildDirectory.dir("classes/kotlin/jvm/main"))
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
val jvmJar by getting(Jar::class) {
dependsOn(fixMissingResources)
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
}

tasks.named("jvmTest") {
dependsOn("fixMissingResources")
}
14 changes: 14 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ pluginManagement {
val nexusStagingVersion = extra["nexusStaging.version"] as String
val nexusPublishVersion = extra["nexusPublish.version"] as String

val kspVersion = extra["ksp.version"] as String
val jupyterApiVersion = extra["jupyterApi.version"] as String

kotlin("multiplatform") version kotlinVersion
kotlin("jvm").version(kotlinVersion)

id("org.jetbrains.dokka") version dokkaVersion

id("io.codearte.nexus-staging") version nexusStagingVersion
id("io.github.gradle-nexus.publish-plugin") version nexusPublishVersion

id("com.google.devtools.ksp") version kspVersion
kotlin("jupyter.api") version jupyterApiVersion
}
}

Expand All @@ -39,6 +45,9 @@ include("js-frontend-app")
include("geotools")
include("geotools-batik")
include("dokka")
include("jupyter")
include("geotools-jupyter")
include("json")

project(":demo-common").projectDir = File("./demo/demo-common")
project(":jvm-javafx").projectDir = File("./demo/jvm-javafx")
Expand All @@ -50,3 +59,8 @@ project(":geotools").projectDir = File("./toolkit/geotools")
project(":geotools-batik").projectDir = File("./demo/geotools-batik")

project(":dokka").projectDir = File("./docs/dokka")

project(":jupyter").projectDir = File("./toolkit/jupyter")
project(":geotools-jupyter").projectDir = File("./toolkit/geotools-jupyter")

project(":json").projectDir = File("./toolkit/json")
103 changes: 103 additions & 0 deletions toolkit/geotools-jupyter/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin("jvm")
`maven-publish`
signing
id("com.google.devtools.ksp")
kotlin("jupyter.api")
}

repositories {
mavenCentral()
}

val geoToolsVersion = extra["geotools.version"] as String

dependencies {
implementation(projects.plotApi)
// basic LPK jupyter integration
implementation(projects.jupyter)

// geotools implementations
implementation(projects.geotools)
implementation("org.geotools:gt-main:$geoToolsVersion")
implementation("org.geotools:gt-geojson:$geoToolsVersion")

testImplementation(kotlin("test"))
}

kotlin {
jvmToolchain(11)
}
tasks.withType<KotlinCompile>().all {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
}

tasks.withType<JavaCompile>().all {
sourceCompatibility = JavaVersion.VERSION_11.toString()
targetCompatibility = JavaVersion.VERSION_11.toString()
}

tasks.processJupyterApiResources {
libraryProducers = listOf("org.jetbrains.letsPlot.toolkit.geotools.jupyter.Integration")
}

val artifactBaseName = "lets-plot-kotlin-geotools-jupyter"
val artifactGroupId = project.group as String
val artifactVersion = project.version as String

afterEvaluate {

publishing {
publications {
// Build artifact with all dependencies.
create<MavenPublication>("letsPlotKotlinGeotoolsJupyter") {

groupId = artifactGroupId
artifactId = artifactBaseName
version = artifactVersion

from(components["java"])

pom {
name.set("Lets-Plot Kotlin Geotools Jupyter Integration")
description.set(
"Lets-Plot Kotlin Geotools Integration For Kotlin Jupyter Kernel."
)
url.set("https://github.com/JetBrains/lets-plot-kotlin")
licenses {
license {
name.set("MIT")
url.set("https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/LICENSE")
}
}
developers {
developer {
id.set("jetbrains")
name.set("JetBrains")
email.set("[email protected]")
}
}
scm {
url.set("https://github.com/JetBrains/lets-plot-kotlin")
}
}
}
}

repositories {
mavenLocal {
val localMavenRepository: String by project
url = uri(localMavenRepository)
}
}
}
}
signing {
if (!(project.version as String).contains("SNAPSHOT")) {
sign(publishing.publications)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.jetbrains.letsPlot.toolkit.geotools.jupyter

import org.jetbrains.kotlinx.jupyter.api.Notebook
import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
import org.jetbrains.kotlinx.jupyter.api.libraries.repositories
import org.jetbrains.letsPlot.export.VersionChecker

@Suppress("unused")
class Integration(private val notebook: Notebook, private val options: MutableMap<String, String?>) :
JupyterIntegration() {
private val api = options["api"] ?: VersionChecker.letsPlotKotlinAPIVersion
override fun Builder.onLoaded() {
repositories {
maven("https://repo.osgeo.org/repository/release")
}
import("org.jetbrains.letsPlot.toolkit.geotools.toSpatialDataset")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.jetbrains.letsPlot.toolkit.geotools.jupyter

import org.jetbrains.kotlinx.jupyter.testkit.JupyterReplTestCase
import kotlin.test.Test

class NaturalEarthTest : JupyterReplTestCase() {
private val geotoolsDependencies = """
USE {
dependencies {
implementation("org.geotools:gt-shapefile:30.0")
}
}
""".trimIndent()

private val naturalEarthMap = """
import org.geotools.data.shapefile.ShapefileDataStoreFactory
import org.geotools.data.simple.SimpleFeatureCollection
import java.net.URL
val factory = ShapefileDataStoreFactory()
val worldFeatures : SimpleFeatureCollection = with("naturalearth_lowres") {
val url = "https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/docs/examples/shp/${'$'}this/${'$'}this.shp"
factory.createDataStore(URL(url)).featureSource.features
}
val world = worldFeatures.toSpatialDataset(10)
letsPlot() +
geomMap(map = world) +
ggsize(700, 400) +
themeVoid()
""".trimIndent()

@Test
fun `natural earth example compilation in jupyter`() {
execRendered(geotoolsDependencies)
execRendered(naturalEarthMap)
}
}
68 changes: 68 additions & 0 deletions toolkit/json/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
plugins {
kotlin("jvm")
`maven-publish`
signing
}

val serializationVersion = extra["serialization.version"] as String

dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")

testImplementation(kotlin("test"))
}


val artifactBaseName = "lets-plot-kotlin-json"
val artifactGroupId = project.group as String
val artifactVersion = project.version as String

afterEvaluate {
publishing {
publications {
create<MavenPublication>("letsPlotKotlinJson") {
groupId = artifactGroupId
artifactId = artifactBaseName
version = artifactVersion

from(components["java"])

pom {
name.set("Lets-Plot Kotlin Util")
description.set(
"Lets-Plot Kotlin Util For Json Serialization."
)
url.set("https://github.com/JetBrains/lets-plot-kotlin")
licenses {
license {
name.set("MIT")
url.set("https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/LICENSE")
}
}
developers {
developer {
id.set("jetbrains")
name.set("JetBrains")
email.set("[email protected]")
}
}
scm {
url.set("https://github.com/JetBrains/lets-plot-kotlin")
}
}
}
}

repositories {
mavenLocal {
val localMavenRepository: String by project
url = uri(localMavenRepository)
}
}
}
}
signing {
if (!(project.version as String).contains("SNAPSHOT")) {
sign(publishing.publications)
}
}
Loading

0 comments on commit c81d496

Please sign in to comment.