def _execute_command(args): """Asserts that ``args.function`` is present and callable. Tries different approaches to calling the function (with an `argparse.Namespace` object or with ordinary signature). Yields the results line by line. If CommandError is raised, its message is appended to the results (i.e. yielded by the generator as a string). All other exceptions propagate unless marked as wrappable by :func:`wrap_errors`. """ assert hasattr(args, 'function') and hasattr(args.function, '__call__') # the function is nested to catch certain exceptions (see below) def _call(): # Actually call the function if getattr(args.function, ATTR_NO_NAMESPACE, False): # filter the namespace variables so that only those expected by the # actual function will pass f = args.function if hasattr(f, 'func_code'): # Python 2 expected_args = f.func_code.co_varnames[:f.func_code.co_argcount] else: # Python 3 expected_args = f.__code__.co_varnames[:f.__code__.co_argcount] ok_args = [x for x in args._get_args() if x in expected_args] ok_kwargs = dict((k,v) for k,v in args._get_kwargs() if k in expected_args) result = args.function(*ok_args, **ok_kwargs) else: result = args.function(args) # Yield the results if isinstance(result, (GeneratorType, list, tuple)): # yield each line ASAP, convert CommandError message to a line for line in result: yield line else: # yield non-empty non-iterable result as a single line if result is not None: yield result wrappable_exceptions = [CommandError] wrappable_exceptions += getattr(args.function, ATTR_WRAPPED_EXCEPTIONS, []) try: result = _call() for line in result: yield line except tuple(wrappable_exceptions) as e: yield text_type(e)
def _encode(line, output_file, encoding=None): """Converts given string to given encoding. If no encoding is specified, it is determined from terminal settings or, if none, from system settings. """ # Convert string to Unicode if not isinstance(line, text_type): try: line = text_type(line) except UnicodeDecodeError: line = b(line).decode('utf-8') # Choose output encoding if not encoding: # choose between terminal's and system's preferred encodings if output_file.isatty(): encoding = getattr(output_file, 'encoding', None) encoding = encoding or locale.getpreferredencoding() # Convert string from Unicode to the output encoding return line.encode(encoding)