Skip to content

Instantly share code, notes, and snippets.

@bgrenet
Created February 2, 2017 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bgrenet/060ad8cdd471f5f0e776688feff837b7 to your computer and use it in GitHub Desktop.
Save bgrenet/060ad8cdd471f5f0e776688feff837b7 to your computer and use it in GitHub Desktop.
(Extremely basic) Python script to create jupyter notebooks from markdown
#! /usr/bin/env python3
############################################################################
# #
# (Extremely basic) Python script to create jupyter notebook from markdown #
# Bruno Grenet, 02.02.2017 #
# License: Public Domain #
# #
############################################################################
# Input format:
# ------------
# Code in fenced blocks (delimited by "```" or "~~~") is put into code cells
# in the notebook. The rest is put in markdown cells. In particular, indented
# code blocks are put into markdown cells.
import re, sys, os, getopt
begincode = """ {
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"""
beginmd = """ {
"cell_type": "markdown",
"metadata": {},
"source": [
"""
endjson = """ ],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"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.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 1
}"""
def process(line):
s = line[:-1]
s = s.replace('\\', '\\\\')
s = s.replace('"', '\\"')
return ' "' + s + '\\n"'
def md2ipynb(inputfile, outputfile):
if not os.path.isfile(inputfile):
print("{} is not a valid input file.".format(inputfile))
return 1
if os.path.exists(outputfile):
if not os.path.isfile(outputfile):
print("{} already exists and is not a file.".format(outputfile))
return 1
answer = input("The file {} already exists. Overwrite? [Y/n] ".format(outputfile))
if answer in ['n', 'N', 'no', 'NO', 'No']:
return 0
f = open(inputfile, 'r')
o = open(outputfile, 'w')
md = False
code = False
first = True
first_of_code = False
width = 0
codex = "^[~`]{3,}"
endblock = '\n ]\n }'
o.write('{\n "cells": [\n')
for line in f:
m = re.search(codex, line)
if m is not None:
w = len(m.group(0))
if code and w >= width:
o.write(endblock)
code = False
elif code:
o.write(',\n')
o.write(process(line))
else:
if md:
o.write(endblock)
o.write(',\n')
md = False
o.write(begincode)
code = True
code_width = w
first_of_code = True
else:
if not (code or md):
if not first:
o.write(',\n')
o.write(beginmd)
md = True
else:
if first_of_code:
first_of_code = False
else:
o.write(',\n')
o.write(process(line))
first = False
if md or code:
o.write(endblock)
md = code = False
o.write(endjson)
f.close()
o.close()
return 0
def main():
usage = "{} [-o outfile|--output=outfile] inputfile".format(sys.argv[0])
try:
opts, args = getopt.getopt(sys.argv[1:], "ho:", ["help", "output="])
except getopt.GetoptError as err:
print(err)
print(usage)
sys.exit(2)
outputfile = ''
for o, a in opts:
if o in ('-h', '--help'):
print(usage)
sys.exit()
elif o in ('-o', '--output'):
outputfile = a
else:
print(usage)
sys.exit(1)
if len(args) != 1:
print(usage)
sys.exit(1)
inputfile = args[0]
if outputfile == '':
outputfile = os.path.splitext(inputfile)[0] + '.ipynb'
ret = md2ipynb(inputfile, outputfile)
if ret == 0:
print("{} converted into {} successfully".format(inputfile, outputfile))
sys.exit()
else:
print("Conversion failed")
sys.exit(1)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment