Exemple #1
0
    def test_get_static_enumeration(self):
        rq, _ = self.loader.getTextForName('test-enum')

        metadata = gquery.get_metadata(rq, '')
        self.assertIn('enumerate', metadata, 'Should contain enumerate')

        enumeration = gquery.get_enumeration(rq, 'o',
                                             'http://mock-endpoint/sparql',
                                             metadata)
        self.assertIsInstance(enumeration, list,
                              'Should return a list of values')
        self.assertEquals(len(enumeration), 2, 'Should have two elements')
Exemple #2
0
    def test_get_metadata(self):
        rq, _ = self.loader.getTextForName('test-sparql')

        metadata = gquery.get_metadata(rq, '')
        self.assertIn('type', metadata, 'Should have a type field')
        self.assertIn('variables', metadata, 'Should have a variables field')
        self.assertEqual(metadata['type'], 'SelectQuery',
                         'Should be type SelectQuery')
        self.assertIsInstance(
            metadata['variables'], list, 'Should be a list of variables')
        for var in metadata['variables']:
            self.assertIsInstance(var, rdflib.term.Variable,
                                  'Should be of type Variable')
Exemple #3
0
def dispatchSPARQLQuery(raw_sparql_query, loader, requestArgs, acceptHeader,
                        content, formData, requestUrl):
    """Executes the specified SPARQL query."""
    endpoint, auth = gquery.guess_endpoint_uri(raw_sparql_query, loader)
    if endpoint == '':
        return 'No SPARQL endpoint indicated', 407, {}

    glogger.debug("=====================================================")
    glogger.debug("Sending query to SPARQL endpoint: {}".format(endpoint))
    glogger.debug("=====================================================")

    try:
        query_metadata = gquery.get_metadata(raw_sparql_query, endpoint)
    except Exception as e:
        # extracting metadata
        return {'error': str(e)}, 400, {}

    acceptHeader = 'application/json' if isinstance(raw_sparql_query,
                                                    dict) else acceptHeader
    pagination = query_metadata[
        'pagination'] if 'pagination' in query_metadata else ""

    rewritten_query = query_metadata['query']

    # Rewrite query using parameter values
    if query_metadata['type'] == 'SelectQuery' or query_metadata[
            'type'] == 'ConstructQuery':
        rewritten_query = gquery.rewrite_query(
            query_metadata['original_query'], query_metadata['parameters'],
            requestArgs)

    # Rewrite query using pagination
    if query_metadata[
            'type'] == 'SelectQuery' and 'pagination' in query_metadata:
        rewritten_query = gquery.paginate_query(rewritten_query,
                                                query_metadata['pagination'],
                                                requestArgs)

    resp = None
    headers = {}

    # If we have a mime field, we load the remote dump and query it locally
    if 'mime' in query_metadata and query_metadata['mime']:
        glogger.debug(
            "Detected {} MIME type, proceeding with locally loading remote dump"
            .format(query_metadata['mime']))
        g = Graph()
        try:
            query_metadata = gquery.get_metadata(raw_sparql_query, endpoint)
            g.parse(endpoint, format=query_metadata['mime'])
            glogger.debug(
                "Local RDF graph loaded successfully with {} triples".format(
                    len(g)))
        except Exception as e:
            glogger.error(e)
        results = g.query(rewritten_query, result='sparql')
        # Prepare return format as requested
        resp_string = ""
        if 'application/json' in acceptHeader or (
                content and 'application/json' in static.mimetypes[content]):
            resp_string = results.serialize(format='json')
            glogger.debug(
                "Results of SPARQL query against locally loaded dump: {}".
                format(resp_string))
        elif 'text/csv' in acceptHeader or (content and 'text/csv'
                                            in static.mimetypes[content]):
            resp_string = results.serialize(format='csv')
            glogger.debug(
                "Results of SPARQL query against locally loaded dump: {}".
                format(resp_string))
        else:
            return 'Unacceptable requested format', 415, {}
        glogger.debug(
            "Finished processing query against RDF dump, end of use case")
        del g

    # Check for INSERT/POST
    elif query_metadata['type'] == 'InsertData':
        glogger.debug("Processing INSERT query")
        # Rewrite INSERT
        rewritten_query = rewritten_query.replace(
            "?_g_iri", "{}".format(formData.get('g')))
        rewritten_query = rewritten_query.replace("<s> <p> <o>",
                                                  formData.get('data'))
        glogger.debug("INSERT query rewritten as {}".format(rewritten_query))

        # Prepare HTTP POST request
        reqHeaders = {
            'Accept': acceptHeader,
            'Content-Type': 'application/sparql-update'
        }
        response = requests.post(endpoint,
                                 data=rewritten_query,
                                 headers=reqHeaders,
                                 auth=auth)
        glogger.debug('Response header from endpoint: ' +
                      response.headers['Content-Type'])

        # Response headers
        resp = response.text
        headers['Content-Type'] = response.headers['Content-Type']

    # If there's no mime type, the endpoint is an actual SPARQL endpoint
    else:
        reqHeaders = {'Accept': acceptHeader}
        if content:
            reqHeaders = {'Accept': static.mimetypes[content]}
        data = {'query': rewritten_query}

        glogger.debug(
            'Sending HTTP request to SPARQL endpoint with params: {}'.format(
                data))
        glogger.debug(
            'Sending HTTP request to SPARQL endpoint with headers: {}'.format(
                reqHeaders))
        glogger.debug(
            'Sending HTTP request to SPARQL endpoint with auth: {}'.format(
                auth))
        try:
            response = requests.get(endpoint,
                                    params=data,
                                    headers=reqHeaders,
                                    auth=auth)
        except Exception as e:
            # Error contacting SPARQL endpoint
            glogger.debug(
                'Exception encountered while connecting to SPARQL endpoint')
            return {'error': str(e)}, 400, headers
        glogger.debug('Response header from endpoint: ' +
                      response.headers['Content-Type'])

        # Response headers
        resp = response.text
        headers['Content-Type'] = response.headers['Content-Type']

    # If the query is paginated, set link HTTP headers
    if pagination:
        # Get number of total results
        count = gquery.count_query_results(rewritten_query, endpoint)
        pageArg = requestArgs.get('page', None)

        url = urlparse(requestUrl)
        replaced = url._replace(netloc=static.SERVER_NAME)
        headerLink = pageUtils.buildPaginationHeader(count,
                                                     pagination, pageArg,
                                                     replaced.geturl())
        headers['Link'] = headerLink

    if 'proto' in query_metadata:  # sparql transformer
        resp = SPARQLTransformer.post_process(json.loads(resp),
                                              query_metadata['proto'],
                                              query_metadata['opt'])

    if 'transform' in query_metadata and acceptHeader == 'application/json':  # sparql transformer
        rq = {'proto': query_metadata['transform']}
        _, _, opt = SPARQLTransformer.pre_process(rq)
        resp = SPARQLTransformer.post_process(json.loads(resp),
                                              query_metadata['transform'], opt)

    headers['Server'] = 'grlc/' + grlc_version
    return resp, 200, headers
Exemple #4
0
def process_sparql_query_text(query_text, loader, call_name, extraMetadata):
    """Generates a swagger specification item based on the given SPARQL query file."""
    # We get the endpoint name first, since some query metadata fields (eg enums) require it
    endpoint, _ = gquery.guess_endpoint_uri(query_text, loader)
    glogger.debug("Read query endpoint: {}".format(endpoint))

    try:
        query_metadata = gquery.get_metadata(query_text, endpoint)
    except Exception as e:
        raise Exception('Could not parse query {}: {}'.format(call_name, str(e)))

    tags = query_metadata['tags'] if 'tags' in query_metadata else []

    summary = query_metadata['summary'] if 'summary' in query_metadata else ""

    description = query_metadata['description'] if 'description' in query_metadata else ""

    method = query_metadata['method'].lower() if 'method' in query_metadata else ""
    if method not in ['get', 'post', 'head', 'put', 'delete', 'options', 'connect']:
        method = ""

    pagination = query_metadata['pagination'] if 'pagination' in query_metadata else ""

    endpoint_in_url = query_metadata['endpoint_in_url'] if 'endpoint_in_url' in query_metadata else True

    # Processing of the parameters
    params = []

    # PV properties
    item_properties = {}

    # If this query allows pagination, add page number as parameter
    if pagination:
        params.append(pageUtils.getSwaggerPaginationDef(pagination))

    if query_metadata['type'] in ['SelectQuery', 'ConstructQuery', 'InsertData']:
        # TODO: do something intelligent with the parameters!
        # As per #3, prefetching IRIs via SPARQL and filling enum
        parameters = query_metadata['parameters']

        for _, p in list(parameters.items()):
            param = {}
            param['name'] = p['name']
            param['type'] = p['type']
            param['required'] = p['required']
            param['in'] = "query"
            param['description'] = "A value of type {} that will substitute {} in the original query".format(
                    p['type'],  p['original'])
            if 'lang' in p:
                param['description'] = "A value of type {}@{} that will substitute {} in the original query".format(
                    p['type'], p['lang'], p['original'])
            if 'format' in p:
                param['format'] = p['format']
                param['description'] = "A value of type {} ({}) that will substitute {} in the original query".format(
                    p['type'], p['format'], p['original'])
            if 'enum' in p:
                param['enum'] = p['enum']
            if 'default' in p:
                param['default'] = p['default']

            params.append(param)

    if endpoint_in_url:
        endpoint_param = {}
        endpoint_param['name'] = "endpoint"
        endpoint_param['type'] = "string"
        endpoint_param['in'] = "query"
        endpoint_param['description'] = "Alternative endpoint for SPARQL query"
        endpoint_param['default'] = endpoint
        params.append(endpoint_param)

    # If this is a URL generated spec we need to force API calls with the specUrl parameter set
    if type(loader) is URLLoader:
        specUrl_param = {}
        specUrl_param['name'] = "specUrl"
        specUrl_param['type'] = "string"
        specUrl_param['in'] = "query"
        specUrl_param['description'] = "URL of the API specification"
        specUrl_param['default'] = loader.getRawRepoUri()
        params.append(specUrl_param)

    if query_metadata['type'] == 'SelectQuery':
        # Fill in the spec for SELECT
        if not method:
            method = 'get'
        for pv in query_metadata['variables']:
            item_properties[pv] = {
                "name": pv,
                "type": "object",
                "required": ["type", "value"],
                "properties": {
                    "type": {
                        "type": "string"
                    },
                    "value": {
                        "type": "string"
                    },
                    "xml:lang": {
                        "type": "string"
                    },
                    "datatype": {
                        "type": "string"
                    }
                }
            }

    elif query_metadata['type'] == 'ConstructQuery':
        if not method:
            method = 'get'
    elif query_metadata['type'] == 'UNKNOWN':
        glogger.warning("grlc could not parse this query; assuming a plain, non-parametric SELECT in the API spec")
        if not method:
            method = 'get'
    else:
        # TODO: process all other kinds of queries
        raise Exception('Could not parse query {}: Query of type {} is currently unsupported'.format(call_name, query_metadata['type']))

    # Finally: main structure of the callname spec
    item = packItem('/' + call_name, method, tags, summary, description, params, query_metadata, extraMetadata)

    return item
Exemple #5
0
def process_sparql_query_text(query_text, loader, call_name, extraMetadata):
    # We get the endpoint name first, since some query metadata fields (eg enums) require it

    endpoint, auth = gquery.guess_endpoint_uri(query_text, loader)
    glogger.debug("Read query endpoint: {}".format(endpoint))

    try:
        query_metadata = gquery.get_metadata(query_text, endpoint)
    except Exception:
        raw_repo_uri = loader.getRawRepoUri()
        raw_query_uri = raw_repo_uri + ' / ' + call_name
        glogger.error("Could not parse query at {}".format(raw_query_uri))
        glogger.error(traceback.print_exc())
        return None

    tags = query_metadata['tags'] if 'tags' in query_metadata else []

    summary = query_metadata['summary'] if 'summary' in query_metadata else ""

    description = query_metadata['description'] if 'description' in query_metadata else ""

    method = query_metadata['method'].lower() if 'method' in query_metadata else ""
    if method not in ['get', 'post', 'head', 'put', 'delete', 'options', 'connect']:
        method = ""

    pagination = query_metadata['pagination'] if 'pagination' in query_metadata else ""

    endpoint_in_url = query_metadata['endpoint_in_url'] if 'endpoint_in_url' in query_metadata else True

    projection = loader.getProjectionForQueryName(call_name)

    # Processing of the parameters
    params = []

    # PV properties
    item_properties = {}

    # If this query allows pagination, add page number as parameter
    if pagination:
        params.append(pageUtils.getSwaggerPaginationDef(pagination))

    if query_metadata['type'] == 'SelectQuery' or query_metadata['type'] == 'ConstructQuery' or query_metadata['type'] == 'InsertData':
        # TODO: do something intelligent with the parameters!
        # As per #3, prefetching IRIs via SPARQL and filling enum
        parameters = query_metadata['parameters']

        for v, p in list(parameters.items()):
            param = {}
            param['name'] = p['name']
            param['type'] = p['type']
            param['required'] = p['required']
            param['in'] = "query"
            param['description'] = "A value of type {} that will substitute {} in the original query".format(p['type'], p['original'])
            if 'lang' in p:
                param['description'] = "A value of type {}@{} that will substitute {} in the original query".format(p['type'], p['lang'], p['original'])
            if 'format' in p:
                param['format'] = p['format']
                param['description'] = "A value of type {} ({}) that will substitute {} in the original query".format(p['type'], p['format'], p['original'])
            if 'enum' in p:
                param['enum'] = p['enum']
            if 'default' in p:
                param['default'] = p['default']

            params.append(param)

    if endpoint_in_url:
        endpoint_param = {}
        endpoint_param['name'] = "endpoint"
        endpoint_param['type'] = "string"
        endpoint_param['in'] = "query"
        endpoint_param['description'] = "Alternative endpoint for SPARQL query"
        endpoint_param['default'] = endpoint
        params.append(endpoint_param)

    if query_metadata['type'] == 'SelectQuery':
        # Fill in the spec for SELECT
        if not method:
            method = 'get'
        for pv in query_metadata['variables']:
            item_properties[pv] = {
                "name": pv,
                "type": "object",
                "required": ["type", "value"],
                "properties": {
                    "type": {
                        "type": "string"
                    },
                    "value": {
                        "type": "string"
                    },
                    "xml:lang": {
                        "type": "string"
                    },
                    "datatype": {
                        "type": "string"
                    }
                }
            }

    elif query_metadata['type'] == 'ConstructQuery':
        if not method:
            method = 'get'
    elif query_metadata['type'] == 'UNKNOWN':
        glogger.warning("grlc could not parse this query; assuming a plain, non-parametric SELECT in the API spec")
        if not method:
            method = 'get'
    else:
        # TODO: process all other kinds of queries
        glogger.warning("Query of type {} is currently unsupported! Skipping".format(query_metadata['type']))

    # Finally: main structure of the callname spec
    item = packItem('/' + call_name, method, tags, summary, description, params, query_metadata, extraMetadata, projection)

    return item