From 251e6221f626e9f69b76c5d2717cf708c8875e4e Mon Sep 17 00:00:00 2001 From: roy reznik Date: Fri, 9 Feb 2024 12:00:26 +0200 Subject: [PATCH] Adding input file option (#6) * Adding input file option * Fix typing that break typer * fix make file --- rexi/cli.py | 28 ++++++++++++++++++++-------- tests/test_cli.py | 16 +++++++++++++++- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/rexi/cli.py b/rexi/cli.py index 934bfc7..91b720d 100644 --- a/rexi/cli.py +++ b/rexi/cli.py @@ -1,5 +1,6 @@ import os import sys +from typing import Annotated, Optional import typer @@ -10,12 +11,23 @@ # noinspection SpellCheckingInspection @app.command("rexi") -def rexi_cli() -> None: - stdin = sys.stdin.read() - try: - os.close(sys.stdin.fileno()) - except OSError: - pass - sys.stdin = open("/dev/tty", "rb") # type: ignore[assignment] - app: RexiApp[int] = RexiApp(stdin) +def rexi_cli( + input_file: Annotated[ + Optional[typer.FileText], + typer.Option( + "--input", "-i", + help="Input file to pass to rexi; if not provided, stdin will be used.", + ), + ] = None, +) -> None: + if input_file: + input_text = input_file.read() + else: + input_text = sys.stdin.read() + try: + os.close(sys.stdin.fileno()) + except OSError: + pass + sys.stdin = open("/dev/tty", "rb") # type: ignore[assignment] + app: RexiApp[int] = RexiApp(input_text) app.run() diff --git a/tests/test_cli.py b/tests/test_cli.py index bc196dc..e834bd8 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,5 @@ from io import BytesIO +from pathlib import Path from unittest.mock import Mock from _pytest.monkeypatch import MonkeyPatch @@ -6,7 +7,7 @@ from rexi.cli import app -def test_app(monkeypatch: MonkeyPatch) -> None: +def test_stdin_cli(monkeypatch: MonkeyPatch) -> None: """ Couldn't find a better way to test the CLI without patching everything :( """ @@ -24,3 +25,16 @@ def test_app(monkeypatch: MonkeyPatch) -> None: open_mock.assert_called_once_with("/dev/tty", "rb") class_mock.assert_called_once_with(text.decode()) instance_mock.run.assert_called_once() + + +def test_file_input_cli(monkeypatch: MonkeyPatch, tmp_path: Path) -> None: + runner = CliRunner() + text = "This iS! aTe xt2 F0r T3sT!ng" + (tmp_path / "text_file").write_text(text) + class_mock = Mock() + instance_mock = Mock() + with monkeypatch.context(): + class_mock.return_value = instance_mock + monkeypatch.setattr("rexi.cli.RexiApp", class_mock) + runner.invoke(app, args=["-i", str(tmp_path / "text_file")]) + class_mock.assert_called_once_with(text)