16
16
from __future__ import division
17
17
from __future__ import print_function
18
18
19
+ import sys
20
+ import unittest
21
+
19
22
import fire
20
23
from fire import test_components as tc
21
- from fire import trace
24
+ from fire import testutils
22
25
26
+ import mock
23
27
import six
24
- import unittest
25
28
26
29
27
- class FireTest (unittest . TestCase ):
30
+ class FireTest (testutils . BaseTestCase ):
28
31
29
32
def testFire (self ):
30
- fire .Fire (tc .Empty )
31
- fire .Fire (tc .OldStyleEmpty )
32
- fire .Fire (tc .WithInit )
33
+ with mock .patch .object (sys , 'argv' , ['progname' ]):
34
+ fire .Fire (tc .Empty )
35
+ fire .Fire (tc .OldStyleEmpty )
36
+ fire .Fire (tc .WithInit )
33
37
self .assertEqual (fire .Fire (tc .NoDefaults , 'double 2' ), 4 )
34
38
self .assertEqual (fire .Fire (tc .NoDefaults , 'triple 4' ), 12 )
35
39
self .assertEqual (fire .Fire (tc .WithDefaults , 'double 2' ), 4 )
@@ -41,10 +45,13 @@ def testFireNoArgs(self):
41
45
self .assertEqual (fire .Fire (tc .MixedDefaults , 'ten' ), 10 )
42
46
43
47
def testFireExceptions (self ):
44
- # Exceptions of Fire are printed to stderr and None is returned.
45
- self .assertIsNone (fire .Fire (tc .Empty , 'nomethod' )) # Member doesn't exist.
46
- self .assertIsNone (fire .Fire (tc .NoDefaults , 'double' )) # Missing argument.
47
- self .assertIsNone (fire .Fire (tc .TypedProperties , 'delta x' )) # Missing key.
48
+ # Exceptions of Fire are printed to stderr and a FireExit is raised.
49
+ with self .assertRaisesFireExit (2 ):
50
+ fire .Fire (tc .Empty , 'nomethod' ) # Member doesn't exist.
51
+ with self .assertRaisesFireExit (2 ):
52
+ fire .Fire (tc .NoDefaults , 'double' ) # Missing argument.
53
+ with self .assertRaisesFireExit (2 ):
54
+ fire .Fire (tc .TypedProperties , 'delta x' ) # Missing key.
48
55
49
56
# Exceptions of the target components are still raised.
50
57
with self .assertRaises (ZeroDivisionError ):
@@ -89,11 +96,13 @@ def testFirePartialNamedArgs(self):
89
96
fire .Fire (tc .MixedDefaults , 'identity --beta 1 --alpha 2' ), (2 , 1 ))
90
97
91
98
def testFirePartialNamedArgsOneMissing (self ):
92
- # By default, errors are written to standard out and None is returned.
93
- self .assertIsNone ( # Identity needs an arg.
94
- fire .Fire (tc .MixedDefaults , 'identity' ))
95
- self .assertIsNone ( # Identity needs a value for alpha.
96
- fire .Fire (tc .MixedDefaults , 'identity --beta 2' ))
99
+ # Errors are written to standard out and a FireExit is raised.
100
+ with self .assertRaisesFireExit (2 ):
101
+ fire .Fire (tc .MixedDefaults , 'identity' ) # Identity needs an arg.
102
+
103
+ with self .assertRaisesFireExit (2 ):
104
+ # Identity needs a value for alpha.
105
+ fire .Fire (tc .MixedDefaults , 'identity --beta 2' )
97
106
98
107
self .assertEqual (fire .Fire (tc .MixedDefaults , 'identity 1' ), (1 , '0' ))
99
108
self .assertEqual (
@@ -103,9 +112,11 @@ def testFireAnnotatedArgs(self):
103
112
self .assertEqual (fire .Fire (tc .Annotations , 'double 5' ), 10 )
104
113
self .assertEqual (fire .Fire (tc .Annotations , 'triple 5' ), 15 )
105
114
106
- @unittest .skipIf (six .PY2 , 'Keyword-only arguments not supported in Python 2' )
115
+ @unittest .skipIf (six .PY2 , 'Keyword-only arguments not in Python 2. ' )
107
116
def testFireKeywordOnlyArgs (self ):
108
- self .assertIsNone (fire .Fire (tc .py3 .KeywordOnly , 'double 5' ))
117
+ with self .assertRaisesFireExit (2 ):
118
+ # Keyword arguments must be passed with flag syntax.
119
+ fire .Fire (tc .py3 .KeywordOnly , 'double 5' )
109
120
110
121
self .assertEqual (fire .Fire (tc .py3 .KeywordOnly , 'double --count 5' ), 10 )
111
122
self .assertEqual (fire .Fire (tc .py3 .KeywordOnly , 'triple --count 5' ), 15 )
@@ -252,17 +263,19 @@ def fn1(thing, nothing):
252
263
self .assertEqual (fire .Fire (fn1 , '--thing --nothing' ), (True , True ))
253
264
self .assertEqual (fire .Fire (fn1 , '--thing --nonothing' ), (True , False ))
254
265
255
- # In the next example nothing=False (since rightmost setting of a flag gets
256
- # precedence), but it errors because thing has no value.
257
- self .assertEqual (fire .Fire (fn1 , '--nothing --nonothing' ), None )
266
+ with self .assertRaisesFireExit (2 ):
267
+ # In this case nothing=False (since rightmost setting of a flag gets
268
+ # precedence), but it errors because thing has no value.
269
+ fire .Fire (fn1 , '--nothing --nonothing' )
258
270
259
271
# In these examples, --nothing sets thing=False:
260
272
def fn2 (thing , ** kwargs ):
261
273
return thing , kwargs
262
274
self .assertEqual (fire .Fire (fn2 , '--thing' ), (True , {}))
263
275
self .assertEqual (fire .Fire (fn2 , '--nothing' ), (False , {}))
264
- # In the next one, nothing=True, but it errors because thing has no value.
265
- self .assertEqual (fire .Fire (fn2 , '--nothing=True' ), None )
276
+ with self .assertRaisesFireExit (2 ):
277
+ # In this case, nothing=True, but it errors because thing has no value.
278
+ fire .Fire (fn2 , '--nothing=True' )
266
279
self .assertEqual (fire .Fire (fn2 , '--nothing --nothing=True' ),
267
280
(False , {'nothing' : True }))
268
281
@@ -276,26 +289,28 @@ def fn3(arg, **kwargs):
276
289
('value' , {'nothing' : False }))
277
290
278
291
def testTraceFlag (self ):
279
- self .assertIsInstance (
280
- fire .Fire (tc .BoolConverter , 'as-bool True -- --trace' ), trace . FireTrace )
281
- self .assertIsInstance (
282
- fire .Fire (tc .BoolConverter , 'as-bool True -- -t' ), trace . FireTrace )
283
- self .assertIsInstance (
284
- fire .Fire (tc .BoolConverter , '-- --trace' ), trace . FireTrace )
292
+ with self .assertRaisesFireExit ( 0 , 'Fire trace: \n ' ):
293
+ fire .Fire (tc .BoolConverter , 'as-bool True -- --trace' )
294
+ with self .assertRaisesFireExit ( 0 , 'Fire trace: \n ' ):
295
+ fire .Fire (tc .BoolConverter , 'as-bool True -- -t' )
296
+ with self .assertRaisesFireExit ( 0 , 'Fire trace: \n ' ):
297
+ fire .Fire (tc .BoolConverter , '-- --trace' )
285
298
286
299
def testHelpFlag (self ):
287
- self .assertIsNone (fire .Fire (tc .BoolConverter , 'as-bool True -- --help' ))
288
- self .assertIsNone (fire .Fire (tc .BoolConverter , 'as-bool True -- -h' ))
289
- self .assertIsNone (fire .Fire (tc .BoolConverter , '-- --help' ))
300
+ with self .assertRaisesFireExit (0 ):
301
+ fire .Fire (tc .BoolConverter , 'as-bool True -- --help' )
302
+ with self .assertRaisesFireExit (0 ):
303
+ fire .Fire (tc .BoolConverter , 'as-bool True -- -h' )
304
+ with self .assertRaisesFireExit (0 ):
305
+ fire .Fire (tc .BoolConverter , '-- --help' )
290
306
291
307
def testHelpFlagAndTraceFlag (self ):
292
- self .assertIsInstance (
293
- fire .Fire (tc .BoolConverter , 'as-bool True -- --help --trace' ),
294
-
10000
trace .FireTrace )
295
- self .assertIsInstance (
296
- fire .Fire (tc .BoolConverter , 'as-bool True -- -h -t' ), trace .FireTrace )
297
- self .assertIsInstance (
298
- fire .Fire (tc .BoolConverter , '-- -h --trace' ), trace .FireTrace )
308
+ with self .assertRaisesFireExit (0 , 'Fire trace:\n .*Usage:' ):
309
+ fire .Fire (tc .BoolConverter , 'as-bool True -- --help --trace' )
310
+ with self .assertRaisesFireExit (0 , 'Fire trace:\n .*Usage:' ):
311
+ fire .Fire (tc .BoolConverter , 'as-bool True -- -h -t' )
312
+ with self .assertRaisesFireExit (0 , 'Fire trace:\n .*Usage:' ):
313
+ fire .Fire (tc .BoolConverter , '-- -h --trace' )
299
314
300
315
def testTabCompletionNoName (self ):
301
316
with self .assertRaises (ValueError ):
@@ -323,7 +338,8 @@ def testBasicSeparator(self):
323
338
('-' , '_' ))
324
339
325
340
# The separator triggers a function call, but there aren't enough arguments.
326
- self .assertEqual (fire .Fire (tc .MixedDefaults , 'identity - _ +' ), None )
341
+ with self .assertRaisesFireExit (2 ):
342
+ fire .Fire (tc .MixedDefaults , 'identity - _ +' )
327
343
328
344
def testNonComparable (self ):
329
345
"""Fire should work with classes that disallow comparisons."""
@@ -367,24 +383,34 @@ def testFloatForExpectedInt(self):
367
383
def testClassInstantiation (self ):
368
384
self .assertIsInstance (fire .Fire (tc .InstanceVars , '--arg1=a1 --arg2=a2' ),
369
385
tc .InstanceVars )
370
- # Cannot instantiate a class with positional args by default.
371
- self .assertIsNone (fire .Fire (tc .InstanceVars , 'a1 a2' ))
386
+ with self .assertRaisesFireExit (2 ):
387
+ # Cannot instantiate a class with positional args.
388
+ fire .Fire (tc .InstanceVars , 'a1 a2' )
372
389
373
390
def testTraceErrors (self ):
374
391
# Class needs additional value but runs out of args.
375
- self .assertIsNone (fire .Fire (tc .InstanceVars , 'a1' ))
376
- self .assertIsNone (fire .Fire (tc .InstanceVars , '--arg1=a1' ))
392
+ with self .assertRaisesFireExit (2 ):
393
+ fire .Fire (tc .InstanceVars , 'a1' )
394
+ with self .assertRaisesFireExit (2 ):
395
+ fire .Fire (tc .InstanceVars , '--arg1=a1' )
396
+
377
397
# Routine needs additional value but runs out of args.
378
- self .assertIsNone (fire .Fire (tc .InstanceVars , 'a1 a2 - run b1' ))
379
- self .assertIsNone (
380
- fire .Fire (tc .InstanceVars , '--arg1=a1 --arg2=a2 - run b1' ))
398
+ with self .assertRaisesFireExit (2 ):
399
+ fire .Fire (tc .InstanceVars , 'a1 a2 - run b1' )
400
+ with self .assertRaisesFireExit (2 ):
401
+ fire .Fire (tc .InstanceVars , '--arg1=a1 --arg2=a2 - run b1' )
402
+
381
403
# Extra args cannot be consumed.
382
- self .assertIsNone (fire .Fire (tc .InstanceVars , 'a1 a2 - run b1 b2 b3' ))
383
- self .assertIsNone (
384
- fire .Fire (tc .InstanceVars , '--arg1=a1 --arg2=a2 - run b1 b2 b3' ))
404
+ with self .assertRaisesFireExit (2 ):
405
+ fire .Fire (tc .InstanceVars , 'a1 a2 - run b1 b2 b3' )
406
+ with self .assertRaisesFireExit (2 ):
407
+ fire .Fire (tc .InstanceVars , '--arg1=a1 --arg2=a2 - run b1 b2 b3' )
408
+
385
409
# Cannot find member to access.
386
- self .assertIsNone (fire .Fire (tc .InstanceVars , 'a1 a2 - jog' ))
387
- self .assertIsNone (fire .Fire (tc .InstanceVars , '--arg1=a1 --arg2=a2 - jog' ))
410
+ with self .assertRaisesFireExit (2 ):
411
+ fire .Fire (tc .InstanceVars , 'a1 a2 - jog' )
412
+ with self .assertRaisesFireExit (2 ):
413
+ fire .Fire (tc .InstanceVars , '--arg1=a1 --arg2=a2 - jog' )
388
414
389
415
390
416
if __name__ == '__main__' :
0 commit comments