Repository: mwouts/jupytext
Pull request #378 (2019-11-08 19:57:09)

Add Robot Framework (.robot) -language support
* [x] document the language extension and comment by adding one line to _SCRIPT_EXTENSIONS in languages.py.
* [x] contribute a sample notebook in tests/notebooks/ipynb_[language].
* [x] add two tests in test_mirror.py: one for the light format, and another one for the percent format.
* [x] Make sure that the tests pass, and that the text representations of your notebook, found in tests/notebooks/mirror/ipynb_to_script and tests/notebooks/mirror/ipynb_to_percent, are valid scripts.


codecov[bot]: # [Codecov](https://codecov.io/gh/mwouts/jupytext/pull/378?src=pr&el=h1) Report
> Merging [#378](https://codecov.io/gh/mwouts/jupytext/pull/378?src=pr&el=desc) into [master](https://codecov.io/gh/mwouts/jupytext/commit/700f03a61b81b0f80df3f67551ecc2bf956a873c?src=pr&el=desc) will **decrease** coverage by `10.6%`.
> The diff coverage is `50%`.

[![Impacted file tree graph](https://codecov.io/gh/mwouts/jupytext/pull/378/graphs/tree.svg?width=650&token=a1pNjsiILi&height=150&src=pr)](https://codecov.io/gh/mwouts/jupytext/pull/378?src=pr&el=tree)

```diff
@@             Coverage Diff             @@
##           master     #378       +/-   ##
===========================================
- Coverage   99.05%   88.45%   -10.61%     
===========================================
  Files          75       75               
  Lines        7431     7277      -154     
===========================================
- Hits         7361     6437      -924     
- Misses         70      840      +770
```


| [Impacted Files](https://codecov.io/gh/mwouts/jupytext/pull/378?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [jupytext/languages.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-anVweXRleHQvbGFuZ3VhZ2VzLnB5) | `100% <ø> (ø)` | :arrow_up: |
| [tests/test\_mirror.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9taXJyb3IucHk=) | `37.28% <50%> (-62.72%)` | :arrow_down: |
| [tests/test\_hide\_remove\_input\_outputs\_rmarkdown.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9oaWRlX3JlbW92ZV9pbnB1dF9vdXRwdXRzX3JtYXJrZG93bi5weQ==) | `28.57% <0%> (-71.43%)` | :arrow_down: |
| [tests/test\_black.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9ibGFjay5weQ==) | `31.53% <0%> (-68.47%)` | :arrow_down: |
| [tests/test\_cell\_metadata.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9jZWxsX21ldGFkYXRhLnB5) | `40.5% <0%> (-59.5%)` | :arrow_down: |
| [tests/test\_read\_simple\_pandoc.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9yZWFkX3NpbXBsZV9wYW5kb2MucHk=) | `44.82% <0%> (-55.18%)` | :arrow_down: |
| [jupytext/pandoc.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-anVweXRleHQvcGFuZG9jLnB5) | `40.81% <0%> (-55.11%)` | :arrow_down: |
| [tests/test\_knitr\_spin.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9rbml0cl9zcGluLnB5) | `45.45% <0%> (-54.55%)` | :arrow_down: |
| [tests/test\_active\_cells.py](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree#diff-dGVzdHMvdGVzdF9hY3RpdmVfY2VsbHMucHk=) | `52.54% <0%> (-47.46%)` | :arrow_down: |
| ... and [32 more](https://codecov.io/gh/mwouts/jupytext/pull/378/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/mwouts/jupytext/pull/378?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/mwouts/jupytext/pull/378?src=pr&el=footer). Last update [700f03a...88f6fd9](https://codecov.io/gh/mwouts/jupytext/pull/378?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

mwouts: Awesome! Thank you @datakurre . By the way I see that the instructions for adding a new language were not completely up-to-date (adding test functions is not required any more), so I've fixed them.

Thanks again for your contribution!

Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 11b0ee36..9c105432 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,8 +28,7 @@ You want to submit an enhancement on Jupytext? Unless this is a small change, we
 A pull request for which you do not need to contact us in advance is the addition of a new language to Jupytext. In principle that should be easy - you would only have to:
 - document the language extension and comment by adding one line to `_SCRIPT_EXTENSIONS` in `languages.py`.
 - contribute a sample notebook in `tests/notebooks/ipynb_[language]`.
-- add two tests in `test_mirror.py`: one for the `light` format, and another one for the `percent` format.
-- Make sure that the tests pass, and that the text representations of your notebook, found in  `tests/notebooks/mirror/ipynb_to_script` and `tests/notebooks/mirror/ipynb_to_percent`, are valid scripts.
+- run the tests suite (with just `pytest`). The mirror tests will generate various text representations corresponding to your notebook under  `tests/notebooks/mirror/`. Please verify that these files are valid scripts, and commit them.
 
 # How to setup a development environment for Jupytext
 
diff --git a/HISTORY.rst b/HISTORY.rst
index 79684e2a..52edf686 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -25,6 +25,7 @@ Release History
 - ``jupytext --check pytest notebook.ipynb`` can be used to run test functions in a notebook (#286)
 - ``jupytext --check`` and ``jupytext --pipe`` can run commands that only operate on files: when ``{}`` is found in the text of the command, ``jupytext`` saves the text representation of the notebook in a temp file, and replaces ``{}`` with the name of that file before executing the command. (#286)
 - Added support for Rust/Evxcr, by Jonas Bushart (#351)
+- Added support for Robot Framework, by Akso Soukka (#378)
 - Added support for PowerShell (#349)
 
 **BugFixes**
diff --git a/README.md b/README.md
index 162b2c3f..f40ee791 100755
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ It can also convert these documents **into** Jupyter
 Notebooks, allowing you to synchronize content in both
 directions.
 
-The languages that are currently supported by Jupytext are: Julia, Python, R, Bash, Scheme, Clojure, Matlab, Octave, C++, q/kdb+, IDL, TypeScript, Javascript, Scala, Rust/Evxcr and PowerShell. Extending Jupytext to more languages should be easy - read more at [CONTRIBUTING.md](https://github.com/mwouts/jupytext/blob/master/CONTRIBUTING.md). In addition, jupytext users can choose between two formats for notebooks as scripts:
+The languages that are currently supported by Jupytext are: Julia, Python, R, Bash, Scheme, Clojure, Matlab, Octave, C++, q/kdb+, IDL, TypeScript, Javascript, Scala, Rust/Evxcr, PowerShell and Robot Framework. Extending Jupytext to more languages should be easy - read more at [CONTRIBUTING.md](https://github.com/mwouts/jupytext/blob/master/CONTRIBUTING.md). In addition, jupytext users can choose between two formats for notebooks as scripts:
 - The `percent` format, compatible with several IDEs, including Spyder, Hydrogen, VScode and PyCharm. In that format, cells are delimited with a commented `%%`.
 - The `light` format, designed for this project. Use that format to open standard scripts as notebooks, or to save notebooks as scripts with few cell markers - none when possible.
 
diff --git a/docs/introduction.md b/docs/introduction.md
index 3c4040d8..1401dfac 100644
--- a/docs/introduction.md
+++ b/docs/introduction.md
@@ -10,7 +10,7 @@ Jupytext can save Jupyter notebooks as
 - Markdown and R Markdown documents,
 - Scripts in many languages.
 
-The languages that are currently supported by Jupytext are: Julia, Python, R, Bash, Scheme, Clojure, Matlab, Octave, C++, q/kdb+, IDL, TypeScript, Javascript and Scala. Extending Jupytext to more languages should be easy - read more at [CONTRIBUTING.md](https://github.com/mwouts/jupytext/blob/master/CONTRIBUTING.md#). In addition, jupytext users can choose between two formats for notebooks as scripts:
+The languages that are currently supported by Jupytext are: Julia, Python, R, Bash, Scheme, Clojure, Matlab, Octave, C++, q/kdb+, IDL, TypeScript, Javascript, Scala, Rust/Evxcr, PowerShell and Robot Framework. Extending Jupytext to more languages should be easy - read more at [CONTRIBUTING.md](https://github.com/mwouts/jupytext/blob/master/CONTRIBUTING.md#). In addition, jupytext users can choose between two formats for notebooks as scripts:
 - The `percent` format, compatible with several IDEs, including Spyder, Hydrogen, VScode and PyCharm. In that format, cells are delimited with a commented `%%`.
 - The `light` format, designed for this project. Use that format to open standard scripts as notebooks, or to save notebooks as scripts with few cell markers - none when possible.
 
diff --git a/jupytext/languages.py b/jupytext/languages.py
index eb611461..fc5c4599 100644
--- a/jupytext/languages.py
+++ b/jupytext/languages.py
@@ -3,7 +3,7 @@
 # Jupyter magic commands that are also languages
 _JUPYTER_LANGUAGES = ['R', 'bash', 'sh', 'python', 'python2', 'python3', 'javascript', 'js', 'perl',
                       'html', 'latex', 'markdown', 'pypy', 'ruby', 'script', 'svg',
-                      'matlab', 'octave', 'idl', 'spark', 'sql']
+                      'matlab', 'octave', 'idl', 'robotframework', 'spark', 'sql']
 
 # Supported file extensions (and languages)
 # Please add more languages here (and add a few tests) - see CONTRIBUTING.md
@@ -23,7 +23,8 @@ _SCRIPT_EXTENSIONS = {'.py': {'language': 'python', 'comment': '#'},
                       '.js': {'language': 'javascript', 'comment': '//'},
                       '.ts': {'language': 'typescript', 'comment': '//'},
                       '.scala': {'language': 'scala', 'comment': '//'},
-                      '.rs': {'language': 'rust', 'comment': '//'}}
+                      '.rs': {'language': 'rust', 'comment': '//'},
+                      '.robot': {'language': 'robotframework', 'comment': '#'}}
 
 _COMMENT_CHARS = [_SCRIPT_EXTENSIONS[ext]['comment'] for ext in _SCRIPT_EXTENSIONS if
                   _SCRIPT_EXTENSIONS[ext]['comment'] != '#']


Test patch:
diff --git a/tests/notebooks/ipynb_robot/simple_robot_notebook.ipynb b/tests/notebooks/ipynb_robot/simple_robot_notebook.ipynb
new file mode 100644
index 00000000..7e927762
--- /dev/null
+++ b/tests/notebooks/ipynb_robot/simple_robot_notebook.ipynb
@@ -0,0 +1,70 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "*** Settings ***\n",
+    "\n",
+    "Library  Collections"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "*** Keywords ***\n",
+    "\n",
+    "Head\n",
+    "    [Arguments]  ${list}\n",
+    "    ${value}=  Get from list  ${list}  0\n",
+    "    [Return]  ${value}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "lines_to_next_cell": 0
+   },
+   "outputs": [],
+   "source": [
+    "*** Tasks ***\n",
+    "\n",
+    "Get head\n",
+    "    ${array}=  Create list  1  2  3  4  5\n",
+    "    ${head}=  Head  ${array}\n",
+    "    Should be equal  ${head}  1"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Robot Framework",
+   "language": "robotframework",
+   "name": "robotkernel"
+  },
+  "language_info": {
+   "codemirror_mode": "robotframework",
+   "file_extension": ".robot",
+   "mimetype": "text/plain",
+   "name": "robotframework",
+   "pygments_lexer": "robotframework"
+  },
+  "pycharm": {
+   "stem_cell": {
+    "cell_type": "raw",
+    "source": [],
+    "metadata": {
+     "collapsed": false
+    }
+   }
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/tests/notebooks/mirror/ipynb_to_Rmd/simple_robot_notebook.Rmd b/tests/notebooks/mirror/ipynb_to_Rmd/simple_robot_notebook.Rmd
new file mode 100644
index 00000000..2821c7ca
--- /dev/null
+++ b/tests/notebooks/mirror/ipynb_to_Rmd/simple_robot_notebook.Rmd
@@ -0,0 +1,31 @@
+---
+jupyter:
+  kernelspec:
+    display_name: Robot Framework
+    language: robotframework
+    name: robotkernel
+---
+
+```{robotframework}
+*** Settings ***
+
+Library  Collections
+```
+
+```{robotframework}
+*** Keywords ***
+
+Head
+    [Arguments]  ${list}
+    ${value}=  Get from list  ${list}  0
+    [Return]  ${value}
+```
+
+```{robotframework}
+*** Tasks ***
+
+Get head
+    ${array}=  Create list  1  2  3  4  5
+    ${head}=  Head  ${array}
+    Should be equal  ${head}  1
+```
diff --git a/tests/notebooks/mirror/ipynb_to_hydrogen/simple_robot_notebook.robot b/tests/notebooks/mirror/ipynb_to_hydrogen/simple_robot_notebook.robot
new file mode 100644
index 00000000..932a1334
--- /dev/null
+++ b/tests/notebooks/mirror/ipynb_to_hydrogen/simple_robot_notebook.robot
@@ -0,0 +1,28 @@
+# ---
+# jupyter:
+#   kernelspec:
+#     display_name: Robot Framework
+#     language: robotframework
+#     name: robotkernel
+# ---
+
+# %%
+*** Settings ***
+
+Library  Collections
+
+# %%
+*** Keywords ***
+
+Head
+    [Arguments]  ${list}
+    ${value}=  Get from list  ${list}  0
+    [Return]  ${value}
+
+# %%
+*** Tasks ***
+
+Get head
+    ${array}=  Create list  1  2  3  4  5
+    ${head}=  Head  ${array}
+    Should be equal  ${head}  1
diff --git a/tests/notebooks/mirror/ipynb_to_md/simple_robot_notebook.md b/tests/notebooks/mirror/ipynb_to_md/simple_robot_notebook.md
new file mode 100644
index 00000000..7679d45b
--- /dev/null
+++ b/tests/notebooks/mirror/ipynb_to_md/simple_robot_notebook.md
@@ -0,0 +1,31 @@
+---
+jupyter:
+  kernelspec:
+    display_name: Robot Framework
+    language: robotframework
+    name: robotkernel
+---
+
+```robotframework
+*** Settings ***
+
+Library  Collections
+```
+
+```robotframework
+*** Keywords ***
+
+Head
+    [Arguments]  ${list}
+    ${value}=  Get from list  ${list}  0
+    [Return]  ${value}
+```
+
+```robotframework
+*** Tasks ***
+
+Get head
+    ${array}=  Create list  1  2  3  4  5
+    ${head}=  Head  ${array}
+    Should be equal  ${head}  1
+```
diff --git a/tests/notebooks/mirror/ipynb_to_percent/simple_robot_notebook.robot b/tests/notebooks/mirror/ipynb_to_percent/simple_robot_notebook.robot
new file mode 100644
index 00000000..932a1334
--- /dev/null
+++ b/tests/notebooks/mirror/ipynb_to_percent/simple_robot_notebook.robot
@@ -0,0 +1,28 @@
+# ---
+# jupyter:
+#   kernelspec:
+#     display_name: Robot Framework
+#     language: robotframework
+#     name: robotkernel
+# ---
+
+# %%
+*** Settings ***
+
+Library  Collections
+
+# %%
+*** Keywords ***
+
+Head
+    [Arguments]  ${list}
+    ${value}=  Get from list  ${list}  0
+    [Return]  ${value}
+
+# %%
+*** Tasks ***
+
+Get head
+    ${array}=  Create list  1  2  3  4  5
+    ${head}=  Head  ${array}
+    Should be equal  ${head}  1
diff --git a/tests/notebooks/mirror/ipynb_to_script/simple_robot_notebook.robot b/tests/notebooks/mirror/ipynb_to_script/simple_robot_notebook.robot
new file mode 100644
index 00000000..dfcf06b8
--- /dev/null
+++ b/tests/notebooks/mirror/ipynb_to_script/simple_robot_notebook.robot
@@ -0,0 +1,28 @@
+# ---
+# jupyter:
+#   kernelspec:
+#     display_name: Robot Framework
+#     language: robotframework
+#     name: robotkernel
+# ---
+
+# +
+*** Settings ***
+
+Library  Collections
+
+# +
+*** Keywords ***
+
+Head
+    [Arguments]  ${list}
+    ${value}=  Get from list  ${list}  0
+    [Return]  ${value}
+
+# +
+*** Tasks ***
+
+Get head
+    ${array}=  Create list  1  2  3  4  5
+    ${head}=  Head  ${array}
+    Should be equal  ${head}  1