Skip to content

Commit

Permalink
Merge pull request #487 from c-martinez/transformer_json_check
Browse files Browse the repository at this point in the history
Transformer json check
  • Loading branch information
albertmeronyo authored Aug 7, 2024
2 parents b943349 + 0d659ea commit 5cfd1c7
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 60 deletions.
1 change: 1 addition & 0 deletions src/gquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ def get_yaml_decorators(rq):

yaml_string = ""
query_string = ""
query_metadata = None
if isinstance(rq, dict): # json query (sparql transformer)
if "grlc" in rq:
yaml_string = rq["grlc"]
Expand Down
138 changes: 81 additions & 57 deletions src/swagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ def get_blank_spec():
"""Creates the base (blank) structure of swagger specification."""
swag = {}
swag["swagger"] = "2.0"
swag[
"schemes"
] = [] # 'http' or 'https' -- leave blank to make it dependent on how UI is loaded
swag["schemes"] = (
[]
) # 'http' or 'https' -- leave blank to make it dependent on how UI is loaded
swag["paths"] = {}
swag["definitions"] = {"Message": {"type": "string"}}
return swag
Expand Down Expand Up @@ -109,9 +109,11 @@ def get_path_for_item(item):
"type": "array",
"items": {
"type": "object",
"properties": item["item_properties"]
if "item_properties" in item
else None,
"properties": (
item["item_properties"]
if "item_properties" in item
else None
),
},
},
},
Expand Down Expand Up @@ -162,48 +164,14 @@ def build_spec(
if (
extension in allowed_ext or query_url
): # parameter provided queries may not have extension
call_name = c["name"].split(".")[0]

# Retrieve extra metadata from the query decorators
query_text = loader.getTextFor(c)

item = None
if extension == "json":
query_text = json.loads(query_text)

if extension in ["rq", "sparql", "json"] or query_url:
glogger.debug(
"==================================================================="
)
glogger.debug("Processing SPARQL query: {}".format(c["name"]))
glogger.debug(
"==================================================================="
)
try:
item = process_sparql_query_text(
query_text, loader, call_name, extraMetadata
)
except Exception as e:
warnings.append(str(e))
elif "tpf" == extension:
glogger.debug(
"==================================================================="
)
glogger.debug("Processing TPF query: {}".format(c["name"]))
glogger.debug(
"==================================================================="
)
item = process_tpf_query_text(
query_text, raw_repo_uri, call_name, extraMetadata
)
# TODO: raise exceptions in process_tpf_query_text
else:
glogger.info(
"Ignoring unsupported source call name: {}".format(c["name"])
)

item, warning = _buildItem(
c, extension, query_url, raw_repo_uri, loader, extraMetadata
)
if item:
items.append(item)
if warning:
warnings.append(warning)

# Add a warning if no license is found
if loader.getLicenceURL() is None:
Expand All @@ -214,6 +182,62 @@ def build_spec(
return items, warnings


def _buildItem(c, extension, query_url, raw_repo_uri, loader, extraMetadata):
"""Collect all the information required to build an item from a file in a repository."""
item = None
warning = None

call_name = c["name"].split(".")[0]

# Retrieve extra metadata from the query decorators
query_text = loader.getTextFor(c)

if extension == "json":
query_text = json.loads(query_text)
# Validate loaded json is an actual query.
# If it isn't, do not process it further and item is not built
if not grlc.utils.SPARQLTransformer_validJSON(query_text):
glogger.debug(
"==================================================================="
)
glogger.debug("JSON file not a SPARQL query: {}".format(c["name"]))
glogger.debug(
"==================================================================="
)
return item, warning

if extension in ["rq", "sparql", "json"] or query_url:
glogger.debug(
"==================================================================="
)
glogger.debug("Processing SPARQL query: {}".format(c["name"]))
glogger.debug(
"==================================================================="
)
try:
item = process_sparql_query_text(
query_text, loader, call_name, extraMetadata
)
except Exception as e:
warning = str(e)
elif "tpf" == extension:
glogger.debug(
"==================================================================="
)
glogger.debug("Processing TPF query: {}".format(c["name"]))
glogger.debug(
"==================================================================="
)
item = process_tpf_query_text(
query_text, raw_repo_uri, call_name, extraMetadata
)
# TODO: raise exceptions in process_tpf_query_text
else:
glogger.info("Ignoring unsupported source call name: {}".format(c["name"]))

return item, warning


def process_tpf_query_text(query_text, raw_repo_uri, call_name, extraMetadata):
"""Generates a swagger specification item based on the given TPF query file."""
query_metadata = gquery.get_yaml_decorators(query_text)
Expand Down Expand Up @@ -356,23 +380,23 @@ def build_parameter(p):
param["required"] = p["required"]
param["in"] = "query"
# TODO: can we simplify the description
param[
"description"
] = "A value of type {} that will substitute {} in the original query".format(
p["type"], p["original"]
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"]
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"]
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"]
Expand Down
7 changes: 7 additions & 0 deletions src/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,10 @@ def dispatchTPFQuery(raw_tpf_query, loader, acceptHeader, content):
headers["Content-Type"] = response.headers["Content-Type"]
headers["Server"] = "grlc/" + grlc_version
return resp, 200, headers


def SPARQLTransformer_validJSON(json_file):
"""Validate json file (loaded into Python as a dict) is a valid query for
SPARQLTransformer (see https://github.com/D2KLab/py-sparql-transformer/issues/13).
"""
return ("@graph" in json_file) or ("proto" in json_file)
7 changes: 6 additions & 1 deletion tests/mock_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,12 @@ def mock_process_sparql_query_text(query_text, raw_repo_uri, call_name, extraMet
"name": "fakeFile1.rq",
"download_url": "https://example.org/path/to/fakeFile.rq",
"decoded_content": "CONTENT ?".encode(), # Because Github ContentFile object contains bytes.
}
},
{
"name": "fakeJSONFile1.json",
"download_url": "https://example.org/path/to/fakeJSONFile1.json",
"decoded_content": '{ "x": "y" }'.encode(), # Because Github ContentFile object contains bytes.
},
]

mockLoader = LocalLoader(base_url)
3 changes: 2 additions & 1 deletion tests/test_grlc.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ def test_build_spec(self, mockQueryText, mockLoaderFiles, mockGithubRepo):
repo = "testrepo"
spec, warning = swagger.build_spec(user=user, repo=repo, git_type="github")

self.assertEqual(len(spec), len(filesInRepo))
# Repo contains one JSON file which is not a query, and should be ignored
self.assertEqual(len(spec), len(filesInRepo) - 1)


if __name__ == "__main__":
Expand Down
3 changes: 2 additions & 1 deletion tests/test_swagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ def test_github(self, mockQueryText, mockLoaderFiles, mockGithubRepo):
repo = "testrepo"
spec, warnings = build_spec(user, repo, git_type="github")

self.assertEqual(len(spec), len(filesInRepo))
# Repo contains one JSON file which is not a query, and should be ignored
self.assertEqual(len(spec), len(filesInRepo) - 1)


if __name__ == "__main__":
Expand Down

0 comments on commit 5cfd1c7

Please sign in to comment.