Skip to content

Commit 3e6aa2e

Browse files
committed
Refactor magics arguments handling, make it more uniform
1 parent 58fa508 commit 3e6aa2e

File tree

10 files changed

+85
-50
lines changed

10 files changed

+85
-50
lines changed

build-plugin/common-dependencies/src/org/jetbrains/kotlinx/jupyter/common/ReplLineMagic.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package org.jetbrains.kotlinx.jupyter.common
22

33
enum class ReplLineMagic(val desc: String, val argumentsUsage: String? = null, val visibleInHelp: Boolean = true) {
44
USE("injects code for supported libraries: artifact resolution, default imports, initialization code, type renderers", "klaxon(5.5), lets-plot"),
5-
TRACK_CLASSPATH("logs any changes of current classpath. Useful for debugging artifact resolution failures"),
6-
TRACK_EXECUTION("logs pieces of code that are going to be executed. Useful for debugging of libraries support"),
7-
DUMP_CLASSES_FOR_SPARK("stores compiled repl classes in special folder for Spark integration", visibleInHelp = false),
8-
USE_LATEST_DESCRIPTORS("use latest versions of library descriptors available. By default, bundled descriptors are used", "-[on|off]"),
5+
TRACK_CLASSPATH("logs any changes of current classpath. Useful for debugging artifact resolution failures", "[on|off]"),
6+
TRACK_EXECUTION("logs pieces of code that are going to be executed. Useful for debugging of libraries support", "[all|generated|off]"),
7+
DUMP_CLASSES_FOR_SPARK("stores compiled repl classes in special folder for Spark integration", "[on|off]", visibleInHelp = false),
8+
USE_LATEST_DESCRIPTORS("use latest versions of library descriptors available. By default, bundled descriptors are used", "[on|off]"),
99
OUTPUT("output capturing settings", "--max-cell-size=1000 --no-stdout --max-time=100 --max-buffer=400"),
1010
LOG_LEVEL("set logging level", "[off|error|warn|info|debug]"),
1111
LOG_HANDLER("manage logging handlers", "[list | remove <name> | add <name> --<type> [... typeArgs]]", visibleInHelp = false);

docs/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ The following maven repositories are included by default:
150150

151151
The following line magics are supported:
152152
- `%use` - injects code for supported libraries: artifact resolution, default imports, initialization code, type renderers. Usage example: `%use klaxon(5.5), lets-plot`
153-
- `%trackClasspath` - logs any changes of current classpath. Useful for debugging artifact resolution failures.
154-
- `%trackExecution` - logs pieces of code that are going to be executed. Useful for debugging of libraries support.
155-
- `%useLatestDescriptors` - use latest versions of library descriptors available. By default, bundled descriptors are used. Usage example: `%useLatestDescriptors -[on|off]`
153+
- `%trackClasspath` - logs any changes of current classpath. Useful for debugging artifact resolution failures. Usage example: `%trackClasspath [on|off]`
154+
- `%trackExecution` - logs pieces of code that are going to be executed. Useful for debugging of libraries support. Usage example: `%trackExecution [all|generated|off]`
155+
- `%useLatestDescriptors` - use latest versions of library descriptors available. By default, bundled descriptors are used. Usage example: `%useLatestDescriptors [on|off]`
156156
- `%output` - output capturing settings. Usage example: `%output --max-cell-size=1000 --no-stdout --max-time=100 --max-buffer=400`
157157
- `%logLevel` - set logging level. Usage example: `%logLevel [off|error|warn|info|debug]`
158158

jupyter-lib/shared-compiler/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ dependencies {
3636

3737
// Logging
3838
compileOnly(libs.logging.slf4j.api)
39+
40+
// Clikt library for parsing output magics
41+
implementation(libs.clikt)
3942
}
4043

4144
buildSettings {

jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/AbstractMagicsHandler.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package org.jetbrains.kotlinx.jupyter.magics
22

3+
import com.github.ajalt.clikt.core.CliktCommand
4+
import com.github.ajalt.clikt.parameters.arguments.argument
5+
import com.github.ajalt.clikt.parameters.arguments.optional
6+
import com.github.ajalt.clikt.parameters.types.choice
37
import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryDefinitionProducer
48
import org.jetbrains.kotlinx.jupyter.common.ReplLineMagic
59

@@ -8,6 +12,16 @@ abstract class AbstractMagicsHandler : MagicsHandler {
812
protected var tryIgnoreErrors: Boolean = false
913
protected var parseOnly: Boolean = false
1014

15+
protected fun argumentsList() = arg?.trim()?.takeIf { it.isNotEmpty() }?.split(" ") ?: emptyList()
16+
protected fun handleSingleOptionalFlag(action: (Boolean?) -> Unit) {
17+
object : CliktCommand() {
18+
val arg by nullableFlag()
19+
override fun run() {
20+
action(arg)
21+
}
22+
}.parse(argumentsList())
23+
}
24+
1125
protected val newLibraries: MutableList<LibraryDefinitionProducer> = mutableListOf()
1226

1327
private val callbackMap: Map<ReplLineMagic, () -> Unit> = mapOf(
@@ -45,4 +59,8 @@ abstract class AbstractMagicsHandler : MagicsHandler {
4559
open fun handleOutput() {}
4660
open fun handleLogLevel() {}
4761
open fun handleLogHandler() {}
62+
63+
companion object {
64+
fun CliktCommand.nullableFlag() = argument().choice(mapOf("on" to true, "off" to false)).optional()
65+
}
4866
}

jupyter-lib/shared-compiler/src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/UseMagicsHandler.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@ open class UseMagicsHandler(
2020
}
2121

2222
override fun handleUseLatestDescriptors() {
23-
libraryResolutionInfoSwitcher.switch = when (arg?.trim()) {
24-
"-on" -> DefaultInfoSwitch.GIT_REFERENCE
25-
"-off" -> DefaultInfoSwitch.DIRECTORY
26-
else -> DefaultInfoSwitch.GIT_REFERENCE
23+
handleSingleOptionalFlag {
24+
libraryResolutionInfoSwitcher.switch = if (it == false) DefaultInfoSwitch.DIRECTORY
25+
else DefaultInfoSwitch.GIT_REFERENCE
2726
}
2827
}
2928
}

samples/Titanic.ipynb

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"outputs": [],
1717
"source": [
1818
"// to see autogenerated code, uncomment the line below:\n",
19-
"//%trackExecution -generated"
19+
"//%trackExecution generated"
2020
]
2121
},
2222
{
@@ -1436,17 +1436,8 @@
14361436
"name": "kotlin",
14371437
"pygments_lexer": "kotlin",
14381438
"version": "1.4.0-dev-7568"
1439-
},
1440-
"pycharm": {
1441-
"stem_cell": {
1442-
"cell_type": "raw",
1443-
"metadata": {
1444-
"collapsed": false
1445-
},
1446-
"source": []
1447-
}
14481439
}
14491440
},
14501441
"nbformat": 4,
14511442
"nbformat_minor": 2
1452-
}
1443+
}

src/main/kotlin/org/jetbrains/kotlinx/jupyter/magics/FullMagicsHandler.kt

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import ch.qos.logback.classic.spi.ILoggingEvent
55
import ch.qos.logback.core.Appender
66
import ch.qos.logback.core.FileAppender
77
import com.github.ajalt.clikt.core.CliktCommand
8+
import com.github.ajalt.clikt.parameters.arguments.argument
9+
import com.github.ajalt.clikt.parameters.arguments.optional
810
import com.github.ajalt.clikt.parameters.options.default
911
import com.github.ajalt.clikt.parameters.options.flag
1012
import com.github.ajalt.clikt.parameters.options.option
13+
import com.github.ajalt.clikt.parameters.types.choice
14+
import com.github.ajalt.clikt.parameters.types.enum
1115
import com.github.ajalt.clikt.parameters.types.int
1216
import com.github.ajalt.clikt.parameters.types.long
1317
import org.jetbrains.kotlinx.jupyter.ExecutedCodeLogging
@@ -57,36 +61,46 @@ class FullMagicsHandler(
5761
}
5862

5963
override fun handleTrackExecution() {
60-
repl.executedCodeLogging = when (arg?.trim()) {
61-
"-all" -> ExecutedCodeLogging.All
62-
"-off" -> ExecutedCodeLogging.Off
63-
"-generated" -> ExecutedCodeLogging.Generated
64-
else -> ExecutedCodeLogging.All
65-
}
64+
object : CliktCommand() {
65+
val logLevel by argument().enum<ExecutedCodeLogging>(true) { it.name.lowercase() }.optional()
66+
override fun run() {
67+
repl.executedCodeLogging = logLevel ?: ExecutedCodeLogging.ALL
68+
}
69+
}.parse(argumentsList())
6670
}
6771

6872
override fun handleTrackClasspath() {
69-
repl.trackClasspath = true
73+
handleSingleOptionalFlag {
74+
repl.trackClasspath = it ?: true
75+
}
7076
}
7177

7278
override fun handleDumpClassesForSpark() {
73-
repl.writeCompiledClasses = true
79+
handleSingleOptionalFlag {
80+
repl.writeCompiledClasses = it ?: true
81+
}
7482
}
7583

7684
override fun handleOutput() {
77-
repl.outputConfig = updateOutputConfig(repl.outputConfig, (arg ?: "").split(" "))
85+
repl.outputConfig = updateOutputConfig(repl.outputConfig, argumentsList())
7886
}
7987

8088
override fun handleLogLevel() {
81-
val level = when (val levelStr = arg?.trim()) {
82-
"off" -> Level.OFF
83-
"error" -> Level.ERROR
84-
"warn" -> Level.WARN
85-
"info" -> Level.INFO
86-
"debug" -> Level.DEBUG
87-
else -> throw ReplException("Unknown log level: '$levelStr'")
88-
}
89-
setRootLoggingLevel(level)
89+
object : CliktCommand() {
90+
val level by argument().choice(
91+
mapOf(
92+
"off" to Level.OFF,
93+
"error" to Level.ERROR,
94+
"warn" to Level.WARN,
95+
"info" to Level.INFO,
96+
"debug" to Level.DEBUG,
97+
),
98+
ignoreCase = false
99+
)
100+
override fun run() {
101+
setRootLoggingLevel(level)
102+
}
103+
}.parse(argumentsList())
90104
}
91105

92106
override fun handleLogHandler() {

src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ class EvalRequestData(
9595
class ReplEvalRuntimeException(message: String, cause: Throwable? = null) : ReplException(message, cause)
9696

9797
enum class ExecutedCodeLogging {
98-
Off,
99-
All,
100-
Generated
98+
OFF,
99+
ALL,
100+
GENERATED
101101
}
102102

103103
interface ReplRuntimeProperties {
@@ -212,12 +212,12 @@ class ReplForJupyterImpl(
212212

213213
override var trackClasspath: Boolean = false
214214

215-
private var _executedCodeLogging: ExecutedCodeLogging = ExecutedCodeLogging.Off
215+
private var _executedCodeLogging: ExecutedCodeLogging = ExecutedCodeLogging.OFF
216216
override var executedCodeLogging: ExecutedCodeLogging
217217
get() = _executedCodeLogging
218218
set(value) {
219219
_executedCodeLogging = value
220-
internalEvaluator.logExecution = value != ExecutedCodeLogging.Off
220+
internalEvaluator.logExecution = value != ExecutedCodeLogging.OFF
221221
}
222222

223223
override var writeCompiledClasses: Boolean
@@ -326,7 +326,7 @@ class ReplForJupyterImpl(
326326
jupyterCompiler,
327327
evaluator,
328328
contextUpdater,
329-
executedCodeLogging != ExecutedCodeLogging.Off,
329+
executedCodeLogging != ExecutedCodeLogging.OFF,
330330
internalVariablesMarkersProcessor,
331331
)
332332

src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/parseMagicsTests.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import org.junit.jupiter.api.Assertions.assertEquals
2222
import org.junit.jupiter.api.Assertions.assertNull
2323
import org.junit.jupiter.api.Test
2424
import java.io.File
25+
import kotlin.test.assertFalse
2526
import kotlin.test.assertTrue
2627

2728
private typealias MagicsAndCodeIntervals = Pair<List<CodeInterval>, List<CodeInterval>>
@@ -127,7 +128,7 @@ class ParseMagicsTests {
127128
get() = standardResolverBranch
128129
override val librariesDir = KERNEL_LIBRARIES.localLibrariesDir
129130
override var trackClasspath = false
130-
override var executedCodeLogging = ExecutedCodeLogging.Off
131+
override var executedCodeLogging = ExecutedCodeLogging.OFF
131132
override var writeCompiledClasses = false
132133
override var outputConfig = OutputConfig()
133134
}
@@ -201,6 +202,15 @@ class ParseMagicsTests {
201202
}
202203

203204
assertTrue(options.trackClasspath)
205+
206+
test(
207+
"""
208+
%trackClasspath off
209+
""".trimIndent(),
210+
""
211+
)
212+
213+
assertFalse(options.trackClasspath)
204214
}
205215

206216
@Test
@@ -212,7 +222,7 @@ class ParseMagicsTests {
212222
val x = 9
213223
%wrongMagic
214224
fun f() = 42
215-
%trackExecution -generated
225+
%trackExecution generated
216226
""".trimIndent(),
217227
"""
218228
@@ -226,7 +236,7 @@ class ParseMagicsTests {
226236
assertEquals(1, libs.size)
227237
}
228238

229-
assertEquals(ExecutedCodeLogging.Generated, options.executedCodeLogging)
239+
assertEquals(ExecutedCodeLogging.GENERATED, options.executedCodeLogging)
230240
}
231241

232242
@Test

src/test/kotlin/org/jetbrains/kotlinx/jupyter/test/repl/ReplWithStandardResolverTests.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class ReplWithStandardResolverTests : AbstractSingleReplTest() {
6161
eval("%useLatestDescriptors")
6262
Assertions.assertTrue(infoProvider.fallback is AbstractLibraryResolutionInfo.ByGitRef)
6363

64-
eval("%useLatestDescriptors -off")
64+
eval("%useLatestDescriptors off")
6565
Assertions.assertTrue(infoProvider.fallback === initialDefaultResolutionInfo)
6666
}
6767

0 commit comments

Comments
 (0)