Jupyter SN roundtrip

Jupyter is a great but mostly write once experience, since I tend to figure out an idea and then copy it into a knowledge base. On top of that, I have a ton of code stuff that I'd like to publish just to get it out there. Can we set up roundtrips between Jupyter & Standard Notes?

PS. so this note was a pain to put together: getting markdown-syntax into notes where there's some backtick delimited code blocks, tends to break. and then publishing to listed didn't work so well; probably the best approach is for a note to start in Jupyter, convert to SN-ish Markdown, copy into a plain text note, then convert to SN's SuperNote then continue working on the text around the code?

options

  • pandoc (not tested here)
  • jupytext
  • jupyter nbconvert
  • custom convert?

jupytext https://jupytext.readthedocs.io/en/latest/

the "best practice" tool,

$ jupytext --to markdown Untitled.ipynb
$ cat Untitled.md | grep -v '^$'

which generates

---
jupyter:
  jupytext:
    text_representation:
      extension: .md
      format_name: markdown
      format_version: '1.3'
      jupytext_version: 1.16.4
  kernelspec:
    display_name: Python 3 (ipykernel)
    language: python
    name: python3
---
This is a quick test notebook!
## md h2
with some code

import antigravity

but now let's run that:
```python
import antigravity
import numpy as np
np.r_[:42]+1j
for i in range(3):
    %timeit -n2 -r2 10**i
42,

conclusion

that's all for now! bye


but this doesn't include the stream output which I definitely want.

## `jupyter nbconvert`

this is the classic tool, useful to grep out the empty lines,

```javascript
$ jupyter nbconvert --to markdown Untitled.ipynb
$ cat Untitled.md | grep -v '^$'

which generates

This is a quick test notebook!
## md h2
with some code

import antigravity

```python
import antigravity

gio: https://xkcd.com/353/: Operation not supported

import numpy as np
np.r_[:42]+1j

array([ 0.+1.j, 1.+1.j, 2.+1.j, 3.+1.j, 4.+1.j, 5.+1.j, 6.+1.j,
7.+1.j, 8.+1.j, 9.+1.j, 10.+1.j, 11.+1.j, 12.+1.j, 13.+1.j,
14.+1.j, 15.+1.j, 16.+1.j, 17.+1.j, 18.+1.j, 19.+1.j, 20.+1.j,
21.+1.j, 22.+1.j, 23.+1.j, 24.+1.j, 25.+1.j, 26.+1.j, 27.+1.j,
28.+1.j, 29.+1.j, 30.+1.j, 31.+1.j, 32.+1.j, 33.+1.j, 34.+1.j,
35.+1.j, 36.+1.j, 37.+1.j, 38.+1.j, 39.+1.j, 40.+1.j, 41.+1.j])

for i in range(3):
    %timeit -n2 -r2 10**i

402 ns ± 234 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
303 ns ± 143 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
243 ns ± 91.5 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)

conclusion

that's all for now! bye


but I'd like to have the output quoted to keep it visually distinct

## custom renderer?

sounds fancy, buckle up!

```python
import json
with open('Untitled.ipynb', 'r') as fd:
    nb = json.load(fd)

def println(line):
    print(line, end='' if line.endswith('\n') else '\n')

for cell in nb['cells']:
    if cell['cell_type'] == 'markdown':
        for line in cell['source']:
            if line.strip():
                println(line)
    else:
        # print(cell)
        print('```python')
        print(''.join(cell['source']))
        print('```')
        for o in cell['outputs']:
            if o['output_type'] == 'stream':
                for line in o['text']:
                    println(f'> {line}')
            elif o['output_type'] == 'execute_result':
                for line in o['data']['text/plain']:
                    println(f'> {line}')

which generates

This is a quick test notebook!
## md h2
with some code

import antigravity

but now let's run that:
```python
import antigravity

gio: https://xkcd.com/353/: Operation not supported

import numpy as np

np.r_[:42]+1j

> array([ 0.+1.j,  1.+1.j,  2.+1.j,  3.+1.j,  4.+1.j,  5.+1.j,  6.+1.j,
>         7.+1.j,  8.+1.j,  9.+1.j, 10.+1.j, 11.+1.j, 12.+1.j, 13.+1.j,
>        14.+1.j, 15.+1.j, 16.+1.j, 17.+1.j, 18.+1.j, 19.+1.j, 20.+1.j,
>        21.+1.j, 22.+1.j, 23.+1.j, 24.+1.j, 25.+1.j, 26.+1.j, 27.+1.j,
>        28.+1.j, 29.+1.j, 30.+1.j, 31.+1.j, 32.+1.j, 33.+1.j, 34.+1.j,
>        35.+1.j, 36.+1.j, 37.+1.j, 38.+1.j, 39.+1.j, 40.+1.j, 41.+1.j])
```python
for i in range(3):
    %timeit -n2 -r2 10**i
42,

394 ns ± 181 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
382 ns ± 198 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
The slowest run took 5.20 times longer than the fastest. This could mean that an intermediate result is being cached.
826 ns ± 559 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
(42,)

conclusion

that's all for now! bye

rendered version

So SN's version of Markdown isn't exactly like everyone elses ¯_(ツ)_/¯

This is a quick test notebook!

md h2

with some code

import antigravity

but now let’s run that:

import antigravity

gio: https://xkcd.com/353/: Operation not supported

import numpy as np

np.r_[:42]+1j

array([ 0.+1.j, 1.+1.j, 2.+1.j, 3.+1.j, 4.+1.j, 5.+1.j, 6.+1.j,
7.+1.j, 8.+1.j, 9.+1.j, 10.+1.j, 11.+1.j, 12.+1.j, 13.+1.j,
14.+1.j, 15.+1.j, 16.+1.j, 17.+1.j, 18.+1.j, 19.+1.j, 20.+1.j,
21.+1.j, 22.+1.j, 23.+1.j, 24.+1.j, 25.+1.j, 26.+1.j, 27.+1.j,
28.+1.j, 29.+1.j, 30.+1.j, 31.+1.j, 32.+1.j, 33.+1.j, 34.+1.j,
35.+1.j, 36.+1.j, 37.+1.j, 38.+1.j, 39.+1.j, 40.+1.j, 41.+1.j])

for i in range(3):
    %timeit -n2 -r2 10**i
42,

394 ns ± 181 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
382 ns ± 198 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
The slowest run took 5.20 times longer than the fastest. This could mean that an intermediate result is being cached.
826 ns ± 559 ns per loop (mean ± std. dev. of 2 runs, 2 loops each)
(42,)

conclusion

that’s all for now! bye


You'll only receive email when they publish something new.

More from marmaduke
All posts