Implemented caching for API calls
Introduced new decorators: * response - responsible for parameters processing * cached - get/set to cache Removed all search functionality in API methods. Fixed logging. implements bp cache-api-methods Change-Id: I91d36424a36442a09591c140e9f22401139b7415
This commit is contained in:
parent
68ecbf6db1
commit
f36fd65ab2
@ -32,28 +32,76 @@ from stackalytics import version as stackalytics_version
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _filter_records_by_days(ignore, start_date, end_date, memory_storage_inst):
|
||||
if start_date and 'start_date' not in ignore:
|
||||
start_date = utils.date_to_timestamp_ext(start_date)
|
||||
def _prepare_params(kwargs, ignore):
|
||||
params = kwargs.get('_params')
|
||||
|
||||
if not params:
|
||||
params = {'action': flask.request.path}
|
||||
for key in parameters.FILTER_PARAMETERS:
|
||||
params[key] = parameters.get_parameter(kwargs, key, key)
|
||||
|
||||
if params['start_date']:
|
||||
params['start_date'] = [utils.round_timestamp_to_day(
|
||||
params['start_date'][0])]
|
||||
if params['end_date']:
|
||||
params['end_date'] = [utils.round_timestamp_to_day(
|
||||
params['end_date'][0])]
|
||||
|
||||
kwargs['_params'] = params
|
||||
|
||||
if ignore:
|
||||
return dict([(k, v if k not in ignore else [])
|
||||
for k, v in six.iteritems(params)])
|
||||
else:
|
||||
start_date = memory_storage_inst.get_first_record_day()
|
||||
if end_date and 'end_date' not in ignore:
|
||||
end_date = utils.date_to_timestamp_ext(end_date)
|
||||
else:
|
||||
end_date = utils.date_to_timestamp_ext('now')
|
||||
|
||||
start_day = utils.timestamp_to_day(start_date)
|
||||
end_day = utils.timestamp_to_day(end_date)
|
||||
|
||||
return memory_storage_inst.get_record_ids_by_days(
|
||||
six.moves.range(start_day, end_day + 1))
|
||||
return params
|
||||
|
||||
|
||||
def record_filter(ignore=None, use_default=True):
|
||||
if not ignore:
|
||||
ignore = []
|
||||
def cached(ignore=None):
|
||||
def decorator(func):
|
||||
@functools.wraps(func)
|
||||
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
|
||||
|
||||
return prepare_params_decorated_function
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def record_filter(ignore=None):
|
||||
|
||||
def decorator(f):
|
||||
|
||||
def _filter_records_by_days(start_date, end_date, memory_storage_inst):
|
||||
if start_date:
|
||||
start_date = utils.date_to_timestamp_ext(start_date[0])
|
||||
else:
|
||||
start_date = memory_storage_inst.get_first_record_day()
|
||||
if end_date:
|
||||
end_date = utils.date_to_timestamp_ext(end_date[0])
|
||||
else:
|
||||
end_date = utils.date_to_timestamp_ext('now')
|
||||
|
||||
start_day = utils.timestamp_to_day(start_date)
|
||||
end_day = utils.timestamp_to_day(end_date)
|
||||
|
||||
return memory_storage_inst.get_record_ids_by_days(
|
||||
six.moves.range(start_day, end_day + 1))
|
||||
|
||||
def _filter_records_by_modules(memory_storage_inst, modules, releases):
|
||||
selected = set([])
|
||||
for m, r in vault.resolve_modules(modules, releases):
|
||||
@ -71,87 +119,74 @@ def record_filter(ignore=None, use_default=True):
|
||||
memory_storage_inst = vault.get_memory_storage()
|
||||
record_ids = set(memory_storage_inst.get_record_ids()) # a copy
|
||||
|
||||
releases = []
|
||||
if 'release' not in ignore:
|
||||
releases = parameters.get_parameter(kwargs, 'release',
|
||||
'releases', use_default)
|
||||
if releases:
|
||||
if 'all' not in releases:
|
||||
params = _prepare_params(kwargs, ignore)
|
||||
|
||||
release = params['release']
|
||||
if release:
|
||||
if 'all' not in release:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_releases(
|
||||
c.lower() for c in release))
|
||||
|
||||
project_type = params['project_type']
|
||||
if project_type:
|
||||
record_ids &= _filter_records_by_modules(
|
||||
memory_storage_inst,
|
||||
vault.resolve_project_types(project_type), release)
|
||||
|
||||
module = params['module']
|
||||
if module:
|
||||
record_ids &= _filter_records_by_modules(
|
||||
memory_storage_inst, module, release)
|
||||
|
||||
user_id = params['user_id']
|
||||
user_id = [u for u in user_id
|
||||
if vault.get_user_from_runtime_storage(u)]
|
||||
if user_id:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_user_ids(user_id))
|
||||
|
||||
company = params['company']
|
||||
if company:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_companies(company))
|
||||
|
||||
metric = params['metric']
|
||||
if 'all' not in metric:
|
||||
for metric in metric:
|
||||
if metric in parameters.METRIC_TO_RECORD_TYPE:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_releases(
|
||||
c.lower() for c in releases))
|
||||
memory_storage_inst.get_record_ids_by_type(
|
||||
parameters.METRIC_TO_RECORD_TYPE[metric]))
|
||||
|
||||
modules = parameters.get_parameter(kwargs, 'module', 'modules',
|
||||
use_default)
|
||||
if 'tm_marks' in metric:
|
||||
filtered_ids = []
|
||||
review_nth = int(parameters.get_parameter(
|
||||
kwargs, 'review_nth')[0])
|
||||
for record in memory_storage_inst.get_records(record_ids):
|
||||
parent = memory_storage_inst.get_record_by_primary_key(
|
||||
record['review_id'])
|
||||
if (parent and ('review_number' in parent) and
|
||||
(parent['review_number'] <= review_nth)):
|
||||
filtered_ids.append(record['record_id'])
|
||||
record_ids = filtered_ids
|
||||
|
||||
if 'project_type' not in ignore:
|
||||
param = parameters.get_parameter(kwargs, 'project_type',
|
||||
'project_types', use_default)
|
||||
if param:
|
||||
record_ids &= _filter_records_by_modules(
|
||||
memory_storage_inst,
|
||||
vault.resolve_project_types(param),
|
||||
releases)
|
||||
blueprint_id = params['blueprint_id']
|
||||
if blueprint_id:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_blueprint_ids(
|
||||
blueprint_id))
|
||||
|
||||
if 'module' not in ignore:
|
||||
if modules:
|
||||
record_ids &= _filter_records_by_modules(
|
||||
memory_storage_inst, modules, releases)
|
||||
start_date = params['start_date']
|
||||
end_date = params['end_date']
|
||||
|
||||
if 'user_id' not in ignore:
|
||||
param = parameters.get_parameter(kwargs, 'user_id', 'user_ids')
|
||||
param = [u for u in param
|
||||
if vault.get_user_from_runtime_storage(u)]
|
||||
if param:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_user_ids(param))
|
||||
|
||||
if 'company' not in ignore:
|
||||
param = parameters.get_parameter(kwargs, 'company',
|
||||
'companies')
|
||||
if param:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_companies(param))
|
||||
|
||||
if 'metric' not in ignore:
|
||||
metrics = parameters.get_parameter(kwargs, 'metric')
|
||||
if 'all' not in metrics:
|
||||
for metric in metrics:
|
||||
if metric in parameters.METRIC_TO_RECORD_TYPE:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_type(
|
||||
parameters.METRIC_TO_RECORD_TYPE[metric]))
|
||||
|
||||
if 'tm_marks' in metrics:
|
||||
filtered_ids = []
|
||||
review_nth = int(parameters.get_parameter(
|
||||
kwargs, 'review_nth')[0])
|
||||
for record in memory_storage_inst.get_records(record_ids):
|
||||
parent = memory_storage_inst.get_record_by_primary_key(
|
||||
record['review_id'])
|
||||
if (parent and ('review_number' in parent) and
|
||||
(parent['review_number'] <= review_nth)):
|
||||
filtered_ids.append(record['record_id'])
|
||||
record_ids = filtered_ids
|
||||
|
||||
if 'blueprint_id' not in ignore:
|
||||
param = parameters.get_parameter(kwargs, 'blueprint_id')
|
||||
if param:
|
||||
record_ids &= (
|
||||
memory_storage_inst.get_record_ids_by_blueprint_ids(
|
||||
param))
|
||||
|
||||
start_date = parameters.get_single_parameter(kwargs, 'start_date')
|
||||
end_date = parameters.get_single_parameter(kwargs, 'end_date')
|
||||
|
||||
if (start_date and 'start_date' not in ignore) or (
|
||||
end_date and 'end_date' not in ignore):
|
||||
record_ids &= _filter_records_by_days(ignore,
|
||||
start_date, end_date,
|
||||
if start_date or end_date:
|
||||
record_ids &= _filter_records_by_days(start_date, end_date,
|
||||
memory_storage_inst)
|
||||
|
||||
kwargs['record_ids'] = record_ids
|
||||
kwargs['records'] = memory_storage_inst.get_records(record_ids)
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
return record_filter_decorated_function
|
||||
@ -362,8 +397,19 @@ def jsonify(root='data'):
|
||||
def decorator(func):
|
||||
@functools.wraps(func)
|
||||
def jsonify_decorated_function(*args, **kwargs):
|
||||
return json.dumps({root: func(*args, **kwargs)})
|
||||
|
||||
return jsonify_decorated_function
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def response():
|
||||
def decorator(func):
|
||||
@functools.wraps(func)
|
||||
def response_decorated_function(*args, **kwargs):
|
||||
callback = flask.app.request.args.get('callback', False)
|
||||
data = json.dumps({root: func(*args, **kwargs)})
|
||||
data = func(*args, **kwargs)
|
||||
|
||||
if callback:
|
||||
data = str(callback) + '(' + data + ')'
|
||||
@ -373,7 +419,7 @@ def jsonify(root='data'):
|
||||
|
||||
return flask.current_app.response_class(data, mimetype=mimetype)
|
||||
|
||||
return jsonify_decorated_function
|
||||
return response_decorated_function
|
||||
|
||||
return decorator
|
||||
|
||||
|
@ -48,6 +48,9 @@ METRIC_TO_RECORD_TYPE = {
|
||||
'members': 'member',
|
||||
}
|
||||
|
||||
FILTER_PARAMETERS = ['release', 'project_type', 'module', 'company', 'user_id',
|
||||
'metric', 'start_date', 'end_date', 'blueprint_id']
|
||||
|
||||
DEFAULT_RECORDS_LIMIT = 10
|
||||
DEFAULT_STATIC_ACTIVITY_SIZE = 100
|
||||
|
||||
|
@ -223,6 +223,7 @@ def activity():
|
||||
|
||||
|
||||
@blueprint.route('/large_commits')
|
||||
@decorators.response()
|
||||
@decorators.jsonify('commits')
|
||||
@decorators.exception_handler()
|
||||
@decorators.record_filter()
|
||||
@ -240,6 +241,7 @@ def get_commit_report(records, **kwargs):
|
||||
|
||||
|
||||
@blueprint.route('/single_plus_two_reviews')
|
||||
@decorators.response()
|
||||
@decorators.jsonify()
|
||||
@decorators.exception_handler()
|
||||
@decorators.record_filter(ignore='metric')
|
||||
|
@ -62,8 +62,6 @@ def get_vault():
|
||||
vault['memory_storage'] = memory_storage.get_memory_storage(
|
||||
memory_storage.MEMORY_STORAGE_CACHED)
|
||||
|
||||
_init_releases(vault)
|
||||
|
||||
flask.current_app.stackalytics_vault = vault
|
||||
except Exception as e:
|
||||
LOG.critical('Failed to initialize application: %s', e)
|
||||
@ -77,6 +75,8 @@ def get_vault():
|
||||
compact_records(vault['runtime_storage'].get_update(os.getpid())))
|
||||
|
||||
if have_updates:
|
||||
vault['cache'] = {}
|
||||
vault['cache_size'] = 0
|
||||
_init_releases(vault)
|
||||
_init_module_groups(vault)
|
||||
_init_project_types(vault)
|
||||
|
139
dashboard/web.py
139
dashboard/web.py
@ -46,15 +46,14 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
conf = cfg.CONF
|
||||
conf.register_opts(config.OPTS)
|
||||
logging.setup('dashboard')
|
||||
LOG.info('Logging enabled')
|
||||
|
||||
conf_file = os.getenv('STACKALYTICS_CONF')
|
||||
if conf_file and os.path.isfile(conf_file):
|
||||
conf(default_config_files=[conf_file])
|
||||
app.config['DEBUG'] = cfg.CONF.debug
|
||||
else:
|
||||
LOG.info('Conf file is empty or not exist')
|
||||
|
||||
logging.setup('dashboard')
|
||||
LOG.info('Stackalytics.dashboard is configured via "%s"', conf_file)
|
||||
|
||||
|
||||
# Handlers ---------
|
||||
@ -94,9 +93,10 @@ def _get_aggregated_stats(records, metric_filter, keys, param_id,
|
||||
|
||||
|
||||
@app.route('/api/1.0/new_companies')
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.exception_handler()
|
||||
@decorators.record_filter(ignore='start_date')
|
||||
@decorators.response()
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.record_filter(ignore=['start_date'])
|
||||
def get_new_companies(records, **kwargs):
|
||||
|
||||
days = int(flask.request.args.get('days') or reports.DEFAULT_DAYS_COUNT)
|
||||
@ -123,8 +123,10 @@ def get_new_companies(records, **kwargs):
|
||||
|
||||
|
||||
@app.route('/api/1.0/stats/companies')
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.exception_handler()
|
||||
@decorators.response()
|
||||
@decorators.cached()
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.record_filter()
|
||||
@decorators.aggregate_filter()
|
||||
def get_companies(records, metric_filter, finalize_handler, **kwargs):
|
||||
@ -135,8 +137,10 @@ def get_companies(records, metric_filter, finalize_handler, **kwargs):
|
||||
|
||||
|
||||
@app.route('/api/1.0/stats/modules')
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.exception_handler()
|
||||
@decorators.response()
|
||||
@decorators.cached()
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.record_filter()
|
||||
@decorators.aggregate_filter()
|
||||
def get_modules(records, metric_filter, finalize_handler, **kwargs):
|
||||
@ -156,8 +160,10 @@ def get_core_engineer_branch(user, modules):
|
||||
|
||||
|
||||
@app.route('/api/1.0/stats/engineers')
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.exception_handler()
|
||||
@decorators.response()
|
||||
@decorators.cached()
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.record_filter()
|
||||
@decorators.aggregate_filter()
|
||||
def get_engineers(records, metric_filter, finalize_handler, **kwargs):
|
||||
@ -179,9 +185,11 @@ def get_engineers(records, metric_filter, finalize_handler, **kwargs):
|
||||
|
||||
|
||||
@app.route('/api/1.0/stats/engineers_extended')
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.exception_handler()
|
||||
@decorators.record_filter(ignore='metric')
|
||||
@decorators.response()
|
||||
@decorators.cached(ignore=['metric'])
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.record_filter(ignore=['metric'])
|
||||
def get_engineers_extended(records, **kwargs):
|
||||
modules_names = parameters.get_parameter({}, 'module', 'modules')
|
||||
modules = set([m for m, r in vault.resolve_modules(modules_names, [''])])
|
||||
@ -224,8 +232,10 @@ def get_engineers_extended(records, **kwargs):
|
||||
|
||||
|
||||
@app.route('/api/1.0/stats/distinct_engineers')
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.exception_handler()
|
||||
@decorators.response()
|
||||
@decorators.cached()
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.record_filter()
|
||||
def get_distinct_engineers(records, **kwargs):
|
||||
result = {}
|
||||
@ -238,8 +248,9 @@ def get_distinct_engineers(records, **kwargs):
|
||||
|
||||
|
||||
@app.route('/api/1.0/activity')
|
||||
@decorators.jsonify('activity')
|
||||
@decorators.exception_handler()
|
||||
@decorators.response()
|
||||
@decorators.jsonify('activity')
|
||||
@decorators.record_filter()
|
||||
def get_activity_json(records, **kwargs):
|
||||
start_record = int(flask.request.args.get('start_record') or 0)
|
||||
@ -251,38 +262,40 @@ def get_activity_json(records, **kwargs):
|
||||
|
||||
|
||||
@app.route('/api/1.0/contribution')
|
||||
@decorators.jsonify('contribution')
|
||||
@decorators.exception_handler()
|
||||
@decorators.record_filter(ignore='metric')
|
||||
@decorators.response()
|
||||
@decorators.cached(ignore=['metric'])
|
||||
@decorators.jsonify('contribution')
|
||||
@decorators.record_filter(ignore=['metric'])
|
||||
def get_contribution_json(records, **kwargs):
|
||||
return helpers.get_contribution_summary(records)
|
||||
|
||||
|
||||
@app.route('/api/1.0/companies')
|
||||
@decorators.jsonify('companies')
|
||||
@decorators.exception_handler()
|
||||
@decorators.record_filter(ignore='company')
|
||||
@decorators.query_filter(query_param='company_name')
|
||||
def get_companies_json(record_ids, query_filter, **kwargs):
|
||||
@decorators.response()
|
||||
@decorators.cached(ignore=['company'])
|
||||
@decorators.jsonify('companies')
|
||||
@decorators.record_filter(ignore=['company'])
|
||||
def get_companies_json(record_ids, **kwargs):
|
||||
memory_storage = vault.get_memory_storage()
|
||||
companies = memory_storage.get_index_keys_by_record_ids(
|
||||
'company_name', record_ids)
|
||||
|
||||
result = []
|
||||
for company in companies:
|
||||
if query_filter(company):
|
||||
result.append(memory_storage.get_original_company_name(company))
|
||||
result = [memory_storage.get_original_company_name(company)
|
||||
for company in companies]
|
||||
|
||||
return [{'id': utils.safe_encode(c.lower()), 'text': c}
|
||||
for c in sorted(result)]
|
||||
|
||||
|
||||
@app.route('/api/1.0/modules')
|
||||
@decorators.jsonify('modules')
|
||||
@decorators.exception_handler()
|
||||
@decorators.record_filter(ignore='module')
|
||||
@decorators.query_filter(query_param='query')
|
||||
def get_modules_json(record_ids, query_filter, **kwargs):
|
||||
@decorators.response()
|
||||
@decorators.cached(ignore=['module'])
|
||||
@decorators.jsonify('modules')
|
||||
@decorators.record_filter(ignore=['module'])
|
||||
def get_modules_json(record_ids, **kwargs):
|
||||
module_id_index = vault.get_vault()['module_id_index']
|
||||
|
||||
tags = parameters.get_parameter({}, 'tag', 'tags')
|
||||
@ -305,15 +318,15 @@ def get_modules_json(record_ids, query_filter, **kwargs):
|
||||
result = []
|
||||
for module_id in module_ids:
|
||||
module = module_id_index[module_id]
|
||||
if query_filter(module['module_group_name']):
|
||||
result.append({'id': module['id'],
|
||||
'text': module['module_group_name'],
|
||||
'tag': module['tag']})
|
||||
result.append({'id': module['id'],
|
||||
'text': module['module_group_name'],
|
||||
'tag': module['tag']})
|
||||
|
||||
return sorted(result, key=operator.itemgetter('text'))
|
||||
|
||||
|
||||
@app.route('/api/1.0/companies/<company_name>')
|
||||
@decorators.response()
|
||||
@decorators.jsonify('company')
|
||||
def get_company(company_name):
|
||||
memory_storage_inst = vault.get_memory_storage()
|
||||
@ -328,6 +341,7 @@ def get_company(company_name):
|
||||
|
||||
|
||||
@app.route('/api/1.0/modules/<module>')
|
||||
@decorators.response()
|
||||
@decorators.jsonify('module')
|
||||
def get_module(module):
|
||||
module_id_index = vault.get_vault()['module_id_index']
|
||||
@ -340,8 +354,10 @@ def get_module(module):
|
||||
|
||||
|
||||
@app.route('/api/1.0/members')
|
||||
@decorators.jsonify('members')
|
||||
@decorators.exception_handler()
|
||||
@decorators.response()
|
||||
@decorators.cached(ignore=['release', 'project_type', 'module'])
|
||||
@decorators.jsonify('members')
|
||||
@decorators.record_filter(ignore=['release', 'project_type', 'module'])
|
||||
def get_members(records, **kwargs):
|
||||
response = []
|
||||
@ -359,8 +375,10 @@ def get_members(records, **kwargs):
|
||||
|
||||
|
||||
@app.route('/api/1.0/stats/bp')
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.exception_handler()
|
||||
@decorators.response()
|
||||
@decorators.cached()
|
||||
@decorators.jsonify('stats')
|
||||
@decorators.record_filter()
|
||||
def get_bpd(records, **kwargs):
|
||||
result = []
|
||||
@ -389,25 +407,26 @@ def get_bpd(records, **kwargs):
|
||||
|
||||
|
||||
@app.route('/api/1.0/users')
|
||||
@decorators.jsonify('users')
|
||||
@decorators.exception_handler()
|
||||
@decorators.record_filter(ignore='user_id')
|
||||
@decorators.query_filter(query_param='user_name')
|
||||
def get_users_json(record_ids, query_filter, **kwargs):
|
||||
@decorators.response()
|
||||
@decorators.cached(ignore=['user_id'])
|
||||
@decorators.jsonify('users')
|
||||
@decorators.record_filter(ignore=['user_id'])
|
||||
def get_users_json(record_ids, **kwargs):
|
||||
user_ids = vault.get_memory_storage().get_index_keys_by_record_ids(
|
||||
'user_id', record_ids)
|
||||
|
||||
result = []
|
||||
for user_id in user_ids:
|
||||
user_name = vault.get_user_from_runtime_storage(user_id)['user_name']
|
||||
if query_filter(user_name):
|
||||
result.append({'id': user_id, 'text': user_name})
|
||||
result = [{'id': user_id,
|
||||
'text': (vault.get_user_from_runtime_storage(user_id)
|
||||
['user_name'])}
|
||||
for user_id in user_ids]
|
||||
|
||||
result.sort(key=lambda x: x['text'])
|
||||
return result
|
||||
|
||||
|
||||
@app.route('/api/1.0/users/<user_id>')
|
||||
@decorators.response()
|
||||
@decorators.jsonify('user')
|
||||
def get_user(user_id):
|
||||
user = vault.get_user_from_runtime_storage(user_id)
|
||||
@ -418,16 +437,17 @@ def get_user(user_id):
|
||||
|
||||
|
||||
@app.route('/api/1.0/releases')
|
||||
@decorators.jsonify('releases')
|
||||
@decorators.exception_handler()
|
||||
@decorators.query_filter(query_param='query')
|
||||
def get_releases_json(query_filter):
|
||||
@decorators.response()
|
||||
@decorators.cached(ignore=parameters.FILTER_PARAMETERS)
|
||||
@decorators.jsonify('releases')
|
||||
def get_releases_json(**kwargs):
|
||||
return [{'id': r['release_name'], 'text': r['release_name'].capitalize()}
|
||||
for r in vault.get_release_options()
|
||||
if query_filter(r['release_name'])]
|
||||
for r in vault.get_release_options()]
|
||||
|
||||
|
||||
@app.route('/api/1.0/releases/<release>')
|
||||
@decorators.response()
|
||||
@decorators.jsonify('release')
|
||||
def get_release_json(release):
|
||||
if release != 'all':
|
||||
@ -438,17 +458,18 @@ def get_release_json(release):
|
||||
|
||||
|
||||
@app.route('/api/1.0/metrics')
|
||||
@decorators.jsonify('metrics')
|
||||
@decorators.exception_handler()
|
||||
@decorators.query_filter(query_param='query')
|
||||
def get_metrics_json(query_filter):
|
||||
@decorators.response()
|
||||
@decorators.cached(ignore=parameters.FILTER_PARAMETERS)
|
||||
@decorators.jsonify('metrics')
|
||||
def get_metrics_json(**kwargs):
|
||||
return sorted([{'id': m, 'text': t}
|
||||
for m, t in six.iteritems(parameters.METRIC_LABELS)
|
||||
if query_filter(t)],
|
||||
for m, t in six.iteritems(parameters.METRIC_LABELS)],
|
||||
key=operator.itemgetter('text'))
|
||||
|
||||
|
||||
@app.route('/api/1.0/metrics/<metric>')
|
||||
@decorators.response()
|
||||
@decorators.jsonify('metric')
|
||||
@decorators.exception_handler()
|
||||
def get_metric_json(metric):
|
||||
@ -458,15 +479,17 @@ def get_metric_json(metric):
|
||||
|
||||
|
||||
@app.route('/api/1.0/project_types')
|
||||
@decorators.jsonify('project_types')
|
||||
@decorators.response()
|
||||
@decorators.exception_handler()
|
||||
@decorators.query_filter(query_param='query')
|
||||
def get_project_types_json(query_filter):
|
||||
@decorators.cached(ignore=parameters.FILTER_PARAMETERS)
|
||||
@decorators.jsonify('project_types')
|
||||
def get_project_types_json(**kwargs):
|
||||
return [{'id': pt['id'], 'text': pt['title'], 'items': pt.get('items', [])}
|
||||
for pt in vault.get_project_types() if query_filter(pt['title'])]
|
||||
for pt in vault.get_project_types()]
|
||||
|
||||
|
||||
@app.route('/api/1.0/project_types/<project_type>')
|
||||
@decorators.response()
|
||||
@decorators.jsonify('project_type')
|
||||
@decorators.exception_handler()
|
||||
def get_project_type_json(project_type):
|
||||
@ -487,8 +510,10 @@ def _get_week(kwargs, param_name):
|
||||
|
||||
|
||||
@app.route('/api/1.0/stats/timeline')
|
||||
@decorators.jsonify('timeline')
|
||||
@decorators.exception_handler()
|
||||
@decorators.response()
|
||||
@decorators.cached()
|
||||
@decorators.jsonify('timeline')
|
||||
@decorators.record_filter(ignore=['release', 'start_date'])
|
||||
def timeline(records, **kwargs):
|
||||
# find start and end dates
|
||||
|
@ -42,7 +42,7 @@ def date_to_timestamp(d):
|
||||
def date_to_timestamp_ext(d):
|
||||
try:
|
||||
return date_to_timestamp(d)
|
||||
except ValueError:
|
||||
except (ValueError, TypeError):
|
||||
return int(d)
|
||||
|
||||
|
||||
@ -72,6 +72,10 @@ def timestamp_to_day(timestamp):
|
||||
return timestamp // (24 * 3600)
|
||||
|
||||
|
||||
def round_timestamp_to_day(timestamp):
|
||||
return (int(timestamp) // (24 * 3600)) * (24 * 3600)
|
||||
|
||||
|
||||
def check_email_validity(email):
|
||||
if email:
|
||||
return re.match(r'[\w\d_\.-]+@([\w\d_\.-]+\.)+[\w]+', email)
|
||||
|
@ -70,11 +70,6 @@ class TestAPICompanies(test_api.TestAPI):
|
||||
self.assertEqual([{'id': 'ibm', 'text': 'IBM'},
|
||||
{'id': 'nec', 'text': 'NEC'}], companies)
|
||||
|
||||
response = self.app.get('/api/1.0/companies?metric=commits&'
|
||||
'company_name=ib&module=glance')
|
||||
companies = json.loads(response.data)['companies']
|
||||
self.assertEqual([{'id': 'ibm', 'text': 'IBM'}], companies)
|
||||
|
||||
def test_get_company(self):
|
||||
with test_api.make_runtime_storage(
|
||||
{'repos': [{'module': 'nova', 'project_type': 'openstack',
|
||||
|
@ -68,14 +68,6 @@ class TestAPIModules(test_api.TestAPI):
|
||||
'module groups that are completely within '
|
||||
'project type')
|
||||
|
||||
response = self.app.get('/api/1.0/modules?query=glance&'
|
||||
'project_type=all&metric=commits')
|
||||
modules = json.loads(response.data)['modules']
|
||||
self.assertEqual(
|
||||
[{'id': 'glance', 'text': 'glance', 'tag': 'module'}],
|
||||
modules,
|
||||
message='Expected modules which name contains query')
|
||||
|
||||
def test_get_module(self):
|
||||
with test_api.make_runtime_storage(
|
||||
{'repos': [{'module': 'nova', 'organization': 'openstack',
|
||||
|
@ -20,39 +20,25 @@ from tests.api import test_api
|
||||
|
||||
class TestAPIReleases(test_api.TestAPI):
|
||||
|
||||
def test_releases_empty(self):
|
||||
with test_api.make_runtime_storage({}):
|
||||
response = self.app.get('/api/1.0/releases')
|
||||
self.assertEqual(200, response.status_code)
|
||||
|
||||
def test_releases(self):
|
||||
with test_api.make_runtime_storage(
|
||||
{'releases': [
|
||||
{'release_name': 'prehistory', 'end_date': 1365033600},
|
||||
{'release_name': 'havana', 'end_date': 1381968000},
|
||||
{'release_name': 'icehouse', 'end_date': 1397692800}]}):
|
||||
{'release_name': 'icehouse', 'end_date': 1397692800}]},
|
||||
test_api.make_records(record_type=['commit'])):
|
||||
response = self.app.get('/api/1.0/releases')
|
||||
releases = json.loads(response.data)['releases']
|
||||
self.assertEqual(3, len(releases))
|
||||
self.assertIn({'id': 'all', 'text': 'All'}, releases)
|
||||
self.assertIn({'id': 'icehouse', 'text': 'Icehouse'}, releases)
|
||||
|
||||
def test_releases_search(self):
|
||||
with test_api.make_runtime_storage(
|
||||
{'releases': [
|
||||
{'release_name': 'prehistory', 'end_date': 1365033600},
|
||||
{'release_name': 'havana', 'end_date': 1381968000},
|
||||
{'release_name': 'icehouse', 'end_date': 1397692800}]}):
|
||||
response = self.app.get('/api/1.0/releases?query=hav')
|
||||
releases = json.loads(response.data)['releases']
|
||||
self.assertEqual(1, len(releases))
|
||||
self.assertIn({'id': 'havana', 'text': 'Havana'}, releases)
|
||||
|
||||
def test_release_details(self):
|
||||
with test_api.make_runtime_storage(
|
||||
{'releases': [
|
||||
{'release_name': 'prehistory', 'end_date': 1365033600},
|
||||
{'release_name': 'icehouse', 'end_date': 1397692800}]}):
|
||||
{'release_name': 'icehouse', 'end_date': 1397692800}]},
|
||||
test_api.make_records(record_type=['commit'])):
|
||||
response = self.app.get('/api/1.0/releases/icehouse')
|
||||
release = json.loads(response.data)['release']
|
||||
self.assertEqual({'id': 'icehouse', 'text': 'Icehouse'}, release)
|
||||
|
@ -41,26 +41,6 @@ class TestAPIUsers(test_api.TestAPI):
|
||||
self.assertIn({'id': 'john_doe', 'text': 'John Doe'}, users)
|
||||
self.assertIn({'id': 'bill_smith', 'text': 'Bill Smith'}, users)
|
||||
|
||||
def test_users_search(self):
|
||||
with test_api.make_runtime_storage(
|
||||
{'repos': [{'module': 'nova', 'organization': 'openstack',
|
||||
'uri': 'git://github.com/openstack/nova.git'}],
|
||||
'project_types': [
|
||||
{'id': 'openstack', 'title': 'openstack',
|
||||
'modules': ['nova', 'glance']}],
|
||||
'module_groups': {
|
||||
'nova': test_api.make_module('nova'),
|
||||
'glance': test_api.make_module('glance')},
|
||||
'user:john_doe': {'user_name': 'John Doe'},
|
||||
'user:bill_smith': {'user_name': 'Bill Smith'}},
|
||||
test_api.make_records(record_type=['commit'], module=['nova'],
|
||||
user_name=['John Doe', 'Bill Smith'])):
|
||||
response = self.app.get('/api/1.0/users?'
|
||||
'module=nova&query=doe&metric=commits')
|
||||
users = json.loads(response.data)['users']
|
||||
self.assertEqual(1, len(users))
|
||||
self.assertIn({'id': 'john_doe', 'text': 'John Doe'}, users)
|
||||
|
||||
def test_user_details(self):
|
||||
with test_api.make_runtime_storage(
|
||||
{'user:john_doe': {
|
||||
|
Loading…
x
Reference in New Issue
Block a user