Skip to content

Commit c81d496

Browse files
Add jupyter integration for lets-plot-kotlin and lets-plot-kotlin-geotools (#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
1 parent 11fd59b commit c81d496

File tree

21 files changed

+836
-0
lines changed

21 files changed

+836
-0
lines changed

build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ plugins {
1414
id("io.codearte.nexus-staging") apply false
1515

1616
id("io.github.gradle-nexus.publish-plugin")
17+
18+
// Add the KSP plugin before the Jupyter API to avoid ksp versions incompatibility.
19+
// May be removed when using further versions of the jupyter api
20+
id("com.google.devtools.ksp") apply false
21+
kotlin("jupyter.api") apply false
1722
}
1823

1924
val localProps = Properties()

gradle.properties

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,24 @@ kotlin.code.style=official
1212
kotlin.daemon.jvmargs=-Xmx2048M
1313
kotlin.jvm.target.validation.mode=error
1414

15+
# Jupyter API
16+
kotlin.jupyter.add.scanner=false
17+
1518
# Versions
1619
kotlin.version=1.9.25
1720
datetime.version=0.3.2
1821
kotlinLogging.version=2.0.5
1922
slf4j.version=1.7.32
2023
assertj.version=3.26.3
24+
serialization.version=1.7.3
2125

2226
dokka.version=1.9.20
2327
nexusStaging.version=0.30.0
2428
nexusPublish.version=1.3.0
2529

30+
ksp.version=1.9.25-1.0.20
31+
jupyterApi.version=0.12.0-313
32+
2633
# Also update JS version in <home>/demo/js-frontend-app/src/main/resources/index.html
2734
letsPlot.version=4.5.1
2835

plot-api/build.gradle.kts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,22 @@ tasks {
177177
// print("${project.name}: ${uri(project.localMavenRepository)}")
178178
//}
179179

180+
// Provide jvm resources to jupyter module
181+
// https://youtrack.jetbrains.com/issue/KTIJ-16582/Consumer-Kotlin-JVM-library-cannot-access-a-Kotlin-Multiplatform-JVM-target-resources-in-multi-module-Gradle-project
182+
tasks {
183+
val jvmProcessResources by getting
184+
val fixMissingResources by creating(Copy::class) {
185+
dependsOn(jvmProcessResources)
186+
from(layout.buildDirectory.dir("processedResources/jvm/main"))
187+
into(layout.buildDirectory.dir("classes/kotlin/jvm/main"))
188+
duplicatesStrategy = DuplicatesStrategy.INCLUDE
189+
}
190+
val jvmJar by getting(Jar::class) {
191+
dependsOn(fixMissingResources)
192+
duplicatesStrategy = DuplicatesStrategy.INCLUDE
193+
}
194+
}
195+
196+
tasks.named("jvmTest") {
197+
dependsOn("fixMissingResources")
198+
}

settings.gradle.kts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@ pluginManagement {
1616
val nexusStagingVersion = extra["nexusStaging.version"] as String
1717
val nexusPublishVersion = extra["nexusPublish.version"] as String
1818

19+
val kspVersion = extra["ksp.version"] as String
20+
val jupyterApiVersion = extra["jupyterApi.version"] as String
21+
1922
kotlin("multiplatform") version kotlinVersion
2023
kotlin("jvm").version(kotlinVersion)
2124

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

2427
id("io.codearte.nexus-staging") version nexusStagingVersion
2528
id("io.github.gradle-nexus.publish-plugin") version nexusPublishVersion
29+
30+
id("com.google.devtools.ksp") version kspVersion
31+
kotlin("jupyter.api") version jupyterApiVersion
2632
}
2733
}
2834

@@ -39,6 +45,9 @@ include("js-frontend-app")
3945
include("geotools")
4046
include("geotools-batik")
4147
include("dokka")
48+
include("jupyter")
49+
include("geotools-jupyter")
50+
include("json")
4251

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

5261
project(":dokka").projectDir = File("./docs/dokka")
62+
63+
project(":jupyter").projectDir = File("./toolkit/jupyter")
64+
project(":geotools-jupyter").projectDir = File("./toolkit/geotools-jupyter")
65+
66+
project(":json").projectDir = File("./toolkit/json")
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2+
3+
plugins {
4+
kotlin("jvm")
5+
`maven-publish`
6+
signing
7+
id("com.google.devtools.ksp")
8+
kotlin("jupyter.api")
9+
}
10+
11+
repositories {
12+
mavenCentral()
13+
}
14+
15+
val geoToolsVersion = extra["geotools.version"] as String
16+
17+
dependencies {
18+
implementation(projects.plotApi)
19+
// basic LPK jupyter integration
20+
implementation(projects.jupyter)
21+
22+
// geotools implementations
23+
implementation(projects.geotools)
24+
implementation("org.geotools:gt-main:$geoToolsVersion")
25+
implementation("org.geotools:gt-geojson:$geoToolsVersion")
26+
27+
testImplementation(kotlin("test"))
28+
}
29+
30+
kotlin {
31+
jvmToolchain(11)
32+
}
33+
tasks.withType<KotlinCompile>().all {
34+
kotlinOptions {
35+
jvmTarget = JavaVersion.VERSION_11.toString()
36+
}
37+
}
38+
39+
tasks.withType<JavaCompile>().all {
40+
sourceCompatibility = JavaVersion.VERSION_11.toString()
41+
targetCompatibility = JavaVersion.VERSION_11.toString()
42+
}
43+
44+
tasks.processJupyterApiResources {
45+
libraryProducers = listOf("org.jetbrains.letsPlot.toolkit.geotools.jupyter.Integration")
46+
}
47+
48+
val artifactBaseName = "lets-plot-kotlin-geotools-jupyter"
49+
val artifactGroupId = project.group as String
50+
val artifactVersion = project.version as String
51+
52+
afterEvaluate {
53+
54+
publishing {
55+
publications {
56+
// Build artifact with all dependencies.
57+
create<MavenPublication>("letsPlotKotlinGeotoolsJupyter") {
58+
59+
groupId = artifactGroupId
60+
artifactId = artifactBaseName
61+
version = artifactVersion
62+
63+
from(components["java"])
64+
65+
pom {
66+
name.set("Lets-Plot Kotlin Geotools Jupyter Integration")
67+
description.set(
68+
"Lets-Plot Kotlin Geotools Integration For Kotlin Jupyter Kernel."
69+
)
70+
url.set("https://github.com/JetBrains/lets-plot-kotlin")
71+
licenses {
72+
license {
73+
name.set("MIT")
74+
url.set("https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/LICENSE")
75+
}
76+
}
77+
developers {
78+
developer {
79+
id.set("jetbrains")
80+
name.set("JetBrains")
81+
email.set("lets-plot@jetbrains.com")
82+
}
83+
}
84+
scm {
85+
url.set("https://github.com/JetBrains/lets-plot-kotlin")
86+
}
87+
}
88+
}
89+
}
90+
91+
repositories {
92+
mavenLocal {
93+
val localMavenRepository: String by project
94+
url = uri(localMavenRepository)
95+
}
96+
}
97+
}
98+
}
99+
signing {
100+
if (!(project.version as String).contains("SNAPSHOT")) {
101+
sign(publishing.publications)
102+
}
103+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.jetbrains.letsPlot.toolkit.geotools.jupyter
2+
3+
import org.jetbrains.kotlinx.jupyter.api.Notebook
4+
import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
5+
import org.jetbrains.kotlinx.jupyter.api.libraries.repositories
6+
import org.jetbrains.letsPlot.export.VersionChecker
7+
8+
@Suppress("unused")
9+
class Integration(private val notebook: Notebook, private val options: MutableMap<String, String?>) :
10+
JupyterIntegration() {
11+
private val api = options["api"] ?: VersionChecker.letsPlotKotlinAPIVersion
12+
override fun Builder.onLoaded() {
13+
repositories {
14+
maven("https://repo.osgeo.org/repository/release")
15+
}
16+
import("org.jetbrains.letsPlot.toolkit.geotools.toSpatialDataset")
17+
}
18+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.jetbrains.letsPlot.toolkit.geotools.jupyter
2+
3+
import org.jetbrains.kotlinx.jupyter.testkit.JupyterReplTestCase
4+
import kotlin.test.Test
5+
6+
class NaturalEarthTest : JupyterReplTestCase() {
7+
private val geotoolsDependencies = """
8+
USE {
9+
dependencies {
10+
implementation("org.geotools:gt-shapefile:30.0")
11+
}
12+
}
13+
""".trimIndent()
14+
15+
private val naturalEarthMap = """
16+
import org.geotools.data.shapefile.ShapefileDataStoreFactory
17+
import org.geotools.data.simple.SimpleFeatureCollection
18+
import java.net.URL
19+
20+
val factory = ShapefileDataStoreFactory()
21+
val worldFeatures : SimpleFeatureCollection = with("naturalearth_lowres") {
22+
val url = "https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/docs/examples/shp/${'$'}this/${'$'}this.shp"
23+
factory.createDataStore(URL(url)).featureSource.features
24+
}
25+
26+
val world = worldFeatures.toSpatialDataset(10)
27+
letsPlot() +
28+
geomMap(map = world) +
29+
ggsize(700, 400) +
30+
themeVoid()
31+
""".trimIndent()
32+
33+
@Test
34+
fun `natural earth example compilation in jupyter`() {
35+
execRendered(geotoolsDependencies)
36+
execRendered(naturalEarthMap)
37+
}
38+
}

toolkit/json/build.gradle.kts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
plugins {
2+
kotlin("jvm")
3+
`maven-publish`
4+
signing
5+
}
6+
7+
val serializationVersion = extra["serialization.version"] as String
8+
9+
dependencies {
10+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
11+
12+
testImplementation(kotlin("test"))
13+
}
14+
15+
16+
val artifactBaseName = "lets-plot-kotlin-json"
17+
val artifactGroupId = project.group as String
18+
val artifactVersion = project.version as String
19+
20+
afterEvaluate {
21+
publishing {
22+
publications {
23+
create<MavenPublication>("letsPlotKotlinJson") {
24+
groupId = artifactGroupId
25+
artifactId = artifactBaseName
26+
version = artifactVersion
27+
28+
from(components["java"])
29+
30+
pom {
31+
name.set("Lets-Plot Kotlin Util")
32+
description.set(
33+
"Lets-Plot Kotlin Util For Json Serialization."
34+
)
35+
url.set("https://github.com/JetBrains/lets-plot-kotlin")
36+
licenses {
37+
license {
38+
name.set("MIT")
39+
url.set("https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/LICENSE")
40+
}
41+
}
42+
developers {
43+
developer {
44+
id.set("jetbrains")
45+
name.set("JetBrains")
46+
email.set("lets-plot@jetbrains.com")
47+
}
48+
}
49+
scm {
50+
url.set("https://github.com/JetBrains/lets-plot-kotlin")
51+
}
52+
}
53+
}
54+
}
55+
56+
repositories {
57+
mavenLocal {
58+
val localMavenRepository: String by project
59+
url = uri(localMavenRepository)
60+
}
61+
}
62+
}
63+
}
64+
signing {
65+
if (!(project.version as String).contains("SNAPSHOT")) {
66+
sign(publishing.publications)
67+
}
68+
}

0 commit comments

Comments
 (0)