From f36fd65ab24cf8e42e57b29c4d7b813a4c19ed61 Mon Sep 17 00:00:00 2001 From: Ilya Shakhat Date: Wed, 21 May 2014 14:32:34 +0400 Subject: [PATCH] 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 --- dashboard/decorators.py | 228 +++++++++++++++++++------------- dashboard/parameters.py | 3 + dashboard/reports.py | 2 + dashboard/vault.py | 4 +- dashboard/web.py | 139 +++++++++++-------- stackalytics/processor/utils.py | 6 +- tests/api/test_companies.py | 5 - tests/api/test_modules.py | 8 -- tests/api/test_releases.py | 22 +-- tests/api/test_users.py | 20 --- 10 files changed, 235 insertions(+), 202 deletions(-) diff --git a/dashboard/decorators.py b/dashboard/decorators.py index d48eb9d05..467fcda82 100644 --- a/dashboard/decorators.py +++ b/dashboard/decorators.py @@ -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 diff --git a/dashboard/parameters.py b/dashboard/parameters.py index 74144877e..68f3a195a 100644 --- a/dashboard/parameters.py +++ b/dashboard/parameters.py @@ -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 diff --git a/dashboard/reports.py b/dashboard/reports.py index 12bff532c..9034d9a40 100644 --- a/dashboard/reports.py +++ b/dashboard/reports.py @@ -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') diff --git a/dashboard/vault.py b/dashboard/vault.py index 49ac91064..4bdb986a2 100644 --- a/dashboard/vault.py +++ b/dashboard/vault.py @@ -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) diff --git a/dashboard/web.py b/dashboard/web.py index 1188b468d..42ce3655e 100644 --- a/dashboard/web.py +++ b/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/') +@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/') +@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/') +@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/') +@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/') +@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/') +@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 diff --git a/stackalytics/processor/utils.py b/stackalytics/processor/utils.py index 8c1d0be2f..56e2f45fb 100644 --- a/stackalytics/processor/utils.py +++ b/stackalytics/processor/utils.py @@ -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) diff --git a/tests/api/test_companies.py b/tests/api/test_companies.py index c4927cace..79b5ee205 100644 --- a/tests/api/test_companies.py +++ b/tests/api/test_companies.py @@ -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', diff --git a/tests/api/test_modules.py b/tests/api/test_modules.py index 7631a700e..f832b55a3 100644 --- a/tests/api/test_modules.py +++ b/tests/api/test_modules.py @@ -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', diff --git a/tests/api/test_releases.py b/tests/api/test_releases.py index c777dc16e..a4d76a48d 100644 --- a/tests/api/test_releases.py +++ b/tests/api/test_releases.py @@ -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) diff --git a/tests/api/test_users.py b/tests/api/test_users.py index 9d580abd7..ca135b723 100644 --- a/tests/api/test_users.py +++ b/tests/api/test_users.py @@ -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': {