Skip to content

Commit 00d542d

Browse files
committed
Improve argument parser
1 parent 947a3df commit 00d542d

File tree

3 files changed

+88
-4
lines changed

3 files changed

+88
-4
lines changed

julia/pseudo_python_cli.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,51 @@ def make_parser(description=__doc__):
9999
return parser
100100

101101

102+
def parse_args_with(parser, args):
103+
ns = parser.parse_args(list(preprocess_args(args)))
104+
if (ns.command or ns.module) and ns.script:
105+
ns.args = [ns.script] + ns.args
106+
ns.script = None
107+
return ns
108+
109+
110+
def parse_args(args):
111+
return parse_args_with(make_parser(), args)
112+
113+
114+
def preprocess_args(args):
115+
"""
116+
Insert "--" after "[-c cmd | -m mod | script | -]"
117+
118+
This is required for the following to work:
119+
120+
>>> ns = parse_args(["-mjson.tool", "-h"])
121+
>>> ns.args
122+
['-h']
123+
"""
124+
it = iter(args)
125+
for a in it:
126+
yield a
127+
128+
if a in ("-m", "-c"):
129+
try:
130+
yield next(it)
131+
except StopIteration:
132+
return
133+
yield "--"
134+
elif a == "-":
135+
yield "--"
136+
elif a.startswith("-"):
137+
if a[1] in ("m", "c"):
138+
yield "--"
139+
# otherwise, it's some
140+
141+
102142
def main(args=None):
103143
if args is None:
104144
args = sys.argv[1:]
105-
parser = make_parser()
106145
try:
107-
ns = parser.parse_args(args)
146+
ns = parse_args(args)
108147
python(**vars(ns))
109148
except SystemExit as err:
110149
return err.code

julia/python_jl.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import os
2929
import sys
3030

31-
from .pseudo_python_cli import make_parser
31+
from .pseudo_python_cli import make_parser, parse_args_with
3232

3333
script_jl = """
3434
import PyCall
@@ -106,7 +106,7 @@ def parse_pyjl_args(args):
106106
Julia interpreter to be used.
107107
""")
108108

109-
ns = parser.parse_args(args)
109+
ns = parse_args_with(parser, args)
110110
unused_args = list(remove_julia_options(args))
111111
return ns, unused_args
112112

test/test_pseudo_python_cli.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import shlex
2+
3+
import pytest
4+
5+
from julia.pseudo_python_cli import parse_args
6+
7+
8+
def make_dict(**kwargs):
9+
ns = parse_args([])
10+
return dict(vars(ns), **kwargs)
11+
12+
13+
@pytest.mark.parametrize("args, desired", [
14+
("-m json.tool -h", make_dict(module="json.tool", args=["-h"])),
15+
("-mjson.tool -h", make_dict(module="json.tool", args=["-h"])),
16+
("-m ipykernel install --user --name NAME --display-name DISPLAY_NAME",
17+
make_dict(module="ipykernel",
18+
args=shlex.split("install --user --name NAME"
19+
" --display-name DISPLAY_NAME"))),
20+
("-m ipykernel_launcher -f FILE",
21+
make_dict(module="ipykernel_launcher",
22+
args=shlex.split("-f FILE"))),
23+
])
24+
def test_parse_args(args, desired):
25+
ns = parse_args(shlex.split(args))
26+
actual = vars(ns)
27+
assert actual == desired
28+
29+
30+
@pytest.mark.parametrize("cli_args", [
31+
["-h"],
32+
["-i", "--help"],
33+
["-h", "-i"],
34+
["-hi"],
35+
["-ih"],
36+
["-h", "-m", "json.tool"],
37+
["-h", "-mjson.tool"],
38+
])
39+
def test_help_option(cli_args, capsys):
40+
with pytest.raises(SystemExit) as exc_info:
41+
parse_args(cli_args)
42+
assert exc_info.value.code == 0
43+
44+
captured = capsys.readouterr()
45+
assert "usage:" in captured.out

0 commit comments

Comments
 (0)