Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b257895

Browse files
committedMar 10, 2021
Merge remote-tracking branch 'upstream/master'
2 parents eae6394 + 679aacd commit b257895

File tree

9 files changed

+222
-40
lines changed

9 files changed

+222
-40
lines changed
 

‎docs/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
# Kotlin kernel for IPython/Jupyter
88

9-
[Kotlin](https://kotlinlang.org/) (1.4.30) kernel for [Jupyter](https://jupyter.org).
9+
[Kotlin](https://kotlinlang.org/) (1.4.31) kernel for [Jupyter](https://jupyter.org).
1010

1111
Beta version. Tested with Jupyter Notebook 6.0.3, Jupyter Lab 1.2.6 and Jupyter Console 6.1.0
1212
on Windows, Ubuntu Linux and macOS. Using with Jupyter Console frontend is problematic now because of
@@ -189,7 +189,7 @@ List of supported libraries:
189189
- [kaliningraph](https://github.com/breandan/kaliningraph) - Graph library with a DSL for constructing graphs and visualizing the behavior of graph algorithms
190190
- [khttp](https://github.com/jkcclemens/khttp) - HTTP networking library
191191
- [klaxon](https://github.com/cbeust/klaxon) - JSON parser for Kotlin
192-
- [kmath](https://github.com/mipt-npm/kmath) - Experimental Kotlin mathematical library operating on generic algebras
192+
- [kmath](https://github.com/mipt-npm/kmath) - Experimental Kotlin algebra-based mathematical library
193193
- [koma](https://koma.kyonifer.com/index.html) - Scientific computing library
194194
- [kotlin-dl](https://github.com/JetBrains/KotlinDL) - KotlinDL library which provides Keras-like API for deep learning
195195
- [kotlin-statistics](https://github.com/thomasnield/kotlin-statistics) - Idiomatic statistical operators for Kotlin

‎gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# kotlinVersion=1.4.255-SNAPSHOT
2-
kotlinVersion=1.4.30
2+
kotlinVersion=1.4.31
33
kotlinLanguageLevel=1.4
44
jvmTarget=1.8
55

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package org.jetbrains.kotlinx.jupyter.api.libraries
2+
3+
import java.io.File
4+
import java.util.logging.Logger
5+
6+
/**
7+
* Build a resource tree using [ResourcesBuilder]. The builder allows to construct `js` and `css` bundles. Each bundle
8+
* could contain multiple files or urls. Each of those could contain multiple fallback paths (for example if URL not found,
9+
* local resource is used.
10+
*/
11+
fun JupyterIntegration.Builder.resources(block: ResourcesBuilder.() -> Unit) {
12+
val resources = ResourcesBuilder().apply(block)
13+
resources.resources.forEach {
14+
resource(it)
15+
}
16+
}
17+
18+
class ResourcesBuilder {
19+
internal val resources = ArrayList<LibraryResource>()
20+
21+
class BundleBuilder {
22+
internal val bundles = ArrayList<ResourceFallbacksBundle>()
23+
24+
private fun checkLocalPath(localPath: String) {
25+
if (!File(localPath).exists()) {
26+
Logger.getLogger("JupyterIntegration").warning("A resource with local file path '$localPath' not found.")
27+
}
28+
}
29+
30+
private fun checkClassPath(classPath: String) {
31+
if (javaClass.getResource(classPath) == null) {
32+
Logger.getLogger("JupyterIntegration").warning("A resource with classpath '$classPath' not found.")
33+
}
34+
}
35+
36+
/**
37+
* Create an url resource with optional embedding (governed by [embed] flag) with optional local file fallback and
38+
* a class-path fallback. If fallbacks are null, they are not used.
39+
*/
40+
@OptIn(ExperimentalStdlibApi::class)
41+
fun url(url: String, localFallBack: String? = null, classpathFallBack: String? = null, embed: Boolean = false) {
42+
val libraryResource = ResourceFallbacksBundle(
43+
buildList {
44+
if (embed) {
45+
add(ResourceLocation(url, ResourcePathType.URL_EMBEDDED))
46+
} else {
47+
add(ResourceLocation(url, ResourcePathType.URL))
48+
}
49+
localFallBack?.let {
50+
checkLocalPath(localFallBack)
51+
add(ResourceLocation(localFallBack, ResourcePathType.LOCAL_PATH))
52+
}
53+
classpathFallBack?.let {
54+
checkClassPath(classpathFallBack)
55+
add(ResourceLocation(classpathFallBack, ResourcePathType.CLASSPATH_PATH))
56+
}
57+
}
58+
)
59+
bundles.add(libraryResource)
60+
}
61+
62+
/**
63+
* Use local resource from file
64+
*/
65+
fun local(localPath: String) {
66+
checkLocalPath(localPath)
67+
bundles.add(
68+
ResourceFallbacksBundle(
69+
listOf(ResourceLocation(localPath, ResourcePathType.LOCAL_PATH))
70+
)
71+
)
72+
}
73+
74+
/**
75+
* Use Jar class-path resource
76+
*/
77+
fun classPath(classPath: String) {
78+
checkClassPath(classPath)
79+
bundles.add(
80+
ResourceFallbacksBundle(
81+
listOf(ResourceLocation(classPath, ResourcePathType.CLASSPATH_PATH))
82+
)
83+
)
84+
}
85+
}
86+
87+
/**
88+
* Create a JS resource bundle
89+
*/
90+
fun js(name: String, block: BundleBuilder.() -> Unit) {
91+
val bundles = BundleBuilder().apply(block).bundles
92+
resources.add(
93+
LibraryResource(
94+
name = name,
95+
type = ResourceType.JS,
96+
bundles = bundles
97+
)
98+
)
99+
}
100+
101+
/**
102+
* Create a Css resource bundle
103+
*/
104+
fun css(name: String, block: BundleBuilder.() -> Unit) {
105+
val bundles = BundleBuilder().apply(block).bundles
106+
resources.add(
107+
LibraryResource(
108+
name = name,
109+
type = ResourceType.CSS,
110+
bundles = bundles
111+
)
112+
)
113+
}
114+
}

‎jupyter-lib/kotlin-jupyter-api-gradle-plugin/build.gradle.kts

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ project.version = rootProject.version
1010
project.group = "org.jetbrains.kotlin"
1111

1212
val junitVersion: String by rootProject
13+
val kotlinVersion: String by rootProject
1314

1415
repositories {
1516
jcenter()
@@ -21,7 +22,7 @@ dependencies {
2122
// Temporary solution until Kotlin 1.4 will be supported in
2223
// .kts buildscripts and it will be possible to use
2324
// kotlinx.serialization in plugin code
24-
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.20")
25+
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
2526
implementation("com.google.code.gson:gson:2.8.6")
2627

2728
testImplementation(kotlin("test"))

‎jupyter-lib/kotlin-jupyter-api-gradle-plugin/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/plugin/ApiGradlePlugin.kt

+37-14
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,75 @@ package org.jetbrains.kotlinx.jupyter.api.plugin
22

33
import org.gradle.api.Plugin
44
import org.gradle.api.Project
5+
import org.gradle.kotlin.dsl.findByType
56
import org.gradle.kotlin.dsl.invoke
67
import org.gradle.kotlin.dsl.register
78
import org.gradle.kotlin.dsl.repositories
9+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
810
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin
911
import org.jetbrains.kotlin.gradle.plugin.KaptExtension
12+
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
1013
import org.jetbrains.kotlinx.jupyter.api.plugin.tasks.JupyterApiResourcesTask
1114

1215
class ApiGradlePlugin : Plugin<Project> {
13-
override fun apply(target: Project) {
14-
target.pluginManager.run {
16+
override fun apply(target: Project): Unit = with(target) {
17+
pluginManager.run {
1518
apply(Kapt3GradleSubplugin::class.java)
1619
}
1720

18-
val jupyterBuildPath = target.buildDir.resolve(FQNS_PATH)
19-
target.extensions.configure<KaptExtension>("kapt") {
21+
val jupyterBuildPath = buildDir.resolve(FQNS_PATH)
22+
extensions.configure<KaptExtension>("kapt") {
2023
arguments {
2124
arg("kotlin.jupyter.fqn.path", jupyterBuildPath)
2225
}
2326
}
2427

25-
target.repositories {
28+
repositories {
2629
mavenCentral()
2730
}
2831

2932
val pluginExtension = KotlinJupyterPluginExtension(target)
30-
target.extensions.add("kotlinJupyter", pluginExtension)
33+
extensions.add("kotlinJupyter", pluginExtension)
3134
pluginExtension.addDependenciesIfNeeded()
3235

33-
target.tasks {
36+
tasks {
3437
val cleanJupyterTask = register("cleanJupyterPluginFiles") {
3538
doLast {
3639
jupyterBuildPath.deleteRecursively()
3740
}
3841
}
3942

4043
val resourcesTaskName = "processJupyterApiResources"
41-
register<JupyterApiResourcesTask>(resourcesTaskName) {
42-
val kaptKotlinTask = findByName("kaptKotlin")
43-
if (kaptKotlinTask != null) {
44-
dependsOn(kaptKotlinTask)
45-
kaptKotlinTask.dependsOn(cleanJupyterTask)
44+
fun registerResourceTask() {
45+
register<JupyterApiResourcesTask>(resourcesTaskName) {
46+
val kaptKotlinTask = findByName("kaptKotlin")
47+
if (kaptKotlinTask != null) {
48+
dependsOn(kaptKotlinTask)
49+
kaptKotlinTask.dependsOn(cleanJupyterTask)
50+
}
4651
}
4752
}
4853

49-
named("processResources") {
50-
dependsOn(resourcesTaskName)
54+
// apply configuration to JVM-only project
55+
plugins.withId("org.jetbrains.kotlin.jvm") {
56+
// Task should be registered after plugin is applied
57+
registerResourceTask()
58+
named("processResources") {
59+
dependsOn(resourcesTaskName)
60+
}
61+
}
62+
63+
// apply only to multiplatform plugin
64+
plugins.withId("org.jetbrains.kotlin.multiplatform") {
65+
// Task should be registered after plugin is applied
66+
registerResourceTask()
67+
extensions.findByType<KotlinMultiplatformExtension>()?.apply {
68+
val jvmTargetName = targets.filterIsInstance<KotlinJvmTarget>().firstOrNull()?.name
69+
?: error("Single JVM target not found in a multiplatform project")
70+
named(jvmTargetName + "ProcessResources") {
71+
dependsOn(resourcesTaskName)
72+
}
73+
}
5174
}
5275
}
5376
}

‎jupyter-lib/kotlin-jupyter-api-gradle-plugin/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/plugin/KotlinJupyterPluginExtension.kt

+32-10
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,49 @@ package org.jetbrains.kotlinx.jupyter.api.plugin
22

33
import org.gradle.api.Project
44
import org.gradle.kotlin.dsl.dependencies
5+
import org.gradle.kotlin.dsl.findByType
6+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
7+
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
8+
9+
private fun Project.configureDependency(scope: String, dependencyNotation: Any) {
10+
// apply configuration to JVM-only project
11+
plugins.withId("org.jetbrains.kotlin.jvm") {
12+
val configuration = project.configurations.findByName(scope)
13+
?: error("$scope configuration is not resolved for a Kotlin-JVM project")
14+
dependencies {
15+
configuration.invoke(dependencyNotation)
16+
}
17+
}
18+
// apply only to multiplatform plugin
19+
plugins.withId("org.jetbrains.kotlin.multiplatform") {
20+
extensions.findByType<KotlinMultiplatformExtension>()?.apply {
21+
val jvmTargetName = targets.filterIsInstance<KotlinJvmTarget>().firstOrNull()?.name
22+
?: error("Single JVM target not found in a multiplatform project")
23+
val configuration = project.configurations.findByName(jvmTargetName + scope.capitalize())
24+
?: error("$scope configuration is not resolved for a multiplatform project")
25+
dependencies {
26+
configuration.invoke(dependencyNotation)
27+
}
28+
}
29+
}
30+
}
531

632
class KotlinJupyterPluginExtension(
733
private val project: Project
834
) {
9-
fun addApiDependency(version: String? = null) {
35+
fun addApiDependency(version: String? = null) = with(project) {
1036
val apiVersion = version ?: apiVersion()
11-
val compileOnlyConf = project.configurations.findByName("compileOnly") ?: return
12-
project.dependencies {
13-
compileOnlyConf("$GROUP_ID:kotlin-jupyter-api:$apiVersion")
14-
}
37+
configureDependency("compileOnly", "$GROUP_ID:kotlin-jupyter-api:$apiVersion")
1538
}
1639

17-
fun addScannerDependency(version: String? = null) {
18-
val implementationConf = project.configurations.findByName("implementation") ?: return
19-
val kaptConf = project.configurations.findByName("kapt") ?: return
40+
fun addScannerDependency(version: String? = null) = with(project) {
41+
val kaptConf = configurations.findByName("kapt") ?: return
2042
val apiVersion = version ?: apiVersion()
2143
val mavenCoordinates = "$GROUP_ID:kotlin-jupyter-api-annotations:$apiVersion"
22-
project.dependencies {
23-
implementationConf(mavenCoordinates)
44+
dependencies {
2445
kaptConf(mavenCoordinates)
2546
}
47+
configureDependency("implementation", mavenCoordinates)
2648
}
2749

2850
internal fun addDependenciesIfNeeded() {

‎jupyter-lib/kotlin-jupyter-api-gradle-plugin/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/plugin/tasks/JupyterApiResourcesTask.kt

+23-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ import com.google.gson.Gson
44
import org.gradle.api.DefaultTask
55
import org.gradle.api.tasks.Input
66
import org.gradle.api.tasks.OutputDirectory
7+
import org.gradle.api.tasks.SourceSet
78
import org.gradle.api.tasks.SourceSetContainer
89
import org.gradle.api.tasks.TaskAction
10+
import org.gradle.kotlin.dsl.findByType
11+
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
12+
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
913
import org.jetbrains.kotlinx.jupyter.api.plugin.ApiGradlePlugin
1014
import java.io.File
1115

@@ -31,9 +35,25 @@ open class JupyterApiResourcesTask : DefaultTask() {
3135

3236
init {
3337
val sourceSets = project.extensions.getByName("sourceSets") as SourceSetContainer
34-
val mainSourceSet = sourceSets.named("main").get()
35-
outputDir = mainSourceSet.output.resourcesDir?.resolve("META-INF/kotlin-jupyter-libraries")
36-
?: throw IllegalStateException("No resources dir for main source set")
38+
when {
39+
project.plugins.findPlugin("org.jetbrains.kotlin.jvm") != null -> {
40+
val mainSourceSet: SourceSet = sourceSets.named("main").get()
41+
outputDir = mainSourceSet.output.resourcesDir?.resolve("META-INF/kotlin-jupyter-libraries")
42+
?: throw IllegalStateException("No resources dir for main source set")
43+
}
44+
project.plugins.findPlugin("org.jetbrains.kotlin.multiplatform") != null -> {
45+
val mppExtension = project.extensions.findByType<KotlinMultiplatformExtension>()
46+
?: error("Kotlin MPP extension not found")
47+
val jvmTargetName = mppExtension.targets.filterIsInstance<KotlinJvmTarget>().firstOrNull()?.name
48+
?: error("Single JVM target not found in a multiplatform project")
49+
// TODO properly resolve resource directory
50+
outputDir = project.buildDir.resolve("processedResources/$jvmTargetName/main")
51+
.resolve("META-INF/kotlin-jupyter-libraries")
52+
}
53+
else -> {
54+
error("Kotlin plugin not found in the project")
55+
}
56+
}
3757
}
3858

3959
@TaskAction

‎jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/libraries/JsLibraryResourcesProcessor.kt

+10-8
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class JsLibraryResourcesProcessor : LibraryResourcesProcessor {
5252

5353
override fun wrapLibrary(resource: LibraryResource, classLoader: ClassLoader): String {
5454
val resourceName = resource.name
55+
val resourceIndex = """["$resourceName"]"""
56+
val callResourceIndex = """["call_$resourceName"]"""
5557
val elementId = "kotlin_out_$outputCounter"
5658
++outputCounter
5759

@@ -65,10 +67,10 @@ class JsLibraryResourcesProcessor : LibraryResourcesProcessor {
6567
if(!window.kotlinQueues) {
6668
window.kotlinQueues = {};
6769
}
68-
if(!window.kotlinQueues.$resourceName) {
70+
if(!window.kotlinQueues$resourceIndex) {
6971
var resQueue = [];
70-
window.kotlinQueues.$resourceName = resQueue;
71-
window.call_$resourceName = function(f) {
72+
window.kotlinQueues$resourceIndex = resQueue;
73+
window$callResourceIndex = function(f) {
7274
resQueue.push(f);
7375
}
7476
}
@@ -79,13 +81,13 @@ class JsLibraryResourcesProcessor : LibraryResourcesProcessor {
7981
var script = document.createElement("script");
8082
gen(script)
8183
script.onload = function() {
82-
window.call_$resourceName = function(f) {f();};
83-
window.kotlinQueues.$resourceName.forEach(function(f) {f();});
84-
window.kotlinQueues.$resourceName = [];
84+
window$callResourceIndex = function(f) {f();};
85+
window.kotlinQueues$resourceIndex.forEach(function(f) {f();});
86+
window.kotlinQueues$resourceIndex = [];
8587
};
8688
script.onerror = function() {
87-
window.call_$resourceName = function(f) {};
88-
window.kotlinQueues.$resourceName = [];
89+
window$callResourceIndex = function(f) {};
90+
window.kotlinQueues$resourceIndex = [];
8991
var div = document.createElement("div");
9092
div.style.color = 'darkred';
9193
div.textContent = 'Error loading resource $resourceName';

‎libraries/dataframe.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"description": "Kotlin framework for structured data processing",
33
"properties": {
4-
"v": "0.7.2-dev-169"
4+
"v": "0.7.2-dev-178-0.8.3.260"
55
},
66
"repositories": [
77
"https://kotlin.bintray.com/kotlin-datascience"

0 commit comments

Comments
 (0)
Please sign in to comment.