def extend_module(module_id, project_type, release): module_id_index = vault.get_vault()['module_id_index'] module_id = module_id.lower() if module_id not in module_id_index: return None repos_index = vault.get_vault()['repos_index'] module = module_id_index[module_id] name = module['module_group_name'] if name[0].islower(): name = name.capitalize() # (module, release) pairs own_sub_modules = set(vault.resolve_modules([module_id], [release])) visible_sub_modules = own_sub_modules & set( vault.resolve_modules(vault.resolve_project_types([project_type]), [release])) child_modules = [] for m, r in own_sub_modules: child = {'module_name': m, 'visible': (m, r) in visible_sub_modules} if m in repos_index: child['repo_uri'] = repos_index[m]['uri'] child_modules.append(child) child_modules.sort(key=lambda x: x['module_name']) return { 'id': module_id, 'name': name, 'tag': module['tag'], 'modules': child_modules, }
def extend_module(module_id): module_id_index = vault.get_vault()['module_id_index'] module_id = module_id.lower() if module_id not in module_id_index: return None repos_index = vault.get_vault()['repos_index'] module = module_id_index[module_id] name = module['module_group_name'] if name[0].islower(): name = name.capitalize() child_modules = [] for m in module['modules']: child = {'module_name': m} if m in repos_index: child['repo_uri'] = repos_index[m]['uri'] child_modules.append(child) return { 'id': module_id, 'name': name, 'tag': module['tag'], 'modules': child_modules, }
def extend_module(module_id, project_type, release): module_id_index = vault.get_vault()['module_id_index'] module_id = module_id.lower() if module_id not in module_id_index: return None repos_index = vault.get_vault()['repos_index'] module = module_id_index[module_id] name = module['module_group_name'] if name[0].islower(): name = name.capitalize() # (module, release) pairs own_sub_modules = set(vault.resolve_modules([module_id], [release])) visible_sub_modules = own_sub_modules & set(vault.resolve_modules( vault.resolve_project_types([project_type]), [release])) child_modules = [] for m, r in own_sub_modules: child = {'module_name': m, 'visible': (m, r) in visible_sub_modules} if m in repos_index: child['repo_uri'] = repos_index[m]['uri'] child_modules.append(child) child_modules.sort(key=lambda x: x['module_name']) return { 'id': module_id, 'name': name, 'tag': module['tag'], 'modules': child_modules, }
def _get_aggregated_stats(records, metric_filter, keys, param_id, param_title=None, finalize_handler=None): param_title = param_title or param_id result = dict((c, {'metric': 0, 'id': c}) for c in keys) context = {'vault': vault.get_vault()} if metric_filter: for record in records: metric_filter(result, record, param_id, context) result[getattr(record, param_id)]['name'] = (getattr(record, param_title)) else: for record in records: record_param_id = getattr(record, param_id) result[record_param_id]['metric'] += 1 result[record_param_id]['name'] = getattr(record, param_title) response = [r for r in result.values() if r['metric']] if finalize_handler: response = [item for item in map(finalize_handler, response) if item] response.sort(key=lambda x: x['metric'], reverse=True) utils.add_index(response, item_filter=lambda x: x['id'] != '*independent') return response
def open_reviews(module): memory_storage_inst = vault.get_memory_storage() time_now = int(time.time()) module_id_index = vault.get_vault()['module_id_index'] module = module.lower() if module not in module_id_index: flask.abort(404) modules = module_id_index[module]['modules'] review_ids = (memory_storage_inst.get_record_ids_by_modules(modules) & memory_storage_inst.get_record_ids_by_types(['review'])) waiting_on_reviewer = [] total_open = 0 for review in memory_storage_inst.get_records(review_ids): if review.status == 'NEW': total_open += 1 if review.value in [1, 2]: waiting_on_reviewer.append(vault.extend_record(review)) return { 'module': module, 'total_open': total_open, 'waiting_on_reviewer': len(waiting_on_reviewer), 'waiting_on_submitter': total_open - len(waiting_on_reviewer), 'latest_revision': _process_stat( waiting_on_reviewer, 'updated_on', time_now), 'first_revision': _process_stat(waiting_on_reviewer, 'date', time_now), }
def get_modules_json(record_ids, **kwargs): module_id_index = vault.get_vault()['module_id_index'] tags = parameters.get_parameter({}, 'tag', 'tags') # all modules mentioned in records module_ids = vault.get_memory_storage().get_index_keys_by_record_ids( 'module', record_ids) add_modules = set([]) for module in six.itervalues(module_id_index): if set(module['modules']) & module_ids: add_modules.add(module['id']) module_ids |= add_modules # keep only modules with specified tags if tags: module_ids = set(module_id for module_id in module_ids if ((module_id in module_id_index) and (module_id_index[module_id].get('tag') in tags))) result = [] for module_id in module_ids: module = module_id_index[module_id] result.append({'id': module['id'], 'text': module['module_group_name'], 'tag': module['tag']}) return sorted(result, key=operator.itemgetter('text'))
def _get_week(kwargs, param_name): date_param = parameters.get_single_parameter(kwargs, param_name) if date_param: ts = utils.date_to_timestamp_ext(date_param) else: ts = vault.get_vault()[param_name] return utils.timestamp_to_week(ts)
def get_releases_json(**kwargs): releases = [{'id': release['release_name'], 'text': release['release_name'].capitalize()} for release in vault.get_vault()['releases'].values()] releases.append({'id': 'all', 'text': 'All'}) releases.reverse() return (releases, parameters.get_default('release'))
def get_modules_json(record_ids, **kwargs): module_id_index = vault.get_vault()['module_id_index'] tags = parameters.get_parameter({}, 'tag', 'tags') # all modules mentioned in records module_ids = vault.get_memory_storage().get_index_keys_by_record_ids( 'module', record_ids) add_modules = set([]) for module in six.itervalues(module_id_index): if set(module['modules']) & module_ids: add_modules.add(module['id']) module_ids |= add_modules # keep only modules with specified tags if tags: module_ids = set(module_id for module_id in module_ids if ((module_id in module_id_index) and ( module_id_index[module_id].get('tag') in tags))) result = [] for module_id in module_ids: module = module_id_index[module_id] result.append({ 'id': module['id'], 'text': module['module_group_name'], 'tag': module['tag'] }) return sorted(result, key=operator.itemgetter('text'))
def get_module(module, **kwargs): module_id_index = vault.get_vault()['module_id_index'] module = module.lower() if module in module_id_index: return {'id': module_id_index[module]['id'], 'text': module_id_index[module]['module_group_name'], 'tag': module_id_index[module]['tag']} flask.abort(404)
def prepare_params_decorated_function(*args, **kwargs): params = _prepare_params(kwargs, ignore) cache_inst = vault.get_vault()['cache'] key = json.dumps(params) value = cache_inst.get(key) if not value: value = func(*args, **kwargs) cache_inst[key] = value vault.get_vault()['cache_size'] += len(key) + len(value) LOG.debug('Cache size: %(size)d, entries: %(len)d', {'size': vault.get_vault()['cache_size'], 'len': len(cache_inst.keys())}) return value
def get_releases_json(**kwargs): releases = [{ 'id': release['release_name'], 'text': release['release_name'].capitalize() } for release in vault.get_vault()['releases'].values()] releases.append({'id': 'all', 'text': 'All'}) releases.reverse() return (releases, parameters.get_default('release'))
def open_reviews(module): memory_storage_inst = vault.get_memory_storage() time_now = int(time.time()) module_id_index = vault.get_vault()['module_id_index'] module = module.lower() if module not in module_id_index: flask.abort(404) modules = module_id_index[module]['modules'] review_ids = (memory_storage_inst.get_record_ids_by_modules(modules) & memory_storage_inst.get_record_ids_by_types(['review'])) waiting_on_reviewer = [] waiting_on_submitter = [] total_open = 0 for review in memory_storage_inst.get_records(review_ids): if review.status == 'NEW': total_open += 1 # review.value is minimum from votes made for the latest patch if review.value in [1, 2]: # CI or engineer liked this change request, waiting for someone # to merge or to put dislike waiting_on_reviewer.append(helpers.extend_record(review)) elif review.value in [-1, -2]: # CI or reviewer do not like this, waiting for submitter to fix waiting_on_submitter.append(helpers.extend_record(review)) else: # new requests without votes, waiting for CI pass limit = int(flask.request.args.get('limit') or CONF.report_default_limit) if limit < 0: limit = None return { 'module': module, 'total_open': total_open, 'waiting_on_reviewer': len(waiting_on_reviewer), 'waiting_on_submitter': len(waiting_on_submitter), 'waiting_on_ci': (total_open - len(waiting_on_reviewer) - len(waiting_on_submitter)), 'reviewer_latest_revision': _process_stat( waiting_on_reviewer, 'updated_on', time_now, limit), 'reviewer_first_revision': _process_stat( waiting_on_reviewer, 'date', time_now, limit), 'submitter_latest_revision': _process_stat( waiting_on_submitter, 'updated_on', time_now, limit), 'submitter_first_revision': _process_stat( waiting_on_submitter, 'date', time_now, limit), }
def _validate_params(params): vault_inst = vault.get_vault() memory_storage_inst = vault.get_memory_storage() _check_param_in(params, 'release', vault_inst['releases'], True) _check_param_in(params, 'project_type', vault_inst['project_types_index']) _check_param_in(params, 'module', vault_inst['module_id_index']) _check_param_in(params, 'company', memory_storage_inst.get_companies_lower()) _check_param_in(params, 'user_id', memory_storage_inst.get_user_ids()) _check_param_in(params, 'metric', parameters.METRIC_TO_RECORD_TYPE, True)
def open_reviews(module): memory_storage_inst = vault.get_memory_storage() time_now = int(time.time()) module_id_index = vault.get_vault()['module_id_index'] module = module.lower() if module not in module_id_index: flask.abort(404) modules = module_id_index[module]['modules'] review_ids = (memory_storage_inst.get_record_ids_by_modules(modules) & memory_storage_inst.get_record_ids_by_types(['review'])) waiting_on_reviewer = [] waiting_on_submitter = [] total_open = 0 for review in memory_storage_inst.get_records(review_ids): if review.status == 'NEW': total_open += 1 # review.value is minimum from votes made for the latest patch if review.value in [1, 2]: # CI or engineer liked this change request, waiting for someone # to merge or to put dislike waiting_on_reviewer.append(helpers.extend_record(review)) elif review.value in [-1, -2]: # CI or reviewer do not like this, waiting for submitter to fix waiting_on_submitter.append(helpers.extend_record(review)) else: # new requests without votes, waiting for CI pass return { 'module': module, 'total_open': total_open, 'waiting_on_reviewer': len(waiting_on_reviewer), 'waiting_on_submitter': len(waiting_on_submitter), 'waiting_on_ci': (total_open - len(waiting_on_reviewer) - len(waiting_on_submitter)), 'reviewer_latest_revision': _process_stat(waiting_on_reviewer, 'updated_on', time_now), 'reviewer_first_revision': _process_stat(waiting_on_reviewer, 'date', time_now), 'submitter_latest_revision': _process_stat(waiting_on_submitter, 'updated_on', time_now), 'submitter_first_revision': _process_stat(waiting_on_submitter, 'date', time_now), }
def response_decorated_function(*args, **kwargs): callback = flask.app.request.args.get('callback', False) data = func(*args, **kwargs) if callback: data = str(callback) + '(' + data + ')' mimetype = 'application/javascript' else: mimetype = 'application/json' resp = flask.current_app.response_class(data, mimetype=mimetype) update_time = vault.get_vault()['vault_next_update_time'] now = utils.date_to_timestamp('now') if now < update_time: max_age = update_time - now else: max_age = 0 resp.headers['cache-control'] = 'public, max-age=%d' % (max_age,) resp.headers['expires'] = time.strftime( '%a, %d %b %Y %H:%M:%S GMT', time.gmtime(vault.get_vault()['vault_next_update_time'])) resp.headers['access-control-allow-origin'] = '*' return resp
def response_decorated_function(*args, **kwargs): callback = flask.app.request.args.get('callback', False) data = func(*args, **kwargs) if callback: data = str(callback) + '(' + data + ')' mimetype = 'application/javascript' else: mimetype = 'application/json' resp = flask.current_app.response_class(data, mimetype=mimetype) update_time = vault.get_vault()['vault_next_update_time'] now = utils.date_to_timestamp('now') if now < update_time: max_age = update_time - now else: max_age = 0 resp.headers['cache-control'] = 'public, max-age=%d' % (max_age, ) resp.headers['expires'] = time.strftime( '%a, %d %b %Y %H:%M:%S GMT', time.gmtime(vault.get_vault()['vault_next_update_time'])) resp.headers['access-control-allow-origin'] = '*' return resp
def get_default(param_name): if 'release' not in DEFAULTS: release = cfg.CONF.default_release if not release: runtime_storage_inst = vault.get_vault()['runtime_storage'] releases = runtime_storage_inst.get_by_key('releases') if releases: release = releases[-1]['release_name'] else: release = 'all' DEFAULTS['release'] = release.lower() DEFAULTS['metric'] = cfg.CONF.default_metric.lower() DEFAULTS['project_type'] = cfg.CONF.default_project_type.lower() if param_name in DEFAULTS: return DEFAULTS[param_name] else: return None
def _get_aggregated_stats(records, metric_filter, keys, param_id, param_title=None, finalize_handler=None): param_title = param_title or param_id result = dict((c, {'metric': 0, 'id': c}) for c in keys) context = {'vault': vault.get_vault()} if metric_filter: for record in records: metric_filter(result, record, param_id, context) result[getattr(record, param_id)]['name'] = ( getattr(record, param_title)) else: for record in records: record_param_id = getattr(record, param_id) result[record_param_id]['metric'] += 1 result[record_param_id]['name'] = getattr(record, param_title) response = [r for r in result.values() if r['metric']] if finalize_handler: response = [item for item in map(finalize_handler, response) if item] response.sort(key=lambda x: x['metric'], reverse=True) utils.add_index(response, item_filter=lambda x: x['id'] != '*independent') return response
def templated_decorated_function(*args, **kwargs): vault_inst = vault.get_vault() template_name = template if template_name is None: template_name = (flask.request.endpoint.replace('.', '/') + '.html') ctx = f(*args, **kwargs) if ctx is None: ctx = {} # put parameters into template metric = flask.request.args.get('metric') if metric not in parameters.METRIC_LABELS: metric = None ctx['metric'] = metric or parameters.get_default('metric') ctx['metric_label'] = parameters.METRIC_LABELS[ctx['metric']] project_type = flask.request.args.get('project_type') if not vault.is_project_type_valid(project_type): project_type = parameters.get_default('project_type') ctx['project_type'] = project_type release = flask.request.args.get('release') releases = vault_inst['releases'] if release: release = release.lower() if release != 'all': if release not in releases: release = None else: release = releases[release]['release_name'] ctx['release'] = (release or parameters.get_default('release')).lower() ctx['review_nth'] = (flask.request.args.get('review_nth') or parameters.get_default('review_nth')) ctx['company'] = parameters.get_single_parameter(kwargs, 'company') ctx['company_original'] = ( vault.get_memory_storage().get_original_company_name( ctx['company'])) module = parameters.get_single_parameter(kwargs, 'module') ctx['module'] = module module_name = None if module and module in vault_inst['module_id_index']: ctx['module_inst'] = vault_inst['module_id_index'][module] module_name = ctx['module_inst']['module_group_name'] ctx['user_id'] = parameters.get_single_parameter(kwargs, 'user_id') if ctx['user_id']: ctx['user_inst'] = vault.get_user_from_runtime_storage( ctx['user_id']) ctx['page_title'] = helpers.make_page_title( ctx['company'], ctx['user_id'], module_name, ctx['release']) ctx['stackalytics_version'] = ( stackalytics_version.version_info.version_string()) ctx['stackalytics_release'] = ( stackalytics_version.version_info.release_string()) ctx['runtime_storage_update_time'] = ( vault_inst['runtime_storage_update_time']) return flask.render_template(template_name, **ctx), return_code
def templated_decorated_function(*args, **kwargs): vault_inst = vault.get_vault() template_name = template if template_name is None: template_name = (flask.request.endpoint.replace('.', '/') + '.html') ctx = f(*args, **kwargs) if ctx is None: ctx = {} try: _prepare_params(kwargs, []) except Exception: if return_code == 200: raise # do not re-raise on error page # put parameters into template ctx['metric'] = parameters.get_single_parameter( kwargs, 'metric', use_default=True) ctx['metric_label'] = parameters.METRIC_LABELS.get(ctx['metric']) project_type = parameters.get_single_parameter( kwargs, 'project_type', use_default=True) ctx['project_type'] = project_type ctx['project_type_inst'] = vault.get_project_type(project_type) ctx['release'] = parameters.get_single_parameter( kwargs, 'release', use_default=True) company = parameters.get_single_parameter(kwargs, 'company') ctx['company'] = company if company: ctx['company_original'] = ( vault.get_memory_storage().get_original_company_name( ctx['company'])) module = parameters.get_single_parameter(kwargs, 'module') ctx['module'] = module if module and module in vault_inst['module_id_index']: ctx['module_inst'] = vault_inst['module_id_index'][module] ctx['user_id'] = parameters.get_single_parameter(kwargs, 'user_id') if ctx['user_id']: ctx['user_inst'] = vault.get_user_from_runtime_storage( ctx['user_id']) ctx['page_title'] = helpers.make_page_title( ctx['project_type_inst'], ctx.get('release'), ctx.get('module_inst'), ctx.get('company_original'), ctx.get('user_inst')) ctx['stackalytics_version'] = ( stackalytics_version.version_info.version_string()) ctx['stackalytics_release'] = ( stackalytics_version.version_info.release_string()) update_time = vault_inst['runtime_storage_update_time'] ctx['runtime_storage_update_time'] = update_time ctx['runtime_storage_update_time_str'] = helpers.format_datetime( update_time) if update_time else None # deprecated -- top mentor report ctx['review_nth'] = parameters.get_single_parameter( kwargs, 'review_nth') return flask.render_template(template_name, **ctx), return_code
def timeline(records, **kwargs): # find start and end dates metric = parameters.get_parameter(kwargs, 'metric') start_date = int( parameters.get_single_parameter(kwargs, 'start_date') or 0) release_name = parameters.get_single_parameter(kwargs, 'release') or 'all' releases = vault.get_vault()['releases'] if 'all' in release_name: start_week = release_start_week = _get_week(kwargs, 'start_date') end_week = release_end_week = _get_week(kwargs, 'end_date') else: release = releases[release_name] start_week = release_start_week = utils.timestamp_to_week( release['start_date']) end_week = release_end_week = utils.timestamp_to_week( release['end_date']) now = utils.timestamp_to_week(int(time.time())) + 1 # expand start-end to year if needed if release_end_week - release_start_week < 52: expansion = (52 - (release_end_week - release_start_week)) // 2 if release_end_week + expansion < now: end_week += expansion else: end_week = now start_week = end_week - 52 # empty stats for all weeks in range weeks = range(start_week, end_week) week_stat_loc = dict((c, 0) for c in weeks) week_stat_commits = dict((c, 0) for c in weeks) week_stat_commits_hl = dict((c, 0) for c in weeks) if ('commits' in metric) or ('loc' in metric): handler = lambda record: record.loc else: handler = lambda record: 0 # fill stats with the data if 'person-day' in metric: # special case for man-day effort metric release_stat = collections.defaultdict(set) all_stat = collections.defaultdict(set) for record in records: if start_week <= record.week < end_week: day = utils.timestamp_to_day(record.date) user_id = record.user_id if record.release == release_name: release_stat[day].add(user_id) all_stat[day].add(user_id) for day, users in six.iteritems(release_stat): week = utils.timestamp_to_week(day * 24 * 3600) week_stat_commits_hl[week] += len(users) for day, users in six.iteritems(all_stat): week = utils.timestamp_to_week(day * 24 * 3600) week_stat_commits[week] += len(users) else: for record in records: week = record.week if start_week <= week < end_week: week_stat_loc[week] += handler(record) week_stat_commits[week] += 1 if 'members' in metric: if record.date >= start_date: week_stat_commits_hl[week] += 1 else: if record.release == release_name: week_stat_commits_hl[week] += 1 if 'all' == release_name and 'members' not in metric: week_stat_commits_hl = week_stat_commits # form arrays in format acceptable to timeline plugin array_loc = [] array_commits = [] array_commits_hl = [] for week in weeks: week_str = utils.week_to_date(week) array_loc.append([week_str, week_stat_loc[week]]) array_commits.append([week_str, week_stat_commits[week]]) array_commits_hl.append([week_str, week_stat_commits_hl[week]]) return [array_commits, array_commits_hl, array_loc]
def templated_decorated_function(*args, **kwargs): vault_inst = vault.get_vault() template_name = template if template_name is None: template_name = (flask.request.endpoint.replace('.', '/') + '.html') ctx = f(*args, **kwargs) if ctx is None: ctx = {} try: _prepare_params(kwargs, []) except Exception: if return_code == 200: raise # do not re-raise on error page # put parameters into template ctx['metric'] = parameters.get_single_parameter(kwargs, 'metric', use_default=True) ctx['metric_label'] = parameters.METRIC_LABELS.get(ctx['metric']) project_type = parameters.get_single_parameter(kwargs, 'project_type', use_default=True) ctx['project_type'] = project_type ctx['release'] = parameters.get_single_parameter(kwargs, 'release', use_default=True) company = parameters.get_single_parameter(kwargs, 'company') ctx['company'] = company if company: ctx['company_original'] = ( vault.get_memory_storage().get_original_company_name( ctx['company'])) module = parameters.get_single_parameter(kwargs, 'module') ctx['module'] = module if module and module in vault_inst['module_id_index']: ctx['module_inst'] = vault_inst['module_id_index'][module] ctx['user_id'] = parameters.get_single_parameter(kwargs, 'user_id') if ctx['user_id']: ctx['user_inst'] = vault.get_user_from_runtime_storage( ctx['user_id']) ctx['page_title'] = helpers.make_page_title( ctx.get('release'), ctx.get('module_inst'), ctx.get('company_original'), ctx.get('user_inst')) ctx['stackalytics_version'] = ( stackalytics_version.version_info.version_string()) ctx['stackalytics_release'] = ( stackalytics_version.version_info.release_string()) ctx['runtime_storage_update_time'] = ( vault_inst['runtime_storage_update_time']) # deprecated -- top mentor report ctx['review_nth'] = parameters.get_single_parameter( kwargs, 'review_nth') return flask.render_template(template_name, **ctx), return_code
def timeline(records, **kwargs): # find start and end dates metric = parameters.get_parameter(kwargs, 'metric') start_date = int(parameters.get_single_parameter(kwargs, 'start_date') or 0) release_name = parameters.get_single_parameter(kwargs, 'release') or 'all' releases = vault.get_vault()['releases'] if 'all' in release_name: start_week = release_start_week = _get_week(kwargs, 'start_date') end_week = release_end_week = _get_week(kwargs, 'end_date') else: release = releases[release_name] start_week = release_start_week = utils.timestamp_to_week( release['start_date']) end_week = release_end_week = utils.timestamp_to_week( release['end_date']) now = utils.timestamp_to_week(int(time.time())) + 1 # expand start-end to year if needed if release_end_week - release_start_week < 52: expansion = (52 - (release_end_week - release_start_week)) // 2 if release_end_week + expansion < now: end_week += expansion else: end_week = now start_week = end_week - 52 # empty stats for all weeks in range weeks = range(start_week, end_week) week_stat_loc = dict((c, 0) for c in weeks) week_stat_commits = dict((c, 0) for c in weeks) week_stat_commits_hl = dict((c, 0) for c in weeks) if ('commits' in metric) or ('loc' in metric): handler = lambda record: record['loc'] else: handler = lambda record: 0 # fill stats with the data if 'person-day' in metric: # special case for man-day effort metric release_stat = collections.defaultdict(set) all_stat = collections.defaultdict(set) for record in records: if ((record['record_type'] in ['commit', 'member']) or (record['week'] not in weeks)): continue day = utils.timestamp_to_day(record['date']) user = vault.get_user_from_runtime_storage(record['user_id']) if record['release'] == release_name: release_stat[day] |= set([user['seq']]) all_stat[day] |= set([user['seq']]) for day, users in six.iteritems(release_stat): week = utils.timestamp_to_week(day * 24 * 3600) week_stat_commits_hl[week] += len(users) for day, users in six.iteritems(all_stat): week = utils.timestamp_to_week(day * 24 * 3600) week_stat_commits[week] += len(users) else: for record in records: week = record['week'] if week in weeks: week_stat_loc[week] += handler(record) week_stat_commits[week] += 1 if 'members' in metric: if record['date'] >= start_date: week_stat_commits_hl[week] += 1 else: if record['release'] == release_name: week_stat_commits_hl[week] += 1 if 'all' == release_name and 'members' not in metric: week_stat_commits_hl = week_stat_commits # form arrays in format acceptable to timeline plugin array_loc = [] array_commits = [] array_commits_hl = [] for week in weeks: week_str = utils.week_to_date(week) array_loc.append([week_str, week_stat_loc[week]]) array_commits.append([week_str, week_stat_commits[week]]) array_commits_hl.append([week_str, week_stat_commits_hl[week]]) return [array_commits, array_commits_hl, array_loc]