Completed
Push — master ( de7136...b8e623 )
by Chris
01:25
created

cytoscape()   A

Complexity

Conditions 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
1
"""A separate Flask app that serves fake endpoints for demo purposes."""
2
3
# -*- coding: utf-8 -*-
4
5
import json
6
import locale
7
import os
8
from datetime import timedelta as td
9
from datetime import datetime as dt
10
from random import randrange as rr
11
from random import choice, random
12
import time
13
14
from flask import (
15
    Flask,
16
    abort,
17
    request,
18
    jsonify,
19
    render_template,
20
)
21
from flask_cors import CORS
22
from flask_cors import cross_origin
23
24
app = Flask('endpoints_test')
25
CORS(app)
26
app.config['SECRET_KEY'] = 'NOTSECURELOL'
27
app.debug = True
28
29
STRESS_MAX_POINTS = 300
30
31
locale.setlocale(locale.LC_ALL, '')
32
33
cwd = os.getcwd()
34
35
36
def recursive_d3_data(current=0, max_iters=12, data=None):
37
    """Generate d3js data for stress testing.
38
    Format is suitable in treemap, circlepack and dendrogram testing.
39
    """
40
    if current >= max_iters:
41
        return data
42
    if data is None:
43
        data = dict(name='foo', size=rr(10, 10000), children=[])
44
    data = dict(name='foo', size=rr(10, 10000),
45
                children=[data, data])
46
    return recursive_d3_data(
47
        current=current + 1,
48
        max_iters=max_iters,
49
        data=data)
50
51
52
def dates_list(max_dates=10):
53
    """Generate a timeseries dates list."""
54
    now = dt.now()
55
    return [str(now + td(days=i * 10))[0:10] for i in range(max_dates)]
56
57
58
def rr_list(max_range=10):
59
    """Generate a list of random integers."""
60
    return [rr(0, 100) for i in range(max_range)]
61
62
63
@cross_origin()
64
@app.route('/combination')
65
def combination():
66
    """Fake endpoint."""
67
    data = {
68
        'columns': [
69
            ['data1', 30, 20, 50, 40, 60, 50],
70
            ['data2', 200, 130, 90, 240, 130, 220],
71
            ['data3', 300, 200, 160, 400, 250, 250],
72
            ['data4', 200, 130, 90, 240, 130, 220],
73
            ['data5', 130, 120, 150, 140, 160, 150],
74
            ['data6', 90, 70, 20, 50, 60, 120],
75
        ],
76
        'type': 'bar',
77
        'types': {
78
            'data3': 'spline',
79
            'data4': 'line',
80
            'data6': 'area',
81
        },
82
        'groups': [
83
            ['data1', 'data2'],
84
        ]
85
    }
86
    return jsonify(dict(data=data))
87
88
89
@cross_origin()
90
@app.route('/stacked-bar')
91
def stackedbar():
92
    """Fake endpoint."""
93
    return jsonify({
94
        'data': {
95
            'columns': [
96
                ['data1', -30, 200, 200, 400, -150, 250],
97
                ['data2', 130, 100, -100, 200, -150, 50],
98
                ['data3', -230, 200, 200, -300, 250, 250]
99
            ],
100
            'type': 'bar',
101
            'groups': [
102
                ['data1', 'data2']
103
            ]
104
        },
105
        'grid': {
106
            'y': {
107
                'lines': [{'value': 0}]
108
            }
109
        }
110
    })
111
112
113
@cross_origin()
114
@app.route('/wordcloud')
115
def wordcloud():
116
    """Fake endpoint."""
117
    words = [
118
        'awesome', 'rad', 'neato', 'the', 'flask', 'jsondash', 'graphs',
119
        'charts', 'd3', 'js', 'dashboards', 'c3',
120
    ]
121
    sizes = range(len(words))
122
    return jsonify([
123
        {'text': word, 'size': sizes[i] * 12} for i, word in enumerate(words)
124
    ])
125
126
127
@cross_origin()
128
@app.route('/cytoscape')
129
def cytoscape():
130
    """Fake endpoint.
131
132
    Reads data from a local cytoscape spec, and if there is a
133
    remote url specified, (assuming it exists here), open and load it as well.
134
135
    This returns all required json as a single endpoint.
136
    """
137
    chart_name = request.args.get('name', 'dagre')
138
    filename = '{}/examples/cytoscape/{}.json'.format(cwd, chart_name)
139
    try:
140
        with open(filename, 'r') as chartjson:
141
            return chartjson.read()
142
    except IOError:
143
        pass
144
    return jsonify({})
145
146
147
@cross_origin()
148
@app.route('/vegalite')
149
def vegalite():
150
    """Fake endpoint.
151
152
    Reads data from a local vega spec, and if there is a
153
    remote url specified, (assuming it exists here), open and load it as well.
154
155
    This returns all required json as a single endpoint.
156
    """
157
    chart_type = request.args.get('type', 'bar')
158
    filename = '{}/examples/vegalite/{}.json'.format(cwd, chart_type)
159
    try:
160
        with open(filename, 'r') as chartjson:
161
            chartjson = chartjson.read()
162
            data = json.loads(chartjson)
163
            if data.get('data', {}).get('url') is not None:
164
                datapath = '{}/examples/vegalite/{}'.format(
165
                    cwd, data['data']['url']
166
                )
167
                with open(datapath, 'r') as datafile:
168
                    if datapath.endswith('.json'):
169
                        raw_data = datafile.read()
170
                        raw_data = json.loads(raw_data)
171
                    # TODO: adding csv support for example.
172
                    data.update(data=dict(
173
                        name='some data',
174
                        values=raw_data,
175
                    ))
176
                    return jsonify(data)
177
            else:
178
                return chartjson
179
    except IOError:
180
        pass
181
    return jsonify({})
182
183
184
@cross_origin()
185
@app.route('/plotly')
186
def plotly():
187
    """Fake endpoint."""
188
    chart_type = request.args.get('chart', 'line')
189
    filename = '{}/examples/plotly/{}.json'.format(cwd, chart_type)
190
    with open(filename, 'r') as chartjson:
191
        return chartjson.read()
192
    return jsonify({})
193
194
195
@cross_origin
196
@app.route('/plotly-dynamic')
197
def plotly_dynamic():
198
    """Fake endpoint."""
199
    filename = '{}/examples/plotly/bar_line_dynamic.json'.format(cwd)
200
    with open(filename, 'r') as chartjson:
201
        return chartjson.read()
202
    return jsonify({})
203
204
205
@cross_origin()
206
@app.route('/timeline')
207
def timeline():
208
    """Fake endpoint."""
209
    with open('{}/examples/timeline3.json'.format(cwd), 'r') as timelinejson:
210
        return timelinejson.read()
211
    return jsonify({})
212
213
214
@app.route('/dtable', methods=['GET'])
215
def dtable():
216
    """Fake endpoint."""
217
    if 'stress' in request.args:
218
        return jsonify([
219
            dict(
220
                foo=rr(1, 1000),
221
                bar=rr(1, 1000),
222
                baz=rr(1, 1000),
223
                quux=rr(1, 1000)) for _ in range(STRESS_MAX_POINTS)
224
        ])
225
    fname = 'dtable-override' if 'override' in request.args else 'dtable'
226
    with open('{}/examples/{}.json'.format(os.getcwd(), fname), 'r') as djson:
227
        return djson.read()
228
    return jsonify({})
229
230
231
@cross_origin()
232
@app.route('/timeseries')
233
def timeseries():
234
    """Fake endpoint."""
235
    return jsonify({
236
        "dates": dates_list(),
237
        "line1": rr_list(max_range=10),
238
        "line2": rr_list(max_range=10),
239
        "line3": rr_list(max_range=10),
240
    })
241
242
243
@cross_origin()
244
@app.route('/custom')
245
def custompage():
246
    """Fake endpoint."""
247
    kwargs = dict(number=rr(1, 1000))
248
    return render_template('examples/custom.html', **kwargs)
249
250
251
@cross_origin()
252
@app.route('/gauge')
253
def gauge():
254
    """Fake endpoint."""
255
    return jsonify({'data': rr(1, 100)})
256
257
258
@cross_origin()
259
@app.route('/area-custom')
260
def area_custom():
261
    """Fake endpoint."""
262
    return jsonify({
263
        "data": {
264
            "columns": [
265
                ["data1", 300, 350, 300, 0, 0, 0],
266
                ["data2", 130, 100, 140, 200, 150, 50]
267
            ],
268
            "types": {
269
                "data1": "area",
270
                "data2": "area-spline"
271
            }
272
        }
273
    })
274
275
276
@cross_origin()
277
@app.route('/scatter')
278
def scatter():
279
    """Fake endpoint."""
280
    if 'override' in request.args:
281
        with open('{}/examples/overrides.json'.format(cwd), 'r') as jsonfile:
282
            return jsonfile.read()
283
    return jsonify({
284
        "bar1": [1, 2, 30, 12, 100],
285
        "bar2": rr_list(max_range=40),
286
        "bar3": rr_list(max_range=40),
287
        "bar4": [-10, 1, 5, 4, 10, 20],
288
    })
289
290
291
@cross_origin()
292
@app.route('/pie')
293
def pie():
294
    """Fake endpoint."""
295
    letters = list('abcde')
296
    if 'stress' in request.args:
297
        letters = range(STRESS_MAX_POINTS)
298
    return jsonify({'data {}'.format(name): rr(1, 100) for name in letters})
299
300
301
@cross_origin()
302
@app.route('/custom-inputs')
303
def custom_inputs():
304
    """Fake endpoint."""
305
    _range = int(request.args.get('range', 5))
306
    entries = int(request.args.get('entries', 3))
307
    starting = int(request.args.get('starting_num', 0))
308
    prefix = request.args.get('prefix', 'item')
309
    if 'override' in request.args:
310
        show_axes = request.args.get('show_axes', False)
311
        show_axes = show_axes == 'on'
312
        data = dict(
313
            data=dict(
314
                columns=[
315
                    ['{} {}'.format(prefix, i)] + rr_list(max_range=entries)
316
                    for i in range(starting, _range)
317
                ],
318
            )
319
        )
320
        if show_axes:
321
            data.update(axis=dict(
322
                x=dict(label='This is the X axis'),
323
                y=dict(label='This is the Y axis')))
324
        return jsonify(data)
325
    return jsonify({
326
        i: rr_list(max_range=_range) for i in range(starting, entries)
327
    })
328
329
330
@cross_origin()
331
@app.route('/bar')
332
def barchart():
333
    """Fake endpoint."""
334
    if 'stress' in request.args:
335
        return jsonify({
336
            'bar-{}'.format(k): rr_list(max_range=STRESS_MAX_POINTS)
337
            for k in range(STRESS_MAX_POINTS)
338
        })
339
    return jsonify({
340
        "bar1": [1, 2, 30, 12, 100],
341
        "bar2": rr_list(max_range=5),
342
        "bar3": rr_list(max_range=5),
343
    })
344
345
346
@cross_origin()
347
@app.route('/line')
348
def linechart():
349
    """Fake endpoint."""
350
    if 'stress' in request.args:
351
        return jsonify({
352
            'bar-{}'.format(k): rr_list(max_range=STRESS_MAX_POINTS)
353
            for k in range(STRESS_MAX_POINTS)
354
        })
355
    return jsonify({
356
        "line1": [1, 4, 3, 10, 12, 14, 18, 10],
357
        "line2": [1, 2, 10, 20, 30, 6, 10, 12, 18, 2],
358
        "line3": rr_list(),
359
    })
360
361
362
@cross_origin()
363
@app.route('/singlenum')
364
def singlenum():
365
    """Fake endpoint."""
366
    _min, _max = 10, 10000
367
    if 'sales' in request.args:
368
        val = locale.currency(float(rr(_min, _max)), grouping=True)
369
    else:
370
        val = rr(_min, _max)
371
    if 'negative' in request.args:
372
        val = '-{}'.format(val)
373
    return jsonify(val)
374
375
376
@cross_origin()
377
@app.route('/deadend')
378
def test_die():
379
    """Fake endpoint that ends in a random 50x error."""
380
    # Simulate slow connection
381
    sleep = request.args.get('sleep', True)
382
    if sleep != '':
383
        sleep_for = request.args.get('sleep_for')
384
        time.sleep(int(sleep_for) if sleep_for is not None else random())
385
    err_code = request.args.get('error_code')
386
    rand_err = choice([500, 501, 502, 503, 504])
387
    abort(int(err_code) if err_code is not None else rand_err)
388
389
390
@cross_origin()
391
@app.route('/venn')
392
def test_venn():
393
    """Fake endpoint."""
394
    data = [
395
        {'sets': ['A'], 'size': rr(10, 100)},
396
        {'sets': ['B'], 'size': rr(10, 100)},
397
        {'sets': ['C'], 'size': rr(10, 100)},
398
        {'sets': ['A', 'B'], 'size': rr(10, 100)},
399
        {'sets': ['A', 'B', 'C'], 'size': rr(10, 100)},
400
    ]
401
    return jsonify(data)
402
403
404
@cross_origin()
405
@app.route('/sparklines', methods=['GET'])
406
def sparklines():
407
    """Fake endpoint."""
408
    if any([
409
        'pie' in request.args,
410
        'discrete' in request.args,
411
    ]):
412
        return jsonify([rr(1, 100) for _ in range(10)])
413
    return jsonify([[i, rr(i, 100)] for i in range(10)])
414
415
416
@cross_origin()
417
@app.route('/circlepack', methods=['GET'])
418
def circlepack():
419
    """Fake endpoint."""
420
    if 'stress' in request.args:
421
        # Build a very large dataset
422
        return jsonify(recursive_d3_data())
423
    with open('{}/examples/flare.json'.format(cwd), 'r') as djson:
424
        return djson.read()
425
    return jsonify({})
426
427
428
@cross_origin()
429
@app.route('/treemap', methods=['GET'])
430
def treemap():
431
    """Fake endpoint."""
432
    if 'stress' in request.args:
433
        # Build a very large dataset
434
        return jsonify(recursive_d3_data())
435
    with open('{}/examples/flare.json'.format(cwd), 'r') as djson:
436
        return djson.read()
437
    return jsonify({})
438
439
440
@cross_origin()
441
@app.route('/map', methods=['GET'])
442
def datamap():
443
    """Fake endpoint."""
444
    return render_template('examples/map.html')
445
446
447
@cross_origin()
448
@app.route('/dendrogram', methods=['GET'])
449
def dendro():
450
    """Fake endpoint."""
451
    if 'stress' in request.args:
452
        # Build a very large dataset
453
        return jsonify(recursive_d3_data())
454
    filename = 'flare-simple' if 'simple' in request.args else 'flare'
455
    with open('{}/examples/{}.json'.format(cwd, filename), 'r') as djson:
456
        return djson.read()
457
    return jsonify({})
458
459
460
@cross_origin()
461
@app.route('/voronoi', methods=['GET'])
462
def voronoi():
463
    """Fake endpoint."""
464
    w, h = request.args.get('width', 800), request.args.get('height', 800)
465
    max_points = int(request.args.get('points', 100))
466
    if 'stress' in request.args:
467
        max_points = 500
468
    return jsonify([[rr(1, h), rr(1, w)] for _ in range(max_points)])
469
470
471
@cross_origin()
472
@app.route('/digraph', methods=['GET'])
473
def graphdata():
474
    """Fake endpoint."""
475
    if 'filetree' in request.args:
476
        with open('{}/examples/filetree_digraph.dot'.format(cwd), 'r') as dot:
477
            return jsonify(dict(graph=dot.read()))
478
    if 'simple' in request.args:
479
        graphdata = """
480
        digraph {
481
            a -> b;
482
            a -> c;
483
            b -> c;
484
            b -> a;
485
            b -> b;
486
        }
487
        """
488
        return jsonify(dict(graph=graphdata))
489
    nodes = list('abcdefghijkl')
490
    node_data = '\n'.join([
491
        '{0} -> {1};'.format(choice(nodes), choice(nodes))
492
        for _ in range(10)
493
    ])
494
    graphdata = """digraph {lb} {nodes} {rb}""".format(
495
        lb='{', rb='}', nodes=node_data)
496
    return jsonify(dict(
497
        graph=graphdata,
498
    ))
499
500
501
if __name__ == '__main__':
502
    PORT = int(os.getenv('PORT', 5004))
503
    HOST = os.getenv('HOST', '0.0.0.0')
504
    app.run(debug=True, host=HOST, port=PORT)
505