Skip to content

Commit

Permalink
Merge pull request #357 from c-martinez/extended-yaml
Browse files Browse the repository at this point in the history
Extended yaml API specification
  • Loading branch information
c-martinez authored Apr 22, 2023
2 parents 877d3b6 + 58722bd commit 3b31bd1
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 16 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ A grlc API specification file is a YAML file which includes the necessary inform
- `description`: API description
- `contact`: Contact details of the API owner. This should include the `name` and `url` properties.
- `licence`: A URL pointing to the licence file for the API.
- `queries`: A list of URLs of SPARQL queries (with header decorators).
- `queries`: A list of URLs of SPARQL queries (with header decorators). Alternatively a query can be defined as a dictionary with a `name` and a `url`.

For example:
```YAML
Expand All @@ -97,6 +97,8 @@ queries:
- https://www.mywebsite.org/query1.rq
- https://www.mywebsite.org/query2.rq
- https://www.otherwebsite.org/query3.rq
- name: QueryFour
url: https://www.mywebsite.org/query4.rq
```
### grlc generated API
Expand Down
54 changes: 39 additions & 15 deletions src/fileLoaders.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import grlc.static as static
from grlc.queryTypes import qType
from grlc.queryTypes import qType, guessQueryType
import grlc.glogging as glogging

import json
Expand All @@ -23,15 +23,14 @@ def getTextForName(self, query_name):
for `query_name='query1'` would return the content of file `query1.rq`
from the loader's source (assuming such file exists)."""
# The URIs of all candidates
rq_name = query_name + '.rq'
sparql_name = query_name + '.sparql'
tpf_name = query_name + '.tpf'
json_name = query_name + '.json'
candidateNames = [
query_name + '.rq',
query_name + '.sparql',
query_name + '.tpf',
query_name + '.json'
]
candidates = [
(rq_name, qType['SPARQL']),
(sparql_name, qType['SPARQL']),
(tpf_name, qType['TPF']),
(json_name, qType['JSON'])
(name, guessQueryType(name)) for name in candidateNames
]

for queryFullName, queryType in candidates:
Expand Down Expand Up @@ -257,7 +256,6 @@ def getRepoDescription(self):
return self.api_description



class URLLoader(BaseLoader):
"""URL specification loader. Retrieves information to construct a grlc
specification from a specification YAML file located on a remote server."""
Expand All @@ -273,18 +271,33 @@ def __init__(self, spec_url):
self.spec = yaml.load(resp.text)
self.spec['url'] = spec_url
self.spec['files'] = {}
for queryUrl in self.spec['queries']:
queryNameExt = path.basename(queryUrl)
queryName = path.splitext(queryNameExt)[0] # Remove extention

for query in self.spec['queries']:
queryName, queryUrl = self.extractQueryInfo(query)

item = {
'name': queryName,
'download_url': queryUrl
}
self.spec['files'][queryNameExt] = item
self.spec['files'][queryName] = item
del self.spec['queries']
else:
raise Exception(resp.text)

def extractQueryInfo(self, query):
"""Extract query name and URL from specification. These could
either be explicitly declared (values in a dict) or need to be
infered from the URL (which itself could be explicilty declared or
be the only element of query."""
queryUrl = query['url'] if type(query) is dict else query

if type(query) is dict and 'name' in query:
queryName = query['name']
else:
queryNameExt = path.basename(queryUrl)
queryName = path.splitext(queryNameExt)[0] # Remove extention
return queryName, queryUrl

def fetchFiles(self):
"""Returns a list of file items contained on specification."""
files = [
Expand All @@ -300,7 +313,18 @@ def getTextFor(self, fileItem):
"""Returns the contents of the given file item on the specification."""
# TODO: tiene sentido esto? O es un hack horrible ?
nameExt = path.basename(fileItem['download_url'])
return self._getText(nameExt)
return self._getText(fileItem['name'])

def getTextForName(self, query_name):
"""Return the query text and query type for the given query name.
Specific implementation for URLLoader."""
try:
queryText = self._getText(query_name)
queryType = guessQueryType(self.spec['files'][query_name]['download_url'])
return queryText, queryType
except Exception as e:
# No query found...
return '', None

def _getText(self, itemName):
"""Return the content of the specified item in the specification."""
Expand Down
13 changes: 13 additions & 0 deletions src/queryTypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,16 @@
'TPF': 'tpf',
'JSON': 'json'
}

def guessQueryType(queryUrl):
queryUrl = queryUrl.lower()
if queryUrl.endswith('.rq'):
return qType['SPARQL']
elif queryUrl.endswith('.sparql'):
return qType['SPARQL']
elif queryUrl.endswith('.tpf'):
return qType['TPF']
elif queryUrl.endswith('.json'):
return qType['JSON']
else:
raise Exception('Unknown query type: ' + queryUrl)

0 comments on commit 3b31bd1

Please sign in to comment.