diff --git a/dclient/cli.py b/dclient/cli.py index afb5bcc..cb5d3cb 100644 --- a/dclient/cli.py +++ b/dclient/cli.py @@ -37,16 +37,43 @@ def query(url, sql, token): if token: headers["Authorization"] = f"Bearer {token}" response = httpx.get(url, params={"sql": sql, "_shape": "objects"}, headers=headers) - if response.status_code != 200 or not response.json()["ok"]: - data = response.json() + if response.status_code != 200: + # Is it valid JSON? + try: + data = response.json() + except json.JSONDecodeError: + raise click.ClickException( + "{} status code. Response was not valid JSON".format( + response.status_code + ) + ) bits = [] if data.get("title"): bits.append(data["title"]) if data.get("error"): bits.append(data["error"]) + raise click.ClickException( + "{} status code. {}".format(response.status_code, ": ".join(bits)) + ) + + # We should have JSON now + try: + data = response.json() + except json.JSONDecodeError: + raise click.ClickException("Response was not valid JSON") + # ... but it may have a {"ok": false} error + if not data.get("ok"): + bits = [] + if data.get("title"): + bits.append(data["title"]) + if data.get("error"): + bits.append(data["error"]) + if not bits: + bits = [json.dumps(data)] raise click.ClickException(": ".join(bits)) - else: - click.echo(json.dumps(response.json()["rows"], indent=2)) + + # Output results + click.echo(json.dumps(response.json()["rows"], indent=2)) def _token_for_url_from_auth(url, auth_file): diff --git a/tests/test_query.py b/tests/test_query.py index d565750..c13dfdc 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -17,7 +17,10 @@ def test_query_error(httpx_mock): runner = CliRunner() result = runner.invoke(cli, ["query", "https://example.com", "hello"]) assert result.exit_code == 1 - assert result.output == "Error: Invalid SQL: Statement must be a SELECT\n" + assert ( + result.output + == "Error: 400 status code. Invalid SQL: Statement must be a SELECT\n" + ) def test_query(httpx_mock):