Skip to content

Commit

Permalink
feat: add 'GET ../tool/{id}'
Browse files Browse the repository at this point in the history
  • Loading branch information
krish8484 committed Oct 9, 2020
1 parent df9e1d0 commit 589fef8
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 0 deletions.
117 changes: 117 additions & 0 deletions tests/test_client.py
Expand Up @@ -54,6 +54,53 @@
"name": "string"
}

MOCK_VERSION = {
"author": [
"author"
],
'containerfile': None,
'descriptor_type': None,
"id": "v1",
"images": None,
"included_apps": [
"https://bio.tools/tool/mytum.de/SNAP2/1",
"https://bio.tools/bioexcel_seqqc"
],
"is_production": True,
"meta_version": None,
"name": "name",
"signed": True,
"url": "abcde.com",
"verified": None,
"verified_source": [
"verified_source",
]
}
MOCK_TOOL_CLASS_WITH_ID = {
"description": "description",
"id": "234561",
"name": "name",
}
MOCK_TOOL = {
"aliases": [
"alias_1",
"alias_2",
"alias_3",
],
"checker_url": "checker_url",
"description": "description",
"has_checker": True,
"id": MOCK_ID,
"meta_version": "1",
"name": "name",
"organization": "organization",
"toolclass": MOCK_TOOL_CLASS_WITH_ID,
"url": "abc.com",
"versions": [
MOCK_VERSION
],
}


def _raise(exception) -> None:
"""General purpose exception raiser."""
Expand Down Expand Up @@ -151,6 +198,76 @@ def test_no_success_InvalidResponseError(self, requests_mock):
)


class TestGetTool:
"""Test getter for tool with a given id."""

cli = TRSClient(
uri=MOCK_TRS_URI,
token=MOCK_TOKEN,
)
endpoint = f"{cli.uri}/tools/{MOCK_ID}"

def test_ConnectionError(self, monkeypatch):
"""Connection error occurs."""
monkeypatch.setattr(
'requests.get',
lambda *args, **kwargs: _raise(requests.exceptions.ConnectionError)
)
with pytest.raises(requests.exceptions.ConnectionError):
self.cli.get_tool(
tool_id=MOCK_TRS_URI,
token=MOCK_TOKEN,
)

def test_success(self, monkeypatch, requests_mock):
"""Returns 200 response."""
requests_mock.get(self.endpoint, json=MOCK_TOOL)
r = self.cli.get_tool(
tool_id=MOCK_ID,
)
assert r.dict() == MOCK_TOOL

def test_success_trs_uri(self, monkeypatch, requests_mock):
"""Returns 200 response with TRS URI."""
requests_mock.get(self.endpoint, json=MOCK_TOOL)
r = self.cli.get_tool(
tool_id=MOCK_TRS_URI,
)
assert r.dict() == MOCK_TOOL

def test_success_InvalidResponseError(self, requests_mock):
"""Returns 200 response but schema validation fails."""
requests_mock.get(self.endpoint, json=MOCK_RESPONSE_INVALID)
with pytest.raises(InvalidResponseError):
self.cli.get_tool(
tool_id=MOCK_ID,
)

def test_no_success_valid_error_response(self, requests_mock):
"""Returns no 200 but valid error response."""
requests_mock.get(
self.endpoint,
json=MOCK_ERROR,
status_code=400,
)
r = self.cli.get_tool(
tool_id=MOCK_ID,
)
assert r.dict() == MOCK_ERROR

def test_no_success_InvalidResponseError(self, requests_mock):
"""Returns no 200 and error schema validation fails."""
requests_mock.get(
self.endpoint,
json=MOCK_RESPONSE_INVALID,
status_code=400,
)
with pytest.raises(InvalidResponseError):
self.cli.get_tool(
tool_id=MOCK_ID,
)


class TestGetDescriptor:
"""Test getter for primary descriptor of a given descriptor type."""

Expand Down
63 changes: 63 additions & 0 deletions trs_cli/client.py
Expand Up @@ -28,6 +28,7 @@
FileWrapper,
ToolFile,
ToolClassRegister,
Tool,
)

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -166,6 +167,68 @@ def post_tool_class(
logger.info(f"ToolClass registered: {response_val}")
return response_val

def get_tool(
self,
tool_id: str,
token: Optional[str] = None,
) -> Union[Error, Tool]:
"""Retrieve TRS tool.
Arguments:
tool_id: Implementation-specific TRS identifier hostname-based
TRS URI pointing to a given tool
token: Bearer token for authentication. Set if required by TRS
implementation and if not provided when instatiating client or
if expired.
Returns:
Unmarshalled TRS response as either an instance of `Tool`
in case of a `200` response, or an instance of `Error` for all
other JSON reponses.
Raises:
requests.exceptions.ConnectionError: A connection to the provided
TRS instance could not be established.
trs_cli.errors.InvalidResponseError: The response could not be
validated against the API schema.
"""
tool_id, _ = self._get_tool_id_version_id(tool_id=tool_id)
url = f"{self.uri}/tools/{tool_id}"
logger.info(f"Request URL: {url}")
if token:
self.token = token
self._get_headers()
try:
response = requests.get(
url=url,
headers=self.headers,
)
except (
requests.exceptions.ConnectionError,
socket.gaierror,
urllib3.exceptions.NewConnectionError,
):
raise requests.exceptions.ConnectionError(
"Could not connect to API endpoint."
)
if not response.status_code == 200:
try:
response_val = Error(**response.json())
except (
json.decoder.JSONDecodeError,
pydantic.ValidationError,
):
raise InvalidResponseError(
"Response could not be validated against API schema."
)
logger.warning("Received error response.")
else:
try:
response_val = Tool(**response.json())
except pydantic.ValidationError:
raise InvalidResponseError(
"Response could not be validated against API schema."
)
logger.info(f"Retrieved tool: {tool_id}")
return response_val

def get_descriptor(
self,
type: str,
Expand Down

0 comments on commit 589fef8

Please sign in to comment.