diff --git a/launchable/commands/inspect/__init__.py b/launchable/commands/inspect/__init__.py index 7cfada420..9fb8086c3 100644 --- a/launchable/commands/inspect/__init__.py +++ b/launchable/commands/inspect/__init__.py @@ -2,6 +2,7 @@ from launchable.utils.click import GroupWithAlias +from .model import model from .subset import subset from .tests import tests @@ -11,5 +12,6 @@ def inspect(): pass +inspect.add_command(model) inspect.add_command(subset) inspect.add_command(tests) diff --git a/launchable/commands/inspect/model.py b/launchable/commands/inspect/model.py new file mode 100644 index 000000000..b9c98a293 --- /dev/null +++ b/launchable/commands/inspect/model.py @@ -0,0 +1,50 @@ +import json +import sys +from http import HTTPStatus + +import click +from requests import Response +from tabulate import tabulate + +from ...utils.launchable_client import LaunchableClient + + +@click.command() +@click.option( + '--json', + 'is_json_format', + help='display JSON format', + is_flag=True +) +@click.pass_context +def model(context: click.core.Context, is_json_format: bool): + client = LaunchableClient(app=context.obj) + try: + res: Response = client.request("get", "model-metadata") + + if res.status_code == HTTPStatus.NOT_FOUND: + click.echo(click.style( + "Model metadata currently not available for this workspace.", 'yellow'), err=True) + sys.exit() + + res.raise_for_status() + + if is_json_format: + display_as_json(res) + else: + display_as_table(res) + + except Exception as e: + client.print_exception_and_recover(e, "Warning: failed to inspect model") + + +def display_as_json(res: Response): + res_json = res.json() + click.echo(json.dumps(res_json, indent=2)) + + +def display_as_table(res: Response): + headers = ["Metadata", "Value"] + res_json = res.json() + rows = [["Training Cutoff Test Session ID", res_json['training_cutoff_test_session_id']]] + click.echo(tabulate(rows, headers, tablefmt="github")) diff --git a/tests/cli_test_case.py b/tests/cli_test_case.py index e79611cc5..8adab0c9c 100644 --- a/tests/cli_test_case.py +++ b/tests/cli_test_case.py @@ -194,6 +194,14 @@ def setUp(self): self.workspace), json={'isFailFastMode': False, 'isPtsV2Enabled': False}, status=200) + responses.add( + responses.GET, + "{}/intake/organizations/{}/workspaces/{}/model-metadata".format( + get_base_url(), + self.organization, + self.workspace), + json={'training_cutoff_test_session_id': 256}, + status=200) def get_test_files_dir(self): file_name = Path(inspect.getfile(self.__class__)) # obtain the file of the concrete type diff --git a/tests/commands/inspect/test_model.py b/tests/commands/inspect/test_model.py new file mode 100644 index 000000000..3a8bff80f --- /dev/null +++ b/tests/commands/inspect/test_model.py @@ -0,0 +1,41 @@ +import os +from unittest import mock + +import responses # type: ignore + +from launchable.utils.http_client import get_base_url +from tests.cli_test_case import CliTestCase + + +class ModelTest(CliTestCase): + mock_json = { + "training_cutoff_test_session_id": 256 + } + + @responses.activate + @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) + def test_model(self): + responses.replace(responses.GET, "{}/intake/organizations/{}/workspaces/{}/model-metadata".format( + get_base_url(), self.organization, self.workspace), json=self.mock_json, status=200) + + result = self.cli('inspect', 'model', mix_stderr=False) + expect = """| Metadata | Value | +|---------------------------------|---------| +| Training Cutoff Test Session ID | 256 | +""" + + self.assertEqual(result.stdout, expect) + + @responses.activate + @mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token}) + def test_model_json_format(self): + responses.replace(responses.GET, "{}/intake/organizations/{}/workspaces/{}/model-metadata".format( + get_base_url(), self.organization, self.workspace), json=self.mock_json, status=200) + + result = self.cli('inspect', 'model', "--json", mix_stderr=False) + + self.assertEqual(result.stdout, """{ + "training_cutoff_test_session_id": 256 +} +""" + )