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

Add cli options to output lookml #89

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
29 changes: 25 additions & 4 deletions lkml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ def parse_args(args: Sequence) -> argparse.Namespace:
help="increase logging verbosity to debug",
)

group = parser.add_mutually_exclusive_group()
group.add_argument(
"--json",
action="store_true",
default=True,
help="return a JSON string (default)",
)
group.add_argument(
"--lookml",
action="store_true",
default=False,
help="return a LookML string",
)

return parser.parse_args(args)


Expand All @@ -116,8 +130,15 @@ def cli():

logging.getLogger().setLevel(args.log_level)

result: dict = load(args.file)
args.file.close()
try:
result: dict = load(args.file)

if args.lookml:
lookml_string = dump(result)
print(lookml_string)
elif args.json:
json_string = json.dumps(result, indent=2)
print(json_string)

json_string = json.dumps(result, indent=2)
print(json_string)
finally:
Copy link
Author

Choose a reason for hiding this comment

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

FileType objects dont work with context managers, this makes sure the file is closed even if they cannot be parsed.

args.file.close()
55 changes: 43 additions & 12 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import io
from lkml.tree import ContainerNode, DocumentNode, PairNode, SyntaxToken
from pathlib import Path
from unittest.mock import patch
import logging
import pytest
import lkml
import json

from pathlib import Path
from unittest.mock import patch


@pytest.fixture
Expand All @@ -25,15 +26,45 @@ def test_absence_of_debug_flag_is_parsed_to_log_level_warn(lookml_path):
assert args.log_level == logging.WARN


@patch("lkml.load")
@patch("lkml.parse_args")
def test_run_cli(mock_parse_args, mock_load, lookml_path):
mock_parse_args.return_value.file = io.StringIO()
mock_parse_args.return_value.log_level = logging.WARN
mock_load.return_value = {"a": "1"}
lkml.cli()


def test_load_with_bad_argument_raises_type_error():
with pytest.raises(TypeError):
lkml.load(stream=100)


def test_parse_default_option(lookml_path):
args = lkml.parse_args([lookml_path])
assert args.json is True
assert args.lookml is False


def test_parse_options(lookml_path):
args = lkml.parse_args([lookml_path, "--json"])
assert args.json is True

args = lkml.parse_args([lookml_path, "--lookml"])
assert args.lookml is True

with pytest.raises(SystemExit):
args = lkml.parse_args([lookml_path, "--json", "--lookml"])


def test_run_cli_default_option(lookml_path, capsys):
with patch("sys.argv", ["file.py", lookml_path]):
lkml.cli()
captured = capsys.readouterr()
assert json.loads(captured.out) is not None
assert captured.err == ""


def test_run_cli_options(lookml_path, capsys):
with patch("sys.argv", ["file.py", "--json", lookml_path]):
lkml.cli()
captured = capsys.readouterr()
assert json.loads(captured.out) is not None
assert captured.err == ""

with patch("sys.argv", ["file.py", "--lookml", lookml_path]):
lkml.cli()
captured = capsys.readouterr()
assert lkml.load(captured.out) is not None
assert captured.err == ""