-
-
Notifications
You must be signed in to change notification settings - Fork 71
/
Copy pathutils.py
88 lines (71 loc) · 2.51 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"""
Utility functions for dealing with manipulating notebooks.
Try to not put too many things here, nor to re-implement nbformat.
"""
import ast
PREAMBLE=\
"""
##############################################################################
# This source has been auto generated from an IPython/Jupyter notebook file. #
# Please modify the origin file #
##############################################################################
"""
ALLOWED_NODES = set([
ast.ClassDef,
ast.FunctionDef,
ast.Import,
ast.ImportFrom
])
def validate_nb(nb):
"""
Validate that given notebook JSON is importable
- Check for nbformat == 4
- Check that language is python
Do not re-implement nbformat here :D
"""
if nb['nbformat'] != 4:
return False
language_name = (nb.get('metadata', {})
.get('kernelspec', {})
.get('language', '').lower())
return language_name == 'python'
def filter_ast(module_ast):
"""
Filters a given module ast, removing non-whitelisted nodes
It allows only the following top level items:
- imports
- function definitions
- class definitions
- top level assignments where all the targets on the LHS are all caps
"""
def node_predicate(node):
"""
Return true if given node is whitelisted
"""
for an in ALLOWED_NODES:
if isinstance(node, an):
return True
# Recurse through Assign node LHS targets when an id is not specified,
# otherwise check that the id is uppercase
if isinstance(node, ast.Assign):
return all([node_predicate(t) for t in node.targets if not hasattr(t, 'id')]) \
and all([t.id.isupper() for t in node.targets if hasattr(t, 'id')])
return False
module_ast.body = [n for n in module_ast.body if node_predicate(n)]
return module_ast
def code_from_ipynb(nb, markdown=False):
"""
Get the code for a given notebook
nb is passed in as a dictionary that's a parsed ipynb file
"""
code = PREAMBLE
for cell in nb['cells']:
if cell['cell_type'] == 'code':
# transform the input to executable Python
code += ''.join(cell['source'])
if cell['cell_type'] == 'markdown':
code += '\n# ' + '# '.join(cell['source'])
# We want a blank newline after each cell's output.
# And the last line of source doesn't have a newline usually.
code += '\n\n'
return code