forked from sagemathinc/cocalc-snippets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
read_boilerplate.coffee
401 lines (352 loc) · 14.8 KB
/
read_boilerplate.coffee
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
#!/usr/bin/env coffee
# read the .js files
# for now, we only do this for the physical constants
fs = require('fs')
define = (x) -> x
header = ->
'''
# CoCalc Examples Documentation File
# Copyright: CoCalc Authors, 2018
# This is derived content from the BSD licensed https://github.com/moble/jupyter_boilerplate/
# # # # # # # # # # # # # # # # # # # # # # # # # # #
# THIS FILE IS AUTOGENERATED -- DO NOT EDIT BY HAND #
# # # # # # # # # # # # # # # # # # # # # # # # # # #
---
language: python
''' + '\n'
###
this is the main function doing the conversion. it assumes the .js datastructures are read in
by evaluating the string. it might be necessary to redefine "define" (from the one above)
* entry: the root of a tree of entries. read_submenu might be call recursively (only once), too!
* cat0: the main category name (kept upon recursive calls)
* name_prefix: that's the second level, and cat1 upon recursion. see the computation of "subcat"
* cat_prefix: that's named a bit wrong, because this is the additional setup code for a subcategory
* cat_process: function (by default idempotent) for processing the category name (mainly used to make the words shorter)
* sortweight: some categories should be at the top, e.g. related to introduction, etc. just use (-1 to push them at the top, default 0)
* variables: dictionary of variable defaults, which are added like "setup". they're dynamically inserted by the UI component. for testing, just add them to the setup. Care needs to be taken to use language specific syntax (usually, "key = value", though)
* testing: false if it shouldn't be tested
###
read_submenu = (entry, cat0, name_prefix, cat_prefix, cat_process, sortweight, variables, testing) ->
cat_process ?= (x) -> x
if name_prefix?
prefix = "#{name_prefix}"
else
prefix = ''
submenu = entry['sub-menu']
cat1 = cat_process(entry['name'])
output = []
if cat1 == 'Example'
return output
output.push('---')
subcat = (x for x in [prefix, cat1] when x?.length > 0).join(' / ')
output.push("category: ['#{cat0}', '#{subcat}']")
sw = sortweight?(entry['name'])
if sw
output.push("sortweight: #{sw}")
if cat_prefix?
# JSON.stringify to sanitize linebreaks
output.push("setup: #{JSON.stringify(cat_prefix)}")
if variables?
output.push("variables: #{JSON.stringify(variables)}")
for entry in entry['sub-menu']
# there are weird "---"
if typeof entry == 'string'
continue
# oh yes, sub entries can have subentries ... just skipping them via recursion.
if entry['sub-menu']?
output = output.concat(read_submenu(entry, cat0, cat1, cat_prefix, cat_process, sortweight, variables))
else
continue if not entry.snippet? # there are entries where it is only entry["external-link"]
continue if entry.snippet.join('').trim().length == 0 # ... or some are just empty
output.push('---')
#console.log(JSON.stringify(entry))
output.push("title: |\n #{entry.name}")
#console.log(JSON.stringify(entry))
code = (" #{x}" for x in entry.snippet).join('\n')
output.push("code: |\n#{code}")
if testing == false
output.push("test: false")
return output
# This is specific to scipy special functions file
read_scipy_special = ->
special_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/scipy_special.js', 'utf8')
constants = eval(special_js)
output = []
cat_prefix = '''
from scipy import special, integrate, optimize, interpolate
from scipy.integrate import odeint
'''
variables =
n : 2
v : 1.5
x : 1.5
z : 0.5
alpha : 0.5
beta : 0.5
nt : 5
cat_process = (x) ->
if x.indexOf('Bessel Functions') >= 0
return x.replace('Bessel Functions', 'Bessel').trim()
if x.indexOf('Statistical Functions (see also scipy.stats)') >= 0
return x.replace('Statistical Functions (see also scipy.stats)', 'Statistics').trim()
return x
for entry in constants['sub-menu']
if entry['sub-menu']?
name = cat_process(entry['name'])
if name == 'Statistics'
vars = Object.assign({}, variables,
a : 0
b : 1
k : 1
p : .75
df : 0
dfn : 1
dfd : 0.5
x : .66
std : 3
t : 1
nc : 2
f : 0.7
y : 0.45
)
else if name in ['Mathieu and Related Functions', 'Spheroidal Wave Functions']
vars = Object.assign({}, variables,
m : 1
q : 2
x : 3
c : 1.1
n : 1
cv : 2
)
else if name in ['Other Special Functions']
vars = Object.assign({}, variables,
n : 4
k : 2
z : 1.1
)
else if name in ['Gamma and Related Functions']
vars = Object.assign({}, variables,
a : 2.5
y : 0.45
)
else if name in ['Information Theory Functions']
vars = Object.assign({}, variables,
x : [-1, 2, 3]
y : [1, 0, 1.1]
delta : 0.4
)
else if name in ['Elliptic Functions']
vars = Object.assign({}, variables,
m : 1
p : .5
phi : .45
)
else if name in ['Combinatorics']
vars = Object.assign({}, variables,
N : 5
)
else if name in ['Hypergeometric Functions']
vars = Object.assign({}, variables,
a : 1
b : 2
)
else
vars = variables
output = output.concat(read_submenu(entry, 'SciPy / Special Func', null, cat_prefix, cat_process, undefined, vars))
content = header()
content += output.join('\n')
fs.writeFileSync('src/python/scipy_special.yaml', content, 'utf8')
# This is specific to matplotlib file
read_matplotlib = ->
matplotlib_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/matplotlib.js', 'utf8')
constants = eval(matplotlib_js)
output = []
cat_prefix = '''
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
'''
for entry in constants['sub-menu']
if entry['sub-menu']?
output = output.concat(read_submenu(entry, 'Visualization', 'Matplotlib', cat_prefix, null))
content = header()
content += output.join('\n')
fs.writeFileSync('src/python/matplotlib_boilerplate.yaml', content, 'utf8')
# This is specific to the constants file, prints out yaml to stdout
read_constants = ->
constants_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/scipy_constants.js', 'utf8')
constants = eval(constants_js)
output = []
cat_prefix = 'from scipy import constants'
cat_process = (cat) ->
return cat
.replace('Common physical constants', 'Physical')
.replace('CODATA physical constants', 'CODATA')
.trim()
sortweight = (cat) ->
if cat in ['Mathematical constants', 'Common physical constants']
return -1
return null
for entry in constants['sub-menu']
if entry['sub-menu']?
output = output.concat(read_submenu(entry, 'SciPy / Constants', null, cat_prefix, cat_process, sortweight))
content = header()
content += output.join('\n')
fs.writeFileSync('src/python/constants.yaml', content, 'utf8')
# Importing regex is disabled. The examples aren't really helpful.
# There is still the "python/python_regex.yaml" file with some examples, though...
## This is specific to the constants file, prints out yaml to stdout
#read_python_regex = ->
# pyregex_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/python_regex.js', 'utf8')
# pyregex = eval(pyregex_js)
# output = []
# cat_prefix = 'import re'
#
# for entry in pyregex['sub-menu']
# if entry['sub-menu']?
# output = output.concat(read_submenu(entry, 'Regular Expressions', null, cat_prefix))
#
# content = header()
# content += output.join('\n')
#
# fs.writeFileSync('src/python/python_regex.yaml', content, 'utf8')
read_numpy = ->
numpy_ufuncs_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/numpy_ufuncs.js', 'utf8')
numpy_ufuncs = eval(numpy_ufuncs_js)
numpy_polynomial_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/numpy_polynomial.js', 'utf8')
numpy_polynomial = eval(numpy_polynomial_js)
# redefine define -- in particular, assumptions and functions is defined now
orig_define = define
try
define = (a, b) ->
return b(null, numpy_ufuncs, numpy_polynomial)
numpy_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/numpy.js', 'utf8')
numpy = eval(numpy_js)
finally
define = orig_define
output = []
make_prefix = (group) ->
switch group
when 'Polynomials'
'''
import numpy as np
from numpy.polynomial import Polynomial as P
poly = P([1, 2, 3])
'''
when 'Pretty printing'
'''
import numpy as np
import contextlib
@contextlib.contextmanager
def printoptions(*args, **kwargs):
original = np.get_printoptions()
np.set_printoptions(*args, **kwargs)
yield
np.set_printoptions(**original)
'''
else '''
import numpy as np
'''
variables =
n : 2
a : 'np.array([3, 4, -1, 9.81])'
b : 'np.array([0, -1, 2, -3])'
a_min : 'np.array([-1, -1, 0, 0])'
a_max : 'np.array([1, 1, 5, 10])'
old_array : 'np.array([3, 4, -1, 9.81])'
axis1 : 0
axis2 : 1
x : 'np.array([ 0, 1, 4.4, -9])'
x1 : 'np.array([0.1, 1, 2.2, 3.5])'
x2 : 'np.array([ -4, 3, 0.2, 1.5])'
cat_process = (x) ->
if x == 'NumPy'
return null
if x.indexOf('Vectorized (universal) functions') >= 0
return x.replace('Vectorized (universal) functions', 'UFuncs').trim()
if x.indexOf('Indexing and testing arrays') >= 0
return x.replace('Indexing and testing arrays', 'Indexing').trim()
return x.trim()
for entry in numpy['sub-menu']
if entry['sub-menu']?
#console.log("read_numpy: '#{entry['name']}"', entry)
cat_prefix = make_prefix(entry['name'])
testing = undefined
if entry['name'] == 'File I/O'
testing = false
output = output.concat(read_submenu(entry, 'NumPy', null, cat_prefix, cat_process, undefined, variables, testing))
content = header()
content += output.join('\n')
fs.writeFileSync('src/python/numpy_boilerplate.yaml', content, 'utf8')
read_sympy = ->
assumptions_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/sympy_assumptions.js', 'utf8')
sympy_assumptions = eval(assumptions_js)
functions_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/sympy_functions.js', 'utf8')
sympy_functions = eval(functions_js)
# redefine define -- in particular, assumptions and functions is defined now
orig_define = define
try
define = (a, b) ->
return b(null, sympy_functions, sympy_assumptions)
sympy_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/sympy.js', 'utf8')
sympy = eval(sympy_js)
finally
define = orig_define
output = []
cat_prefix = '''
from sympy import *
from sympy.abc import a, b, s, t, u, v, w, x, y, z
k, m, n = symbols("k, m, n", integer=True)
f, g, h = symbols("f, g, h", cls=Function)
'''
variables =
d: 3
cat_process = (x) ->
if x == 'Sympy'
return null
return x
for entry in sympy['sub-menu']
if entry['sub-menu']?
output = output.concat(read_submenu(entry, 'Sympy', null, cat_prefix, cat_process, undefined, variables))
content = header()
content += output.join('\n')
fs.writeFileSync('src/python/sympy_boilerplate.yaml', content, 'utf8')
read_scipy = ->
orig_define = define
try
define = (a, b) ->
return b(null, {}, {})
scipy_js = fs.readFileSync('tmp/jupyter_boilerplate/snippets_submenus_python/scipy.js', 'utf8')
scipy = eval(scipy_js)
finally
define = orig_define
output = []
cat_prefix = '''
import numpy as np
import scipy
from scipy import integrate, optimize, interpolate
'''
cat_process = (x) ->
if x == 'SciPy'
return null
if x.indexOf('Interpolation and smoothing splines') >= 0
return x.replace('Interpolation and smoothing splines', 'Interpolation').trim()
if x.indexOf('Optimization and root-finding routines') >= 0
return x.replace('Optimization and root-finding routines', 'Optimization').trim()
return x
for entry in scipy['sub-menu']
if entry['sub-menu']?
output = output.concat(read_submenu(entry, 'SciPy', null, cat_prefix, cat_process))
content = header()
content += output.join('\n')
fs.writeFileSync('src/python/scipy_boilerplate.yaml', content, 'utf8')
main = ->
read_constants()
read_scipy_special()
read_matplotlib()
#read_python_regex()
# sympy and numpy redefined "define", hence they must come last!
read_numpy()
read_sympy()
read_scipy()
main()