def test_delta_none_end(self): end = datetime.datetime.utcnow() - datetime.timedelta(seconds=600) end = datetime.datetime.timestamp(end) start, end, delta = assemble_timerange(None, end, 5) eq_(1325375395.0, start) eq_(1325375400.0, end) eq_(5, delta)
def test_delta_none_end(self): end = datetime.datetime.now() - datetime.timedelta(seconds=600) end = time.mktime(end.timetuple()) start, end, delta = assemble_timerange(None, end, 5) eq_(1325375395.0, start) eq_(1325375400.0, end) eq_(5, delta)
def test_none_none_end(self): end = datetime.datetime.now() - datetime.timedelta(seconds=600) end = time.mktime(end.timetuple()) start, end, delta = assemble_timerange(None, end, None) eq_(1325374800.0, start) eq_(1325375400.0, end) eq_(600, delta)
def test_delta_start_none(self): start = datetime.datetime.now() - datetime.timedelta(seconds=600) start = time.mktime(start.timetuple()) start, end, delta = assemble_timerange(start, None, 5) eq_(1325375400.0, start) eq_(1325375405.0, end) eq_(5, delta)
def test_none_start_none(self): start = datetime.datetime.now() - datetime.timedelta(seconds=700) start = time.mktime(start.timetuple()) start, end, delta = assemble_timerange(start, None, None) eq_(1325375300.0, start) eq_(1325376000.0, end) eq_(700, delta)
def test_delta_start_none(self): start = datetime.datetime.utcnow() - datetime.timedelta(seconds=600) start = datetime.datetime.timestamp(start) start, end, delta = assemble_timerange(start, None, 5) eq_(1325375400.0, start) eq_(1325375405.0, end) eq_(5, delta)
def test_none_start_none(self): start = datetime.datetime.utcnow() - datetime.timedelta(seconds=700) start = datetime.datetime.timestamp(start) start, end, delta = assemble_timerange(start, None, None) eq_(1325375300.0, start) eq_(1325376000.0, end) eq_(700, delta)
def test_delta_start_end(self): end = datetime.datetime.utcnow() - datetime.timedelta(seconds=600) end = datetime.datetime.timestamp(end) start = datetime.datetime.utcnow() - datetime.timedelta(seconds=800) start = datetime.datetime.timestamp(start) start, end, delta = assemble_timerange(start, end, 5) eq_(1325375200.0, start) eq_(1325375400.0, end) eq_(200, delta)
def test_delta_start_end(self): end = datetime.datetime.now() - datetime.timedelta(seconds=600) end = time.mktime(end.timetuple()) start = datetime.datetime.now() - datetime.timedelta(seconds=800) start = time.mktime(start.timetuple()) start, end, delta = assemble_timerange(start, end, 5) eq_(1325375200.0, start) eq_(1325375400.0, end) eq_(200, delta)
def from_request_args(cls, request_args): obj = cls() opts = dict() for arg in OPTIONS: opts[arg] = request_args.get(arg, None) for arg in LIST_OPTIONS: opts[arg] = request_args.getlist(arg) opts['start'], opts['end'], opts['delta'] = \ assemble_timerange(opts['start'], opts['end'], opts['delta']) obj.options = opts return obj
def raw(): """ Main API entry point. """ # Perform our complicated datetime logic start = flask.request.args.get('start', None) end = flask.request.args.get('end', None) delta = flask.request.args.get('delta', None) start, end, delta = assemble_timerange(start, end, delta) # Further filters, all ANDed together in CNF style. users = flask.request.args.getlist('user') packages = flask.request.args.getlist('package') categories = flask.request.args.getlist('category') topics = flask.request.args.getlist('topic') # Paging arguments page = int(flask.request.args.get('page', 1)) rows_per_page = int(flask.request.args.get('rows_per_page', 20)) order = flask.request.args.get('order', 'asc') # Response formatting arguments callback = flask.request.args.get('callback', None) meta = flask.request.args.getlist('meta') arguments = dict( start=start, delta=delta, end=end, users=users, packages=packages, categories=categories, topics=topics, page=page, rows_per_page=rows_per_page, order=order, meta=meta, ) if page < 1: raise ValueError("page must be > 0") if rows_per_page > 100: raise ValueError("rows_per_page must be <= 100") if order not in ['desc', 'asc']: raise ValueError("order must be either 'desc' or 'asc'") meta_expected = set(['title', 'subtitle', 'icon', 'secondary_icon', 'link', 'usernames', 'packages', 'objects']) if len(set(meta).intersection(meta_expected)) != len(set(meta)): raise ValueError("meta must be in %s" % ','.join(list(meta_expected))) try: # This fancy classmethod does all of our search for us. total, pages, messages = dm.Message.grep( start=start and datetime.fromtimestamp(start), end=end and datetime.fromtimestamp(end), page=page, rows_per_page=rows_per_page, order=order, users=users, packages=packages, categories=categories, topics=topics, ) # Convert our messages from sqlalchemy objects to json-like dicts messages = [msg.__json__() for msg in messages] if meta: for message in messages: metas = {} for metadata in meta: cmd = 'msg2%s' % metadata metas[metadata] = getattr( fedmsg.meta, cmd)(message, **fedmsg_config) # We have to do this because 'set' is not # JSON-serializable. In the next version of fedmsg, this # will be handled automatically and we can just remove this # statement https://github.com/fedora-infra/fedmsg/pull/139 if isinstance(metas[metadata], set): metas[metadata] = list(metas[metadata]) message['meta'] = metas output = dict( raw_messages=messages, total=total, pages=pages, count=len(messages), arguments=arguments, ) status = 200 except Exception as e: output = dict( error=str(e), arguments=arguments, ) # :D if app.config.get('DEBUG', False): output['tb'] = traceback.format_exc().split('\n') status = 500 body = fedmsg.encoding.dumps(output) mimetype = 'application/json' if callback: mimetype = 'application/javascript' body = "%s(%s);" % (callback, body) return flask.Response( response=body, status=status, mimetype=mimetype, )
def raw(): """ Main API entry point. """ # Perform our complicated datetime logic start = flask.request.args.get('start', None) end = flask.request.args.get('end', None) delta = flask.request.args.get('delta', None) start, end, delta = assemble_timerange(start, end, delta) # Further filters, all ANDed together in CNF style. users = flask.request.args.getlist('user') packages = flask.request.args.getlist('package') categories = flask.request.args.getlist('category') topics = flask.request.args.getlist('topic') contains = flask.request.args.getlist('contains') # Still more filters.. negations of the previous ones. not_users = flask.request.args.getlist('not_user') not_packages = flask.request.args.getlist('not_package') not_categories = flask.request.args.getlist('not_category') not_topics = flask.request.args.getlist('not_topic') # Paging arguments page = int(flask.request.args.get('page', 1)) rows_per_page = int(flask.request.args.get('rows_per_page', 20)) order = flask.request.args.get('order', 'desc') # adding size as paging arguments size = flask.request.args.get('size', 'large') # adding chrome as paging arguments chrome = flask.request.args.get('chrome', 'true') # Response formatting arguments callback = flask.request.args.get('callback', None) meta = flask.request.args.getlist('meta') arguments = dict( start=start, delta=delta, end=end, users=users, packages=packages, categories=categories, topics=topics, contains=contains, not_users=not_users, not_packages=not_packages, not_categories=not_categories, not_topics=not_topics, page=page, rows_per_page=rows_per_page, order=order, meta=meta, ) if page < 1: raise ValueError("page must be > 0") if rows_per_page > 100: raise ValueError("rows_per_page must be <= 100") if order not in ['desc', 'asc']: raise ValueError("order must be either 'desc' or 'asc'") # check size value possible_sizes = ['small', 'medium', 'large', 'extra-large'] if size not in possible_sizes: raise ValueError("size must be in one of these %r" % possible_sizes) # checks chrome value if chrome not in ['true', 'false']: raise ValueError("chrome should be either 'true' or 'false'") try: # This fancy classmethod does all of our search for us. total, pages, messages = dm.Message.grep( start=start and datetime.fromtimestamp(start), end=end and datetime.fromtimestamp(end), page=page, rows_per_page=rows_per_page, order=order, users=users, packages=packages, categories=categories, topics=topics, contains=contains, not_users=not_users, not_packages=not_packages, not_categories=not_categories, not_topics=not_topics, ) # Convert our messages from sqlalchemy objects to json-like dicts messages = [msg.__json__() for msg in messages] if meta: for message in messages: message = meta_argument(message, meta) output = dict( raw_messages=messages, total=total, pages=pages, count=len(messages), arguments=arguments, ) status = 200 except Exception as e: output = dict( error=str(e), arguments=arguments, ) # :D if app.config.get('DEBUG', False): output['tb'] = traceback.format_exc().split('\n') status = 500 body = fedmsg.encoding.dumps(output) mimetype = flask.request.headers.get('Accept') if callback: mimetype = 'application/javascript' body = "%s(%s);" % (callback, body) # return HTML content else json if not callback and request_wants_html(): # convert string into python dictionary obj = json.loads(body) # extract the messages raw_message_list = obj["raw_messages"] final_message_list = [] for msg in raw_message_list: # message_card module will handle size message = message_card(msg, size) # add msg_id to the message dictionary if (msg["msg_id"] is not None): message['msg_id'] = msg["msg_id"] final_message_list.append(message) # removes boilerlate codes if chrome value is false if chrome == 'true': return flask.render_template( "base.html", size=size, response=final_message_list, heading="Raw Messages", ) else: return flask.render_template( "raw.html", size=size, response=final_message_list, ) else: return flask.Response( response=body, status=status, mimetype=mimetype, )
def make_charts(chart_type): """ Return SVGs graphing db content. """ # Perform our complicated datetime logic start = flask.request.args.get('start', None) end = flask.request.args.get('end', None) delta = flask.request.args.get('delta', None) start, end, delta = assemble_timerange(start, end, delta) # Further filters, all ANDed together in CNF style. users = flask.request.args.getlist('user') packages = flask.request.args.getlist('package') categories = flask.request.args.getlist('category') topics = flask.request.args.getlist('topic') contains = flask.request.args.getlist('contains') # Still more filters.. negations of the previous ones. not_users = flask.request.args.getlist('not_user') not_packages = flask.request.args.getlist('not_package') not_categories = flask.request.args.getlist('not_category') not_topics = flask.request.args.getlist('not_topic') end = end and datetime.fromtimestamp(end) start = start and datetime.fromtimestamp(start) end = end or datetime.utcnow() start = start or end - timedelta(days=365) human_readable = flask.request.args.get('human_readable', True, asbool) logarithmic = flask.request.args.get('logarithmic', False, asbool) show_x_labels = flask.request.args.get('show_x_labels', True, asbool) show_y_labels = flask.request.args.get('show_y_labels', True, asbool) show_dots = flask.request.args.get('show_dots', True, asbool) fill = flask.request.args.get('fill', False, asbool) title = flask.request.args.get('title', 'fedmsg events') width = flask.request.args.get('width', 800, int) height = flask.request.args.get('height', 800, int) interpolation = flask.request.args.get('interpolation', None) interpolation_types = [ None, 'quadratic', 'cubic', ] if interpolation not in interpolation_types: flask.abort(404, "%s not in %r" % (interpolation, interpolation_types)) chart_types = { 'line': 'Line', 'stackedline': 'StackedLine', 'xy': 'XY', 'bar': 'Bar', 'horizontalbar': 'HorizontalBar', 'stackedbar': 'StackedBar', 'horizontalstackedbar': 'HorizontalStackedBar', 'funnel': 'Funnel', 'pyramid': 'Pyramid', 'verticalpyramid': 'VerticalPyramid', 'dot': 'Dot', 'gauge': 'Gauge', } if chart_type not in chart_types: flask.abort(404, "%s not in %r" % (chart_type, chart_types)) style = flask.request.args.get('style', 'default') if style not in pygal.style.styles: flask.abort(404, "%s not in %r" % (style, pygal.style.styles)) style = pygal.style.styles[style] chart = getattr(pygal, chart_types[chart_type])( human_readable=human_readable, logarithmic=logarithmic, show_x_labels=show_x_labels, show_y_labels=show_y_labels, show_dots=show_dots, fill=fill, title=title, width=width, height=height, interpolate=interpolation, x_label_rotation=45, style=style, ) lookup = locals() factor_names = flask.request.args.getlist('split_on') factor_names = [name for name in factor_names if lookup[name]] factor_values = [lookup[name] for name in factor_names] factors = list(itertools.product(*factor_values)) N = int(flask.request.args.get('N', 10)) if N < 3: flask.abort(500, 'N must be greater than 3') if N > 15: flask.abort(500, 'N must be less than 15') try: labels = [] kwargs = dict( users=users, packages=packages, categories=categories, topics=topics, contains=contains, ) dates = [i for i, _ in daterange(start, end, N)] if human_readable: labels = [arrow.get(i).humanize() for i in dates] else: labels = [unicode(arrow.get(i).date()) for i in dates] for factor in factors: for i, name in enumerate(factor_names): kwargs[name] = [factor[i]] values = [] for i, j in daterange(start, end, N): count, _, _ = dm.Message.grep( start=i, end=j, rows_per_page=None, defer=True, not_users=not_users, not_packages=not_packages, not_categories=not_categories, not_topics=not_topics, **kwargs ) values.append(count) tag = factor and " & ".join(factor) or "events" # Truncate things to make charts prettier if tag.startswith('org.fedoraproject.prod.'): tag = tag[len('org.fedoraproject.prod.'):] chart.add(tag, values) chart.x_labels = labels output = chart.render() status = 200 mimetype = 'image/svg+xml' except Exception as e: import traceback traceback.print_exc() output = "Error, %r" % e status = 500 mimetype = 'text/html' return flask.Response( response=output, status=status, mimetype=mimetype, )
def raw(): """ Main API entry point. """ # Perform our complicated datetime logic start = flask.request.args.get('start', None) end = flask.request.args.get('end', None) default_delta = app.config['DEFAULT_QUERY_DELTA'] delta = flask.request.args.get('delta') if not (start or end or delta): delta = default_delta start, end, delta = assemble_timerange(start, end, delta) # Further filters, all ANDed together in CNF style. users = flask.request.args.getlist('user') packages = flask.request.args.getlist('package') categories = flask.request.args.getlist('category') topics = flask.request.args.getlist('topic') contains = flask.request.args.getlist('contains') # Still more filters.. negations of the previous ones. not_users = flask.request.args.getlist('not_user') not_packages = flask.request.args.getlist('not_package') not_categories = flask.request.args.getlist('not_category') not_topics = flask.request.args.getlist('not_topic') # Paging arguments page = int(flask.request.args.get('page', 1)) rows_per_page = int(flask.request.args.get('rows_per_page', 25)) order = flask.request.args.get('order', 'desc') # adding size as paging arguments size = flask.request.args.get('size', 'large') # adding chrome as paging arguments chrome = flask.request.args.get('chrome', 'true') # Response formatting arguments callback = flask.request.args.get('callback', None) meta = flask.request.args.getlist('meta') grouped = flask.request.args.get('grouped', False, asbool) arguments = dict( start=start, delta=delta, end=end, users=users, packages=packages, categories=categories, topics=topics, contains=contains, not_users=not_users, not_packages=not_packages, not_categories=not_categories, not_topics=not_topics, page=page, rows_per_page=rows_per_page, order=order, meta=meta, grouped=grouped, ) if page < 1: raise ValueError("page must be > 0") if rows_per_page > 100: raise ValueError("rows_per_page must be <= 100") if order not in ['desc', 'asc']: raise ValueError("order must be either 'desc' or 'asc'") # check size value possible_sizes = ['small', 'medium', 'large', 'extra-large'] if size not in possible_sizes: raise ValueError("size must be in one of these %r" % possible_sizes) # checks chrome value if chrome not in ['true', 'false']: raise ValueError("chrome should be either 'true' or 'false'") if contains and datetime.fromtimestamp( start or 0) < (datetime.utcnow() - timedelta(weeks=4 * 8)): raise BadRequest('When using contains, specify a start at most ' 'eight months into the past') if contains and not (categories or topics): raise BadRequest('When using contains, specify either a topic or' ' a category as well') try: # This fancy classmethod does all of our search for us. total, pages, messages = dm.Message.grep( start=start and datetime.fromtimestamp(start), end=end and datetime.fromtimestamp(end), page=page, rows_per_page=rows_per_page, order=order, users=users, packages=packages, categories=categories, topics=topics, contains=contains, not_users=not_users, not_packages=not_packages, not_categories=not_categories, not_topics=not_topics, ) # Convert our messages from sqlalchemy objects to json-like dicts messages = [msg.__json__() for msg in messages] if grouped: messages = fedmsg.meta.conglomerate(messages, **fedmsg_config) for message in messages: message['date'] = arrow.get(message['timestamp']).humanize() elif meta: for message in messages: message = meta_argument(message, meta) output = dict( raw_messages=messages, total=total, pages=pages, count=len(messages), arguments=arguments, ) status = 200 except Exception as e: traceback.print_exc() output = dict( error=str(e), arguments=arguments, ) # :D if app.config.get('DEBUG', False): output['tb'] = traceback.format_exc().split('\n') status = 500 body = fedmsg.encoding.dumps(output) mimetype = flask.request.headers.get('Accept') # Our default - http://da.gd/vIIV if mimetype == '*/*': mimetype = 'application/json' if callback: mimetype = 'application/javascript' body = "%s(%s);" % (callback, body) # return HTML content else json if not callback and request_wants_html(): # convert string into python dictionary obj = json.loads(body) # extract the messages raw_message_list = obj.get("raw_messages", []) final_message_list = [] for msg in raw_message_list: if not grouped: # message_card module will handle size message = message_card(msg, size) # add msg_id to the message dictionary if (msg['msg_id'] is not None): message['msg_id'] = msg['msg_id'] else: message = msg message['msg_id'] = None if len(message['msg_ids']) == 1: message['msg_id'] = message['msg_ids'].keys()[0] message['date'] = arrow.get(message['timestamp']) final_message_list.append(message) # removes boilerlate codes if chrome value is false if chrome == 'true': return flask.render_template( "base.html", size=size, response=final_message_list, arguments=arguments, autoscroll=True, ) else: return flask.render_template( "raw.html", size=size, response=final_message_list, arguments=arguments, ) else: return flask.Response( response=body, status=status, mimetype=mimetype, )
def test_delta_none_none(self): start, end, delta = assemble_timerange(None, None, 5) eq_(1325375995.0, start) eq_(1325376000.0, end) eq_(5, delta)
def raw(): """ Main API entry point. """ # Perform our complicated datetime logic start = flask.request.args.get('start', None) end = flask.request.args.get('end', None) delta = flask.request.args.get('delta', None) start, end, delta = assemble_timerange(start, end, delta) start_id = flask.request.args.get('start_id', None) end_id = flask.request.args.get('end_id', None) # Further filters, all ANDed together in CNF style. users = flask.request.args.getlist('user') packages = flask.request.args.getlist('package') categories = flask.request.args.getlist('category') topics = flask.request.args.getlist('topic') contains = flask.request.args.getlist('contains') # Still more filters.. negations of the previous ones. not_users = flask.request.args.getlist('not_user') not_packages = flask.request.args.getlist('not_package') not_categories = flask.request.args.getlist('not_category') not_topics = flask.request.args.getlist('not_topic') # Paging arguments page = int(flask.request.args.get('page', 1)) rows_per_page = int(flask.request.args.get('rows_per_page', 25)) order = flask.request.args.get('order', 'desc') # adding size as paging arguments size = flask.request.args.get('size', 'large') # adding chrome as paging arguments chrome = flask.request.args.get('chrome', 'true') # Response formatting arguments callback = flask.request.args.get('callback', None) meta = flask.request.args.getlist('meta') grouped = flask.request.args.get('grouped', False, asbool) arguments = dict( start=start, delta=delta, end=end, start_id=start_id, end_id=end_id, users=users, packages=packages, categories=categories, topics=topics, contains=contains, not_users=not_users, not_packages=not_packages, not_categories=not_categories, not_topics=not_topics, page=page, rows_per_page=rows_per_page, order=order, meta=meta, grouped=grouped, ) if page < 1: raise ValueError("page must be > 0") if rows_per_page > 100: raise ValueError("rows_per_page must be <= 100") if order not in ['desc', 'asc']: raise ValueError("order must be either 'desc' or 'asc'") # check size value possible_sizes = ['small', 'medium', 'large', 'extra-large'] if size not in possible_sizes: raise ValueError("size must be in one of these %r" % possible_sizes) # checks chrome value if chrome not in ['true', 'false']: raise ValueError("chrome should be either 'true' or 'false'") if start or end or delta: start_id = None end_id = None else: if start_id: start_msg = dm.Message.query.filter_by(msg_id=start_id).first() start = start_msg.timestamp.strftime('%s') if end_id: end_msg = dm.Message.query.filter_by(msg_id=end_id).first() end = end_msg.timestamp.strftime('%s') start, end, delta = assemble_timerange(start, end, delta) if contains and datetime.fromtimestamp(start or 0) < (datetime.utcnow() - timedelta(weeks=4*8)): raise BadRequest('When using contains, specify a start at most ' 'eight months into the past') if contains and not (categories or topics): raise BadRequest('When using contains, specify either a topic or' ' a category as well') try: # This fancy classmethod does all of our search for us. total, pages, messages = dm.Message.grep( start=start and datetime.fromtimestamp(start), end=end and datetime.fromtimestamp(end), page=page, rows_per_page=rows_per_page, order=order, users=users, packages=packages, categories=categories, topics=topics, contains=contains, not_users=not_users, not_packages=not_packages, not_categories=not_categories, not_topics=not_topics, ) # Convert our messages from sqlalchemy objects to json-like dicts messages = [msg.__json__() for msg in messages] if grouped: messages = fedmsg.meta.conglomerate(messages, **fedmsg_config) for message in messages: message['date'] = arrow.get(message['timestamp']).humanize() elif meta: for message in messages: message = meta_argument(message, meta) output = dict( raw_messages=messages, total=total, pages=pages, count=len(messages), arguments=arguments, ) status = 200 except Exception as e: traceback.print_exc() output = dict( error=str(e), arguments=arguments, ) # :D if app.config.get('DEBUG', False): output['tb'] = traceback.format_exc().split('\n') status = 500 body = fedmsg.encoding.dumps(output) mimetype = flask.request.headers.get('Accept') # Our default - http://da.gd/vIIV if mimetype == '*/*': mimetype = 'application/json' if callback: mimetype = 'application/javascript' body = "%s(%s);" % (callback, body) # return HTML content else json if not callback and request_wants_html(): # convert string into python dictionary obj = json.loads(body) # extract the messages raw_message_list = obj.get("raw_messages", []) final_message_list = [] for msg in raw_message_list: if not grouped: # message_card module will handle size message = message_card(msg, size) # add msg_id to the message dictionary if (msg['msg_id'] is not None): message['msg_id'] = msg['msg_id'] else: message = msg message['msg_id'] = None if len(message['msg_ids']) == 1: message['msg_id'] = message['msg_ids'].keys()[0] message['date'] = arrow.get(message['timestamp']) final_message_list.append(message) # removes boilerlate codes if chrome value is false if chrome == 'true': return flask.render_template( "base.html", size=size, response=final_message_list, arguments=arguments, autoscroll=True, ) else: return flask.render_template( "raw.html", size=size, response=final_message_list, arguments=arguments, ) else: return flask.Response( response=body, status=status, mimetype=mimetype, )
def test_none_none_none(self): start, end, delta = assemble_timerange(None, None, None) eq_(None, start) eq_(None, end) eq_(None, delta)
def make_charts(chart_type): """ Return SVGs graphing db content. """ # Perform our complicated datetime logic start = flask.request.args.get('start', None) end = flask.request.args.get('end', None) delta = flask.request.args.get('delta', None) start, end, delta = assemble_timerange(start, end, delta) # Further filters, all ANDed together in CNF style. users = flask.request.args.getlist('user') packages = flask.request.args.getlist('package') categories = flask.request.args.getlist('category') topics = flask.request.args.getlist('topic') contains = flask.request.args.getlist('contains') # Still more filters.. negations of the previous ones. not_users = flask.request.args.getlist('not_user') not_packages = flask.request.args.getlist('not_package') not_categories = flask.request.args.getlist('not_category') not_topics = flask.request.args.getlist('not_topic') end = end and datetime.fromtimestamp(end) start = start and datetime.fromtimestamp(start) end = end or datetime.utcnow() start = start or end - timedelta(days=365) human_readable = flask.request.args.get('human_readable', True, asbool) logarithmic = flask.request.args.get('logarithmic', False, asbool) show_x_labels = flask.request.args.get('show_x_labels', True, asbool) show_y_labels = flask.request.args.get('show_y_labels', True, asbool) show_dots = flask.request.args.get('show_dots', True, asbool) fill = flask.request.args.get('fill', False, asbool) title = flask.request.args.get('title', 'fedmsg events') width = flask.request.args.get('width', 800, int) height = flask.request.args.get('height', 800, int) interpolation = flask.request.args.get('interpolation', None) interpolation_types = [ None, 'quadratic', 'cubic', ] if interpolation not in interpolation_types: flask.abort(404, "%s not in %r" % (interpolation, interpolation_types)) chart_types = { 'line': 'Line', 'stackedline': 'StackedLine', 'xy': 'XY', 'bar': 'Bar', 'horizontalbar': 'HorizontalBar', 'stackedbar': 'StackedBar', 'horizontalstackedbar': 'HorizontalStackedBar', 'funnel': 'Funnel', 'pyramid': 'Pyramid', 'verticalpyramid': 'VerticalPyramid', 'dot': 'Dot', 'gauge': 'Gauge', } if chart_type not in chart_types: flask.abort(404, "%s not in %r" % (chart_type, chart_types)) style = flask.request.args.get('style', 'default') if style not in pygal.style.styles: flask.abort(404, "%s not in %r" % (style, pygal.style.styles)) style = pygal.style.styles[style] chart = getattr(pygal, chart_types[chart_type])( human_readable=human_readable, logarithmic=logarithmic, show_x_labels=show_x_labels, show_y_labels=show_y_labels, show_dots=show_dots, fill=fill, title=title, width=width, height=height, interpolate=interpolation, x_label_rotation=45, style=style, ) lookup = locals() factor_names = flask.request.args.getlist('split_on') factor_names = [name for name in factor_names if lookup[name]] factor_values = [lookup[name] for name in factor_names] factors = list(itertools.product(*factor_values)) N = int(flask.request.args.get('N', 10)) if N < 3: flask.abort(500, 'N must be greater than 3') if N > 15: flask.abort(500, 'N must be less than 15') try: labels = [] kwargs = dict( users=users, packages=packages, categories=categories, topics=topics, contains=contains, ) dates = [i for i, _ in daterange(start, end, N)] if human_readable: labels = [arrow.get(i).humanize() for i in dates] else: labels = [unicode(arrow.get(i).date()) for i in dates] for factor in factors: for i, name in enumerate(factor_names): kwargs[name] = [factor[i]] values = [] for i, j in daterange(start, end, N): count, _, _ = dm.Message.grep(start=i, end=j, rows_per_page=None, defer=True, not_users=not_users, not_packages=not_packages, not_categories=not_categories, not_topics=not_topics, **kwargs) values.append(count) tag = factor and " & ".join(factor) or "events" # Truncate things to make charts prettier if tag.startswith('org.fedoraproject.prod.'): tag = tag[len('org.fedoraproject.prod.'):] chart.add(tag, values) chart.x_labels = labels output = chart.render() status = 200 mimetype = 'image/svg+xml' except Exception as e: import traceback traceback.print_exc() output = "Error, %r" % e status = 500 mimetype = 'text/html' return flask.Response( response=output, status=status, mimetype=mimetype, )