diff --git a/.gitignore b/.gitignore
index 3e6988e0e..5e567f110 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
.idea/
out/
build/
+distrib-build/
+artifacts/
.gradle/
*.iml
**/.ipynb*
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 9d10e2b20..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-language: java
-
-sudo: false
-
-before_cache:
- - sudo chown -R travis:travis $HOME/.m2
-
-cache:
- directories:
- - ${HOME}/.m2
-
-matrix:
- include:
- # All tests
- - os: linux
- sudo: false
- jdk: "openjdk8"
- dist: xenial
- # env: ENV=...
-
-script:
- - ./gradlew test
-
-after_success:
- - echo "Travis exited with ${TRAVIS_TEST_RESULT}"
-
-after_failure:
- - echo "Travis exited with ${TRAVIS_TEST_RESULT}"
diff --git a/readme.md b/README.md
similarity index 86%
rename from readme.md
rename to README.md
index 1980acfd2..a6f03ad79 100644
--- a/readme.md
+++ b/README.md
@@ -1,4 +1,6 @@
-[](https://travis-ci.com/Kotlin/kotlin-jupyter)
+[](https://pypi.org/project/kotlin-jupyter-kernel/)
+[](https://anaconda.org/jetbrains/kotlin-jupyter-kernel)
+[](https://www.apache.org/licenses/LICENSE-2.0)
# Kotlin kernel for IPython/Jupyter
@@ -18,11 +20,21 @@ Try samples online: [](https://myb
There are two ways to install kernel:
-### Conda package
+### Conda/PyPi packages
-If you have `conda` installed, just run:
+If you have `conda` installed, just run the following command to install stable package version:
-`conda install kotlin-jupyter-kernel -c jetbrains`
+`conda install -c jetbrains kotlin-jupyter-kernel` ([package home](https://anaconda.org/jetbrains/kotlin-jupyter-kernel))
+
+To install conda package from the dev channel:
+
+`conda install -c jetbrains-dev kotlin-jupyter-kernel` ([package home](https://anaconda.org/jetbrains-dev/kotlin-jupyter-kernel))
+
+You can also install this package through `pip` (stable and dev channels accordingly):
+
+`pip install kotlin-jupyter-kernel` ([package home](https://pypi.org/project/kotlin-jupyter-kernel/))
+
+`pip install -i https://test.pypi.org/simple/ kotlin-jupyter-kernel` ([package home](https://test.pypi.org/project/kotlin-jupyter-kernel/))
### From sources
@@ -165,4 +177,4 @@ If a library descriptor with the same name is found in several locations, the fo
2. ['libraries'](libraries) folder at the latest master branch of `https://github.com/Kotlin/kotlin-jupyter` repository
3. Kernel installation directory
-If you don't want some library to be updated automatically, put fixed version of its library descriptor into local settings folder.
\ No newline at end of file
+If you don't want some library to be updated automatically, put fixed version of its library descriptor into local settings folder.
diff --git a/build.gradle b/build.gradle
index d93d9dbd7..26c0f53fe 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,10 +1,12 @@
-import java.nio.file.Files
+import com.beust.klaxon.JsonObject
+
import java.nio.file.Paths
-import java.nio.file.StandardCopyOption
+import java.util.regex.Pattern
buildscript {
ext.shadowJarVersion = "5.2.0"
ext.kotlinVersion = '1.3.70-dev-2104'
+ ext.baseVersion = '0.7.40'
repositories {
jcenter()
mavenLocal()
@@ -13,8 +15,10 @@ buildscript {
maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
}
dependencies {
+ //noinspection DifferentKotlinGradleVersion
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "com.github.jengelman.gradle.plugins:shadow:$shadowJarVersion"
+ classpath "com.beust:klaxon:5.2"
}
}
@@ -25,7 +29,7 @@ allprojects {
jcenter()
mavenLocal()
mavenCentral()
-// only when using Kotlin EAP releases ...
+ // only when using Kotlin EAP releases ...
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
maven { url 'https://kotlin.bintray.com/kotlin-dependencies' }
@@ -38,13 +42,86 @@ allprojects {
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
}
- version = '0.7.3'
+ String artifactsPathStr = rootProject.findProperty('artifactsPath') ?: 'artifacts'
+ String buildCounterStr = rootProject.findProperty('build.counter') ?: '100500'
+ String buildNumber = rootProject.findProperty('build.number') ?: ''
+ String installPath = rootProject.findProperty('installPath')
+
+ ext.rootPath = rootDir.toPath()
+ ext.packageName = 'kotlin-jupyter-kernel'
+ ext.artifactsDir = rootPath.resolve(artifactsPathStr)
+ ext.isProtectedBranch = isProtectedBranch()
+ ext.versionFileName = "VERSION"
+
+ ext.installPathLocal = installPath ? Paths.get(installPath) :
+ Paths.get(System.properties['user.home'].toString(), ".ipython", "kernels", "kotlin")
+ ext.distributionPath = rootPath.resolve("distrib")
+ ext.distribBuildPath = rootPath.resolve("distrib-build")
+ ext.logosPath = getSubDir(rootPath, "resources", "logos")
+
+ String devAddition = isProtectedBranch ? '' : '.dev1'
+ String defaultBuildNumber = "$baseVersion.$buildCounterStr$devAddition"
+ String buildNumberRegex = "[0-9]+(\\.[0-9]+){3}(\\.dev[0-9]+)?"
+
+ if (!Pattern.matches(buildNumberRegex, buildNumber)) {
+ def versionFile = artifactsDir.resolve(versionFileName).toFile()
+ if (versionFile.exists()) {
+ def lines = versionFile.readLines()
+ assert !lines.empty, "There should be at least one line in VERSION file"
+ buildNumber = lines.first().trim()
+ } else {
+ buildNumber = defaultBuildNumber
+ }
+ }
+
+ project.version = buildNumber
+ println("##teamcity[buildNumber '$version']")
+
+ ext {
+ debugPort = 1044
+ debuggerConfig = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort".toString()
+
+ jarsPath = "jars"
+ librariesPath = "libraries"
+ kernelFile = "kernel.json"
+ configDir = "config"
+ // Straight slash is used 'cause it's universal across the platforms, and is used in jar_args config
+ jarArgsFile = configDir + "/jar_args.json"
+
+ distribKernelDir = "kernel"
+ runKernelDir = "run_kotlin_kernel"
+ setupPy = "setup.py"
+ runKernelPy = "run_kernel.py"
+
+ condaMetaDir = "conda"
+ condaMetaYaml = "meta.yaml"
+ condaPackageDir = "conda-package"
+ condaPackageName = packageName
+ condaPackageFileName = "$condaPackageName-${version}-py_0.tar.bz2".toString()
+
+ pyPiPackageDir = "pip-package"
+ pyPiPackageName = packageName.replaceAll("-", "_")
+ pyPiPackageFileName = "$pyPiPackageName-${version}-py3-none-any.whl".toString()
- ext.installPath = project.hasProperty('installPath') ?
- project.getProperty('installPath') :
- Paths.get(System.properties['user.home'].toString(), ".ipython", "kernels", "kotlin").toAbsolutePath().toString()
- ext.debugPort = 1044
- ext.debuggerConfig = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort"
+ copyLibrariesTaskPrefix = "copyLibraries"
+ installLibsTaskPrefix = "installLibs"
+ installKernelTaskPrefix = "installKernel"
+ cleanInstallDirTaskPrefix = "cleanInstallDir"
+
+ localGroup = "local install"
+ distribGroup = "distrib"
+ condaGroup = "conda"
+ pyPiGroup = "pip"
+
+ condaUserStable = rootProject.findProperty('condaUserStable') ?: ''
+ condaPasswordStable = rootProject.findProperty('condaPasswordStable') ?: ''
+ condaUserDev = rootProject.findProperty('condaUserDev') ?: ''
+
+ stablePyPiUser = rootProject.findProperty('stablePyPiUser') ?: ''
+ stablePyPiPassword = rootProject.findProperty('stablePyPiPassword') ?: ''
+ devPyPiUser = rootProject.findProperty('devPyPiUser') ?: ''
+ devPyPiPassword = rootProject.findProperty('devPyPiPassword') ?: ''
+ }
}
apply plugin: 'com.github.johnrengelman.shadow'
@@ -68,7 +145,7 @@ dependencies {
compile "org.apache.maven:maven-core:3.0.3"
compile 'org.slf4j:slf4j-api:1.7.25'
- compile "khttp:khttp:1.0.0"
+ compile 'khttp:khttp:1.0.0'
compile 'org.zeromq:jeromq:0.3.5'
compile 'com.beust:klaxon:5.2'
runtime 'org.slf4j:slf4j-simple:1.7.25'
@@ -85,74 +162,163 @@ jar.manifest.attributes(
)
shadowJar {
- baseName = 'kotlin-jupyter-kernel'
- classifier = ''
+ archiveBaseName.set(packageName)
+ archiveClassifier.set('')
mergeServiceFiles()
}
-task cleanInstallDir(){
- doLast {
- File installDir = new File("$installPath")
- installDir.deleteDir()
+boolean isProtectedBranch() {
+ def branchProp = 'build.branch'
+ def branch = project.findProperty(branchProp) as String
+ println("Current branch: $branch")
+ if (branch != null) {
+ branch = branch.substring(branch.lastIndexOf('/') + 1)
+ return branch == 'master'
}
+ return false
}
-task installKernel(type: Copy, dependsOn: [cleanInstallDir, shadowJar]) {
- from shadowJar.outputs
- into installPath
+static String makeTaskName(String prefix, Boolean local) {
+ return prefix + (local ? "Local" : "Distrib")
}
-void createTaskForSpecs(Boolean debug) {
- String taskName = debug ? "createDebugSpecs" : "createSpecs"
- task(taskName) {
- dependsOn cleanInstallDir
- doLast {
- String sep = File.separator
- String spec = new File("kernelspec${sep}kernel.json.template").getText('UTF-8')
- File kernelFile = files { shadowJar }.singleFile
- spec = substitute(spec, "KERNEL_JAR_PATH", "$installPath${sep}${kernelFile.name}")
-
- String libsCp = files { configurations.deploy }.files.collect {
- "$installPath${sep}${it.name}"
- } .join(File.pathSeparator)
- spec = substitute(spec, "RUNTIME_CLASSPATH", libsCp)
- spec = substitute(spec, "DEBUGGER_CONFIG", debug ? "\"$debuggerConfig\"," : "")
- spec = substitute(spec, "KERNEL_HOME", "$installPath")
- File installDir = new File("$installPath")
- if (!installDir.exists()) {
- installDir.mkdirs();
+static void makeDirs(java.nio.file.Path path) {
+ File dir = path.toFile()
+ if (!dir.exists()) {
+ dir.mkdirs()
+ }
+}
+
+static java.nio.file.Path getSubDir(java.nio.file.Path dir, String... subDir) {
+ def newDir = dir
+ for (s in subDir) {
+ newDir = newDir.resolve(s)
+ }
+ return newDir
+}
+
+static void writeJson(Map json, java.nio.file.Path path) {
+ def jsonString = new JsonObject(json).toJsonString(true, false)
+ path.toFile().write(jsonString, 'UTF-8')
+}
+
+void createCleanTasks() {
+ [true, false].forEach { local ->
+ def dir = local ? installPathLocal : distribBuildPath
+ task(makeTaskName(cleanInstallDirTaskPrefix, local)) {
+ group(local ? localGroup : distribGroup)
+ doLast {
+ dir.deleteDir()
}
- new File("$installPath${sep}kernel.json").write(spec, 'UTF-8')
- Files.walk(Paths.get(projectDir.toPath().toString(), "kernelspec", "logos"))
- .filter { Files.isRegularFile(it) }
- .forEach {
- Files.copy(it,
- Paths.get(installPath, it.fileName.toString()),
- StandardCopyOption.REPLACE_EXISTING)
- }
}
}
}
+createCleanTasks()
+
+@SuppressWarnings("unused")
+void createInstallTasks(Boolean local, java.nio.file.Path specPath, java.nio.file.Path mainInstallPath) {
+ def groupName = local ? localGroup : distribGroup
+ def cleanDirTask = getTasks().getByName(makeTaskName(cleanInstallDirTaskPrefix, local))
+ def args = [type: Copy, dependsOn: cleanDirTask, group: groupName]
+
+ task (args, makeTaskName(copyLibrariesTaskPrefix, local)) {
+ from librariesPath
+ into mainInstallPath.resolve(librariesPath)
+ }
+
+ task (args, makeTaskName(installLibsTaskPrefix, local)) {
+ from configurations.deploy
+ into mainInstallPath.resolve(jarsPath)
+ }
+
+ task ([type: Copy, group: groupName, dependsOn: [cleanDirTask, shadowJar]], makeTaskName(installKernelTaskPrefix, local)) {
+ from shadowJar.outputs
+ into mainInstallPath.resolve(jarsPath)
+ }
+
+ [true, false].forEach { debug ->
+ def specTaskName = createTaskForSpecs(debug, local, groupName, cleanDirTask, specPath, mainInstallPath)
+ createMainInstallTask(debug, local, groupName, specTaskName)
+ }
+}
+
+String createTaskForSpecs(Boolean debug, Boolean local, String group, Task cleanDir, java.nio.file.Path specPath, java.nio.file.Path mainInstallPath) {
+ String taskName = makeTaskName(debug ? "createDebugSpecs" : "createSpecs", local)
+ task([group: group], taskName) {
+ dependsOn cleanDir, shadowJar
+ doLast {
+ File kernelFile = files { shadowJar }.singleFile
+
+ List libsCp = files { configurations.deploy }.files.collect {
+ it.name
+ }.asList()
-static String substitute(String spec, String template, String val) {
- return spec.replace("\${$template}", val.replace("\\", "\\\\"))
+ makeDirs(mainInstallPath.resolve(jarsPath))
+ makeDirs(mainInstallPath.resolve(configDir))
+ makeDirs(specPath)
+
+ makeJarArgs(mainInstallPath, kernelFile.name, libsCp, debug ? debuggerConfig : "")
+ makeKernelSpec(specPath, local)
+ }
+ }
+ return taskName
}
-task copyLibraries(type: Copy, dependsOn: cleanInstallDir) {
- from "libraries"
- into Paths.get(installPath, "libraries").toString()
+void createMainInstallTask(Boolean debug, Boolean local, String group, String specsTaskName) {
+ def taskNamePrefix = local ? "install" : "prepare"
+ def taskNameMiddle = debug ? "Debug": ""
+ def taskNameSuffix = local ? "" : "Package"
+ def taskName = "$taskNamePrefix$taskNameMiddle$taskNameSuffix"
+
+ def dependencies = [
+ local ? copyRunKernelPy : prepareDistributionDir,
+ makeTaskName(installKernelTaskPrefix, local),
+ makeTaskName(installLibsTaskPrefix, local),
+ specsTaskName,
+ makeTaskName(copyLibrariesTaskPrefix, local)
+ ]
+
+ task([group: group], taskName) {
+ dependsOn(dependencies)
+ }
}
-createTaskForSpecs(true)
-createTaskForSpecs(false)
+void makeKernelSpec(java.nio.file.Path installPath, Boolean localInstall) {
+ def argv = localInstall ?
+ Arrays.asList("python",
+ installPath.resolve(runKernelPy).toString(),
+ "{connection_file}",
+ installPath.resolve(jarArgsFile).toString(),
+ installPath.toString()) :
+ Arrays.asList("python", "-m", "run_kotlin_kernel", "{connection_file}")
+
+ writeJson([
+ "display_name": "Kotlin",
+ "language": "kotlin",
+ "argv": argv,
+ ], installPath.resolve(kernelFile))
-task installLibs(type: Copy, dependsOn: cleanInstallDir) {
- into "$installPath"
- from configurations.deploy
+ project.copy {
+ from logosPath
+ into installPath
+ }
}
-task install(dependsOn: [installKernel, installLibs, createSpecs, copyLibraries]) {
+void makeJarArgs(java.nio.file.Path installPath, String kernelJarPath, List classPath, String debuggerConfig = "") {
+ writeJson([
+ "mainJar": kernelJarPath,
+ "classPath": classPath,
+ "debuggerConfig": debuggerConfig,
+ ], installPath.resolve(project.jarArgsFile))
}
-task installDebug(dependsOn: [installKernel, installLibs, createDebugSpecs, copyLibraries]) {
+/****** Local install ******/
+
+task copyRunKernelPy(type: Copy, dependsOn: cleanInstallDirLocal, group: localGroup) {
+ from distributionPath.resolve(runKernelDir).resolve(runKernelPy)
+ into installPathLocal
}
+
+createInstallTasks(true, installPathLocal, installPathLocal)
+
+apply from: 'distrib.gradle'
diff --git a/distrib.gradle b/distrib.gradle
new file mode 100644
index 000000000..ee88e80e0
--- /dev/null
+++ b/distrib.gradle
@@ -0,0 +1,178 @@
+import java.util.function.Consumer
+
+/****** Prepare distribution ******/
+
+task copyDistribFiles(type: Copy, dependsOn: cleanInstallDirDistrib, group: distribGroup) {
+ from distributionPath
+ into distribBuildPath
+ exclude '.idea/**'
+}
+
+task prepareDistributionDir(dependsOn: [cleanInstallDirDistrib, copyDistribFiles], group: distribGroup) {
+ doLast {
+ def versionFilePath = distribBuildPath.resolve(versionFileName)
+ versionFilePath.toFile().write(version as String)
+ project.copy {
+ from versionFilePath
+ into artifactsDir
+ }
+ }
+}
+
+createInstallTasks(false, distribBuildPath.resolve(distribKernelDir), distribBuildPath.resolve(runKernelDir))
+
+/****** Conda upload ******/
+
+task condaPackage(type: Exec, dependsOn: [cleanInstallDirDistrib, preparePackage], group: condaGroup) {
+ commandLine 'conda-build', 'conda', '--output-folder', condaPackageDir
+ workingDir distribBuildPath
+ doLast {
+ copy {
+ from distribBuildPath.resolve(condaPackageDir).resolve("noarch").resolve(condaPackageFileName)
+ into artifactsDir
+ }
+ }
+}
+
+class TaskSpec {
+ String taskName
+}
+
+class UploadTaskSpecs {
+ T stable
+ T dev
+
+ Project project
+ String repoName
+ String taskGroup
+
+ UploadTaskSpecs(Project project, String repoName, String taskGroup, T stable, T dev) {
+ this.project = project
+ this.repoName = repoName
+ this.taskGroup = taskGroup
+ this.stable = stable
+ this.dev = dev
+
+ this.stable.taskName = taskName("Stable")
+ this.dev.taskName = taskName("Dev")
+ }
+
+ String taskName(String type) {
+ return repoName + "Upload" + type
+ }
+
+ void createTasks(Consumer taskCreationAction) {
+ if (project.isProtectedBranch) {
+ taskCreationAction.accept(stable)
+ }
+ taskCreationAction.accept(dev)
+
+ project.task([dependsOn: project.cleanInstallDirDistrib, group: taskGroup], taskName("Protected")) {
+ if (project.isProtectedBranch) {
+ dependsOn(dev.taskName)
+ }
+ }
+ }
+}
+
+class CondaCredentials {
+ String username
+ String password
+}
+
+class CondaTaskSpec extends TaskSpec {
+ String username
+ CondaCredentials credentials
+}
+
+ext.condaCredentials = new CondaCredentials(
+ username: condaUserStable,
+ password: condaPasswordStable
+)
+
+ext.condaTaskSpecs = new UploadTaskSpecs(
+ project, "conda", condaGroup,
+ new CondaTaskSpec(
+ username: condaUserStable,
+ credentials: ext.condaCredentials
+ ),
+ new CondaTaskSpec(
+ username: condaUserDev,
+ credentials: ext.condaCredentials
+ )
+)
+
+condaTaskSpecs.createTasks { TaskSpec taskSpec ->
+ task(taskSpec.taskName, group: condaGroup) {
+ def artifactPath = artifactsDir.resolve(condaPackageFileName)
+
+ if (!artifactPath.toFile().exists()) {
+ dependsOn([cleanInstallDirDistrib, condaPackage])
+ }
+
+ doLast {
+ exec {
+ commandLine 'anaconda', 'login',
+ '--username', taskSpec.credentials.username,
+ '--password', taskSpec.credentials.password
+ standardInput new ByteArrayInputStream("yes".bytes)
+ }
+
+ exec {
+ commandLine('anaconda', 'upload', '-u', taskSpec.username, artifactPath.toString())
+ }
+ }
+ }
+}
+
+/****** PyPi upload ******/
+
+task pyPiPackage(type: Exec, dependsOn: preparePackage, group: pyPiGroup) {
+ commandLine 'python', 'setup.py', 'bdist_wheel',
+ '--dist-dir', pyPiPackageDir
+ workingDir distribBuildPath
+
+ doLast {
+ copy {
+ from distribBuildPath.resolve(pyPiPackageDir).resolve(pyPiPackageFileName)
+ into artifactsDir
+ }
+ }
+}
+
+class PyPiTaskSpec extends TaskSpec {
+ String repoURL
+ String username
+ String password
+}
+
+def pyPiTaskSpecs = new UploadTaskSpecs(
+ project, "pyPi", pyPiGroup,
+ new PyPiTaskSpec(
+ repoURL: "https://upload.pypi.org/legacy/",
+ username: stablePyPiUser,
+ password: stablePyPiPassword
+ ),
+ new PyPiTaskSpec(
+ repoURL: "https://test.pypi.org/legacy/",
+ username: devPyPiUser,
+ password: devPyPiPassword
+ )
+)
+
+pyPiTaskSpecs.createTasks { taskSpec ->
+ task([type: Exec, group: pyPiGroup], taskSpec.taskName) {
+ workingDir(artifactsDir)
+ def artifactPath = artifactsDir.resolve(pyPiPackageFileName)
+
+ if (!artifactPath.toFile().exists()) {
+ dependsOn([pyPiPackage])
+ }
+
+ commandLine "twine", "upload",
+ "-u", taskSpec.username,
+ "-p", taskSpec.password,
+ "--repository-url", taskSpec.repoURL,
+ pyPiPackageFileName
+ }
+}
diff --git a/distrib/conda/meta.yaml b/distrib/conda/meta.yaml
new file mode 100644
index 000000000..bf484d7ad
--- /dev/null
+++ b/distrib/conda/meta.yaml
@@ -0,0 +1,31 @@
+{% set data = load_setup_py_data() %}
+
+package:
+ name: kotlin-jupyter-kernel
+ version: "{{ data.version }}"
+
+source:
+ - path: ..
+
+build:
+ number: 0
+ noarch: python
+ script: "{{ PYTHON }} -m pip install --no-deps --force-reinstall -vv ."
+
+requirements:
+ build:
+ - python
+ - pip
+
+ run:
+ - python >=3
+
+test:
+ imports:
+ - run_kotlin_kernel
+
+about:
+ home: "{{ data.url }}"
+ license: "{{ data.license }}"
+ license-family: "{{ data.license }}"
+ summary: "{{ data.description }}"
diff --git a/distrib/run_kotlin_kernel/__init__.py b/distrib/run_kotlin_kernel/__init__.py
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/distrib/run_kotlin_kernel/__init__.py
@@ -0,0 +1 @@
+
diff --git a/distrib/run_kotlin_kernel/__main__.py b/distrib/run_kotlin_kernel/__main__.py
new file mode 100644
index 000000000..e739f9806
--- /dev/null
+++ b/distrib/run_kotlin_kernel/__main__.py
@@ -0,0 +1,5 @@
+from sys import argv
+from run_kotlin_kernel.run_kernel import run_kernel
+
+if __name__ == "__main__":
+ run_kernel(*(argv[1:]))
diff --git a/distrib/run_kotlin_kernel/run_kernel.py b/distrib/run_kotlin_kernel/run_kernel.py
new file mode 100644
index 000000000..bc12bb219
--- /dev/null
+++ b/distrib/run_kotlin_kernel/run_kernel.py
@@ -0,0 +1,50 @@
+import json
+import os
+import subprocess
+import sys
+from typing import List
+
+
+def run_kernel(*args) -> None:
+ try:
+ run_kernel_impl(*args)
+ except KeyboardInterrupt:
+ print("Kernel interrupted")
+ try:
+ sys.exit(130)
+ except SystemExit:
+ # noinspection PyProtectedMember
+ os._exit(130)
+
+
+def run_kernel_impl(connection_file: str, jar_args_file: str = None, executables_dir: str = None) -> None:
+ abspath = os.path.abspath(__file__)
+ current_dir = os.path.dirname(abspath)
+
+ if jar_args_file is None:
+ jar_args_file = os.path.join(current_dir, "config", "jar_args.json")
+ if executables_dir is None:
+ executables_dir = current_dir
+
+ jars_dir = os.path.join(executables_dir, "jars")
+
+ with open(jar_args_file, "r") as fd:
+ jar_args_json = json.load(fd)
+
+ debug: str = jar_args_json["debuggerConfig"]
+ cp: List[str] = jar_args_json["classPath"]
+ main_jar: str = jar_args_json["mainJar"]
+
+ debug_list = [] if debug is None or debug == "" else [debug]
+ class_path_arg = os.pathsep.join([os.path.join(jars_dir, jar_name) for jar_name in cp])
+ main_jar_path = os.path.join(jars_dir, main_jar)
+
+ subprocess.call(["java", "-jar"] + debug_list +
+ [main_jar_path,
+ "-classpath=" + class_path_arg,
+ connection_file,
+ "-home=" + executables_dir])
+
+
+if __name__ == "__main__":
+ run_kernel(*(sys.argv[1:]))
diff --git a/distrib/setup.py b/distrib/setup.py
new file mode 100644
index 000000000..1203cd171
--- /dev/null
+++ b/distrib/setup.py
@@ -0,0 +1,31 @@
+import glob
+from os import path
+from setuptools import setup, find_packages
+
+abspath = path.abspath(__file__)
+current_dir = path.dirname(abspath)
+version_file = path.join(current_dir, 'VERSION')
+
+with open(version_file, 'r') as f:
+ version = f.read().strip()
+
+DATA_FILES = [
+ ('share/jupyter/kernels/kotlin', glob.glob('kernel/*.json'))
+]
+
+
+PACKAGE_DATA = {
+ 'run_kotlin_kernel': ['jars/*.jar', 'config/*.json']
+}
+
+if __name__ == "__main__":
+ setup(name="kotlin-jupyter-kernel",
+ author="JetBrains",
+ version=version,
+ url="https://github.com/Kotlin/kotlin-jupyter",
+ license="Apache 2.0",
+ description="Kotlin kernel for Jupyter notebooks",
+ packages=find_packages(),
+ package_data=PACKAGE_DATA,
+ data_files=DATA_FILES
+ )
diff --git a/gradle.properties.template b/gradle.properties.template
index a14541584..e2883d710 100644
--- a/gradle.properties.template
+++ b/gradle.properties.template
@@ -1 +1,16 @@
installPath=/kernels/kotlin
+
+build.branch=dev
+build.number=1.0.0
+build.counter=1
+
+condaUserStable=jetbrains
+condaPasswordStable=
+condaUserDev=jetbrains-dev
+
+stablePyPiUser=jetbrains
+stablePyPiPassword=
+devPyPiUser=jetbrains
+devPyPiPassword=
+
+org.gradle.jvmargs=-Xmx2048m
diff --git a/kernelspec/kernel.json.template b/kernelspec/kernel.json.template
deleted file mode 100644
index fdf4a8922..000000000
--- a/kernelspec/kernel.json.template
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "argv": [ "java", "-jar", ${DEBUGGER_CONFIG} "${KERNEL_JAR_PATH}", "{connection_file}", "-cp=${RUNTIME_CLASSPATH}", "-home=${KERNEL_HOME}"],
- "display_name": "Kotlin",
- "language": "kotlin"
-}
\ No newline at end of file
diff --git a/kernelspec/logos/logo-16x16.png b/resources/logos/logo-16x16.png
similarity index 100%
rename from kernelspec/logos/logo-16x16.png
rename to resources/logos/logo-16x16.png
diff --git a/kernelspec/logos/logo-64x64.png b/resources/logos/logo-64x64.png
similarity index 100%
rename from kernelspec/logos/logo-64x64.png
rename to resources/logos/logo-64x64.png
diff --git a/src/main/kotlin/org/jetbrains/kotlin/jupyter/util.kt b/src/main/kotlin/org/jetbrains/kotlin/jupyter/util.kt
index c5550e40c..ddefafc01 100644
--- a/src/main/kotlin/org/jetbrains/kotlin/jupyter/util.kt
+++ b/src/main/kotlin/org/jetbrains/kotlin/jupyter/util.kt
@@ -1,16 +1,11 @@
package org.jetbrains.kotlin.jupyter
-import com.beust.klaxon.JsonObject
-import com.beust.klaxon.Parser
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
-import org.json.JSONObject
import org.slf4j.Logger
import java.io.File
-import java.io.StringReader
-import javax.xml.bind.JAXBElement
fun catchAll(body: () -> T): T? = try {
body()
@@ -46,8 +41,3 @@ fun File.tryReadIniConfig() =
existsOrNull()?.let {
catchAll { it.readText().parseIniConfig() }
}
-
-fun readJson(path: String) =
- Parser.default().parse(path) as JsonObject
-
-fun JSONObject.toJsonObject() = Parser.default().parse(StringReader(toString())) as JsonObject
\ No newline at end of file
diff --git a/src/test/kotlin/org/jetbrains/kotlin/jupyter/test/replTests.kt b/src/test/kotlin/org/jetbrains/kotlin/jupyter/test/replTests.kt
index e08145d33..3c4cd8795 100644
--- a/src/test/kotlin/org/jetbrains/kotlin/jupyter/test/replTests.kt
+++ b/src/test/kotlin/org/jetbrains/kotlin/jupyter/test/replTests.kt
@@ -8,6 +8,7 @@ import kotlinx.coroutines.async
import org.jetbrains.kotlin.jupyter.*
import org.jetbrains.kotlin.jupyter.repl.completion.CompletionResultSuccess
import org.junit.Assert
+import org.junit.Ignore
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
@@ -161,6 +162,7 @@ class ReplTest {
assertEquals(1, res.displayValues.count())
}
+ @Ignore
@Test
//TODO: https://github.com/Kotlin/kotlin-jupyter/issues/25
fun TestKranglImportInfixFun() {