def fetch_details(options): """ Fetch details call for a BrAPI object (ex: /brapi/v1/studies/{id}) """ source, logger, entity, object_id = options if 'detail' not in entity: return detail_call_group = entity['detail'] in_store = object_id in entity['store'] skip_if_in_store = detail_call_group.get('skip-if-in-store') already_detailed = get_in(entity['store'], [object_id, 'etl:detailed']) if in_store and (skip_if_in_store or already_detailed): return entity_name = entity['name'] entity_id = entity_name + 'DbId' detail_call = get_implemented_call(source, detail_call_group, {entity_id: object_id}) if not detail_call: return details = BreedingAPIIterator.fetch_all(source['brapi:endpointUrl'], detail_call, logger).__next__() details['etl:detailed'] = True return entity_name, [details]
def fetch_all_links(source, logger, entities): """ Link objects across entities. - Internal: link an object (ex: study) to another using an identifier inside the JSON object (ex: link a location via study.locationDbId) - Internal object: link an object (ex: study) to another contained inside the first (ex: link a location via study.location.locationDbId) - External object: link an object (ex: study) to another using a dedicated call (ex: link to observation variables via /brapi/v1/studies/{id}/observationVariables) """ for (entity_name, entity) in entities.items(): if 'links' not in entity: continue for link in entity['links']: for (object_id, object) in entity['store'].items(): linked_entity_name = link['entity'] linked_entity = entities[linked_entity_name] linked_objects_by_id = {} if link['type'].startswith('internal'): link_path = link['json-path'] link_path_list = remove_empty(link_path.split('.')) link_values = remove_none(as_list(get_in(object, link_path_list))) if not link_values: if link.get('required'): raise BrokenLink("Could not find required field '{}' in {} object id '{}'" .format(link_path, entity_name, object_id)) continue if link['type'] == 'internal-object': for link_value in link_values: link_id = get_identifier(linked_entity_name, link_value) linked_objects_by_id[link_id] = link_value elif link['type'] == 'internal': link_id_field = linked_entity['name'] + 'DbId' link_name_field = linked_entity['name'] + 'Name' for link_value in link_values: link_id = link_value.get(link_id_field) link_name = link_value.get(link_name_field) if link_id: linked_objects_by_id[link_id] = {link_id_field: link_id, link_name_field: link_name} elif link['type'] == 'external-object': call = get_implemented_call(source, link, context=object) if not call: continue link_values = list(BreedingAPIIterator.fetch_all(source['brapi:endpointUrl'], call, logger)) for link_value in link_values: link_id = get_identifier(linked_entity_name, link_value) linked_objects_by_id[link_id] = link_value link_objects(entity, object, linked_entity, linked_objects_by_id)
def list_object(options): """ Fetch list for one entity (studies-search, germplasm-search, etc.) """ source, logger, entity = options if 'list' not in entity: return call = get_implemented_call(source, entity['list']) if call is None: return data_list = list(BreedingAPIIterator.fetch_all(source['brapi:endpointUrl'], call, logger)) return entity['name'], data_list
def fetch_details(options): """ Fetch details call for a BrAPI object (ex: /brapi/v1/studies/{id}) """ source, logger, entity, object_id = options if 'detail' not in entity: return detail_call_group = entity['detail'] in_store = object_id in entity['store'] skip_if_in_store = detail_call_group.get('skip-if-in-store') already_detailed = get_in(entity['store'], [object_id, 'etl:detailed']) if in_store and (skip_if_in_store or already_detailed): return entity_name = entity['name'] entity_id = entity_name + 'DbId' detail_call = get_implemented_call(source, detail_call_group, {entity_id: object_id}) if not detail_call: return details = BreedingAPIIterator.fetch_all(source['brapi:endpointUrl'], detail_call, logger).__next__() details['etl:detailed'] = True # ----------------------------------------------------------------- # Detect bugy endpoints that returns several studies instead of one. if "expect-single-result" in detail_call_group and detail_call_group[ "expect-single-result"] and 'data' in details and len( details['data']) != 1: logger.debug(f"More than one results for {detail_call}") raise EndPointError(f"More than one results for {detail_call}") if 'data' in details and len(details['data']) == 1: details = details['data'][0] # ----------------------------------------------------------------- return entity_name, [details]