![License BSD](https://img.shields.io/badge/License-BSD-blue.svg "License BSD")
![Python 3](https://img.shields.io/badge/Python-3-brightgreen.svg "Python 3")
![blabla](https://img.shields.io/pypi/v/proactive-jupyter-kernel.svg "bla")
# proactive-jupyter-kernel
The ActiveEon Jupyter Kernel adds a kernel backend to Jupyter. This kernel interfaces directly with the ProActive
scheduler and constructs tasks and workflows to execute them on the fly.
With this interface, users can run their code locally and test it using a native python kernel, and by a simple switch to
ProActive kernel, run it on remote public or private infrastructures without having to modify the code. See the example below:
![Image not found](./images/direct_execution_from_jupyter.png "Direct execution from Jupyter with ActiveEon Kernel")
## 1. Installation:
### 1.1 Requirements:
Python 2 or 3
### 1.2 Using PyPi
* open a terminal
* install the ProActive jupyter kernel with the following commands:
```bash
$ pip install proactive proactive-jupyter-kernel --upgrade
$ python -m proactive-jupyter-kernel.install
```
### 1.3 Using source code
* open a terminal
* clone the repository on your local machine:
```bash
$ git clone git@github.com:ow2-proactive/proactive-jupyter-kernel.git
```
* install the ProActive jupyter kernel with the following commands:
```bash
$ pip install proactive-jupyter-kernel/
$ python -m proactive-jupyter-kernel.install
```
## 2. Platform
You can use any jupyter platform.
We recommend to use [jupyter lab](https://jupyterlab.readthedocs.io/en/stable/). To launch it from your terminal after
having installed it:
```bash
$ jupyter lab
```
or in daemon mode:
```bash
$ nohup jupyter lab &>/dev/null &
```
When opened, click on the ProActive icon to open a notebook based on the ProActive kernel.
## 3. Help
As a quick start, we recommend the user to run the `#%help()` pragma using the following script:
```python
#%help()
```
This script gives a brief description of all the different pragmas that the ProActive Kernel provides.
To get a more detailed description of a needed pragma, the user can run the following script:
```python
#%help(pragma=PRAGMA_NAME)
```
## 4. Connection
### 4.1 Using connect()
If you are trying ProActive for the first time, sign up on the [try platform](https://try.activeeon.com/signup.html).
Once you receive your login and password, connect to the trial platform using the `#%connect()` pragma:
```python
#%connect(login=YOUR_LOGIN, password=YOUR_PASSWORD)
```
To connect to another ProActive server host, use the later pragma this way:
```python
#%connect(host=YOUR_HOST, [port=YOUR_PORT], login=YOUR_LOGIN, password=YOUR_PASSWORD)
```
Notice that the `port` parameter is optional. The default connexion port is `8080`.
You can also connect to a distant server by providing its `url` in the following way:
```python
#%connect(url=YOUR_SERVER_URL, login=YOUR_LOGIN, password=YOUR_PASSWORD)
```
By providing the complete `url` of the server, users can eventually connect through the secure HTTPS protocol.
### 4.2 Using a configuration file:
For automatic sign in, create a file named *proactive_config.ini* in your notebook working directory.
Fill your configuration file according to one of the following two formats:
- By providing the server `host` and `port`:
```ini
[proactive_server]
host=YOUR_HOST
port=YOUR_PORT
[user]
login=YOUR_LOGIN
password=YOUR_PASSWORD
```
- By providing the server `url`:
```ini
[proactive_server]
url=YOUR_SERVER_URL
[user]
login=YOUR_LOGIN
password=YOUR_PASSWORD
```
Save your changes and restart the ProActive kernel.
You can also force the current kernel to connect using any _.ini_ config file through the `#%connect()` pragma:
```python
#%connect(path=PATH_TO/YOUR_CONFIG_FILE.ini)
```
(For more information about this format please check
[configParser](https://docs.python.org/3/library/configparser.html))
## 5. Usage
#### 5.1 Creating a Python task
To create a new task, use the pragma `#%task()` followed by the task implementation script written into a notebook
block code.
To use this pragma, a task name has to be provided at least. Example:
```python
#%task(name=myTask)
print('Hello world')
```
General usage:
```python
#%task(name=TASK_NAME, [language=SCRIPT_LANGUAGE], [dep=[TASK_NAME1,TASK_NAME2,...]], [generic_info=[(KEY1,VAL1), (KEY2,VALUE2),...]], [variables=[(VAR1,VAL1), (VAR2,VALUE2),...]], [export=[VAR_NAME1,VAR_NAME2,...]], [import=[VAR_NAME1,VAR_NAME2,...]], [path=IMPLEMENTATION_FILE_PATH])\n'
```
Users can also provide more information about the task using the pragma's options. In the following, we give more
details about the possible options:
##### 5.1.1 Language
The `language` parameter is needed when the task script is not written in native Python. If not provided, Python will be
selected as the default language.
The supported programming languages are:
* Linux_Bash
* Windows_Cmd
* DockerCompose
* Scalaw
* Groovy
* Javascript
* Jython
* Python
* Ruby
* Perl
* PowerShell
* R
Here is an example that shows a task implementation written in `Linux_Bash`:
```bash
#%task(name=myTask, language=Linux_Bash)
echo 'Hello, World!'
```
##### 5.1.2 Dependencies
One of the most important notions in workflows is the dependencies between tasks. To specify this information, use the
`dep` parameter. Its value should be a list of all tasks on which the new task depends. Example:
```python
#%task(name=myTask,dep=[parentTask1,parentTask2])
print('Hello world')
```
##### 5.1.3 Variables
To specify [task variables](https://doc.activeeon.com/latest/user/ProActiveUserGuide.html#_task_variables),
you should provide the `variables` parameter. Its value should be a list of tuples `(key,value)` that corresponds to
the names and adequate values of the corresponding task variables. Example:
```python
#%task(name=myTask, variables=[(var1,value1),(var2,value2)])
print('Hello world')
```
##### 5.1.4 Generic information
To specify the values of some advanced ProActive variables called
[generic_information](https://doc.activeeon.com/latest/user/ProActiveUserGuide.html#_generic_information), you should
provide the `generic_info` parameter. Its value should be a list of tuples `(key,value)` that corresponds to the names
and adequate values of the Generic Information. Example:
```python
#%task(name=myTask, generic_info=[(var1,value1),(var2,value2)])
print('Hello world')
```
##### 5.1.5 Export/import variables
The `export` and `import` parameters ensure variables propagation between the different tasks of a workflow.
If `myTask1` variables `var1` and `var2` are needed in `myTask2`, both pragmas have to specify this information as
follows:
* `myTask1` should include an `export` parameter with a list of these variable names,
* `myTask2` should include an `import` parameter with a list including the same names.
Example:
`myTask1` implementation block would be:
```python
#%task(name=myTask1, export=[var1,var2])
var1 = "Hello"
var2 = "ActiveEon!"
```
and `myTask2` implementation block would be:
```python
#%task(name=myTask2, dep=[myTask1], import[var1,var2])
print(var1 + " from " + var2)
```
##### 5.1.6 Implementation file
It is also possible to use an external implementation file to define the task implementation. To do so, the option `path`
should be used.
Example:
```python
#%task(name=myTask,path=PATH_TO/IMPLEMENTATION_FILE.py)
```
#### 5.2 Importing libraries
The main difference between the ProActive and 'native language' kernels resides in the way the memory is accessed
during blocks execution. In a common native language kernel, the whole script code (all the notebook blocks) is
locally executed in the same shared memory space; whereas the ProActive kernel will execute each created task in an
independent process. In order to facilitate the transition from native language to ProActive kernels, we included the
pragma `#%import()`. This pragma gives the user the ability to add libraries tha