Skip to content

Commit 76822b0

Browse files
authored
Fix argument parsing (#6)
1 parent c95fccd commit 76822b0

3 files changed

Lines changed: 56 additions & 20 deletions

File tree

naughtty/__main__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
from sys import argv
2+
3+
14
def cli_entry() -> None:
25
from naughtty.cli import make_response
36

4-
print(make_response())
7+
print(make_response(argv[1:]))
58

69

710
if __name__ == "__main__":

naughtty/cli.py

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,57 @@
11
from argparse import ArgumentParser, Namespace
2-
from typing import List, Optional, Tuple
2+
from typing import Dict, List, Optional, Tuple, Union
33

44
from naughtty.constants import DEFAULT_CHARACTER_PIXELS, DEFAULT_TERMINAL_SIZE
55
from naughtty.naughtty import NaughTTY
66
from naughtty.version import get_version
77

88

9+
def make_namespace(cli_args: List[str]) -> Namespace:
10+
"""Reads `cli_args` into a `Namespace`."""
11+
12+
# We need to perform our own strict left-to-right reading of the arguments
13+
# because `ArgumentParser` can't tell if any "--help" or "--version" is
14+
# intended for us or the child command.
15+
16+
wip: Dict[str, Union[bool, str, List[str]]] = {}
17+
name: Optional[str] = None
18+
19+
for index, arg in enumerate(cli_args):
20+
if arg.startswith("--"):
21+
name = arg[2:].replace("-", "_")
22+
wip[name] = True
23+
else:
24+
if name:
25+
wip[name] = arg
26+
name = None
27+
else:
28+
wip["command"] = cli_args[index:]
29+
break
30+
31+
return Namespace(**wip)
32+
33+
934
def make_naughtty(ns: Namespace) -> NaughTTY:
1035
"""Makes a `NaughTTY` instance based on the given command line arguments."""
1136

1237
character_pixels: Optional[Tuple[int, int]] = None
1338

14-
if ns.character_pixels:
39+
if "character_pixels" in ns:
1540
parts = str(ns.character_pixels).split(",")
1641
character_pixels = (int(parts[0]), int(parts[1]))
1742

1843
return NaughTTY(
19-
columns=int(ns.columns) if ns.columns else None,
44+
columns=int(ns.columns) if "columns" in ns else None,
2045
command=ns.command,
2146
character_pixels=character_pixels,
22-
lines=int(ns.lines) if ns.lines else None,
47+
lines=int(ns.lines) if "lines" in ns else None,
2348
)
2449

2550

26-
def make_response(cli_args: Optional[List[str]] = None) -> str:
51+
def make_response(cli_args: List[str]) -> str:
2752
"""Makes a response to the given command line arguments."""
2853

2954
parser = ArgumentParser(
30-
# We don't want ArgumentParser to pick up on "--help" in the child
31-
# command's arguments:
32-
add_help=False,
3355
description="Executes a shell command in a pseudo-terminal and prints its output to stdout.",
3456
epilog="Made with love by Cariad Eccleston: https://github.com/cariad/naughtty",
3557
)
@@ -47,8 +69,6 @@ def make_response(cli_args: Optional[List[str]] = None) -> str:
4769
help=f"columns (default=system default or {DEFAULT_TERMINAL_SIZE[0]})",
4870
)
4971

50-
parser.add_argument("--help", action="store_true", help="print this help")
51-
5272
parser.add_argument(
5373
"--lines",
5474
help=f"lines (default=system default or {DEFAULT_TERMINAL_SIZE[1]})",
@@ -60,14 +80,12 @@ def make_response(cli_args: Optional[List[str]] = None) -> str:
6080
help="print the version",
6181
)
6282

63-
args = parser.parse_args(cli_args)
83+
args = make_namespace(cli_args)
6484

65-
if args.version:
85+
if "version" in args:
6686
return get_version()
6787

68-
# If we discover "--help" AND a command then that "--help" is intended for
69-
# the command and not us:
70-
if not args.command or (args.help and not args.command):
88+
if "command" not in args or "help" in args:
7189
return parser.format_help()
7290

7391
n = make_naughtty(args)

tests/test_cli.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
from argparse import Namespace
2+
from typing import List
23

3-
from naughtty.cli import make_naughtty, make_response
4+
from pytest import mark
5+
6+
from naughtty.cli import make_namespace, make_naughtty, make_response
7+
8+
9+
@mark.parametrize(
10+
"args, expect",
11+
[
12+
([], Namespace()),
13+
(["--help"], Namespace(help=True)),
14+
(["pipenv", "--help"], Namespace(command=["pipenv", "--help"])),
15+
(["--lines", "30"], Namespace(lines="30")),
16+
(["--lines", "30", "foo"], Namespace(command=["foo"], lines="30")),
17+
(["foo", "--lines", "30"], Namespace(command=["foo", "--lines", "30"])),
18+
],
19+
)
20+
def test_make_namespace(args: List[str], expect: Namespace) -> None:
21+
assert make_namespace(args) == expect
422

523

624
def test_make_naughtty__custom() -> None:
@@ -21,10 +39,7 @@ def test_make_naughtty__custom() -> None:
2139
def test_make_naughtty__defaults() -> None:
2240
naughtty = make_naughtty(
2341
Namespace(
24-
character_pixels=None,
25-
columns=None,
2642
command=["python", "tests/out-color.py"],
27-
lines=None,
2843
)
2944
)
3045

0 commit comments

Comments
 (0)