# Copyright (C) 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for the fire module."""
import os
import sys
from unittest import mock
import fire
from fire import test_components as tc
from fire import testutils
class FireTest(testutils.BaseTestCase):
def testFire(self):
with mock.patch.object(sys, 'argv', ['progname']):
fire.Fire(tc.Empty)
fire.Fire(tc.OldStyleEmpty)
fire.Fire(tc.WithInit)
# Test both passing command as a sequence and as a string.
self.assertEqual(fire.Fire(tc.NoDefaults, command='triple 4'), 12)
self.assertEqual(fire.Fire(tc.WithDefaults, command=('double', '2')), 4)
self.assertEqual(fire.Fire(tc.WithDefaults, command=['triple', '4']), 12)
self.assertEqual(fire.Fire(tc.OldStyleWithDefaults,
command=['double', '2']), 4)
self.assertEqual(fire.Fire(tc.OldStyleWithDefaults,
command=['triple', '4']), 12)
def testFirePositionalCommand(self):
# Test passing command as a positional argument.
self.assertEqual(fire.Fire(tc.NoDefaults, 'double 2'), 4)
self.assertEqual(fire.Fire(tc.NoDefaults, ['double', '2']), 4)
def testFireInvalidCommandArg(self):
with self.assertRaises(ValueError):
# This is not a valid command.
fire.Fire(tc.WithDefaults, command=10)
def testFireDefaultName(self):
with mock.patch.object(sys, 'argv',
[os.path.join('python-fire', 'fire',
'base_filename.py')]):
with self.assertOutputMatches(stdout='SYNOPSIS.*base_filename.py',
stderr=None):
fire.Fire(tc.Empty)
def testFireNoArgs(self):
self.assertEqual(fire.Fire(tc.MixedDefaults, command=['ten']), 10)
def testFireExceptions(self):
# Exceptions of Fire are printed to stderr and a FireExit is raised.
with self.assertRaisesFireExit(2):
fire.Fire(tc.Empty, command=['nomethod']) # Member doesn't exist.
with self.assertRaisesFireExit(2):
fire.Fire(tc.NoDefaults, command=['double']) # Missing argument.
with self.assertRaisesFireExit(2):
fire.Fire(tc.TypedProperties, command=['delta', 'x']) # Missing key.
# Exceptions of the target components are still raised.
with self.assertRaises(ZeroDivisionError):
fire.Fire(tc.NumberDefaults, command=['reciprocal', '0.0'])
def testFireNamedArgs(self):
self.assertEqual(fire.Fire(tc.WithDefaults,
command=['double', '--count', '5']), 10)
self.assertEqual(fire.Fire(tc.WithDefaults,
command=['triple', '--count', '5']), 15)
self.assertEqual(
fire.Fire(tc.OldStyleWithDefaults, command=['double', '--count', '5']),
10)
self.assertEqual(
fire.Fire(tc.OldStyleWithDefaults, command=['triple', '--count', '5']),
15)
def testFireNamedArgsSingleHyphen(self):
self.assertEqual(fire.Fire(tc.WithDefaults,
command=['double', '-count', '5']), 10)
self.assertEqual(fire.Fire(tc.WithDefaults,
command=['triple', '-count', '5']), 15)
self.assertEqual(
fire.Fire(tc.OldStyleWithDefaults, command=['double', '-count', '5']),
10)
self.assertEqual(
fire.Fire(tc.OldStyleWithDefaults, command=['triple', '-count', '5']),
15)
def testFireNamedArgsWithEquals(self):
self.assertEqual(fire.Fire(tc.WithDefaults,
command=['double', '--count=5']), 10)
self.assertEqual(fire.Fire(tc.WithDefaults,
command=['triple', '--count=5']), 15)
def testFireNamedArgsWithEqualsSingleHyphen(self):
self.assertEqual(fire.Fire(tc.WithDefaults,
command=['double', '-count=5']), 10)
self.assertEqual(fire.Fire(tc.WithDefaults,
command=['triple', '-count=5']), 15)
def testFireAllNamedArgs(self):
self.assertEqual(fire.Fire(tc.MixedDefaults, command=['sum', '1', '2']), 5)
self.assertEqual(fire.Fire(tc.MixedDefaults,
command=['sum', '--alpha', '1', '2']), 5)
self.assertEqual(fire.Fire(tc.MixedDefaults,
command=['sum', '--beta', '1', '2']), 4)
self.assertEqual(fire.Fire(tc.MixedDefaults,
command=['sum', '1', '--alpha', '2']), 4)
self.assertEqual(fire.Fire(tc.MixedDefaults,
command=['sum', '1', '--beta', '2']), 5)
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['sum', '--alpha', '1', '--beta', '2']), 5)
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['sum', '--beta', '1', '--alpha', '2']), 4)
def testFireAllNamedArgsOneMissing(self):
self.assertEqual(fire.Fire(tc.MixedDefaults, command=['sum']), 0)
self.assertEqual(fire.Fire(tc.MixedDefaults, command=['sum', '1']), 1)
self.assertEqual(fire.Fire(tc.MixedDefaults,
command=['sum', '--alpha', '1']), 1)
self.assertEqual(fire.Fire(tc.MixedDefaults,
command=['sum', '--beta', '2']), 4)
def testFirePartialNamedArgs(self):
self.assertEqual(
fire.Fire(tc.MixedDefaults, command=['identity', '1', '2']), (1, 2))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--alpha', '1', '2']), (1, 2))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--beta', '1', '2']), (2, 1))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '1', '--alpha', '2']), (2, 1))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '1', '--beta', '2']), (1, 2))
self.assertEqual(
fire.Fire(
tc.MixedDefaults,
command=['identity', '--alpha', '1', '--beta', '2']), (1, 2))
self.assertEqual(
fire.Fire(
tc.MixedDefaults,
command=['identity', '--beta', '1', '--alpha', '2']), (2, 1))
def testFirePartialNamedArgsOneMissing(self):
# Errors are written to standard out and a FireExit is raised.
with self.assertRaisesFireExit(2):
fire.Fire(tc.MixedDefaults,
command=['identity']) # Identity needs an arg.
with self.assertRaisesFireExit(2):
# Identity needs a value for alpha.
fire.Fire(tc.MixedDefaults, command=['identity', '--beta', '2'])
self.assertEqual(
fire.Fire(tc.MixedDefaults, command=['identity', '1']), (1, '0'))
self.assertEqual(
fire.Fire(tc.MixedDefaults, command=['identity', '--alpha', '1']),
(1, '0'))
def testFireAnnotatedArgs(self):
self.assertEqual(fire.Fire(tc.Annotations, command=['double', '5']), 10)
self.assertEqual(fire.Fire(tc.Annotations, command=['triple', '5']), 15)
def testFireKeywordOnlyArgs(self):
with self.assertRaisesFireExit(2):
# Keyword arguments must be passed with flag syntax.
fire.Fire(tc.py3.KeywordOnly, command=['double', '5'])
self.assertEqual(
fire.Fire(tc.py3.KeywordOnly, command=['double', '--count', '5']), 10)
self.assertEqual(
fire.Fire(tc.py3.KeywordOnly, command=['triple', '--count', '5']), 15)
def testFireProperties(self):
self.assertEqual(fire.Fire(tc.TypedProperties, command=['alpha']), True)
self.assertEqual(fire.Fire(tc.TypedProperties, command=['beta']), (1, 2, 3))
def testFireRecursion(self):
self.assertEqual(
fire.Fire(tc.TypedProperties,
command=['charlie', 'double', 'hello']), 'hellohello')
self.assertEqual(fire.Fire(tc.TypedProperties,
command=['charlie', 'triple', 'w']), 'www')
def testFireVarArgs(self):
self.assertEqual(
fire.Fire(tc.VarArgs,
command=['cumsums', 'a', 'b', 'c', 'd']),
['a', 'ab', 'abc', 'abcd'])
self.assertEqual(
fire.Fire(tc.VarArgs, command=['cumsums', '1', '2', '3', '4']),
[1, 3, 6, 10])
def testFireVarArgsWithNamedArgs(self):
self.assertEqual(
fire.Fire(tc.VarArgs, command=['varchars', '1', '2', 'c', 'd']),
(1, 2, 'cd'))
self.assertEqual(
fire.Fire(tc.VarArgs, command=['varchars', '3', '4', 'c', 'd', 'e']),
(3, 4, 'cde'))
def testFireKeywordArgs(self):
self.assertEqual(
fire.Fire(
tc.Kwargs,
command=['props', '--name', 'David', '--age', '24']),
{'name': 'David', 'age': 24})
# Run this test both with a list command and a string command.
self.assertEqual(
fire.Fire(
tc.Kwargs,
command=['props', '--message',
'"This is a message it has -- in it"']), # Quotes stripped
{'message': 'This is a message it has -- in it'})
self.assertEqual(
fire.Fire(
tc.Kwargs,
command=['props', '--message',
'This is a message it has -- in it']),
{'message': 'This is a message it has -- in it'})
self.assertEqual(
fire.Fire(
tc.Kwargs,
command='props --message "This is a message it has -- in it"'),
{'message': 'This is a message it has -- in it'})
self.assertEqual(
fire.Fire(tc.Kwargs,
command=['upper', '--alpha', 'A', '--beta', 'B']),
'ALPHA BETA')
self.assertEqual(
fire.Fire(
tc.Kwargs,
command=['upper', '--alpha', 'A', '--beta', 'B', '-', 'lower']),
'alpha beta')
def testFireKeywordArgsWithMissingPositionalArgs(self):
self.assertEqual(
fire.Fire(tc.Kwargs, command=['run', 'Hello', 'World', '--cell', 'is']),
('Hello', 'World', {'cell': 'is'}))
self.assertEqual(
fire.Fire(tc.Kwargs, command=['run', 'Hello', '--cell', 'ok']),
('Hello', None, {'cell': 'ok'}))
def testFireObject(self):
self.assertEqual(
fire.Fire(tc.WithDefaults(), command=['double', '--count', '5']), 10)
self.assertEqual(
fire.Fire(tc.WithDefaults(), command=['triple', '--count', '5']), 15)
def testFireDict(self):
component = {
'double': lambda x=0: 2 * x,
'cheese': 'swiss',
}
self.assertEqual(fire.Fire(component, command=['double', '5']), 10)
self.assertEqual(fire.Fire(component, command=['cheese']), 'swiss')
def testFireObjectWithDict(self):
self.assertEqual(
fire.Fire(tc.TypedProperties, command=['delta', 'echo']), 'E')
self.assertEqual(
fire.Fire(tc.TypedProperties, command=['delta', 'echo', 'lower']), 'e')
self.assertIsInstance(
fire.Fire(tc.TypedProperties, command=['delta', 'nest']), dict)
self.assertEqual(
fire.Fire(tc.TypedProperties, command=['delta', 'nest', '0']), 'a')
def testFireSet(self):
component = tc.simple_set()
result = fire.Fire(component, command=[])
self.assertEqual(len(result), 3)
def testFireFrozenset(self):
component = tc.simple_frozenset()
result = fire.Fire(component, command=[])
self.assertEqual(len(result), 3)
def testFireList(self):
component = ['zero', 'one', 'two', 'three']
self.assertEqual(fire.Fire(component, command=['2']), 'two')
self.assertEqual(fire.Fire(component, command=['3']), 'three')
self.assertEqual(fire.Fire(component, command=['-1']), 'three')
def testFireObjectWithList(self):
self.assertEqual(fire.Fire(tc.TypedProperties, command=['echo', '0']),
'alex')
self.assertEqual(fire.Fire(tc.TypedProperties, command=['echo', '1']),
'bethany')
def testFireObjectWithTuple(self):
self.assertEqual(fire.Fire(tc.TypedProperties, command=['fox', '0']),
'carry')
self.assertEqual(fire.Fire(tc.TypedProperties, command=['fox', '1']),
'divide')
def testFireObjectWithListAsObject(self):
self.assertEqual(
fire.Fire(tc.TypedProperties, command=['echo', 'count', 'bethany']),
1)
def testFireObjectWithTupleAsObject(self):
self.assertEqual(
fire.Fire(tc.TypedProperties, command=['fox', 'count', 'divide']),
1)
def testFireNoComponent(self):
self.assertEqual(fire.Fire(command=['tc', 'WithDefaults', 'double', '10']),
20)
last_char = lambda text: text[-1] # pylint: disable=unused-variable
self.assertEqual(fire.Fire(command=['last_char', '"Hello"']), 'o')
self.assertEqual(fire.Fire(command=['last-char', '"World"']), 'd')
rset = lambda count=0: set(range(count)) # pylint: disable=unused-variable
self.assertEqual(fire.Fire(command=['rset', '5']), {0, 1, 2, 3, 4})
def testFireUnderscores(self):
self.assertEqual(
fire.Fire(tc.Underscores,
command=['underscore-example']), 'fish fingers')
self.assertEqual(
fire.Fire(tc.Underscores,
command=['underscore_example']), 'fish fingers')
def testFireUnderscoresInArg(self):
self.assertEqual(
fire.Fire(tc.Underscores,
command=['underscore-function', 'example']), 'example')
self.assertEqual(
fire.Fire(tc.Underscores,
command=['underscore_function', '--underscore-arg=score']),
'score')
self.assertEqual(
fire.Fire(tc.Underscores,
command=['underscore_function', '--underscore_arg=score']),
'score')
def testBoolParsing(self):
self.assertEqual(fire.Fire(tc.BoolConverter, command=['as-bool', 'True']),
True)
self.assertEqual(
fire.Fire(tc.BoolConverter, command=['as-bool', 'False']), False)
self.assertEqual(
fire.Fire(tc.BoolConverter, command=['as-bool', '--arg=True']), True)
self.assertEqual(
fire.Fire(tc.BoolConverter, command=['as-bool', '--arg=False']), False)
self.assertEqual(fire.Fire(tc.BoolConverter, command=['as-bool', '--arg']),
True)
self.assertEqual(
fire.Fire(tc.BoolConverter, command=['as-bool', '--noarg']), False)
def testBoolParsingContinued(self):
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', 'True', 'False']), (True, False))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--alpha=False', '10']), (False, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--alpha', '--beta', '10']), (True, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--alpha', '--beta=10']), (True, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--noalpha', '--beta']), (False, True))
self.assertEqual(
fire.Fire(tc.MixedDefaults, command=['identity', '10', '--beta']),
(10, True))
def testBoolParsingSingleHyphen(self):
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-alpha=False', '10']), (False, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-alpha', '-beta', '10']), (True, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-alpha', '-beta=10']), (True, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-noalpha', '-beta']), (False, True))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-alpha', '-10', '-beta']), (-10, True))
def testBoolParsingLessExpectedCases(self):
# Note: Does not return (True, 10).
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--alpha', '10']), (10, '0'))
# To get (True, 10), use one of the following:
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--alpha', '--beta=10']),
(True, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', 'True', '10']), (True, 10))
# Note: Does not return (True, '--test') or ('--test', 0).
with self.assertRaisesFireExit(2):
fire.Fire(tc.MixedDefaults, command=['identity', '--alpha', '--test'])
self.assertEqual(
fire.Fire(
tc.MixedDefaults,
command=['identity', '--alpha', 'True', '"--test"']),
(True, '--test'))
# To get ('--test', '0'), use one of the following:
self.assertEqual(fire.Fire(tc.MixedDefaults,
command=['identity', '--alpha=--test']),
('--test', '0'))
self.assertEqual(
fire.Fire(tc.MixedDefaults, command=r'identity --alpha \"--test\"'),
('--test', '0'))
def testSingleCharFlagParsing(self):
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a']), (True, '0'))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a', '--beta=10']), (True, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a', '-b']), (True, True))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a', '42', '-b']), (42, True))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a', '42', '-b', '10']), (42, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '--alpha', 'True', '-b', '10']),
(True, 10))
with self.assertRaisesFireExit(2):
# This test attempts to use an ambiguous shortcut flag on a function with
# a naming conflict for the shortcut, triggering a FireError.
fire.Fire(tc.SimilarArgNames, command=['identity', '-b'])
def testSingleCharFlagParsingEqualSign(self):
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a=True']), (True, '0'))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a=3', '--beta=10']), (3, 10))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a=False', '-b=15']), (False, 15))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a', '42', '-b=12']), (42, 12))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-a=42', '-b', '10']), (42, 10))
def testSingleCharFlagParsingExactMatch(self):
self.assertEqual(
fire.Fire(tc.SimilarArgNames,
command=['identity2', '-a']), (True, None))
self.assertEqual(
fire.Fire(tc.SimilarArgNames,
command=['identity2', '-a=10']), (10, None))
self.assertEqual(
fire.Fire(tc.SimilarArgNames,
command=['identity2', '--a']), (True, None))
self.assertEqual(
fire.Fire(tc.SimilarArgNames,
command=['identity2', '-alpha']), (None, True))
self.assertEqual(
fire.Fire(tc.SimilarArgNames,
command=['identity2', '-a', '-alpha']), (True, True))
def testSingleCharFlagParsingCapitalLetter(self):
self.assertEqual(
fire.Fire(tc.CapitalizedArgNames,
command=['sum', '-D', '5', '-G', '10']), 15)
def testBoolParsingWithNo(self):
# In these examples --nothing always refers to the nothing argument:
def fn1(thing, nothing):
return thing, nothing
self.assertEqual(fire.Fire(fn1, command=['--thing', '--nothing']),
(True, True))
self.assertEqual(fire.Fire(fn1, command=['--thing', '--nonothing']),
(True, False))
with self.assertRaisesFireExit(2):
# In this case nothing=False (since rightmost setting of a flag gets
# precedence), but it errors because thing has no value.
fire.Fire(fn1, command=['--nothing', '--nonothing'])
# In these examples, --nothing sets thing=False:
def fn2(thing, **kwargs):
return thing, kwargs
self.assertEqual(fire.Fire(fn2, command=['--thing']), (True, {}))
self.assertEqual(fire.Fire(fn2, command=['--nothing']), (False, {}))
with self.assertRaisesFireExit(2):
# In this case, nothing=True, but it errors because thing has no value.
fire.Fire(fn2, command=['--nothing=True'])
self.assertEqual(fire.Fire(fn2, command=['--nothing', '--nothing=True']),
(False, {'nothing': True}))
def fn3(arg, **kwargs):
return arg, kwargs
self.assertEqual(fire.Fire(fn3, command=['--arg=value', '--thing']),
('value', {'thing': True}))
self.assertEqual(fire.Fire(fn3, command=['--arg=value', '--nothing']),
('value', {'thing': False}))
self.assertEqual(fire.Fire(fn3, command=['--arg=value', '--nonothing']),
('value', {'nothing': False}))
def testTraceFlag(self):
with self.assertRaisesFireExit(0, 'Fire trace:\n'):
fire.Fire(tc.BoolConverter, command=['as-bool', 'True', '--', '--trace'])
with self.assertRaisesFireExit(0, 'Fire trace:\n'):
fire.Fire(tc.BoolConverter, command=['as-bool', 'True', '--', '-t'])
with self.assertRaisesFireExit(0, 'Fire trace:\n'):
fire.Fire(tc.BoolConverter, command=['--', '--trace'])
def testHelpFlag(self):
with self.assertRaisesFireExit(0):
fire.Fire(tc.BoolConverter, command=['as-bool', 'True', '--', '--help'])
with self.assertRaisesFireExit(0):
fire.Fire(tc.BoolConverter, command=['as-bool', 'True', '--', '-h'])
with self.assertRaisesFireExit(0):
fire.Fire(tc.BoolConverter, command=['--', '--help'])
def testHelpFlagAndTraceFlag(self):
with self.assertRaisesFireExit(0, 'Fire trace:\n.*SYNOPSIS'):
fire.Fire(tc.BoolConverter,
command=['as-bool', 'True', '--', '--help', '--trace'])
with self.assertRaisesFireExit(0, 'Fire trace:\n.*SYNOPSIS'):
fire.Fire(tc.BoolConverter, command=['as-bool', 'True', '--', '-h', '-t'])
with self.assertRaisesFireExit(0, 'Fire trace:\n.*SYNOPSIS'):
fire.Fire(tc.BoolConverter, command=['--', '-h', '--trace'])
def testTabCompletionNoName(self):
completion_script = fire.Fire(tc.NoDefaults, command=['--', '--completion'])
self.assertIn('double', completion_script)
self.assertIn('triple', completion_script)
def testTabCompletion(self):
completion_script = fire.Fire(
tc.NoDefaults, command=['--', '--completion'], name='c')
self.assertIn('double', completion_script)
self.assertIn('triple', completion_script)
def testTabCompletionWithDict(self):
actions = {'multiply': lambda a, b: a * b}
completion_script = fire.Fire(
actions, command=['--', '--completion'], name='actCLI')
self.assertIn('actCLI', completion_script)
self.assertIn('multiply', completion_script)
def testBasicSeparator(self):
# '-' is the default separator.
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '+', '_']), ('+', '_'))
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '_', '+', '-']), ('_', '+'))
# If we change the separator we can use '-' as an argument.
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['identity', '-', '_', '--', '--separator', '&']),
('-', '_'))
# The separator triggers a function call, but there aren't enough arguments.
with self.assertRaisesFireExit(2):
fire.Fire(tc.MixedDefaults, command=['identity', '-', '_', '+'])
def testNonComparable(self):
"""Fire should work with classes that disallow comparisons."""
# Make sure this test passes both with a string command or a list command.
self.assertIsInstance(
fire.Fire(tc.NonComparable, command=''), tc.NonComparable)
self.assertIsInstance(
fire.Fire(tc.NonComparable, command=[]), tc.NonComparable)
# The first separator instantiates the NonComparable object.
# The second separator causes Fire to check if the separator was necessary.
self.assertIsInstance(
fire.Fire(tc.NonComparable, command=['-', '-']), tc.NonComparable)
def testExtraSeparators(self):
self.assertEqual(
fire.Fire(
tc.ReturnsObj,
command=['get-obj', 'arg1', 'arg2', '-', '-', 'as-bool', 'True']),
True)
self.assertEqual(
fire.Fire(
tc.ReturnsObj,
command=['get-obj', 'arg1', 'arg2', '-', '-', '-', 'as-bool',
'True']),
True)
def testSeparatorForChaining(self):
# Without a separator all args are consumed by get_obj.
self.assertIsInstance(
fire.Fire(tc.ReturnsObj,
command=['get-obj', 'arg1', 'arg2', 'as-bool', 'True']),
tc.BoolConverter)
# With a separator only the preceding args are consumed by get_obj.
self.assertEqual(
fire.Fire(
tc.ReturnsObj,
command=['get-obj', 'arg1', 'arg2', '-', 'as-bool', 'True']), True)
self.assertEqual(
fire.Fire(tc.ReturnsObj,
command=['get-obj', 'arg1', 'arg2', '&', 'as-bool', 'True',
'--', '--separator', '&']),
True)
self.assertEqual(
fire.Fire(tc.ReturnsObj,
command=['get-obj', 'arg1', '$$', 'as-bool', 'True', '--',
'--separator', '$$']),
True)
def testNegativeNumbers(self):
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['sum', '--alpha', '-3', '--beta', '-4']), -11)
def testFloatForExpectedInt(self):
self.assertEqual(
fire.Fire(tc.MixedDefaults,
command=['sum', '--alpha', '2.2', '--beta', '3.0']), 8.2)
self.assertEqual(
fire.Fire(
tc.NumberDefaults,
command=['integer_reciprocal', '--divisor', '5.0']), 0.2)
self.assertEqual(
fire.Fire(tc.NumberDefaults, command=['integer_reciprocal', '4.0']),
0.25)
def testClassInstantiation(self):
self.assertIsInstance(fire.Fire(tc.InstanceVars,
command=['--arg1=a1', '--arg2=a2']),
tc.InstanceVars)
with self.assertRaisesFireExit(2):
# Cannot instantiate a class with positional args.
fire.Fire(tc.InstanceVars, command=['a1', 'a2'])
def testTraceErrors(self):
# Class needs additional value but runs out of args.
with self.assertRaisesFireExit(2):
fire.Fire(tc.InstanceVars, command=['a1'])
with self.assertRaisesFireExit(2):
fire.Fire(tc.InstanceVars, command=['--arg1=a1'])
# Routine needs additional value but runs out of args.
with self.assertRaisesFireExit(2):
fire.Fire(tc.InstanceVars, command=['a1', 'a2', '-', 'run', 'b1'])
with self.assertRaisesFireExit(2):
fire.Fire(tc.InstanceVars,
command=['--arg1=a1', '--arg2=a2', '-', 'run b1'])
# Extra args cannot be consumed.
with self.assertRaisesFireExit(2):
fire.Fire(tc.InstanceVars,
command=['a1', 'a2', '-', 'run', 'b1', 'b2', 'b3'])
with self.assertRaisesFireExit(2):
fire.Fire(
tc.InstanceVars,
command=['--arg1=a1', '--arg2=a2', '-', 'run', 'b1', 'b2', 'b3'])
# Cannot find member to access.
with self.assertRaisesFireExit(2):
fire.Fire(tc.InstanceVars, command=['a1', 'a2', '-', 'jog'])
with self.assertRaisesFireExit(2):
fire.Fire(tc.InstanceVars, command=['--arg1=a1', '--arg2=a2', '-', 'jog'])
def testClassWithDefaultMethod(self):
self.assertEqual(
fire.Fire(tc.DefaultMethod, command=['double', '10']), 20
)
def testClassWithInvalidProperty(self):
self.assertEqual(
fire.Fire(tc.InvalidProperty, command=['double', '10']), 20
)
def testHelpKwargsDecorator(self):
# Issue #190, follow the wrapped method instead of crashing.
with self.assertRaisesFireExit(0):
fire.Fire(tc.decorated_method, command=['-h'])
with self.assertRaisesFireExit(0):
fire.Fire(tc.decorated_method, command=['--help'])
def testFireAsyncio(self):
self.assertEqual(fire.Fire(tc.py3.WithAsyncio,
command=['double', '--count', '10']), 20)
if __name__ == '__main__':
testutils.main()