-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add jupyter integration for lets-plot-kotlin and lets-plot-kotlin-geotools #258
Conversation
I've run into the problem that the latest versions of the Kotlin jupyter api use java 11, which makes it completely incompatible with geotools module, and partially with plot-api. In particular, I had to add different versions of the plugin to them because of this. But it's clear that this is a bad solution. @ileasile suggested the following: Kotlin/kotlin-jupyter-libraries#421 (comment) |
I suggest adding lets-plot-jupyter and lets-plot-geotools-jupyter modules. They should have all dependencies that are now listed in corresponding descriptors, and also integration classes. Also, they should target 11th version of JVM bytecode. I'm ready to pair-program it with you if there are any problems in implementation |
Shouldn't be difficult, but I'm interested in @alshan opinion. |
Jupyter integration doesn't belong to the "plot-api" project in my opinion. Let's move it to a separate project nested in the 'toolkit' folder? Can have java 11 as a target there. |
plot-api/src/commonMain/kotlin/org/jetbrains/letsPlot/frontend/NotebookFrontendContext.kt
Outdated
Show resolved
Hide resolved
@alshan, we can fix the version of the lets-plot library (and, but not necessarily - js) when compiling the artifact with integration. This will help user to avoid version incompatibility. That is, there will be only one version in the descriptor - Lets-Plot Kotlin, one dependency that will load the lpk of this version and lp corresponding to it (bundled at compilation). What do you think? |
And of course it will avoid cases when the integration code is written on a version incompatible with the specified in argument. |
Do you mean drop arguments in |
Yes. There will be only one dependency on lets-plot-kotlin-jupyter, that will load lets-plot-kotlin with the same version and lets-plot artifacts with tge corresonding for this lpk versions. |
Sounds good. |
…K implementations; extract spec serialization to util module
Extracted integrations to separated modules |
toolkit/util/build.gradle.kts
Outdated
@@ -0,0 +1,66 @@ | |||
plugins { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We like self-descriptive code. Could we rename "utils" to something more specific? Who's the utils client?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, this module is responsible for spec serialization. Also, I'd like to move here a specific logic, that is used for example in Kotlin Notebook - applying the flavour for spec if it is not set (this is necessary for auto-applying the environment theme).
So generally, this is useful stuff for those who create a Lets-plot spec on the client and send it (like Kotlin Notebook).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The package is package org.jetbrains.letsPlot.toolkit.jupyter.util
.
If this project is jupyter specific I would propose to rename it to "jupyter-util".
On the other hand, if it's not jupyter specific then we better remove "jupyter" from the package name and rename the project to smth like "kotlinx-serialization" (and the package - accordingly).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, may be just "serialization"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure now. This is generic serialization code not related to LP or Jupyter. Strictly speaking it shouldn't be here at all. Do you use it in Jupyter integration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, let's remove mentioning of letsPlot and spec:
typealias LetsPlotSpec = Map<String, Any>
fun serializeSpec(spec: LetsPlotSpec): JsonElement {
return serialize(spec)
}
Next, this module is looking as a patch/missing feature for kotlinx.serilization.json wherefore we can name the package as "org.jetbrains.letsPlot.toolkit.kotlinx.json" and the project name would be "kotlinx-json".
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But why would we remove the mention of lets-plot? We can more generally say that it is a serialisation of a Map that contains nested only Map, List and primitives
, but it is exactly a serialisation of Lets-Plot spec. Yes, the module does not use Lets-plot directly, but this function is restricted to work specifically with Lets-Plot spec. If the spec structure is changed in the future (like adding a new possible type, or something like that), then we will also have to change this logic. So this implementation depends directly on Lets-Plot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But JSON is essentially just Maps, Lists and primitives. I don't see anything that is specific for lets-plot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to json
. All Lets-plot mentions are removed.
is String -> JsonPrimitive(obj) | ||
is Boolean -> JsonPrimitive(obj) | ||
is Number -> JsonPrimitive(obj) | ||
else -> error("Don't know how to parse object [$obj] of class ${obj::class}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message: Don't know how to serialize object .. ?
} | ||
} | ||
|
||
fun deserializeSpec(json: JsonElement): LetsPlotSpec { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be replaced with deserializeMap
with an additional parameter controlling handling of null
(i.e. keep/drop/error).
json is JsonNull -> null | ||
json.isString -> json.content | ||
else -> { | ||
json.booleanOrNull ?: json.doubleOrNull ?: error("Unknown JSON primitive type: [$json]") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alshan we don't try to parse int here (and most likely it will result in an error) so I would say it's not completely universal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK there is only one numeric type in JSON - double-precision floating-point and decimal point in the string representation is just an option. Accordingly, the code above looks right and universal.
Add Jupyter Integration plot-api and toolkit/geotools modules. All the old logic (imports/init/renders) from descriptors has been moved into them. Updated descriptors are in this PR.
A new type returned by rendering has also been added, which allows you to use the following features that are now available for Kandy plots in Kotlin Notebook:
Added
letsPlotNotebookConfig
variable (in notebooks only) which allows to disable native rendering in KTNB.These changes do not affect Jupyter and Datalore notebooks.
Also this rendering adds static SVG in the output, hidden by script which allows to show static part of plot on GitHub/Gist.
Several simple tests for Jupyter Integration are also added.