Repository: mwouts/jupytext (language: python)

Issue:
Conversion of a simple .ipynb to py then back to ipynb gives "KeyError: 'env'"

```utils1.ipynb
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "a=5\n",
    "print('hello',a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "argv": [
    "python",
    "-m",
    "ipykernel_launcher",
    "-f",
    "{connection_file}"
   ],
   "display_name": "Python 3",
   "env": null,
   "interrupt_mode": "signal",
   "language": "python",
   "metadata": null,
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "name": "utils1.ipynb"
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
```

First convertsion work:
```
$ jupytext --to py:percent --from ipynb utils1.ipynb
[jupytext] Reading utils1.ipynb in format ipynb
[jupytext] Updating the timestamp of utils1.py
```

Conversion back to original does not
```
$ jupytext --from py:percent --to ipynb utils1.py
[jupytext] Reading utils1.py in format py:percent
Traceback (most recent call last):
  File "/home/gmuller/Python/DataScience/bin/jupytext", line 8, in <module>
    sys.exit(jupytext())
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/cli.py", line 427, in jupytext
    exit_code += jupytext_single_file(nb_file, args, log)
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/cli.py", line 494, in jupytext_single_file
    notebook = read(nb_file, fmt=fmt, config=config)
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/jupytext.py", line 435, in read
    return read(stream, as_version=as_version, fmt=fmt, config=config, **kwargs)
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/jupytext.py", line 444, in read
    return reads(fp.read(), fmt, config=config, **kwargs)
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/jupytext.py", line 384, in reads
    format_name = read_format_from_metadata(text, ext) or fmt.get("format_name")
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/formats.py", line 280, in read_format_from_metadata
    metadata = read_metadata(text, ext)
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/formats.py", line 259, in read_metadata
    metadata, _, _, _ = header_to_metadata_and_cell(lines, comment, ext)
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/header.py", line 228, in header_to_metadata_and_cell
    recursive_update(metadata, yaml.safe_load("\n".join(jupyter))["jupyter"])
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/header.py", line 148, in recursive_update
    target[key] = recursive_update(target.get(key, {}), value)
  File "/home/gmuller/Python/DataScience/lib/python3.8/site-packages/jupytext/header.py", line 146, in recursive_update
    del target[key]
KeyError: 'env'
```



Discussion / hints:
Thanks @liar666 for reporting this.

Do you have any idea where this `"env": null` and `"metadata": null` in your `kernelspec` come from?

Anyway I agree they should not make Jupytext fail, I'll fix that part.

Fix patch:
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 62a8b6051..b0be4da72 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -1,7 +1,7 @@
 Jupytext ChangeLog
 ==================
 
-1.11.3 (2021-05-??)
+1.11.3 (2021-06-??)
 -------------------
 
 **Changed**
@@ -10,6 +10,7 @@ Jupytext ChangeLog
 **Fixed**
 - Dependencies of the JupyterLab extension have been upgraded to fix a security vulnerability ([#783](https://github.com/mwouts/jupytext/issues/783))
 - Variables assigned from a magic command are commented out in `py` scripts ([#781](https://github.com/mwouts/jupytext/issues/781))
+- Fixed a round-trip issue on notebooks that have None/null in their metadata ([#792](https://github.com/mwouts/jupytext/issues/792))
 
 
 1.11.2 (2021-05-02)
diff --git a/jupytext/header.py b/jupytext/header.py
index a1fd4a042..cf6d704b4 100644
--- a/jupytext/header.py
+++ b/jupytext/header.py
@@ -143,7 +143,7 @@ def recursive_update(target, update):
     for key in update:
         value = update[key]
         if value is None:
-            del target[key]
+            target.pop(key, None)
         elif isinstance(value, dict):
             target[key] = recursive_update(target.get(key, {}), value)
         else:


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 1184c90d7..048f6e46c 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -1360,3 +1360,19 @@ def test_use_source_timestamp(tmpdir, cwd_tmpdir, python_notebook, capsys, forma
             cm.get("test.ipynb")
     else:
         cm.get("test.ipynb")
+
+
+def test_round_trip_with_null_metadata_792(tmpdir, cwd_tmpdir, python_notebook):
+    nb = python_notebook
+    nb.metadata.kernelspec = {
+        "argv": ["python", "-m", "ipykernel_launcher", "-f", "{connection_file}"],
+        "display_name": "Python 3",
+        "env": None,
+        "interrupt_mode": "signal",
+        "language": "python",
+        "metadata": None,
+        "name": "python3",
+    }
+    write(nb, "test.ipynb")
+    jupytext(["--to", "py:percent", "test.ipynb"])
+    jupytext(["--to", "ipynb", "test.py"])