def _PrintError(component_trace): """Prints the Fire trace and the error to stdout.""" print('Fire trace:\n{trace}\n'.format(trace=component_trace), file=sys.stderr) result = component_trace.GetResult() print( helputils.HelpString(result, component_trace, component_trace.verbose), file=sys.stderr)
def _PrintResult(component_trace, verbose=False): """Prints the result of the Fire call to stdout in a human readable way.""" # TODO: Design human readable deserializable serialization method # and move serialization to it's own module. result = component_trace.GetResult() if isinstance(result, list): for i in result: print(_OneLineResult(i)) elif isinstance(result, set): for i in result: print(_OneLineResult(i)) elif inspect.isgenerator(result): for i in result: print(_OneLineResult(i)) elif inspect.isgeneratorfunction(result): raise NotImplementedError elif isinstance(result, dict): print(_DictAsString(result, verbose)) elif isinstance(result, tuple): print(_OneLineResult(result)) elif isinstance( result, (bool, six.string_types, six.integer_types, float, complex)): print(result) elif result is not None: print(helputils.HelpString(result, component_trace, verbose))
def testHelpStringInt(self): helpstring = helputils.HelpString(7) self.assertIn('Type: int', helpstring) self.assertIn('String form: 7', helpstring) self.assertIn('Usage: bit-length\n' ' conjugate\n' ' denominator\n', helpstring)
def testHelpStringIntType(self): helpstring = helputils.HelpString(int) self.assertIn('Type: type', helpstring) if six.PY2: self.assertIn("String form: <type 'int'>", helpstring) else: self.assertIn("String form: <class 'int'>", helpstring) self.assertNotIn('Usage', helpstring)
def testHelpStringClass(self): helpstring = helputils.HelpString(tc.NoDefaults) self.assertIn('Type: type', helpstring) self.assertIn("String form: <class 'fire.test_components.NoDefaults'>", helpstring) self.assertIn('test_components.py', helpstring) self.assertIn('Line: ', helpstring) self.assertNotIn('Usage', helpstring)
def testHelpClassNoInit(self): helpstring = helputils.HelpString(tc.OldStyleEmpty) if six.PY2: self.assertIn('Type: classobj\n', helpstring) else: self.assertIn('Type: type\n', helpstring) self.assertIn('String form: ', helpstring) self.assertIn('fire.test_components.OldStyleEmpty', helpstring) self.assertIn(os.path.join('fire', 'test_components.py'), helpstring) self.assertIn('Line: ', helpstring)
def testHelpStringObject(self): obj = tc.NoDefaults() helpstring = helputils.HelpString(obj) self.assertIn('Type: NoDefaults', helpstring) self.assertIn('String form: <fire.test_components.NoDefaults object at ', helpstring) # TODO(dbieber): We comment this out since it only works with IPython: # self.assertIn('test_components.py', helpstring) self.assertIn('Usage: double\n' ' triple', helpstring)
def testHelpStringObject(self): obj = tc.NoDefaults() helpstring = helputils.HelpString(obj) self.assertIn('Type: NoDefaults', helpstring) self.assertIn( 'String form: <fire.test_components.NoDefaults object at ', helpstring) self.assertIn('test_components.py', helpstring) self.assertIn('Usage: double\n' ' triple', helpstring)
def testHelpStringFunctionWithDefaults(self): obj = tc.WithDefaults() helpstring = helputils.HelpString(obj.triple) if six.PY2: self.assertIn('Type: instancemethod\n', helpstring) else: self.assertIn('Type: method\n', helpstring) self.assertIn( 'String form: <bound method WithDefaults.triple of ' '<fire.test_components.WithDefaults object', helpstring) self.assertIn('test_components.py', helpstring) self.assertIn('Line: ', helpstring) self.assertIn('Usage: [COUNT]\n' ' [--count COUNT]', helpstring)
def testHelpStringFunction(self): obj = tc.NoDefaults() helpstring = helputils.HelpString(obj.double) if six.PY2: self.assertIn('Type: instancemethod\n', helpstring) else: self.assertIn('Type: method\n', helpstring) self.assertIn( 'String form: <bound method NoDefaults.double of ' '<fire.test_components.NoDefaults object', helpstring) self.assertIn('test_components.py', helpstring) self.assertIn('Line: ', helpstring) self.assertIn('Usage: COUNT\n' ' --count COUNT', helpstring)
def _DisplayError(component_trace): """Prints the Fire trace and the error to stdout.""" output = [] for help_flag in ('-h', '--help'): if help_flag in component_trace.elements[-1].args: command = '{cmd} -- --help'.format(cmd=component_trace.GetCommand()) message = 'INFO: Showing help with the command {cmd}.\n'.format( cmd=pipes.quote(command)) output.append(message) output.append('Fire trace:\n{trace}\n'.format(trace=component_trace)) result = component_trace.GetResult() help_string = helputils.HelpString(result, component_trace, component_trace.verbose) output.append(help_string) Display(output)
def _PrintResult(component_trace, verbose=False): """Prints the result of the Fire call to stdout in a human readable way.""" # TODO(dbieber): Design human readable deserializable serialization method # and move serialization to its own module. result = component_trace.GetResult() if isinstance(result, (list, set, types.GeneratorType)): for i in result: print(_OneLineResult(i)) elif inspect.isgeneratorfunction(result): raise NotImplementedError elif isinstance(result, dict): print(_DictAsString(result, verbose)) elif isinstance(result, tuple): print(_OneLineResult(result)) elif isinstance(result, value_types.VALUE_TYPES): print(result) elif result is not None: print(helputils.HelpString(result, component_trace, verbose))
def testHelpStringBuiltin(self): helpstring = helputils.HelpString('test'.upper) self.assertIn('Type: builtin_function_or_method', helpstring) self.assertIn('String form: <built-in method upper of', helpstring) self.assertIn('Usage: [VARS ...] [--KWARGS ...]', helpstring)
def Fire(component=None, command=None, name=None): """This function, Fire, is the main entrypoint for Python Fire. Executes a command either from the `command` argument or from sys.argv by recursively traversing the target object `component`'s members consuming arguments, evaluating functions, and instantiating classes as it goes. When building a CLI with Fire, your main method should call this function. Args: component: The initial target component. command: Optional. If supplied, this is the command executed. If not supplied, then the command is taken from sys.argv instead. This can be a string or a list of strings; a list of strings is preferred. name: Optional. The name of the command as entered at the command line. Used in interactive mode and for generating the completion script. Returns: The result of executing the Fire command. Execution begins with the initial target component. The component is updated by using the command arguments to either access a member of the current component, call the current component (if it's a function), or instantiate the current component (if it's a class). When all arguments are consumed and there's no function left to call or class left to instantiate, the resulting current component is the final result. Raises: ValueError: If the command argument is supplied, but not a string or a sequence of arguments. FireExit: When Fire encounters a FireError, Fire will raise a FireExit with code 2. When used with the help or trace flags, Fire will raise a FireExit with code 0 if successful. """ name = name or os.path.basename(sys.argv[0]) # Get args as a list. if isinstance(command, six.string_types): args = shlex.split(command) elif isinstance(command, (list, tuple)): args = command elif command is None: # Use the command line args by default if no command is specified. args = sys.argv[1:] else: raise ValueError( 'The command argument must be a string or a sequence of ' 'arguments.') # Determine the calling context. caller = inspect.stack()[1] caller_frame = caller[0] caller_globals = caller_frame.f_globals caller_locals = caller_frame.f_locals context = {} context.update(caller_globals) context.update(caller_locals) component_trace = _Fire(component, args, context, name) if component_trace.HasError(): _DisplayError(component_trace) raise FireExit(2, component_trace) if component_trace.show_trace and component_trace.show_help: output = ['Fire trace:\n{trace}\n'.format(trace=component_trace)] result = component_trace.GetResult() help_string = helputils.HelpString(result, component_trace, component_trace.verbose) output.append(help_string) Display(output) raise FireExit(0, component_trace) if component_trace.show_trace: output = ['Fire trace:\n{trace}'.format(trace=component_trace)] Display(output) raise FireExit(0, component_trace) if component_trace.show_help: result = component_trace.GetResult() help_string = helputils.HelpString(result, component_trace, component_trace.verbose) output = [help_string] Display(output) raise FireExit(0, component_trace) # The command succeeded normally; print the result. _PrintResult(component_trace, verbose=component_trace.verbose) result = component_trace.GetResult() return result
def testHelpStringEmptyList(self): helpstring = helputils.HelpString([]) self.assertIn('Type: list', helpstring) self.assertIn('String form: []', helpstring) self.assertIn('Length: 0', helpstring)
def Fire(component=None, command=None, name=None): """This function, Fire, is the main entrypoint for Python Fire. Executes a command either from the `command` argument or from sys.argv by recursively traversing the target object `component`'s members consuming arguments, evaluating functions, and instantiating classes as it goes. When building a CLI with Fire, your main method should call this function. Args: component: The initial target component. command: Optional. If supplied, this is the command executed. If not supplied, then the command is taken from sys.argv instead. name: Optional. The name of the command as entered at the command line. Used in interactive mode and for generating the completion script. Returns: The result of executing the Fire command. Execution begins with the initial target component. The component is updated by using the command arguments to either access a member of the current component, call the current component (if it's a function), or instantiate the current component (if it's a class). When all arguments are consumed and there's no function left to call or class left to instantiate, the resulting current component is the final result. Raises: FireExit: When Fire encounters a FireError, Fire will raise a FireExit with code 2. When used with the help or trace flags, Fire will raise a FireExit with code 0 if successful. """ # Get args as a list. if command is None: # Use the command line args by default if no command is specified. name = name or sys.argv[0] args = sys.argv[1:] else: # Otherwise use the specified command. args = shlex.split(command) # Determine the calling context. caller = inspect.stack()[1] caller_frame = caller[0] caller_globals = caller_frame.f_globals caller_locals = caller_frame.f_locals context = {} context.update(caller_globals) context.update(caller_locals) component_trace = _Fire(component, args, context, name) if component_trace.HasError(): for help_flag in ['-h', '--help']: if help_flag in component_trace.elements[-1].args: command = '{cmd} -- --help'.format( cmd=component_trace.GetCommand()) print(('WARNING: The proper way to show help is {cmd}.\n' 'Showing help anyway.\n').format( cmd=pipes.quote(command))) print('Fire trace:\n{trace}\n'.format(trace=component_trace)) result = component_trace.GetResult() print( helputils.HelpString(result, component_trace, component_trace.verbose)) raise FireExit(2, component_trace) elif component_trace.show_trace and component_trace.show_help: print('Fire trace:\n{trace}\n'.format(trace=component_trace)) result = component_trace.GetResult() print( helputils.HelpString(result, component_trace, component_trace.verbose)) raise FireExit(0, component_trace) elif component_trace.show_trace: print('Fire trace:\n{trace}'.format(trace=component_trace)) raise FireExit(0, component_trace) elif component_trace.show_help: result = component_trace.GetResult() print( helputils.HelpString(result, component_trace, component_trace.verbose)) raise FireExit(0, component_trace) else: _PrintResult(component_trace, verbose=component_trace.verbose) result = component_trace.GetResult() return result
def testHelpStringShortList(self): helpstring = helputils.HelpString([10]) self.assertIn('Type: list', helpstring) self.assertIn('String form: [10]', helpstring) self.assertIn('Length: 1', helpstring) self.assertIn('Usage: [0]', helpstring) # [] denotes optional.