mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
Merge branch 'master' into fix/tutorialNote
This commit is contained in:
commit
eca8026471
39 changed files with 447 additions and 301 deletions
8
STYLE.md
8
STYLE.md
|
|
@ -25,11 +25,11 @@ bower.json
|
|||
In the override section at the bottom, include the Highlightjs stylesheet (eg. styles/github.css)
|
||||
For the selected Ace Editor theme script, include it in the override section. (eg. src-noconflict/theme-github.js)
|
||||
(bower will automatically add the appropriate .js and .css in app/index.html)
|
||||
```
|
||||
```diff
|
||||
"src-noconflict/mode-sql.js",
|
||||
"src-noconflict/mode-markdown.js",
|
||||
"src-noconflict/keybinding-emacs.js",
|
||||
"src-noconflict/ext-language_tools.js",
|
||||
"src-noconflict/ext-language_tools.js",
|
||||
+ "src-noconflict/theme-github.js"],
|
||||
"version": "1.1.8",
|
||||
"name": "ace-builds"
|
||||
|
|
@ -48,13 +48,13 @@ Highlight.js style - depends on the style, a few themes have jpg - if so, one mu
|
|||
### Example - change Ace Editor theme to monokai
|
||||
|
||||
app/scripts/controllers/paragraph.js
|
||||
```
|
||||
```diff
|
||||
- $scope.editor.setTheme('ace/theme/github');
|
||||
+ $scope.editor.setTheme('ace/theme/monokai');
|
||||
```
|
||||
|
||||
bower.json
|
||||
```
|
||||
```diff
|
||||
- "src-noconflict/theme-github.js"],
|
||||
+ "src-noconflict/theme-monokai.js"],
|
||||
```
|
||||
|
|
|
|||
|
|
@ -84,9 +84,4 @@ if not exist %ZEPPELIN_PID_DIR% (
|
|||
mkdir "%ZEPPELIN_PID_DIR%"
|
||||
)
|
||||
|
||||
if not exist %ZEPPELIN_NOTEBOOK_DIR% (
|
||||
echo Notebook dir doesn't exist, create %ZEPPELIN_NOTEBOOK_DIR%
|
||||
mkdir "%ZEPPELIN_NOTEBOOK_DIR%"
|
||||
)
|
||||
|
||||
"%ZEPPELIN_RUNNER%" %JAVA_OPTS% -cp %CLASSPATH% %ZEPPELIN_SERVER% "%*"
|
||||
|
|
|
|||
|
|
@ -83,9 +83,4 @@ if [[ ! -d "${ZEPPELIN_PID_DIR}" ]]; then
|
|||
$(mkdir -p "${ZEPPELIN_PID_DIR}")
|
||||
fi
|
||||
|
||||
if [[ ! -d "${ZEPPELIN_NOTEBOOK_DIR}" ]]; then
|
||||
echo "Pid dir doesn't exist, create ${ZEPPELIN_NOTEBOOK_DIR}"
|
||||
$(mkdir -p "${ZEPPELIN_NOTEBOOK_DIR}")
|
||||
fi
|
||||
|
||||
exec $ZEPPELIN_RUNNER $JAVA_OPTS -cp $ZEPPELIN_CLASSPATH_OVERRIDES:$CLASSPATH $ZEPPELIN_SERVER "$@"
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
<!--<li><a href="{{BASE_PATH}}/manual/dynamicinterpreterload.html">Dynamic Interpreter Loading</a></li>-->
|
||||
<li><a href="{{BASE_PATH}}/manual/dependencymanagement.html">Interpreter Dependency Management</a></li>
|
||||
<li><a href="{{BASE_PATH}}/manual/userimpersonation.html">Interpreter User Impersonation</a></li>
|
||||
<li><a href="{{BASE_PATH}}/manual/interpreterexechooks.html">Interpreter Execution Hooks (Experimental)</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li class="title"><span><b>Available Interpreters</b><span></li>
|
||||
<li><a href="{{BASE_PATH}}/interpreter/alluxio.html">Alluxio</a></li>
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ Join to our [Mailing list](https://zeppelin.apache.org/community.html) and repor
|
|||
* [Interpreter Installation](./manual/interpreterinstallation.html): Install not only community managed interpreters but also 3rd party interpreters
|
||||
* [Interpreter Dependency Management](./manual/dependencymanagement.html) when you include external libraries to interpreter
|
||||
* [Interpreter User Impersonation](./manual/userimpersonation.html) when you want to run interpreter as end user
|
||||
* [Interpreter Execution Hooks](./manual/interpreterexechooks.html) to specify additional code to be executed by an interpreter at pre and post-paragraph code execution
|
||||
* Available Interpreters: currently, about 20 interpreters are available in Apache Zeppelin.
|
||||
|
||||
####Display System
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ wget http://www.gutenberg.org/ebooks/10.txt.utf-8
|
|||
{% highlight scala %}
|
||||
%flink
|
||||
case class WordCount(word: String, frequency: Int)
|
||||
val bible:DataSet[String] = env.readTextFile("10.txt.utf-8")
|
||||
val bible:DataSet[String] = benv.readTextFile("10.txt.utf-8")
|
||||
val partialCounts: DataSet[WordCount] = bible.flatMap{
|
||||
line =>
|
||||
"""\b\w+\b""".r.findAllIn(line).map(word => WordCount(word, 1))
|
||||
|
|
|
|||
81
docs/manual/interpreterexechooks.md
Normal file
81
docs/manual/interpreterexechooks.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
layout: page
|
||||
title: "Interpreter Execution Hooks (Experimental)"
|
||||
description: "Apache Zeppelin allows for users to specify additional code to be executed by an interpreter at pre and post-paragraph code execution."
|
||||
group: manual
|
||||
---
|
||||
<!--
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
{% include JB/setup %}
|
||||
|
||||
# Interpreter Execution Hooks (Experimental)
|
||||
|
||||
<div id="toc"></div>
|
||||
|
||||
## Overview
|
||||
|
||||
Apache Zeppelin allows for users to specify additional code to be executed by an interpreter at pre and post-paragraph code execution.
|
||||
This is primarily useful if you need to run the same set of code for all of the paragraphs within your notebook at specific times.
|
||||
Currently, this feature is only available for the spark and pyspark interpreters.
|
||||
To specify your hook code, you may use `z.registerHook()`.
|
||||
For example, enter the following into one paragraph:
|
||||
|
||||
```python
|
||||
%pyspark
|
||||
z.registerHook("post_exec", "print 'This code should be executed before the parapgraph code!'")
|
||||
z.registerHook("pre_exec", "print 'This code should be executed after the paragraph code!'")
|
||||
```
|
||||
|
||||
These calls will not take into effect until the next time you run a paragraph.
|
||||
|
||||
|
||||
In another paragraph, enter
|
||||
|
||||
```python
|
||||
%pyspark
|
||||
print "This code should be entered into the paragraph by the user!"
|
||||
```
|
||||
|
||||
The output should be:
|
||||
|
||||
```
|
||||
This code should be executed before the paragraph code!
|
||||
This code should be entered into the paragraph by the user!
|
||||
This code should be executed after the paragraph code!
|
||||
```
|
||||
|
||||
If you ever need to know the hook code, use `z.getHook()`:
|
||||
|
||||
```python
|
||||
%pyspark
|
||||
print z.getHook("post_exec")
|
||||
|
||||
print 'This code should be executed after the paragraph code!'
|
||||
```
|
||||
Any call to `z.registerHook()` will automatically overwrite what was previously registered.
|
||||
To completely unregister a hook event, use `z.unregisterHook(eventCode)`.
|
||||
Currently only `"post_exec"` and `"pre_exec"` are valid event codes for the Zeppelin Hook Registry system.
|
||||
|
||||
Finally, the hook registry is internally shared by other interpreters in the same group.
|
||||
This would allow for hook code for one interpreter REPL to be set by another as follows:
|
||||
|
||||
```scala
|
||||
%spark
|
||||
z.unregisterHook("post_exec", "pyspark")
|
||||
```
|
||||
|
||||
The API is identical for both the spark (scala) and pyspark (python) implementations.
|
||||
|
||||
### Caveats
|
||||
Calls to `z.registerHook("pre_exec", ...)` should be made with care. If there are errors in your specified hook code, this will cause the interpreter REPL to become unable to execute any code pass the pre-execute stage making it impossible for direct calls to `z.unregisterHook()` to take into effect. Current workarounds include calling `z.unregisterHook()` from a different interpreter REPL in the same interpreter group (see above) or manually restarting the interpreter group in the UI.
|
||||
|
|
@ -82,49 +82,3 @@ interpreter.start()
|
|||
The above code will start interpreter thread inside your process. Once the interpreter is started you can configure zeppelin to connect to RemoteInterpreter by checking **Connect to existing process** checkbox and then provide **Host** and **Port** on which interpreter process is listening as shown in the image below:
|
||||
|
||||
<img src="../assets/themes/zeppelin/img/screenshots/existing_interpreter.png" width="450px">
|
||||
|
||||
|
||||
## (Experimental) Interpreter Execution Hooks
|
||||
|
||||
Zeppelin allows for users to specify additional code to be executed by an interpreter at pre and post-paragraph code execution. This is primarily useful if you need to run the same set of code for all of the paragraphs within your notebook at specific times. Currently, this feature is only available for the spark and pyspark interpreters. To specify your hook code, you may use '`z.registerHook()`. For example, enter the following into one paragraph:
|
||||
|
||||
```python
|
||||
%pyspark
|
||||
z.registerHook("post_exec", "print 'This code should be executed before the parapgraph code!'")
|
||||
z.registerHook("pre_exec", "print 'This code should be executed after the paragraph code!'")
|
||||
```
|
||||
|
||||
These calls will not take into effect until the next time you run a paragraph. In another paragraph, enter
|
||||
```python
|
||||
%pyspark
|
||||
print "This code should be entered into the paragraph by the user!"
|
||||
```
|
||||
|
||||
The output should be:
|
||||
```
|
||||
This code should be executed before the paragraph code!
|
||||
This code should be entered into the paragraph by the user!
|
||||
This code should be executed after the paragraph code!
|
||||
```
|
||||
|
||||
If you ever need to know the hook code, use `z.getHook()`:
|
||||
```python
|
||||
%pyspark
|
||||
print z.getHook("post_exec")
|
||||
```
|
||||
```
|
||||
print 'This code should be executed after the paragraph code!'
|
||||
```
|
||||
Any call to `z.registerHook()` will automatically overwrite what was previously registered. To completely unregister a hook event, use `z.unregisterHook(eventCode)`. Currently only `"post_exec"` and `"pre_exec"` are valid event codes for the Zeppelin Hook Registry system.
|
||||
|
||||
Finally, the hook registry is internally shared by other interpreters in the same group. This would allow for hook code for one interpreter REPL to be set by another as follows:
|
||||
|
||||
```scala
|
||||
%spark
|
||||
z.unregisterHook("post_exec", "pyspark")
|
||||
```
|
||||
The API is identical for both the spark (scala) and pyspark (python) implementations.
|
||||
|
||||
### Caveats
|
||||
Calls to `z.registerHook("pre_exec", ...)` should be made with care. If there are errors in your specified hook code, this will cause the interpreter REPL to become unable to execute any code pass the pre-execute stage making it impossible for direct calls to `z.unregisterHook()` to take into effect. Current workarounds include calling `z.unregisterHook()` from a different interpreter REPL in the same interpreter group (see above) or manually restarting the interpreter group in the UI.
|
||||
|
||||
|
|
|
|||
|
|
@ -118,14 +118,16 @@ cd zeppelin
|
|||
Package Zeppelin.
|
||||
|
||||
```
|
||||
mvn clean package -DskipTests -Pspark-1.6 -Dflink.version=1.1.2
|
||||
mvn clean package -DskipTests -Pspark-1.6 -Dflink.version=1.1.3 -Pscala-2.10
|
||||
```
|
||||
|
||||
`-DskipTests` skips build tests- you're not developing (yet), so you don't need to do tests, the clone version *should* build.
|
||||
|
||||
`-Pspark-1.6` tells maven to build a Zeppelin with Spark 1.6. This is important because Zeppelin has its own Spark interpreter and the versions must be the same.
|
||||
|
||||
`-Dflink.version=1.1.2` tells maven specifically to build Zeppelin with Flink version 1.1.2.
|
||||
`-Dflink.version=1.1.3` tells maven specifically to build Zeppelin with Flink version 1.1.3.
|
||||
|
||||
-`-Pscala-2.10` tells maven to build with Scala v2.10.
|
||||
|
||||
|
||||
**Note:** You may wish to include additional build flags such as `-Ppyspark` or `-Psparkr`. See [the build section of github for more details](https://github.com/apache/zeppelin#build).
|
||||
|
|
@ -162,7 +164,7 @@ Create a new notebook named "Flink Test" and copy and paste the following code.
|
|||
|
||||
%flink // let Zeppelin know what interpreter to use.
|
||||
|
||||
val text = env.fromElements("In the time of chimpanzees, I was a monkey", // some lines of text to analyze
|
||||
val text = benv.fromElements("In the time of chimpanzees, I was a monkey", // some lines of text to analyze
|
||||
"Butane in my veins and I'm out to cut the junkie",
|
||||
"With the plastic eyeballs, spray paint the vegetables",
|
||||
"Dog food stalls with the beefcake pantyhose",
|
||||
|
|
@ -252,16 +254,16 @@ Building from source is recommended where possible, for simplicity in this tuto
|
|||
To download the Flink Binary use `wget`
|
||||
|
||||
```bash
|
||||
wget "http://mirror.cogentco.com/pub/apache/flink/flink-1.0.3/flink-1.0.3-bin-hadoop24-scala_2.10.tgz"
|
||||
tar -xzvf flink-1.0.3-bin-hadoop24-scala_2.10.tgz
|
||||
wget "http://mirror.cogentco.com/pub/apache/flink/flink-1.1.3/flink-1.1.3-bin-hadoop24-scala_2.10.tgz"
|
||||
tar -xzvf flink-1.1.3-bin-hadoop24-scala_2.10.tgz
|
||||
```
|
||||
|
||||
This will download Flink 1.0.3, compatible with Hadoop 2.4. You do not have to install Hadoop for this binary to work, but if you are using Hadoop, please change `24` to your appropriate version.
|
||||
This will download Flink 1.1.3, compatible with Hadoop 2.4. You do not have to install Hadoop for this binary to work, but if you are using Hadoop, please change `24` to your appropriate version.
|
||||
|
||||
Start the Flink Cluster.
|
||||
|
||||
```bash
|
||||
flink-1.0.3/bin/start-cluster.sh
|
||||
flink-1.1.3/bin/start-cluster.sh
|
||||
```
|
||||
|
||||
###### Building From source
|
||||
|
|
@ -270,13 +272,13 @@ If you wish to build Flink from source, the following will be instructive. Note
|
|||
|
||||
See the [Flink Installation guide](https://github.com/apache/flink/blob/master/README.md) for more detailed instructions.
|
||||
|
||||
Return to the directory where you have been downloading, this tutorial assumes that is `$HOME`. Clone Flink, check out release-1.0, and build.
|
||||
Return to the directory where you have been downloading, this tutorial assumes that is `$HOME`. Clone Flink, check out release-1.1.3-rc2, and build.
|
||||
|
||||
```
|
||||
cd $HOME
|
||||
git clone https://github.com/apache/flink.git
|
||||
cd flink
|
||||
git checkout release-1.0
|
||||
git checkout release-1.1.3-rc2
|
||||
mvn clean install -DskipTests
|
||||
```
|
||||
|
||||
|
|
@ -297,8 +299,8 @@ If no task managers are present, restart the Flink cluster with the following co
|
|||
|
||||
(if binaries)
|
||||
```
|
||||
flink-1.0.3/bin/stop-cluster.sh
|
||||
flink-1.0.3/bin/start-cluster.sh
|
||||
flink-1.1.3/bin/stop-cluster.sh
|
||||
flink-1.1.3/bin/start-cluster.sh
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -320,12 +322,12 @@ Using binaries is also
|
|||
To download the Spark Binary use `wget`
|
||||
|
||||
```bash
|
||||
wget "http://mirrors.koehn.com/apache/spark/spark-1.6.1/spark-1.6.1-bin-hadoop2.4.tgz"
|
||||
tar -xzvf spark-1.6.1-bin-hadoop2.4.tgz
|
||||
mv spark-1.6.1-bin-hadoop4.4 spark
|
||||
wget "http://d3kbcqa49mib13.cloudfront.net/spark-1.6.3-bin-hadoop2.6.tgz"
|
||||
tar -xzvf spark-1.6.3-bin-hadoop2.6.tgz
|
||||
mv spark-1.6.3-bin-hadoop2.6 spark
|
||||
```
|
||||
|
||||
This will download Spark 1.6.1, compatible with Hadoop 2.4. You do not have to install Hadoop for this binary to work, but if you are using Hadoop, please change `2.4` to your appropriate version.
|
||||
This will download Spark 1.6.3, compatible with Hadoop 2.6. You do not have to install Hadoop for this binary to work, but if you are using Hadoop, please change `2.6` to your appropriate version.
|
||||
|
||||
###### Building From source
|
||||
|
||||
|
|
@ -335,7 +337,7 @@ See the [Spark Installation](https://github.com/apache/spark/blob/master/README.
|
|||
|
||||
Return to the directory where you have been downloading, this tutorial assumes that is $HOME. Clone Spark, check out branch-1.6, and build.
|
||||
**Note:** Recall, we're only checking out 1.6 because it is the most recent Spark for which a Zeppelin profile exists at
|
||||
the time of writing. You are free to check out other version, just make sure you build Zeppelin against the correct version of Spark.
|
||||
the time of writing. You are free to check out other version, just make sure you build Zeppelin against the correct version of Spark. However if you use Spark 2.0, the word count example will need to be changed as Spark 2.0 is not compatible with the following examples.
|
||||
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
<name>Zeppelin: Elasticsearch interpreter</name>
|
||||
|
||||
<properties>
|
||||
<elasticsearch.version>2.3.3</elasticsearch.version>
|
||||
<elasticsearch.version>2.4.3</elasticsearch.version>
|
||||
<guava.version>18.0</guava.version>
|
||||
<json-flattener.version>0.1.6</json-flattener.version>
|
||||
</properties>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ private[scio] object DisplayHelpers {
|
|||
private[scio] val tab = "\t"
|
||||
private[scio] val newline = "\n"
|
||||
private[scio] val table = "%table"
|
||||
private[scio] val endTable = "%text"
|
||||
private[scio] val rowLimitReachedMsg =
|
||||
s"$newline<font color=red>Results are limited to " + maxResults + s" rows.</font>$newline"
|
||||
private[scio] val bQSchemaIncomplete =
|
||||
|
|
@ -52,6 +53,7 @@ private[scio] object DisplayHelpers {
|
|||
println(sCollectionEmptyMsg)
|
||||
} else {
|
||||
println(s"$table value$newline${it.take(maxResults).map(printer).mkString(newline)}")
|
||||
println(endTable)
|
||||
notifyIfTruncated(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +66,7 @@ private[scio] object DisplayHelpers {
|
|||
println(sCollectionEmptyMsg)
|
||||
} else {
|
||||
println(s"$table value$newline${it.take(maxResults).map(printer).mkString(newline)}")
|
||||
println(endTable)
|
||||
notifyIfTruncated(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -77,6 +80,7 @@ private[scio] object DisplayHelpers {
|
|||
} else {
|
||||
val content = it.take(maxResults).map{ case (k, v) => s"$k$tab$v" }.mkString(newline)
|
||||
println(s"$table key${tab}value$newline$content")
|
||||
println(endTable)
|
||||
notifyIfTruncated(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -97,6 +101,7 @@ private[scio] object DisplayHelpers {
|
|||
val firstStr = first.productIterator.mkString(tab)
|
||||
val content = it.take(maxResults - 1).map(_.productIterator.mkString(tab)).mkString(newline)
|
||||
println(s"$table $header$newline$firstStr$newline$content")
|
||||
println(endTable)
|
||||
notifyIfTruncated(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -125,6 +130,7 @@ private[scio] object DisplayHelpers {
|
|||
.map(r => fieldNames.map(r.get).mkString(tab))
|
||||
.mkString(newline)
|
||||
println(s"$table $header$newline$firstStr$newline$content")
|
||||
println(endTable)
|
||||
notifyIfTruncated(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -151,6 +157,7 @@ private[scio] object DisplayHelpers {
|
|||
.mkString(newline)
|
||||
|
||||
println(s"$table $header$newline$content")
|
||||
println(endTable)
|
||||
notifyIfTruncated(it)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
private val anyValHeader = s"$table value"
|
||||
private val endTable = DisplayHelpers.endTable
|
||||
|
||||
"DisplayHelpers" should "support Integer SCollection via AnyVal" in {
|
||||
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
|
||||
|
|
@ -59,8 +60,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(anyValHeader,
|
||||
"1",
|
||||
"2",
|
||||
"3")
|
||||
"3",
|
||||
endTable)
|
||||
o.head should be(anyValHeader)
|
||||
o.last should be(endTable)
|
||||
}
|
||||
|
||||
it should "support Long SCollection via AnyVal" in {
|
||||
|
|
@ -73,8 +76,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(anyValHeader,
|
||||
"1",
|
||||
"2",
|
||||
"3")
|
||||
"3",
|
||||
endTable)
|
||||
o.head should be(anyValHeader)
|
||||
o.last should be(endTable)
|
||||
}
|
||||
|
||||
it should "support Double SCollection via AnyVal" in {
|
||||
|
|
@ -87,8 +92,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(anyValHeader,
|
||||
"1.0",
|
||||
"2.0",
|
||||
"3.0")
|
||||
"3.0",
|
||||
endTable)
|
||||
o.head should be(anyValHeader)
|
||||
o.last should be(endTable)
|
||||
}
|
||||
|
||||
it should "support Float SCollection via AnyVal" in {
|
||||
|
|
@ -101,8 +108,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(anyValHeader,
|
||||
"1.0",
|
||||
"2.0",
|
||||
"3.0")
|
||||
"3.0",
|
||||
endTable)
|
||||
o.head should be(anyValHeader)
|
||||
o.last should be(endTable)
|
||||
}
|
||||
|
||||
it should "support Short SCollection via AnyVal" in {
|
||||
|
|
@ -115,8 +124,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(anyValHeader,
|
||||
"1",
|
||||
"2",
|
||||
"3")
|
||||
"3",
|
||||
endTable)
|
||||
o.head should be(anyValHeader)
|
||||
o.last should be(endTable)
|
||||
}
|
||||
|
||||
it should "support Byte SCollection via AnyVal" in {
|
||||
|
|
@ -129,8 +140,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(anyValHeader,
|
||||
"1",
|
||||
"2",
|
||||
"3")
|
||||
"3",
|
||||
endTable)
|
||||
o.head should be(anyValHeader)
|
||||
o.last should be(endTable)
|
||||
}
|
||||
|
||||
it should "support Boolean SCollection via AnyVal" in {
|
||||
|
|
@ -143,8 +156,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(anyValHeader,
|
||||
"true",
|
||||
"false",
|
||||
"true")
|
||||
"true",
|
||||
endTable)
|
||||
o.head should be(anyValHeader)
|
||||
o.last should be(endTable)
|
||||
}
|
||||
|
||||
it should "support Char SCollection via AnyVal" in {
|
||||
|
|
@ -157,8 +172,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(anyValHeader,
|
||||
"a",
|
||||
"b",
|
||||
"c")
|
||||
"c",
|
||||
endTable)
|
||||
o.head should be(anyValHeader)
|
||||
o.last should be(endTable)
|
||||
}
|
||||
|
||||
it should "support SCollection of AnyVal over row limit" in {
|
||||
|
|
@ -199,8 +216,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
o should contain theSameElementsAs Seq(stringHeader,
|
||||
"a",
|
||||
"b",
|
||||
"c")
|
||||
"c",
|
||||
endTable)
|
||||
o.head should be (stringHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support empty SCollection of String" in {
|
||||
|
|
@ -240,8 +259,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
}
|
||||
o should contain theSameElementsAs Seq(kvHeader,
|
||||
s"3${tab}4",
|
||||
s"1${tab}2")
|
||||
s"1${tab}2",
|
||||
endTable)
|
||||
o.head should be (kvHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support KV (str keys) SCollection" in {
|
||||
|
|
@ -253,8 +274,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
}
|
||||
o should contain theSameElementsAs Seq(kvHeader,
|
||||
s"foo${tab}2",
|
||||
s"bar${tab}4")
|
||||
s"bar${tab}4",
|
||||
endTable)
|
||||
o.head should be (kvHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support KV (str values) SCollection" in {
|
||||
|
|
@ -266,8 +289,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
}
|
||||
o should contain theSameElementsAs Seq(kvHeader,
|
||||
s"2${tab}foo",
|
||||
s"4${tab}bar")
|
||||
s"4${tab}bar",
|
||||
endTable)
|
||||
o.head should be (kvHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support empty KV SCollection" in {
|
||||
|
|
@ -305,8 +330,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
in.closeAndDisplay()
|
||||
}
|
||||
}
|
||||
o should contain theSameElementsAs (Seq(tupleHeader) ++ Seq.fill(3)(s"1${tab}2${tab}3"))
|
||||
o should contain theSameElementsAs
|
||||
(Seq(tupleHeader, endTable) ++ Seq.fill(3)(s"1${tab}2${tab}3"))
|
||||
o.head should be(tupleHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support SCollection of Tuple of 22" in {
|
||||
|
|
@ -318,9 +345,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
in.closeAndDisplay()
|
||||
}
|
||||
}
|
||||
o should contain theSameElementsAs (Seq(tupleHeader) ++
|
||||
o should contain theSameElementsAs (Seq(tupleHeader, endTable) ++
|
||||
Seq.fill(3)((1 to 21).map(i => s"$i$tab").mkString + "22"))
|
||||
o.head should be(tupleHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support SCollection of Case Class of 22" in {
|
||||
|
|
@ -332,9 +360,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
in.closeAndDisplay()
|
||||
}
|
||||
}
|
||||
o should contain theSameElementsAs (Seq(tupleHeader) ++
|
||||
o should contain theSameElementsAs (Seq(tupleHeader, endTable) ++
|
||||
Seq.fill(3)((1 to 21).map(i => s"$i$tab").mkString + "22"))
|
||||
o.head should be(tupleHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support SCollection of Case Class" in {
|
||||
|
|
@ -344,9 +373,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
in.closeAndDisplay()
|
||||
}
|
||||
}
|
||||
o should contain theSameElementsAs (Seq(testCaseClassHeader) ++
|
||||
o should contain theSameElementsAs (Seq(testCaseClassHeader, endTable) ++
|
||||
Seq.fill(3)(s"1${tab}foo${tab}2.0"))
|
||||
o.head should be(testCaseClassHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support empty SCollection of Product" in {
|
||||
|
|
@ -423,9 +453,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
in.closeAndDisplay()
|
||||
}
|
||||
}
|
||||
o should contain theSameElementsAs (Seq(avroGenericRecordHeader) ++
|
||||
o should contain theSameElementsAs (Seq(avroGenericRecordHeader, endTable) ++
|
||||
Seq.fill(3)(s"1${tab}1.0${tab}user1${tab}checking"))
|
||||
o.head should be(avroGenericRecordHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support SCollection of SpecificRecord Avro" in {
|
||||
|
|
@ -436,9 +467,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
in.closeAndDisplay()
|
||||
}
|
||||
}
|
||||
o should contain theSameElementsAs (Seq(avroAccountHeader) ++
|
||||
o should contain theSameElementsAs (Seq(avroAccountHeader, endTable) ++
|
||||
Seq.fill(3)(s"2${tab}checking${tab}user2${tab}2.0"))
|
||||
o.head should be(avroAccountHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "support empty SCollection of SpecificRecord Avro" in {
|
||||
|
|
@ -509,9 +541,10 @@ class DisplayHelpersTest extends FlatSpec with Matchers {
|
|||
in.closeAndDisplay(bQSchema)
|
||||
}
|
||||
}
|
||||
o should contain theSameElementsAs (Seq(bQHeader) ++
|
||||
o should contain theSameElementsAs (Seq(bQHeader, endTable) ++
|
||||
Seq.fill(3)(s"3${tab}3.0${tab}checking${tab}user3"))
|
||||
o.head should be(bQHeader)
|
||||
o.last should be (endTable)
|
||||
}
|
||||
|
||||
it should "print error on empty BQ schema" in {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public class SparkRInterpreter extends Interpreter {
|
|||
private static final Logger logger = LoggerFactory.getLogger(SparkRInterpreter.class);
|
||||
|
||||
private static String renderOptions;
|
||||
private SparkInterpreter sparkInterpreter;
|
||||
private ZeppelinR zeppelinR;
|
||||
private SparkContext sc;
|
||||
|
||||
|
|
@ -70,7 +71,7 @@ public class SparkRInterpreter extends Interpreter {
|
|||
|
||||
int port = SparkRBackend.port();
|
||||
|
||||
SparkInterpreter sparkInterpreter = getSparkInterpreter();
|
||||
this.sparkInterpreter = getSparkInterpreter();
|
||||
this.sc = sparkInterpreter.getSparkContext();
|
||||
SparkVersion sparkVersion = new SparkVersion(sc.version());
|
||||
ZeppelinRContext.setSparkContext(sc);
|
||||
|
|
@ -185,7 +186,11 @@ public class SparkRInterpreter extends Interpreter {
|
|||
|
||||
@Override
|
||||
public int getProgress(InterpreterContext context) {
|
||||
return 0;
|
||||
if (sparkInterpreter != null) {
|
||||
return sparkInterpreter.getProgress(context);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -16,20 +16,18 @@
|
|||
*/
|
||||
|
||||
package org.apache.zeppelin.spark;
|
||||
|
||||
import org.apache.zeppelin.display.AngularObjectRegistry;
|
||||
import org.apache.zeppelin.display.GUI;
|
||||
import org.apache.zeppelin.interpreter.*;
|
||||
import org.apache.zeppelin.interpreter.InterpreterResult.Type;
|
||||
import org.apache.zeppelin.resource.LocalResourcePool;
|
||||
import org.apache.zeppelin.user.AuthenticationInfo;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
|
@ -40,10 +38,13 @@ import static org.junit.Assert.*;
|
|||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class PySparkInterpreterMatplotlibTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tmpDir = new TemporaryFolder();
|
||||
|
||||
public static SparkInterpreter sparkInterpreter;
|
||||
public static PySparkInterpreter pyspark;
|
||||
public static InterpreterGroup intpGroup;
|
||||
private File tmpDir;
|
||||
public static Logger LOGGER = LoggerFactory.getLogger(PySparkInterpreterTest.class);
|
||||
private InterpreterContext context;
|
||||
|
||||
|
|
@ -79,7 +80,7 @@ public class PySparkInterpreterMatplotlibTest {
|
|||
}
|
||||
}
|
||||
|
||||
public static Properties getPySparkTestProperties() {
|
||||
private Properties getPySparkTestProperties() throws IOException {
|
||||
Properties p = new Properties();
|
||||
p.setProperty("master", "local[*]");
|
||||
p.setProperty("spark.app.name", "Zeppelin Test");
|
||||
|
|
@ -87,6 +88,7 @@ public class PySparkInterpreterMatplotlibTest {
|
|||
p.setProperty("zeppelin.spark.maxResult", "1000");
|
||||
p.setProperty("zeppelin.spark.importImplicit", "true");
|
||||
p.setProperty("zeppelin.pyspark.python", "python");
|
||||
p.setProperty("zeppelin.dep.localrepo", tmpDir.newFolder().getAbsolutePath());
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
@ -106,10 +108,6 @@ public class PySparkInterpreterMatplotlibTest {
|
|||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
tmpDir = new File(System.getProperty("java.io.tmpdir") + "/ZeppelinLTest_" + System.currentTimeMillis());
|
||||
System.setProperty("zeppelin.dep.localrepo", tmpDir.getAbsolutePath() + "/local-repo");
|
||||
tmpDir.mkdirs();
|
||||
|
||||
intpGroup = new InterpreterGroup();
|
||||
intpGroup.put("note", new LinkedList<Interpreter>());
|
||||
|
||||
|
|
@ -137,24 +135,6 @@ public class PySparkInterpreterMatplotlibTest {
|
|||
new InterpreterOutput(null));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
delete(tmpDir);
|
||||
}
|
||||
|
||||
private void delete(File file) {
|
||||
if (file.isFile()) file.delete();
|
||||
else if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
if (files != null && files.length > 0) {
|
||||
for (File f : files) {
|
||||
delete(f);
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dependenciesAreInstalled() {
|
||||
// matplotlib
|
||||
|
|
|
|||
|
|
@ -16,20 +16,22 @@
|
|||
*/
|
||||
|
||||
package org.apache.zeppelin.spark;
|
||||
|
||||
import org.apache.zeppelin.display.AngularObjectRegistry;
|
||||
import org.apache.zeppelin.display.GUI;
|
||||
import org.apache.zeppelin.interpreter.*;
|
||||
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
|
||||
import org.apache.zeppelin.resource.LocalResourcePool;
|
||||
import org.apache.zeppelin.user.AuthenticationInfo;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
|
@ -39,14 +41,17 @@ import static org.junit.Assert.*;
|
|||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class PySparkInterpreterTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tmpDir = new TemporaryFolder();
|
||||
|
||||
public static SparkInterpreter sparkInterpreter;
|
||||
public static PySparkInterpreter pySparkInterpreter;
|
||||
public static InterpreterGroup intpGroup;
|
||||
private File tmpDir;
|
||||
public static Logger LOGGER = LoggerFactory.getLogger(PySparkInterpreterTest.class);
|
||||
private InterpreterContext context;
|
||||
|
||||
public static Properties getPySparkTestProperties() {
|
||||
private Properties getPySparkTestProperties() throws IOException {
|
||||
Properties p = new Properties();
|
||||
p.setProperty("master", "local[*]");
|
||||
p.setProperty("spark.app.name", "Zeppelin Test");
|
||||
|
|
@ -54,6 +59,7 @@ public class PySparkInterpreterTest {
|
|||
p.setProperty("zeppelin.spark.maxResult", "1000");
|
||||
p.setProperty("zeppelin.spark.importImplicit", "true");
|
||||
p.setProperty("zeppelin.pyspark.python", "python");
|
||||
p.setProperty("zeppelin.dep.localrepo", tmpDir.newFolder().getAbsolutePath());
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
@ -73,10 +79,6 @@ public class PySparkInterpreterTest {
|
|||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
tmpDir = new File(System.getProperty("java.io.tmpdir") + "/ZeppelinLTest_" + System.currentTimeMillis());
|
||||
System.setProperty("zeppelin.dep.localrepo", tmpDir.getAbsolutePath() + "/local-repo");
|
||||
tmpDir.mkdirs();
|
||||
|
||||
intpGroup = new InterpreterGroup();
|
||||
intpGroup.put("note", new LinkedList<Interpreter>());
|
||||
|
||||
|
|
@ -104,24 +106,6 @@ public class PySparkInterpreterTest {
|
|||
new InterpreterOutput(null));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
delete(tmpDir);
|
||||
}
|
||||
|
||||
private void delete(File file) {
|
||||
if (file.isFile()) file.delete();
|
||||
else if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
if (files != null && files.length > 0) {
|
||||
for (File f : files) {
|
||||
delete(f);
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicIntp() {
|
||||
if (getSparkVersionNumber() > 11) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package org.apache.zeppelin.spark;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
|
@ -35,20 +35,24 @@ import org.apache.zeppelin.user.AuthenticationInfo;
|
|||
import org.apache.zeppelin.display.GUI;
|
||||
import org.apache.zeppelin.interpreter.*;
|
||||
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class SparkInterpreterTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tmpDir = new TemporaryFolder();
|
||||
|
||||
public static SparkInterpreter repl;
|
||||
public static InterpreterGroup intpGroup;
|
||||
private InterpreterContext context;
|
||||
private File tmpDir;
|
||||
public static Logger LOGGER = LoggerFactory.getLogger(SparkInterpreterTest.class);
|
||||
|
||||
/**
|
||||
|
|
@ -65,28 +69,24 @@ public class SparkInterpreterTest {
|
|||
return version;
|
||||
}
|
||||
|
||||
public static Properties getSparkTestProperties() {
|
||||
public static Properties getSparkTestProperties(TemporaryFolder tmpDir) throws IOException {
|
||||
Properties p = new Properties();
|
||||
p.setProperty("master", "local[*]");
|
||||
p.setProperty("spark.app.name", "Zeppelin Test");
|
||||
p.setProperty("zeppelin.spark.useHiveContext", "true");
|
||||
p.setProperty("zeppelin.spark.maxResult", "1000");
|
||||
p.setProperty("zeppelin.spark.importImplicit", "true");
|
||||
p.setProperty("zeppelin.dep.localrepo", tmpDir.newFolder().getAbsolutePath());
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
tmpDir = new File(System.getProperty("java.io.tmpdir") + "/ZeppelinLTest_" + System.currentTimeMillis());
|
||||
System.setProperty("zeppelin.dep.localrepo", tmpDir.getAbsolutePath() + "/local-repo");
|
||||
|
||||
tmpDir.mkdirs();
|
||||
|
||||
if (repl == null) {
|
||||
intpGroup = new InterpreterGroup();
|
||||
intpGroup.put("note", new LinkedList<Interpreter>());
|
||||
repl = new SparkInterpreter(getSparkTestProperties());
|
||||
repl = new SparkInterpreter(getSparkTestProperties(tmpDir));
|
||||
repl.setInterpreterGroup(intpGroup);
|
||||
intpGroup.get("note").add(repl);
|
||||
repl.open();
|
||||
|
|
@ -102,24 +102,6 @@ public class SparkInterpreterTest {
|
|||
new InterpreterOutput(null));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
delete(tmpDir);
|
||||
}
|
||||
|
||||
private void delete(File file) {
|
||||
if (file.isFile()) file.delete();
|
||||
else if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
if (files != null && files.length > 0) {
|
||||
for (File f : files) {
|
||||
delete(f);
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicIntp() {
|
||||
assertEquals(InterpreterResult.Code.SUCCESS,
|
||||
|
|
@ -194,7 +176,7 @@ public class SparkInterpreterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSparkSql(){
|
||||
public void testSparkSql() throws IOException {
|
||||
repl.interpret("case class Person(name:String, age:Int)\n", context);
|
||||
repl.interpret("val people = sc.parallelize(Seq(Person(\"moon\", 33), Person(\"jobs\", 51), Person(\"gates\", 51), Person(\"park\", 34)))\n", context);
|
||||
assertEquals(Code.SUCCESS, repl.interpret("people.take(3)", context).code());
|
||||
|
|
@ -202,7 +184,7 @@ public class SparkInterpreterTest {
|
|||
|
||||
if (getSparkVersionNumber() <= 11) { // spark 1.2 or later does not allow create multiple SparkContext in the same jvm by default.
|
||||
// create new interpreter
|
||||
SparkInterpreter repl2 = new SparkInterpreter(getSparkTestProperties());
|
||||
SparkInterpreter repl2 = new SparkInterpreter(getSparkTestProperties(tmpDir));
|
||||
repl2.setInterpreterGroup(intpGroup);
|
||||
intpGroup.get("note").add(repl2);
|
||||
repl2.open();
|
||||
|
|
@ -236,9 +218,9 @@ public class SparkInterpreterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void shareSingleSparkContext() throws InterruptedException {
|
||||
public void shareSingleSparkContext() throws InterruptedException, IOException {
|
||||
// create another SparkInterpreter
|
||||
SparkInterpreter repl2 = new SparkInterpreter(getSparkTestProperties());
|
||||
SparkInterpreter repl2 = new SparkInterpreter(getSparkTestProperties(tmpDir));
|
||||
repl2.setInterpreterGroup(intpGroup);
|
||||
intpGroup.get("note").add(repl2);
|
||||
repl2.open();
|
||||
|
|
@ -252,10 +234,10 @@ public class SparkInterpreterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testEnableImplicitImport() {
|
||||
public void testEnableImplicitImport() throws IOException {
|
||||
if (getSparkVersionNumber() >= 13) {
|
||||
// Set option of importing implicits to "true", and initialize new Spark repl
|
||||
Properties p = getSparkTestProperties();
|
||||
Properties p = getSparkTestProperties(tmpDir);
|
||||
p.setProperty("zeppelin.spark.importImplicit", "true");
|
||||
SparkInterpreter repl2 = new SparkInterpreter(p);
|
||||
repl2.setInterpreterGroup(intpGroup);
|
||||
|
|
@ -269,11 +251,11 @@ public class SparkInterpreterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDisableImplicitImport() {
|
||||
public void testDisableImplicitImport() throws IOException {
|
||||
if (getSparkVersionNumber() >= 13) {
|
||||
// Set option of importing implicits to "false", and initialize new Spark repl
|
||||
// this test should return error status when creating DataFrame from sequence
|
||||
Properties p = getSparkTestProperties();
|
||||
Properties p = getSparkTestProperties(tmpDir);
|
||||
p.setProperty("zeppelin.spark.importImplicit", "false");
|
||||
SparkInterpreter repl2 = new SparkInterpreter(p);
|
||||
repl2.setInterpreterGroup(intpGroup);
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
package org.apache.zeppelin.spark;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Properties;
|
||||
|
|
@ -29,25 +27,28 @@ import org.apache.zeppelin.user.AuthenticationInfo;
|
|||
import org.apache.zeppelin.display.GUI;
|
||||
import org.apache.zeppelin.interpreter.*;
|
||||
import org.apache.zeppelin.interpreter.InterpreterResult.Type;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SparkSqlInterpreterTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tmpDir = new TemporaryFolder();
|
||||
|
||||
private SparkSqlInterpreter sql;
|
||||
private SparkInterpreter repl;
|
||||
private InterpreterContext context;
|
||||
private InterpreterGroup intpGroup;
|
||||
|
||||
Logger LOGGER = LoggerFactory.getLogger(SparkSqlInterpreterTest.class);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Properties p = new Properties();
|
||||
p.putAll(SparkInterpreterTest.getSparkTestProperties());
|
||||
p.putAll(SparkInterpreterTest.getSparkTestProperties(tmpDir));
|
||||
p.setProperty("zeppelin.spark.maxResult", "1000");
|
||||
p.setProperty("zeppelin.spark.concurrentSQL", "false");
|
||||
p.setProperty("zeppelin.spark.sql.stacktrace", "false");
|
||||
|
|
@ -82,10 +83,6 @@ public class SparkSqlInterpreterTest {
|
|||
new LinkedList<InterpreterContextRunner>(), new InterpreterOutput(null));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
boolean isDataFrameSupported() {
|
||||
return SparkInterpreterTest.getSparkVersionNumber() >= 13;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ The text of each license is also included at licenses/LICENSE-[project]-[version
|
|||
(The MIT License) Java String Similarity 0.12 (info.debatty:java-string-similarity:0.12 - https://github.com/tdebatty/java-string-similarity)
|
||||
(The MIT License) Java LSH 0.10 (info.debatty:java-lsh:0.10 - https://github.com/tdebatty/java-LSH)
|
||||
(The MIT License) JSoup 1.6.1 (org.jsoup:jsoup:1.6.1 - https://github.com/jhy/jsoup/)
|
||||
(The MIT License) ngclipboard v1.1.1 (https://github.com/sachinchoolur/ngclipboard) - https://github.com/sachinchoolur/ngclipboard/blob/1.1.1/LICENSE)
|
||||
|
||||
========================================================================
|
||||
BSD-style licenses
|
||||
|
|
|
|||
|
|
@ -17,14 +17,15 @@
|
|||
|
||||
package org.apache.zeppelin.dep;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.maven.repository.internal.MavenRepositorySystemSession;
|
||||
import org.sonatype.aether.RepositorySystem;
|
||||
import org.sonatype.aether.RepositorySystemSession;
|
||||
import org.sonatype.aether.repository.LocalRepository;
|
||||
import org.sonatype.aether.repository.RemoteRepository;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* Manage mvn repository.
|
||||
*/
|
||||
|
|
@ -35,21 +36,11 @@ public class Booter {
|
|||
|
||||
public static RepositorySystemSession newRepositorySystemSession(
|
||||
RepositorySystem system, String localRepoPath) {
|
||||
Validate.notNull(localRepoPath, "localRepoPath should have a value");
|
||||
|
||||
MavenRepositorySystemSession session = new MavenRepositorySystemSession();
|
||||
|
||||
// find homedir
|
||||
String home = System.getenv("ZEPPELIN_HOME");
|
||||
if (home == null) {
|
||||
home = System.getProperty("zeppelin.home");
|
||||
}
|
||||
if (home == null) {
|
||||
home = "..";
|
||||
}
|
||||
|
||||
String path = home + "/" + localRepoPath;
|
||||
|
||||
LocalRepository localRepo =
|
||||
new LocalRepository(new File(path).getAbsolutePath());
|
||||
LocalRepository localRepo = new LocalRepository(resolveLocalRepoPath(localRepoPath));
|
||||
session.setLocalRepositoryManager(system.newLocalRepositoryManager(localRepo));
|
||||
|
||||
// session.setTransferListener(new ConsoleTransferListener());
|
||||
|
|
@ -61,10 +52,24 @@ public class Booter {
|
|||
return session;
|
||||
}
|
||||
|
||||
static String resolveLocalRepoPath(String localRepoPath) {
|
||||
// todo decouple home folder resolution
|
||||
// find homedir
|
||||
String home = System.getenv("ZEPPELIN_HOME");
|
||||
if (home == null) {
|
||||
home = System.getProperty("zeppelin.home");
|
||||
}
|
||||
if (home == null) {
|
||||
home = "..";
|
||||
}
|
||||
|
||||
return Paths.get(home).resolve(localRepoPath).toAbsolutePath().toString();
|
||||
}
|
||||
|
||||
public static RemoteRepository newCentralRepository() {
|
||||
return new RemoteRepository("central", "default", "http://repo1.maven.org/maven2/");
|
||||
}
|
||||
|
||||
|
||||
public static RemoteRepository newLocalRepository() {
|
||||
return new RemoteRepository("local",
|
||||
"default", "file://" + System.getProperty("user.home") + "/.m2/repository");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.zeppelin.dep;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class BooterTest {
|
||||
|
||||
@Test
|
||||
public void should_return_absolute_path() {
|
||||
String resolvedPath = Booter.resolveLocalRepoPath("path");
|
||||
assertTrue(Paths.get(resolvedPath).isAbsolute());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_not_change_absolute_path() {
|
||||
String absolutePath
|
||||
= Paths.get("first", "second").toAbsolutePath().toString();
|
||||
String resolvedPath = Booter.resolveLocalRepoPath(absolutePath);
|
||||
|
||||
assertThat(resolvedPath, equalTo(absolutePath));
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void should_throw_exception_for_null() {
|
||||
Booter.resolveLocalRepoPath(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -169,8 +169,11 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
LOG.debug("{} message: invalid ticket {} != {}", messagereceived.op,
|
||||
messagereceived.ticket, ticket);
|
||||
} else {
|
||||
LOG.warn("{} message: invalid ticket {} != {}", messagereceived.op,
|
||||
messagereceived.ticket, ticket);
|
||||
if (!messagereceived.op.equals(OP.PING)) {
|
||||
conn.send(serializeMessage(new Message(OP.ERROR_INFO).put("info",
|
||||
"Your ticket is invalid possibly due to server restart. "
|
||||
+ "Please refresh the page and login again.")));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,50 +103,32 @@ module.exports = function(grunt) {
|
|||
}
|
||||
},
|
||||
|
||||
'goog-webfont-dl': {
|
||||
patuaOne: {
|
||||
googlefonts: {
|
||||
build: {
|
||||
options: {
|
||||
ttf: true,
|
||||
eot: true,
|
||||
woff: true,
|
||||
woff2: true,
|
||||
svg: true,
|
||||
fontname: 'Patua One',
|
||||
fontstyles: '400',
|
||||
fontdest: '<%= yeoman.app %>/fonts/',
|
||||
cssdest: '<%= yeoman.app %>/fonts/Patua-One.css',
|
||||
cssprefix: '',
|
||||
subset: ''
|
||||
}
|
||||
},
|
||||
sourceCodePro: {
|
||||
options: {
|
||||
ttf: true,
|
||||
eot: true,
|
||||
woff: true,
|
||||
woff2: true,
|
||||
svg: true,
|
||||
fontname: 'Source Code Pro',
|
||||
fontstyles: '300, 400, 500',
|
||||
fontdest: '<%= yeoman.app %>/fonts/',
|
||||
cssdest: '<%= yeoman.app %>/fonts/Source-Code-Pro.css',
|
||||
cssprefix: '',
|
||||
subset: ''
|
||||
}
|
||||
},
|
||||
roboto: {
|
||||
options: {
|
||||
ttf: true,
|
||||
eot: true,
|
||||
woff: true,
|
||||
woff2: true,
|
||||
svg: true,
|
||||
fontname: 'Roboto',
|
||||
fontstyles: '300, 400, 500',
|
||||
fontdest: '<%= yeoman.app %>/fonts/',
|
||||
cssdest: '<%= yeoman.app %>/fonts/Roboto.css',
|
||||
cssprefix: '',
|
||||
subset: ''
|
||||
fontPath: '<%= yeoman.app %>/fonts/',
|
||||
httpPath: '../fonts/',
|
||||
cssFile: '<%= yeoman.app %>/fonts/google-fonts.css',
|
||||
formats: {
|
||||
eot: true,
|
||||
ttf: true,
|
||||
woff: true,
|
||||
svg: true
|
||||
},
|
||||
fonts: [
|
||||
{
|
||||
family: 'Patua One',
|
||||
styles: [400]
|
||||
},
|
||||
{
|
||||
family: 'Source Code Pro',
|
||||
styles: [300, 400, 500]
|
||||
},
|
||||
{
|
||||
family: 'Roboto',
|
||||
styles: [300, 400, 500]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -493,6 +475,11 @@ module.exports = function(grunt) {
|
|||
cwd: 'bower_components/jquery-ui/themes/base/images',
|
||||
src: '{,*/}*.{png,jpg,jpeg,gif}',
|
||||
dest: '.tmp/styles/images'
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: 'bower_components/ngclipboard',
|
||||
src: 'dist/**',
|
||||
dest: '.tmp'
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: 'bower_components/MathJax',
|
||||
|
|
@ -546,6 +533,11 @@ module.exports = function(grunt) {
|
|||
cwd: 'bower_components/jquery-ui/themes/base/images',
|
||||
src: '{,*/}*.{png,jpg,jpeg,gif}',
|
||||
dest: '<%= yeoman.dist %>/styles/images'
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: 'bower_components/ngclipboard',
|
||||
src: 'dist/**',
|
||||
dest: '<%= yeoman.dist %>'
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: 'bower_components/MathJax',
|
||||
|
|
@ -624,7 +616,6 @@ module.exports = function(grunt) {
|
|||
'htmlhint',
|
||||
'clean:dist',
|
||||
'wiredep',
|
||||
'goog-webfont-dl',
|
||||
'useminPrepare',
|
||||
'concurrent:dist',
|
||||
'postcss',
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@
|
|||
"moment-duration-format": "^1.3.0",
|
||||
"select2": "^4.0.3",
|
||||
"github-markdown-css": "^2.4.0",
|
||||
"MathJax": "2.7.0"
|
||||
"MathJax": "2.7.0",
|
||||
"ngclipboard": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "1.5.0"
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@
|
|||
"version": "0.0.0",
|
||||
"engines" : { "node" : ">=6.0.0" },
|
||||
"scripts": {
|
||||
"postinstall": "node_modules/.bin/bower install --silent",
|
||||
"build": "./node_modules/.bin/grunt build",
|
||||
"start": "./node_modules/.bin/grunt serve",
|
||||
"test": "./node_modules/.bin/grunt test",
|
||||
"pretest": "./node_modules/.bin/npm install karma-phantomjs-launcher"
|
||||
"postinstall": "bower install --silent && grunt googlefonts",
|
||||
"build": "grunt build",
|
||||
"start": "grunt serve",
|
||||
"test": "grunt test",
|
||||
"pretest": "npm install karma-phantomjs-launcher"
|
||||
},
|
||||
"dependencies": {
|
||||
"grunt-angular-templates": "^0.5.7",
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-eslint": "^18.1.0",
|
||||
"grunt-filerev": "^0.2.1",
|
||||
"grunt-goog-webfont-dl": "^0.1.2",
|
||||
"grunt-google-fonts": "^0.4.0",
|
||||
"grunt-htmlhint": "^0.9.13",
|
||||
"grunt-jscs": "^2.1.0",
|
||||
"grunt-karma": "~2.0.0",
|
||||
|
|
|
|||
|
|
@ -86,9 +86,10 @@
|
|||
<exclude>src/styles/font-awesome*</exclude>
|
||||
<exclude>src/fonts/Simple-Line*</exclude>
|
||||
<exclude>src/fonts/simple-line*</exclude>
|
||||
<exclude>src/fonts/Patua-One*</exclude>
|
||||
<exclude>src/fonts/Roboto*</exclude>
|
||||
<exclude>src/fonts/Source-Code-Pro*</exclude>
|
||||
<exclude>src/fonts/patua-one*</exclude>
|
||||
<exclude>src/fonts/roboto*</exclude>
|
||||
<exclude>src/fonts/source-code-pro*</exclude>
|
||||
<exclude>src/fonts/google-fonts.css</exclude>
|
||||
<exclude>bower.json</exclude>
|
||||
<exclude>package.json</exclude>
|
||||
<exclude>*.md</exclude>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@
|
|||
'xeditable',
|
||||
'ngToast',
|
||||
'focus-if',
|
||||
'ngResource'
|
||||
'ngResource',
|
||||
'ngclipboard'
|
||||
])
|
||||
.filter('breakFilter', function() {
|
||||
return function(text) {
|
||||
|
|
|
|||
|
|
@ -112,11 +112,6 @@
|
|||
var top = $id.offset().top - 103;
|
||||
angular.element('html, body').scrollTo({top: top, left: 0});
|
||||
}
|
||||
|
||||
// force notebook reload on user change
|
||||
$scope.$on('setNoteMenu', function(event, note) {
|
||||
initNotebook();
|
||||
});
|
||||
},
|
||||
1000
|
||||
);
|
||||
|
|
@ -125,6 +120,11 @@
|
|||
|
||||
initNotebook();
|
||||
|
||||
// force notebook reload on user change
|
||||
$scope.$on('setNoteMenu', function(event, note) {
|
||||
initNotebook();
|
||||
});
|
||||
|
||||
$scope.focusParagraphOnClick = function(clickEvent) {
|
||||
if (!$scope.note) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -39,8 +39,15 @@ limitations under the License.
|
|||
type="button">
|
||||
</span>
|
||||
<ul class="dropdown-menu" role="menu" style="width:200px;z-index:1002">
|
||||
<li ng-click="$event.stopPropagation()" style="text-align:center;margin-top:4px;">
|
||||
{{paragraph.id}}
|
||||
<li ng-controller="clipboardCtrl" ng-click="$event.stopPropagation()" style="text-align:center;margin-top:4px;">
|
||||
<a ngclipboard
|
||||
ngclipboard-success="complete($event)"
|
||||
ngclipboard-error="clipError($event)"
|
||||
data-clipboard-text="{{paragraph.id}}"
|
||||
tooltip-placement="top"
|
||||
tooltip="{{tooltip}}">
|
||||
<span>{{paragraph.id}}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li>
|
||||
|
|
|
|||
|
|
@ -556,6 +556,7 @@
|
|||
$scope.editor.commands.removeCommand('showSettingsMenu');
|
||||
|
||||
$scope.editor.commands.bindKey('ctrl-alt-l', null);
|
||||
$scope.editor.commands.bindKey('ctrl-alt-w', null);
|
||||
|
||||
// autocomplete on 'ctrl+.'
|
||||
$scope.editor.commands.bindKey('ctrl-.', 'startAutocomplete');
|
||||
|
|
@ -1092,10 +1093,12 @@
|
|||
} else {
|
||||
$scope.showTitle($scope.paragraph);
|
||||
}
|
||||
}else if (keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 67) { // Ctrl + Alt + c
|
||||
} else if (keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 67) { // Ctrl + Alt + c
|
||||
$scope.copyPara('below');
|
||||
} else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 76) { // Ctrl + Alt + l
|
||||
$scope.clearParagraphOutput($scope.paragraph);
|
||||
} else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 87) { // Ctrl + Alt + w
|
||||
$scope.goToSingleParagraph();
|
||||
} else {
|
||||
noShortcutDefined = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,8 @@ table.dataTable.table-condensed .sorting_desc:after {
|
|||
}
|
||||
|
||||
.paragraph .control span {
|
||||
margin-left: 4px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.paragraph .control {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
'use strict';
|
||||
(function() {
|
||||
angular.module('zeppelinWebApp').controller('clipboardCtrl', clipboardCtrl);
|
||||
clipboardCtrl.$inject = ['$scope'];
|
||||
|
||||
function clipboardCtrl($scope) {
|
||||
$scope.complete = function(e) {
|
||||
$scope.copied = true;
|
||||
$scope.tooltip = 'Copied!';
|
||||
setTimeout(function() {
|
||||
$scope.tooltip = 'Copy to clipboard';
|
||||
}, 400);
|
||||
};
|
||||
$scope.$watch('input', function() {
|
||||
$scope.copied = false;
|
||||
$scope.tooltip = 'Copy to clipboard';
|
||||
});
|
||||
$scope.clipError = function(e) {
|
||||
console.log('Error: ' + e.name + ' - ' + e.message);
|
||||
$scope.tooltip = 'Not supported browser';
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
|
@ -199,6 +199,17 @@ limitations under the License.
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="keys">
|
||||
<kbd class="kbd-dark">Ctrl</kbd> + <kbd class="kbd-dark">{{ isMac ? 'Option' : 'Alt'}}</kbd> + <kbd class="kbd-dark">w</kbd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
Link this paragraph
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="keys">
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ limitations under the License.
|
|||
name="defaultInterpreter"
|
||||
id="defaultInterpreter"
|
||||
ng-options="option.name for option in interpreterSettings">
|
||||
<option value="">--Select--</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
defaultInterpreterId = $scope.note.defaultInterpreter.id;
|
||||
}
|
||||
vm.websocketMsgSrv.createNotebook($scope.note.notename, defaultInterpreterId);
|
||||
$scope.note.defaultInterpreter = null;
|
||||
$scope.note.defaultInterpreter = $scope.interpreterSettings[0];
|
||||
} else {
|
||||
var noteId = $routeParams.noteId;
|
||||
vm.websocketMsgSrv.cloneNote(noteId, $scope.note.notename);
|
||||
|
|
@ -104,6 +104,9 @@
|
|||
|
||||
$scope.$on('interpreterSettings', function(event, data) {
|
||||
$scope.interpreterSettings = data.interpreterSettings;
|
||||
|
||||
//initialize default interpreter with Spark interpreter
|
||||
$scope.note.defaultInterpreter = data.interpreterSettings[0];
|
||||
});
|
||||
|
||||
var init = function() {
|
||||
|
|
|
|||
|
|
@ -65,9 +65,7 @@ limitations under the License.
|
|||
<link rel="stylesheet" href="fonts/font-awesome.min.css" />
|
||||
<link rel="stylesheet" href="fonts/simple-line-icons.css" />
|
||||
<link rel="stylesheet" href="fonts/custom-font.css" />
|
||||
<link rel="stylesheet" href="fonts/Patua-One.css" />
|
||||
<link rel="stylesheet" href="fonts/Source-Code-Pro.css" />
|
||||
<link rel="stylesheet" href="fonts/Roboto.css" />
|
||||
<link rel="stylesheet" href="fonts/google-fonts.css" />
|
||||
<!-- endbuild -->
|
||||
<link rel="stylesheet" ng-href="assets/styles/looknfeel/{{looknfeel}}.css" />
|
||||
<link rel="stylesheet" href="assets/styles/printMode.css" />
|
||||
|
|
@ -165,6 +163,8 @@ limitations under the License.
|
|||
<script src="bower_components/moment-duration-format/lib/moment-duration-format.js"></script>
|
||||
<script src="bower_components/select2/dist/js/select2.js"></script>
|
||||
<script src="bower_components/MathJax/MathJax.js"></script>
|
||||
<script src="bower_components/clipboard/dist/clipboard.js"></script>
|
||||
<script src="bower_components/ngclipboard/dist/ngclipboard.js"></script>
|
||||
<!-- endbower -->
|
||||
<!-- endbuild -->
|
||||
<!-- build:js({.tmp,src}) scripts/scripts.js -->
|
||||
|
|
@ -198,6 +198,7 @@ limitations under the License.
|
|||
<script src="app/search/result-list.controller.js"></script>
|
||||
<script src="app/notebookRepos/notebookRepos.controller.js"></script>
|
||||
<script src="components/arrayOrderingSrv/arrayOrdering.service.js"></script>
|
||||
<script src="components/clipboard/clipboard.controller.js"></script>
|
||||
<script src="components/navbar/navbar.controller.js"></script>
|
||||
<script src="components/ngescape/ngescape.directive.js"></script>
|
||||
<script src="components/interpreter/interpreter.directive.js"></script>
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ module.exports = function(config) {
|
|||
'bower_components/moment-duration-format/lib/moment-duration-format.js',
|
||||
'bower_components/select2/dist/js/select2.js',
|
||||
'bower_components/MathJax/MathJax.js',
|
||||
'bower_components/clipboard/dist/clipboard.js',
|
||||
'bower_components/ngclipboard/dist/ngclipboard.js',
|
||||
'bower_components/angular-mocks/angular-mocks.js',
|
||||
// endbower
|
||||
'.tmp/app/app.js',
|
||||
|
|
|
|||
|
|
@ -121,4 +121,20 @@ describe('Controller: NotebookCtrl', function() {
|
|||
expect(scope.note.name).toEqual(newName);
|
||||
expect(websocketMsgSrvMock.updateNote).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should reload note info once per one "setNoteMenu" event', function() {
|
||||
spyOn(websocketMsgSrvMock, 'getNote');
|
||||
spyOn(websocketMsgSrvMock, 'listRevisionHistory');
|
||||
|
||||
scope.$broadcast('setNoteMenu');
|
||||
expect(websocketMsgSrvMock.getNote.calls.count()).toEqual(1);
|
||||
expect(websocketMsgSrvMock.listRevisionHistory.calls.count()).toEqual(1);
|
||||
|
||||
websocketMsgSrvMock.getNote.calls.reset();
|
||||
websocketMsgSrvMock.listRevisionHistory.calls.reset();
|
||||
|
||||
scope.$broadcast('setNoteMenu');
|
||||
expect(websocketMsgSrvMock.getNote.calls.count()).toEqual(1);
|
||||
expect(websocketMsgSrvMock.listRevisionHistory.calls.count()).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ public class ZeppelinConfiguration extends XMLConfiguration {
|
|||
return getRelativeDir(
|
||||
String.format("%s/%s",
|
||||
getConfDir(),
|
||||
getString(path)));
|
||||
path));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +320,7 @@ public class ZeppelinConfiguration extends XMLConfiguration {
|
|||
return getRelativeDir(
|
||||
String.format("%s/%s",
|
||||
getConfDir(),
|
||||
getString(path)));
|
||||
path));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -514,21 +514,19 @@ public class Note implements Serializable, ParagraphJobListener {
|
|||
/**
|
||||
* Run all paragraphs sequentially.
|
||||
*/
|
||||
public void runAll() {
|
||||
public synchronized void runAll() {
|
||||
String cronExecutingUser = (String) getConfig().get("cronExecutingUser");
|
||||
if (null == cronExecutingUser) {
|
||||
cronExecutingUser = "anonymous";
|
||||
}
|
||||
synchronized (paragraphs) {
|
||||
for (Paragraph p : paragraphs) {
|
||||
if (!p.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||
authenticationInfo.setUser(cronExecutingUser);
|
||||
p.setAuthenticationInfo(authenticationInfo);
|
||||
run(p.getId());
|
||||
for (Paragraph p : getParagraphs()) {
|
||||
if (!p.isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||
authenticationInfo.setUser(cronExecutingUser);
|
||||
p.setAuthenticationInfo(authenticationInfo);
|
||||
run(p.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue