Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(checkquery): tool for checking SPARQL query files (resolves #48) #53

Merged
merged 5 commits into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 44 additions & 30 deletions src/scribe_data/checkquery.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env python3

"""Command line tool for testing SPARQl queries against an endpoint."""
"""
Command line tool for testing SPARQl queries against an endpoint.
"""

import argparse
import math
Expand Down Expand Up @@ -29,7 +31,8 @@

@dataclass(repr=False, frozen=True)
class QueryFile:
"""Holds a reference to a file containing a SPARQL query."""
"""
Holds a reference to a file containing a SPARQL query."""

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tripple quote should be on newline. Slipped through final review.

path: Path

Expand All @@ -50,7 +53,9 @@ def __repr__(self) -> str:


class QueryExecutionException(Exception):
"""Raised when execution of a query fails."""
"""
Raised when execution of a query fails.
"""

def __init__(self, message: str, query: QueryFile) -> None:
"""
Expand All @@ -67,7 +72,8 @@ def __str__(self) -> str:


def ping(url: str, timeout: int) -> bool:
"""Test if a URL is reachable.
"""
Test if a URL is reachable.

Args:
url (str): the URL to test.
Expand All @@ -86,7 +92,8 @@ def ping(url: str, timeout: int) -> bool:


def all_queries() -> list[QueryFile]:
"""All the SPARQL queries in, and below, 'Scribe-Data/'.
"""
All the SPARQL queries in, and below, 'Scribe-Data/'.

Returns:
list[QueryFile]: the SPARQL query files.
Expand All @@ -107,7 +114,8 @@ def all_queries() -> list[QueryFile]:


def changed_queries() -> Optional[list[QueryFile]]:
"""Find all the SPARQL queries that have changed.
"""
Find all the SPARQL queries that have changed.

Includes new queries.

Expand Down Expand Up @@ -146,7 +154,8 @@ def changed_queries() -> Optional[list[QueryFile]]:


def sparql_context(url: str) -> SPARQL.SPARQLWrapper:
"""Configure a SPARQL context.
"""
Configure a SPARQL context.

A context allows the execution of SPARQL queries.

Expand All @@ -166,7 +175,8 @@ def sparql_context(url: str) -> SPARQL.SPARQLWrapper:
def execute(
query: QueryFile, limit: int, context: SPARQL.SPARQLWrapper, tries: int = 3
) -> dict:
"""Execute a SPARQL query in a given context.
"""
Execute a SPARQL query in a given context.

Args:
query (QueryFile): the SPARQL query to run.
Expand All @@ -188,8 +198,7 @@ def delay_in_seconds() -> int:

try:
context.setQuery(query.load(limit))
result = context.query().convert()
return result if result else []
return context.queryAndConvert()

except HTTPError:
time.sleep(delay_in_seconds())
Expand All @@ -204,28 +213,30 @@ def delay_in_seconds() -> int:
) from err


def check_sparql_file(query_file: str) -> Path:
"""Check meta information of SPARQL query file.
def check_sparql_file(fpath: str) -> Path:
"""
Check meta information of SPARQL query file.

Args:
query_file (str): the file to validate.
fpath (str): the file to validate.

Returns:
Path: the validated file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd change this to fpath (str): .... To me file_path is also a bit more in line with the variable/function names. I can make these edits though :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"""
fpath = Path(query_file)
path = Path(fpath)

if not fpath.is_file():
raise argparse.ArgumentTypeError(f"Not a valid file path: {fpath}")
if not path.is_file():
raise argparse.ArgumentTypeError(f"Not a valid file path: {path}")

if fpath.suffix != ".sparql":
raise argparse.ArgumentTypeError(f"{fpath} does not have a '.sparql' extension")
if path.suffix != ".sparql":
raise argparse.ArgumentTypeError(f"{path} does not have a '.sparql' extension")

return fpath
return path


def check_positive_number(value: str, err_msg: str) -> int:
"""Ensure 'value' is a positive number.
def check_positive_int(value: str, err_msg: str) -> int:
"""
Ensure 'value' is a positive number.

Args:
value (str): the value to be validated.
Expand All @@ -248,7 +259,8 @@ def check_positive_number(value: str, err_msg: str) -> int:


def check_limit(limit: str) -> int:
"""Validate the 'limit' argument.
"""
Validate the 'limit' argument.

Args:
limit (str): the LIMIT to be validated.
Expand All @@ -259,13 +271,12 @@ def check_limit(limit: str) -> int:
Returns:
int: the validated LIMIT
"""
return check_positive_number(
limit, "LIMIT must be an integer of value 1 or greater."
)
return check_positive_int(limit, "LIMIT must be an integer of value 1 or greater.")


def check_timeout(timeout: str) -> int:
"""Validate the 'timeout' argument.
"""
Validate the 'timeout' argument.

Args:
timeout (str): the timeout to be validated.
Expand All @@ -276,13 +287,14 @@ def check_timeout(timeout: str) -> int:
Returns:
int: the validated timeout.
"""
return check_positive_number(
return check_positive_int(
timeout, "timeout must be an integer of value 1 or greater."
)


def main(argv=None) -> int:
"""The main function.
"""
The main function.

Args:
argv : If set to None then argparse will use sys.argv as the arguments.
Expand Down Expand Up @@ -408,7 +420,8 @@ def main(argv=None) -> int:


def error_report(failures: list[QueryExecutionException]) -> None:
"""Report failed queries.
"""
Report failed queries.

Args:
failures (list[QueryExecutionException]): failed queries.
Expand All @@ -423,7 +436,8 @@ def error_report(failures: list[QueryExecutionException]) -> None:


def success_report(successes: list[tuple[QueryFile, dict]], display: bool) -> None:
"""Report successful queries.
"""
Report successful queries.

Args:
successes (list[tuple[QueryFile, dict]]): successful queries.
Expand Down
4 changes: 3 additions & 1 deletion tests/load/test_checkquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,9 @@ def test_main_help(arg):
],
)
def test_main_mutex_opts(args):
"""some options cannot be used together"""
"""
Some options cannot be used together.
"""
with pytest.raises(SystemExit) as err:
_ = main([args])
assert err.code == 2
Expand Down
Loading