def _fetch_bundles(): """ Fetch bundles by bundle specs OR search keywords. """ keywords = query_get_list('keywords') specs = query_get_list('specs') worksheet_uuid = request.query.get('worksheet') descendant_depth = query_get_type(int, 'depth', None) if keywords: # Handle search keywords keywords = resolve_owner_in_keywords(keywords) bundle_uuids = local.model.search_bundle_uuids(request.user.user_id, worksheet_uuid, keywords) elif specs: # Resolve bundle specs bundle_uuids = canonicalize.get_bundle_uuids(local.model, request.user, worksheet_uuid, specs) else: abort( httplib.BAD_REQUEST, "Request must include either 'keywords' " "or 'specs' query parameter") # Find all descendants down to the provided depth if descendant_depth is not None: bundle_uuids = local.model.get_self_and_descendants( bundle_uuids, depth=descendant_depth) # Return simple dict if scalar result (e.g. .sum or .count queries) if not isinstance(bundle_uuids, list): return json_api_meta({}, {'result': bundle_uuids}) return build_bundles_document(bundle_uuids)
def interpret_search(query): """ Input: specification of a bundle search query. Output: worksheet items based on the result of issuing the search query. """ # Perform search keywords = rest_util.resolve_owner_in_keywords(query['keywords']) bundle_uuids = local.model.search_bundle_uuids(request.user.user_id, keywords) # Single number, just print it out... if not isinstance(bundle_uuids, list): return interpret_items(query['schemas'], [markup_item(str(bundle_uuids))]) # Set display items = [directive_item(('display', ) + tuple(query['display']))] # Show bundles bundle_infos = rest_util.get_bundle_infos(bundle_uuids) for bundle_uuid in bundle_uuids: items.append(bundle_item(bundle_infos[bundle_uuid])) # Finally, interpret the items return interpret_items(query['schemas'], items)
def expand_raw_item(raw_item): """ Raw items that include searches must be expanded into more raw items. Input: Raw item. Output: Array of raw items. If raw item does not need expanding, this returns an 1-length array that contains original raw item, otherwise it contains the search result. You do not need to call resolve_items_into_infos on the returned raw_items. """ (bundle_info, subworksheet_info, value_obj, item_type, id, sort_key) = raw_item is_search = item_type == TYPE_DIRECTIVE and get_command( value_obj) == 'search' is_wsearch = item_type == TYPE_DIRECTIVE and get_command( value_obj) == 'wsearch' if is_search or is_wsearch: command = get_command(value_obj) keywords = value_obj[1:] raw_items = [] if is_search: keywords = rest_util.resolve_owner_in_keywords(keywords) search_result = local.model.search_bundles(request.user.user_id, keywords) if search_result['is_aggregate']: # Add None's for the 'id' and 'sort_key' of the tuple, since these # items are not really worksheet items. raw_items.append( markup_item(str(search_result['result'])) + (None, None)) else: bundle_uuids = search_result['result'] bundle_infos = rest_util.get_bundle_infos(bundle_uuids) for bundle_uuid in bundle_uuids: # Since bundle UUID's are queried first, we can't assume a UUID exists in # the subsequent bundle info query. if bundle_uuid in bundle_infos: raw_items.append( bundle_item(bundle_infos[bundle_uuid]) + (None, None)) elif is_wsearch: worksheet_infos = search_worksheets(keywords) for worksheet_info in worksheet_infos: raw_items.append( subworksheet_item(worksheet_info) + (None, None)) return raw_items else: return [raw_item]
def fetch_worksheets(): """ Fetch worksheets by worksheet specs (names) OR search keywords. Query parameters: - `include`: comma-separated list of related resources to include, such as "owner" """ keywords = query_get_list('keywords') specs = query_get_list('specs') base_worksheet_uuid = request.query.get('base') include_set = query_get_json_api_include_set( supported={'owner', 'group_permissions'}) if specs: uuids = [ get_worksheet_uuid_or_create(base_worksheet_uuid, spec) for spec in specs ] worksheets = [ w.to_dict() for w in local.model.batch_get_worksheets(fetch_items=False, uuid=uuids) ] else: keywords = resolve_owner_in_keywords(keywords) worksheets = local.model.search_worksheets(request.user.user_id, keywords) # Build response document document = WorksheetSchema(many=True).dump(worksheets).data # Include users if 'owner' in include_set: owner_ids = {w['owner_id'] for w in worksheets} if owner_ids: json_api_include( document, UserSchema(), local.model.get_users(user_ids=owner_ids)['results']) # Include permissions if 'group_permissions' in include_set: for w in worksheets: if 'group_permissions' in w: json_api_include(document, WorksheetPermissionSchema(), w['group_permissions']) return document
def expand_raw_item(raw_item): """ Raw items that include searches must be expanded into more raw items. Input: Raw item. Output: Array of raw items. If raw item does not need expanding, this returns an 1-length array that contains original raw item, otherwise it contains the search result. You do not need to call resolve_items_into_infos on the returned raw_items. """ (bundle_info, subworksheet_info, value_obj, item_type) = raw_item is_search = item_type == TYPE_DIRECTIVE and get_command( value_obj) == 'search' is_wsearch = item_type == TYPE_DIRECTIVE and get_command( value_obj) == 'wsearch' if is_search or is_wsearch: command = get_command(value_obj) keywords = value_obj[1:] raw_items = [] if is_search: keywords = rest_util.resolve_owner_in_keywords(keywords) search_result = local.model.search_bundle_uuids( request.user.user_id, keywords) if not isinstance(search_result, list): raw_items.append(markup_item(str(search_result))) else: bundle_uuids = search_result bundle_infos = rest_util.get_bundle_infos(bundle_uuids) for bundle_uuid in bundle_uuids: raw_items.append(bundle_item(bundle_infos[bundle_uuid])) elif is_wsearch: worksheet_infos = search_worksheets(keywords) for worksheet_info in worksheet_infos: raw_items.append(subworksheet_item(worksheet_info)) return raw_items else: return [raw_item]
def perform_search_query(value_obj): """ Perform a search query and return the resulting raw items. Input: directive that is tokenized by formatting.string_to_tokens(), such as formatting.string_to_tokens("search 0x .limit=100") """ command = get_command(value_obj) is_search = command == 'search' is_wsearch = command == 'wsearch' if is_search or is_wsearch: keywords = value_obj[1:] raw_items = [] if is_search: keywords = rest_util.resolve_owner_in_keywords(keywords) search_result = local.model.search_bundles(request.user.user_id, keywords) if search_result['is_aggregate']: # Add None's for the 'id' and 'sort_key' of the tuple, since these # items are not really worksheet items. raw_items.append( markup_item(str(search_result['result'])) + (None, None)) else: bundle_uuids = search_result['result'] bundle_infos = rest_util.get_bundle_infos(bundle_uuids) for bundle_uuid in bundle_uuids: # Since bundle UUID's are queried first, we can't assume a UUID exists in # the subsequent bundle info query. if bundle_uuid in bundle_infos: raw_items.append( bundle_item(bundle_infos[bundle_uuid]) + (None, None)) elif is_wsearch: worksheet_infos = search_worksheets(keywords) for worksheet_info in worksheet_infos: raw_items.append( subworksheet_item(worksheet_info) + (None, None)) return raw_items else: # Not a search query return []
def fetch_worksheets(): """ Fetch bundles by bundle specs OR search keywords. """ keywords = query_get_list('keywords') specs = query_get_list('specs') base_worksheet_uuid = request.query.get('base') if specs: uuids = [ get_worksheet_uuid_or_create(base_worksheet_uuid, spec) for spec in specs ] worksheets = [ w.to_dict() for w in local.model.batch_get_worksheets(fetch_items=False, uuid=uuids) ] else: keywords = resolve_owner_in_keywords(keywords) worksheets = local.model.search_worksheets(request.user.user_id, keywords) # Build response document document = WorksheetSchema(many=True).dump(worksheets).data # Include users owner_ids = {w['owner_id'] for w in worksheets} if owner_ids: json_api_include(document, UserSchema(), local.model.get_users(owner_ids)) # Include permissions for w in worksheets: if 'group_permissions' in w: json_api_include(document, WorksheetPermissionSchema(), w['group_permissions']) return document
def expand_raw_item(raw_item): """ Raw items that include searches must be expanded into more raw items. Input: Raw item. Output: Array of raw items. If raw item does not need expanding, this returns an 1-length array that contains original raw item, otherwise it contains the search result. You do not need to call resolve_items_into_infos on the returned raw_items. """ (bundle_info, subworksheet_info, value_obj, item_type) = raw_item is_search = item_type == TYPE_DIRECTIVE and get_command(value_obj) == 'search' is_wsearch = item_type == TYPE_DIRECTIVE and get_command(value_obj) == 'wsearch' if is_search or is_wsearch: command = get_command(value_obj) keywords = value_obj[1:] raw_items = [] if is_search: keywords = rest_util.resolve_owner_in_keywords(keywords) search_result = local.model.search_bundles(request.user.user_id, keywords) if search_result['is_aggregate']: raw_items.append(markup_item(str(search_result['result']))) else: bundle_uuids = search_result['result'] bundle_infos = rest_util.get_bundle_infos(bundle_uuids) for bundle_uuid in bundle_uuids: raw_items.append(bundle_item(bundle_infos[bundle_uuid])) elif is_wsearch: worksheet_infos = search_worksheets(keywords) for worksheet_info in worksheet_infos: raw_items.append(subworksheet_item(worksheet_info)) return raw_items else: return [raw_item]
def fetch_worksheets(): """ Fetch worksheets by worksheet specs (names) OR search keywords. Query parameters: - `include`: comma-separated list of related resources to include, such as "owner" """ keywords = query_get_list('keywords') specs = query_get_list('specs') base_worksheet_uuid = request.query.get('base') include_set = query_get_json_api_include_set(supported={'owner', 'group_permissions'}) if specs: uuids = [get_worksheet_uuid_or_create(base_worksheet_uuid, spec) for spec in specs] worksheets = [ w.to_dict() for w in local.model.batch_get_worksheets(fetch_items=False, uuid=uuids) ] else: keywords = resolve_owner_in_keywords(keywords) worksheets = local.model.search_worksheets(request.user.user_id, keywords) # Build response document document = WorksheetSchema(many=True).dump(worksheets).data # Include users if 'owner' in include_set: owner_ids = {w['owner_id'] for w in worksheets} if owner_ids: json_api_include(document, UserSchema(), local.model.get_users(owner_ids)) # Include permissions if 'group_permissions' in include_set: for w in worksheets: if 'group_permissions' in w: json_api_include(document, WorksheetPermissionSchema(), w['group_permissions']) return document
def search_worksheets(keywords): keywords = resolve_owner_in_keywords(keywords) results = local.model.search_worksheets(request.user.user_id, keywords) _set_owner_names(results) return results
def _fetch_bundles(): """ Fetch bundles in the following two ways: 1. By bundle `specs` OR search `keywords` . Behavior is undefined when both `specs` and `keywords` are provided. Query parameters: - `worksheet`: UUID of the base worksheet. Required when fetching by specs. - `specs`: Bundle spec of bundle to fetch. May be provided multiples times to fetch multiple bundle specs. A bundle spec is either: 1. a UUID (8 or 32 hex characters with a preceding '0x') 2. a bundle name referring to the last bundle with that name on the given base worksheet 3. or a reverse index of the form `^N` referring to the Nth-to-last bundle on the given base worksheet. - `keywords`: Search keyword. May be provided multiple times for multiple keywords. Bare keywords match the names and descriptions of bundles. Examples of other special keyword forms: - `name=<name> ` : More targeted search of using metadata fields. - `size=.sort ` : Sort by a particular field. - `size=.sort- ` : Sort by a particular field in reverse. - `size=.sum ` : Compute total of a particular field. - `.mine ` : Match only bundles I own. - `.floating ` : Match bundles that aren't on any worksheet. - `.count ` : Count the number of bundles. - `.limit=10 ` : Limit the number of results to the top 10. - `include_display_metadata`: `1` to include additional metadata helpful for displaying the bundle info, `0` to omit them. Default is `0`. - `include`: comma-separated list of related resources to include, such as "owner" When aggregation keywords such as `.count` are used, the resulting value is returned as: ``` { "meta": { "results": <value> } } ``` 2. By bundle `command` and/or `dependencies` (for `--memoized` option in cl [run/mimic] command). When `dependencies` is not defined, the searching result will include bundles that match with command only. Query parameters: - `command` : the command of a bundle in string - `dependencies` : the dependencies of a bundle in the format of '[{"child_path":key1, "parent_uuid":UUID1}, {"child_path":key2, "parent_uuid":UUID2}]' 1. a UUID should be in the format of 32 hex characters with a preceding '0x' (partial UUID is not allowed). 2. the key should be able to uniquely identify a (child_path, parent_uuid) pair in the list. The returning result will be aggregated in the same way as 1. """ keywords = query_get_list('keywords') specs = query_get_list('specs') worksheet_uuid = request.query.get('worksheet') descendant_depth = query_get_type(int, 'depth', None) command = query_get_type(str, 'command', '') dependencies = query_get_type(str, 'dependencies', '[]') if keywords: # Handle search keywords keywords = resolve_owner_in_keywords(keywords) search_result = local.model.search_bundles(request.user.user_id, keywords) # Return simple dict if scalar result (e.g. .sum or .count queries) if search_result['is_aggregate']: return json_api_meta({}, {'result': search_result['result']}) # If not aggregate this is a list bundle_uuids = search_result['result'] elif specs: # Resolve bundle specs bundle_uuids = canonicalize.get_bundle_uuids(local.model, request.user, worksheet_uuid, specs) elif command: bundle_uuids = local.model.get_memoized_bundles( request.user.user_id, command, dependencies) else: abort( http.client.BAD_REQUEST, "Request must include either 'keywords' " "or 'specs' query parameter", ) # Find all descendants down to the provided depth if descendant_depth is not None: bundle_uuids = local.model.get_self_and_descendants( bundle_uuids, depth=descendant_depth) return build_bundles_document(bundle_uuids)
def search_bundles(keywords): keywords = resolve_owner_in_keywords(keywords) results = local.model.search_bundles(request.user.user_id, keywords) return results
def search_bundle_uuids(worksheet_uuid, keywords): keywords = resolve_owner_in_keywords(keywords) return local.model.search_bundle_uuids(request.user.user_id, worksheet_uuid, keywords)
def search_worksheets(keywords, worksheet_uuid=None): keywords = resolve_owner_in_keywords(keywords) results = local.model.search_worksheets(request.user.user_id, keywords) BundleService._set_owner_names(results) return results
def _fetch_bundles(): """ Fetch bundles by bundle `specs` OR search `keywords`. Behavior is undefined when both `specs` and `keywords` are provided. Query parameters: - `worksheet`: UUID of the base worksheet. Required when fetching by specs. - `specs`: Bundle spec of bundle to fetch. May be provided multiples times to fetch multiple bundle specs. A bundle spec is either: 1. a UUID (8 or 32 hex characters with a preceding '0x') 2. a bundle name referring to the last bundle with that name on the given base worksheet 3. or a reverse index of the form `^N` referring to the Nth-to-last bundle on the given base worksheet. - `keywords`: Search keyword. May be provided multiples times for multiple keywords. Bare keywords match the names and descriptions of bundles. Examples of other special keyword forms: - `name=<name> ` : More targeted search of using metadata fields. - `size=.sort ` : Sort by a particular field. - `size=.sort- ` : Sort by a particular field in reverse. - `size=.sum ` : Compute total of a particular field. - `.mine ` : Match only bundles I own. - `.floating ` : Match bundles that aren't on any worksheet. - `.count ` : Count the number of bundles. - `.limit=10 ` : Limit the number of results to the top 10. - `include_display_metadata`: `1` to include additional metadata helpful for displaying the bundle info, `0` to omit them. Default is `0`. - `include`: comma-separated list of related resources to include, such as "owner" When aggregation keywords such as `.count` are used, the resulting value is returned as: ``` { "meta": { "results": <value> } } ``` """ keywords = query_get_list('keywords') specs = query_get_list('specs') worksheet_uuid = request.query.get('worksheet') descendant_depth = query_get_type(int, 'depth', None) if keywords: # Handle search keywords keywords = resolve_owner_in_keywords(keywords) bundle_uuids = local.model.search_bundle_uuids(request.user.user_id, keywords) elif specs: # Resolve bundle specs bundle_uuids = canonicalize.get_bundle_uuids(local.model, request.user, worksheet_uuid, specs) else: abort(httplib.BAD_REQUEST, "Request must include either 'keywords' " "or 'specs' query parameter") # Find all descendants down to the provided depth if descendant_depth is not None: bundle_uuids = local.model.get_self_and_descendants(bundle_uuids, depth=descendant_depth) # Return simple dict if scalar result (e.g. .sum or .count queries) if not isinstance(bundle_uuids, list): return json_api_meta({}, {'result': bundle_uuids}) return build_bundles_document(bundle_uuids)