def session(): # Remove previous db if URI != ':memory:' and os.path.exists(URI): os.unlink(URI) with connect(URI, init=True): VersionCube.load(DATA) yield 'session'
def register_app(app): app.register_blueprint(menger_app) # Force a non-readonly query to let table creation proceed with connect(app.config['MENGER_DATABASE'], init=True): pass
def mng(method, ext): get_permission = current_app.config.get('MENGER_FILTER') filters = [] msr_perm = {} if get_permission: perms = get_permission() filters = perms.get('drill', []) msr_perm = perms.get('measure', {}) if method == 'info': spaces = [] for space in iter_spaces(): if space._name in msr_perm: mp = msr_perm[space._name] msr_info = [{ 'name': m.name, 'label': m.label, } for m in space._measures if m.name in mp] else: msr_info = [{ 'name': m.name, 'label': m.label, } for m in space._measures] space_info = { 'name': space._name, 'measures': msr_info, 'dimensions': [{ 'name': d.name, 'label': d.label, 'levels': [l.label for l in d.levels.values()], } for d in space._dimensions], 'label': space._label, } spaces.append(space_info) return json.jsonify(spaces=spaces) query = expand_query(method) spc_name = query.get('space') # Not cached to avoid trashing other queries if method == 'search': with connect(current_app.config['MENGER_DATABASE']): spc = get_space(spc_name) if not spc: return ('space "%s" not found' % spc_name, 404) name = query.get('dimension') if not hasattr(spc, name): return ('space "%s" has not dimension %s' % (spc_name, name), 404) dim = getattr(spc, name) res = list(dim.search(query['value'], int(query['max_depth']))) return json.jsonify(data=res) # Build unique id for query query_string = json.dumps(sorted(query.items())) h = md5(json.dumps(query_string).encode() + ext.encode()) if filters: filters_str = str(sorted(filters)).encode() h.update(filters_str) qid = h.hexdigest() # Return cached value if any cached_value = fs_cache.get(qid) if cached_value is not None: resp = current_app.response_class(mimetype='application/json', ) accept_encoding = request.headers.get('Accept-Encoding', '') if 'gzip' not in accept_encoding.lower(): resp.set_data(gzip.decompress(cached_value)) else: resp.headers['Content-Encoding'] = 'gzip' resp.set_data(cached_value) return resp res = {} if method == 'drill': with connect(current_app.config['MENGER_DATABASE']): spc = get_space(spc_name) if not spc: return ('space "%s" not found' % spc_name, 404) name = query.get('dimension') if not hasattr(spc, name): return ('space "%s" has not dimension %s' % (spc_name, name), 404) dim = getattr(spc, name) value = tuple(query.get('value', [])) data = list(dim.drill(value)) data.extend(dim.aliases(value)) offset = len(value) mk_label = lambda x: dim.format( value + (x, ), fmt_type='txt', offset=offset) res['data'] = [(d, mk_label(d)) for d in data] elif method == 'dice': with connect(current_app.config['MENGER_DATABASE']): # Add user filters to the permission one query_filters = query.get('filters', []) measures = query['measures'] spc_name = measures[0].split('.')[0] spc = get_space(spc_name) for dim_name, filter_val, depth in query_filters: dim = getattr(spc, dim_name) coord = (None, ) * (depth - 1) + (filter_val, ) filters.append((dim_name, list(dim.glob(coord)))) try: res = do_dice(query, filters, ext) except LimitException as e: return json.jsonify(error='Request too big (%s)' % str(e)) if ext == 'xlsx': output_file = build_xlsx(res) attachment_filename = compute_filename( current_app.config.get('MENGER_EXPORT_PATTERN', '%Y-%m%d')) return send_file(output_file, as_attachment=True, attachment_filename=attachment_filename) else: return ('Unknown method "%s"' % method, 404) if ext not in ('json', 'txt'): return 'Unknown extension "%s"' % ext, 404 # Cache result json_res = json.dumps(res) zipped_res = gzip.compress(json_res.encode()) fs_cache.set(qid, zipped_res) # Return response resp = current_app.response_class(mimetype='application/json', ) accept_encoding = request.headers.get('Accept-Encoding', '') if 'gzip' not in accept_encoding.lower(): resp.set_data(json_res) else: resp.headers['Content-Encoding'] = 'gzip' resp.set_data(zipped_res) return resp
'date': [2012, 7, 26], 'author': ['John'], 'words': 148, 'signs': 743 }, { 'date': [2012, 8, 7], 'author': ['John'], 'words': 34, 'signs': 145 }, { 'date': [2012, 8, 9], 'author': ['Bill'], 'words': 523, 'signs': 2622 }, ]) print('Top-level dice') pprint(list(Post.dice())) print('Per Month dice') pprint(list(Post.dice([Post.date['Month'], Post.average]))) print('Date drill') pprint(list(Post.date.drill((2012, 8)))) with connect(':memory:'): run()