1 | #!bin/ysh
|
2 |
|
3 | # TODO: you should only have to pick parser
|
4 | # and you can use 'args parser' I guess
|
5 |
|
6 | use $LIB_YSH/args.ysh --pick parser flag arg rest parseArgs
|
7 |
|
8 | source $LIB_YSH/yblocks.ysh
|
9 |
|
10 | # TODO: why doesn't this work? Is there a buffering problem wtih read --all?
|
11 | # Why would it not show up with source though?
|
12 | #use $LIB_YSH/yblocks.ysh --pick yb-capture
|
13 |
|
14 | # Can't be 'use' because we're using shell functions?
|
15 | source $LIB_OSH/byo-server.sh
|
16 |
|
17 | proc test-basic {
|
18 | parser (&spec) {
|
19 | flag -v --verbose (help="Verbosely") # default is Bool, false
|
20 |
|
21 | flag -P --max-procs ('int', default=-1, help='''
|
22 | Run at most P processes at a time
|
23 | ''')
|
24 |
|
25 | flag -i --invert ('bool', default=true, help='''
|
26 | Long multiline
|
27 | Description
|
28 | ''')
|
29 |
|
30 | arg src (help='Source')
|
31 | arg dest (help='Dest')
|
32 |
|
33 | rest files
|
34 | }
|
35 |
|
36 | var args = parseArgs(spec, :| mysrc -P 12 mydest a b c |)
|
37 |
|
38 | assert [false === args.verbose]
|
39 |
|
40 | # TODO: clean up this JSON
|
41 | var expected = {"src":"mysrc","max-procs":12,"dest":"mydest","files":["a","b","c"],"verbose":false,"invert":true}
|
42 | assert [expected === args]
|
43 | }
|
44 |
|
45 | proc test-2 {
|
46 | ### Bool flag, positional args, more positional
|
47 |
|
48 | parser (&spec) {
|
49 | flag -v --verbose ('bool')
|
50 | arg src
|
51 | arg dst
|
52 |
|
53 | rest more # allow more args
|
54 | }
|
55 |
|
56 | var argv = ['-v', 'src/path', 'dst/path', 'x', 'y', 'z']
|
57 |
|
58 | var args = parseArgs(spec, argv)
|
59 |
|
60 | #pp test_ (args)
|
61 |
|
62 | assert [true === args.verbose]
|
63 | assert ['src/path' === args.src]
|
64 | assert ['dst/path' === args.dst]
|
65 | assert [ :| x y z | === args.more]
|
66 | }
|
67 |
|
68 | proc test-default-values {
|
69 |
|
70 | parser (&spec) {
|
71 | flag -S --sanitize ('bool', default=false)
|
72 | flag -v --verbose ('bool', default=false)
|
73 | flag -P --max-procs ('int') # Will set to null (the default default)
|
74 | }
|
75 |
|
76 | var args = parseArgs(spec, [])
|
77 |
|
78 | #pp test_ (args)
|
79 | var expected = {"sanitize":false,"verbose":false,"max-procs":null}
|
80 | assert [expected === args]
|
81 | }
|
82 |
|
83 | proc test-multiple-argv-arrays {
|
84 | parser (&spec) {
|
85 | flag -v --verbose ('bool', default=false)
|
86 | flag -c --count ('int', default=120)
|
87 | arg file
|
88 | }
|
89 |
|
90 | # TODO: argCases should go above
|
91 | var argsCases = [
|
92 | :| -v --count 120 example.sh |,
|
93 | :| -v --count 120 example.sh -v |, # duplicate flags are ignored
|
94 | :| -v --count 120 example.sh -v --count 150 |, # the last duplicate has precedence
|
95 | ]
|
96 |
|
97 | yb-capture (&r) {
|
98 | for args in (argsCases) {
|
99 | var args_str = join(args, ' ')
|
100 | echo "---------- $args_str ----------"
|
101 | echo "\$ bin/ysh example.sh $args_str"
|
102 | pp test_ (parseArgs(spec, args))
|
103 |
|
104 | echo
|
105 | }
|
106 | }
|
107 |
|
108 | #pp (r.stdout)
|
109 |
|
110 | var expected = '''
|
111 | ---------- -v --count 120 example.sh ----------
|
112 | $ bin/ysh example.sh -v --count 120 example.sh
|
113 | (Dict) {"verbose":true,"count":120,"file":"example.sh"}
|
114 |
|
115 | ---------- -v --count 120 example.sh -v ----------
|
116 | $ bin/ysh example.sh -v --count 120 example.sh -v
|
117 | (Dict) {"verbose":true,"count":120,"file":"example.sh"}
|
118 |
|
119 | ---------- -v --count 120 example.sh -v --count 150 ----------
|
120 | $ bin/ysh example.sh -v --count 120 example.sh -v --count 150
|
121 | (Dict) {"verbose":true,"count":150,"file":"example.sh"}
|
122 |
|
123 | '''
|
124 |
|
125 | assert [expected === r.stdout]
|
126 | }
|
127 |
|
128 | proc test-duplicate-names-are-errors {
|
129 | try {
|
130 | parser (&spec) {
|
131 | flag -n --name
|
132 | flag -N --name
|
133 | }
|
134 | }
|
135 | assert [3 === _error.code]
|
136 |
|
137 | try {
|
138 | parser (&spec) {
|
139 | flag -n --name
|
140 | arg name
|
141 | }
|
142 | }
|
143 | assert [3 === _error.code]
|
144 |
|
145 | try {
|
146 | parser (&spec) {
|
147 | arg name
|
148 | flag -o --other
|
149 | arg name
|
150 | }
|
151 | }
|
152 | assert [3 === _error.code]
|
153 | }
|
154 |
|
155 | proc test-more-errors {
|
156 |
|
157 | parser (&spec) {
|
158 | flag -v --verbose
|
159 | flag -n --num ('int', required=true)
|
160 |
|
161 | arg action
|
162 | arg other (required=false)
|
163 | }
|
164 |
|
165 | try { call parseArgs(spec, :| -n 10 action other extra |) }
|
166 | assert [2 === _error.code]
|
167 |
|
168 | try { call parseArgs(spec, :| -n |) }
|
169 | assert [2 === _error.code]
|
170 |
|
171 | try { call parseArgs(spec, :| -n -v |) }
|
172 | assert [2 === _error.code]
|
173 |
|
174 | try { = parseArgs(spec, :| -n 10 |) }
|
175 | assert [2 === _error.code]
|
176 |
|
177 | try { call parseArgs(spec, :| -v action |) }
|
178 | assert [2 === _error.code]
|
179 |
|
180 | try { call parseArgs(spec, :| --unknown |) }
|
181 | assert [2 === _error.code]
|
182 | }
|
183 |
|
184 | proc test-print-spec {
|
185 |
|
186 | parser (&spec) {
|
187 | flag -v --verbose ('bool')
|
188 | arg src
|
189 | arg dst
|
190 |
|
191 | rest more # allow more args
|
192 | }
|
193 |
|
194 | yb-capture (&r) {
|
195 | json write (spec)
|
196 | }
|
197 |
|
198 | var expected = '''
|
199 | {
|
200 | "flags": [
|
201 | {
|
202 | "short": "-v",
|
203 | "long": "--verbose",
|
204 | "name": "verbose",
|
205 | "type": "bool",
|
206 | "default": false,
|
207 | "help": null
|
208 | }
|
209 | ],
|
210 | "args": [
|
211 | {
|
212 | "name": "src",
|
213 | "help": null
|
214 | },
|
215 | {
|
216 | "name": "dst",
|
217 | "help": null
|
218 | }
|
219 | ],
|
220 | "rest": "more"
|
221 | }
|
222 | '''
|
223 |
|
224 | assert [expected === r.stdout]
|
225 | }
|
226 |
|
227 | proc test-vs-python3-argparse {
|
228 | var spec = {
|
229 | flags: [
|
230 | {short: '-v', long: '--verbose', name: 'verbose', type: null, default: '', help: 'Enable verbose logging'},
|
231 | {short: '-c', long: '--count', name: 'count', type: 'int', default: 80, help: 'Maximum line length'},
|
232 | ],
|
233 | args: [
|
234 | {name: 'file', type: 'str', help: 'File to check line lengths of'}
|
235 | ],
|
236 | rest: null,
|
237 | }
|
238 |
|
239 | var argsCases = [
|
240 | :| -v --count 120 example.sh |,
|
241 | :| -v --count 120 example.sh -v |, # duplicate flags are ignored
|
242 | :| -v --count 120 example.sh -v --count 150 |, # the last duplicate has precedence
|
243 | ]
|
244 |
|
245 | var argparse_py = '''
|
246 | import argparse
|
247 | import sys
|
248 |
|
249 | spec = argparse.ArgumentParser()
|
250 | spec.add_argument("filename")
|
251 | spec.add_argument("-c", "--count", type=int)
|
252 | spec.add_argument("-v", "--verbose",
|
253 | action="store_true")
|
254 |
|
255 | result = spec.parse_args(sys.argv[1:])
|
256 | print([result.filename, result.count, result.verbose])
|
257 | '''
|
258 |
|
259 | yb-capture (&r) {
|
260 | for args in (argsCases) {
|
261 | var args_str = args => join(" ")
|
262 | echo "---------- $args_str ----------"
|
263 | echo "\$ bin/ysh example.sh $args_str"
|
264 | pp test_ (parseArgs(spec, args))
|
265 |
|
266 | echo
|
267 | echo "\$ python3 example.py $args_str"
|
268 | python3 -c $argparse_py @args
|
269 |
|
270 | echo
|
271 | }
|
272 | }
|
273 |
|
274 | var expected = '''
|
275 | ---------- -v --count 120 example.sh ----------
|
276 | $ bin/ysh example.sh -v --count 120 example.sh
|
277 | (Dict) {"verbose":true,"count":120,"file":"example.sh"}
|
278 |
|
279 | $ python3 example.py -v --count 120 example.sh
|
280 | ['example.sh', 120, True]
|
281 |
|
282 | ---------- -v --count 120 example.sh -v ----------
|
283 | $ bin/ysh example.sh -v --count 120 example.sh -v
|
284 | (Dict) {"verbose":true,"count":120,"file":"example.sh"}
|
285 |
|
286 | $ python3 example.py -v --count 120 example.sh -v
|
287 | ['example.sh', 120, True]
|
288 |
|
289 | ---------- -v --count 120 example.sh -v --count 150 ----------
|
290 | $ bin/ysh example.sh -v --count 120 example.sh -v --count 150
|
291 | (Dict) {"verbose":true,"count":150,"file":"example.sh"}
|
292 |
|
293 | $ python3 example.py -v --count 120 example.sh -v --count 150
|
294 | ['example.sh', 150, True]
|
295 |
|
296 | '''
|
297 |
|
298 | # This is acceptable, but the diff could look nicer and more precise
|
299 | diff -u <(echo $expected) <(echo $[r.stdout])
|
300 | #assert [expected === r.stdout]
|
301 | }
|
302 |
|
303 | if is-main {
|
304 | byo-maybe-run
|
305 | }
|