diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6e51b135..b334bb09 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ default_language_version: python: python3 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: mixed-line-ending @@ -18,16 +18,16 @@ repos: files: .*\.(yaml|yml)$ exclude: '^zuul.d/.*$' - repo: https://github.com/PyCQA/bandit - rev: 1.7.5 + rev: 1.7.7 hooks: - id: bandit args: ['-c', 'bandit.yaml'] -# - repo: https://github.com/psf/black -# rev: 23.3.0 -# hooks: -# - id: black -# args: ['-S', '-l', '79'] + - repo: https://github.com/psf/black + rev: 24.2.0 + hooks: + - id: black + args: ['-S', '-l', '79'] - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 diff --git a/cliff/_argparse.py b/cliff/_argparse.py index cb5e4c5d..b8881b45 100644 --- a/cliff/_argparse.py +++ b/cliff/_argparse.py @@ -19,7 +19,6 @@ from autopage import argparse class _ArgumentContainerMixIn(object): - # NOTE(dhellmann): We have to override the methods for creating # groups to return our objects that know how to deal with the # special conflict handler. @@ -44,13 +43,15 @@ class _ArgumentContainerMixIn(object): class ArgumentParser(_ArgumentContainerMixIn, argparse.ArgumentParser): - pass -def _handle_conflict_ignore(container, option_string_actions, - new_action, conflicting_actions): - +def _handle_conflict_ignore( + container, + option_string_actions, + new_action, + conflicting_actions, +): # Remember the option strings the new action starts with so we can # restore them as part of error reporting if we need to. original_option_strings = new_action.option_strings @@ -58,13 +59,14 @@ def _handle_conflict_ignore(container, option_string_actions, # Remove all of the conflicting option strings from the new action # and report an error if none are left at the end. for option_string, action in conflicting_actions: - # remove the conflicting option from the new action new_action.option_strings.remove(option_string) warnings.warn( - ('Ignoring option string {} for new action ' - 'because it conflicts with an existing option.').format( - option_string)) + ( + 'Ignoring option string {} for new action ' + 'because it conflicts with an existing option.' + ).format(option_string) + ) # if the option now has no option string, remove it from the # container holding it @@ -72,8 +74,10 @@ def _handle_conflict_ignore(container, option_string_actions, new_action.option_strings = original_option_strings raise argparse.ArgumentError( new_action, - ('Cannot resolve conflicting option string, ' - 'all names conflict.'), + ( + 'Cannot resolve conflicting option string, ' + 'all names conflict.' + ), ) @@ -81,8 +85,9 @@ class _ArgumentGroup(_ArgumentContainerMixIn, orig_argparse._ArgumentGroup): pass -class _MutuallyExclusiveGroup(_ArgumentContainerMixIn, - orig_argparse._MutuallyExclusiveGroup): +class _MutuallyExclusiveGroup( + _ArgumentContainerMixIn, orig_argparse._MutuallyExclusiveGroup +): pass diff --git a/cliff/app.py b/cliff/app.py index 10a4941c..2d3be88b 100644 --- a/cliff/app.py +++ b/cliff/app.py @@ -63,17 +63,24 @@ class App(object): LOG = logging.getLogger(NAME) CONSOLE_MESSAGE_FORMAT = '%(message)s' - LOG_FILE_MESSAGE_FORMAT = \ + LOG_FILE_MESSAGE_FORMAT = ( '[%(asctime)s] %(levelname)-8s %(name)s %(message)s' + ) DEFAULT_VERBOSE_LEVEL = 1 DEFAULT_OUTPUT_ENCODING = 'utf-8' - def __init__(self, description, version, command_manager, - stdin=None, stdout=None, stderr=None, - interactive_app_factory=None, - deferred_help=False): - """Initialize the application. - """ + def __init__( + self, + description, + version, + command_manager, + stdin=None, + stdout=None, + stderr=None, + interactive_app_factory=None, + deferred_help=False, + ): + """Initialize the application.""" self.command_manager = command_manager self.command_manager.add_command('help', help.HelpCommand) self.command_manager.add_command('complete', complete.CompleteCommand) @@ -120,8 +127,7 @@ class App(object): self.stdout = stdout or sys.stdout self.stderr = stderr or sys.stderr - def build_option_parser(self, description, version, - argparse_kwargs=None): + def build_option_parser(self, description, version, argparse_kwargs=None): """Return an argparse option parser for this application. Subclasses may override this method to extend @@ -137,9 +143,7 @@ class App(object): """ argparse_kwargs = argparse_kwargs or {} parser = _argparse.ArgumentParser( - description=description, - add_help=False, - **argparse_kwargs + description=description, add_help=False, **argparse_kwargs ) parser.add_argument( '--version', @@ -148,14 +152,16 @@ class App(object): ) verbose_group = parser.add_mutually_exclusive_group() verbose_group.add_argument( - '-v', '--verbose', + '-v', + '--verbose', action='count', dest='verbose_level', default=self.DEFAULT_VERBOSE_LEVEL, help='Increase verbosity of output. Can be repeated.', ) verbose_group.add_argument( - '-q', '--quiet', + '-q', + '--quiet', action='store_const', dest='verbose_level', const=0, @@ -169,14 +175,16 @@ class App(object): ) if self.deferred_help: parser.add_argument( - '-h', '--help', + '-h', + '--help', dest='deferred_help', action='store_true', help="Show help message and exit.", ) else: parser.add_argument( - '-h', '--help', + '-h', + '--help', action=help.HelpAction, nargs=0, default=self, # tricky @@ -191,8 +199,7 @@ class App(object): return parser def configure_logging(self): - """Create logging handlers for any log output. - """ + """Create logging handlers for any log output.""" root_logger = logging.getLogger('') root_logger.setLevel(logging.DEBUG) @@ -207,10 +214,11 @@ class App(object): # Always send higher-level messages to the console via stderr console = logging.StreamHandler(self.stderr) - console_level = {0: logging.WARNING, - 1: logging.INFO, - 2: logging.DEBUG, - }.get(self.options.verbose_level, logging.DEBUG) + console_level = { + 0: logging.WARNING, + 1: logging.INFO, + 2: logging.DEBUG, + }.get(self.options.verbose_level, logging.DEBUG) console.setLevel(console_level) formatter = logging.Formatter(self.CONSOLE_MESSAGE_FORMAT) console.setFormatter(formatter) @@ -320,16 +328,16 @@ class App(object): if self.interactive_app_factory is None: self.interactive_app_factory = InteractiveApp - self.interpreter = self.interactive_app_factory(self, - self.command_manager, - self.stdin, - self.stdout, - ) + self.interpreter = self.interactive_app_factory( + self, + self.command_manager, + self.stdin, + self.stdout, + ) return self.interpreter.cmdloop() def get_fuzzy_matches(self, cmd): - """return fuzzy matches of unknown command - """ + """return fuzzy matches of unknown command""" sep = '_' if self.command_manager.convert_underscores: @@ -343,8 +351,12 @@ class App(object): dist.append((0, candidate)) continue # Levenshtein distance - dist.append((utils.damerau_levenshtein(cmd, prefix, utils.COST)+1, - candidate)) + dist.append( + ( + utils.damerau_levenshtein(cmd, prefix, utils.COST) + 1, + candidate, + ) + ) matches = [] match_distance = 0 @@ -371,10 +383,17 @@ class App(object): article = 'a' if self.NAME[0] in 'aeiou': article = 'an' - self.stdout.write('%s: \'%s\' is not %s %s command. ' - 'See \'%s --help\'.\n' - % (self.NAME, ' '.join(argv), article, - self.NAME, self.NAME)) + self.stdout.write( + '%s: \'%s\' is not %s %s command. ' + 'See \'%s --help\'.\n' + % ( + self.NAME, + ' '.join(argv), + article, + self.NAME, + self.NAME, + ) + ) self.stdout.write('Did you mean one of these?\n') for match in fuzzy_matches: self.stdout.write(' %s\n' % match) @@ -393,10 +412,11 @@ class App(object): err = None try: self.prepare_to_run_command(cmd) - full_name = (cmd_name - if self.interactive_mode - else ' '.join([self.NAME, cmd_name]) - ) + full_name = ( + cmd_name + if self.interactive_mode + else ' '.join([self.NAME, cmd_name]) + ) cmd_parser = cmd.get_parser(full_name) try: parsed_args = cmd_parser.parse_args(sub_argv) @@ -404,6 +424,7 @@ class App(object): if self.interactive_mode: # Defer importing cmd2 as it is a slow import import cmd2 + raise cmd2.exceptions.Cmd2ArgparseError from ex else: raise ex diff --git a/cliff/columns.py b/cliff/columns.py index 34621764..9c17860a 100644 --- a/cliff/columns.py +++ b/cliff/columns.py @@ -17,7 +17,6 @@ import abc class FormattableColumn(object, metaclass=abc.ABCMeta): - def __init__(self, value): self._value = value @@ -27,9 +26,7 @@ class FormattableColumn(object, metaclass=abc.ABCMeta): ) def __lt__(self, other): - return ( - self.__class__ == other.__class__ and self._value < other._value - ) + return self.__class__ == other.__class__ and self._value < other._value def __str__(self): return self.human_readable() diff --git a/cliff/command.py b/cliff/command.py index 1ba5190b..3253a429 100644 --- a/cliff/command.py +++ b/cliff/command.py @@ -39,9 +39,7 @@ def _get_distributions_by_modules(): if _dists_by_mods is None: # There can be multiple distribution in the case of namespace packages # so we'll just grab the first one - _dists_by_mods = { - k: v[0] for k, v in packages_distributions().items() - } + _dists_by_mods = {k: v[0] for k, v in packages_distributions().items()} return _dists_by_mods @@ -85,7 +83,7 @@ class Command(object, metaclass=abc.ABCMeta): if self.app and self.cmd_name: namespace = '{}.{}'.format( self.app.command_manager.namespace, - self.cmd_name.replace(' ', '_') + self.cmd_name.replace(' ', '_'), ) self._hooks = extension.ExtensionManager( namespace=namespace, @@ -132,21 +130,19 @@ class Command(object, metaclass=abc.ABCMeta): ) parts.extend(hook_epilogs) app_dist_name = getattr( - self, 'app_dist_name', _get_distribution_for_module( - inspect.getmodule(self.app) - ) + self, + 'app_dist_name', + _get_distribution_for_module(inspect.getmodule(self.app)), ) dist_name = _get_distribution_for_module(inspect.getmodule(self)) if dist_name and dist_name != app_dist_name: parts.append( - 'This command is provided by the %s plugin.' % - (dist_name,) + 'This command is provided by the %s plugin.' % (dist_name,) ) return '\n\n'.join(parts) def get_parser(self, prog_name): - """Return an :class:`argparse.ArgumentParser`. - """ + """Return an :class:`argparse.ArgumentParser`.""" parser = _argparse.ArgumentParser( description=self.get_description(), epilog=self.get_epilog(), diff --git a/cliff/commandmanager.py b/cliff/commandmanager.py index 4f460148..feb2123a 100644 --- a/cliff/commandmanager.py +++ b/cliff/commandmanager.py @@ -35,8 +35,7 @@ def _get_commands_by_partial_name(args, commands): class EntryPointWrapper(object): - """Wrap up a command class already imported to make it look like a plugin. - """ + """Wrap up a command class already imported to make it look like a plugin.""" def __init__(self, name, command_class): self.name = name @@ -54,6 +53,7 @@ class CommandManager(object): :param convert_underscores: Whether cliff should convert underscores to spaces in entry_point commands. """ + def __init__(self, namespace, convert_underscores=True): self.commands = {} self._legacy = {} @@ -72,9 +72,11 @@ class CommandManager(object): self.group_list.append(namespace) for ep in stevedore.ExtensionManager(namespace): LOG.debug('found command %r', ep.name) - cmd_name = (ep.name.replace('_', ' ') - if self.convert_underscores - else ep.name) + cmd_name = ( + ep.name.replace('_', ' ') + if self.convert_underscores + else ep.name + ) self.commands[cmd_name] = ep.entry_point return @@ -114,7 +116,8 @@ class CommandManager(object): found = name else: candidates = _get_commands_by_partial_name( - argv[:i], self.commands) + argv[:i], self.commands + ) if len(candidates) == 1: found = candidates[0] if found: @@ -131,8 +134,7 @@ class CommandManager(object): cmd_factory = cmd_ep.load() return (cmd_factory, return_name, search_args) else: - raise ValueError('Unknown command %r' % - (argv,)) + raise ValueError('Unknown command %r' % (argv,)) def _get_last_possible_command_index(self, argv): """Returns the index after the last argument diff --git a/cliff/complete.py b/cliff/complete.py index 06f38be9..600fbe52 100644 --- a/cliff/complete.py +++ b/cliff/complete.py @@ -21,15 +21,15 @@ from cliff import command class CompleteDictionary: - """dictionary for bash completion - """ + """dictionary for bash completion""" def __init__(self): self._dictionary = {} def add_command(self, command, actions): - optstr = ' '.join(opt for action in actions - for opt in action.option_strings) + optstr = ' '.join( + opt for action in actions for opt in action.option_strings + ) dicto = self._dictionary last_cmd = command[-1] for subcmd in command[:-1]: @@ -69,8 +69,8 @@ class CompleteDictionary: class CompleteShellBase(object): - """base class for bash completion generation - """ + """base class for bash completion generation""" + def __init__(self, name, output): self.name = str(name) self.output = output @@ -89,8 +89,8 @@ class CompleteShellBase(object): class CompleteNoCode(CompleteShellBase): - """completion with no code - """ + """completion with no code""" + def __init__(self, name, output): super(CompleteNoCode, self).__init__(name, output) @@ -102,23 +102,28 @@ class CompleteNoCode(CompleteShellBase): class CompleteBash(CompleteShellBase): - """completion for bash - """ + """completion for bash""" + def __init__(self, name, output): super(CompleteBash, self).__init__(name, output) def get_header(self): - return ('_' + self.escaped_name + """() + return ( + '_' + + self.escaped_name + + """() { local cur prev words COMPREPLY=() _get_comp_words_by_ref -n : cur prev words # Command data: -""") +""" + ) def get_trailer(self): - return (""" + return ( + """ dash=- underscore=_ cmd="" @@ -157,12 +162,16 @@ class CompleteBash(CompleteShellBase): fi return 0 } -complete -F _""" + self.escaped_name + ' ' + self.name + '\n') +complete -F _""" + + self.escaped_name + + ' ' + + self.name + + '\n' + ) class CompleteCommand(command.Command): - """print bash completion command - """ + """print bash completion command""" log = logging.getLogger(__name__ + '.CompleteCommand') @@ -178,14 +187,14 @@ class CompleteCommand(command.Command): "--name", default=None, metavar='<command_name>', - help="Command name to support with command completion" + help="Command name to support with command completion", ) parser.add_argument( "--shell", default='bash', metavar='<shell>', choices=sorted(self._formatters.names()), - help="Shell being used. Use none for data only (default: bash)" + help="Shell being used. Use none for data only (default: bash)", ) return parser @@ -194,9 +203,9 @@ class CompleteCommand(command.Command): cmd_factory, cmd_name, search_args = the_cmd cmd = cmd_factory(self.app, search_args) if self.app.interactive_mode: - full_name = (cmd_name) + full_name = cmd_name else: - full_name = (' '.join([self.app.NAME, cmd_name])) + full_name = ' '.join([self.app.NAME, cmd_name]) cmd_parser = cmd.get_parser(full_name) return cmd_parser._get_optional_actions() diff --git a/cliff/display.py b/cliff/display.py index 44eadd52..72af099a 100644 --- a/cliff/display.py +++ b/cliff/display.py @@ -21,12 +21,12 @@ from . import command class DisplayCommandBase(command.Command, metaclass=abc.ABCMeta): - """Command base class for displaying data about a single object. - """ + """Command base class for displaying data about a single object.""" def __init__(self, app, app_args, cmd_name=None): - super(DisplayCommandBase, self).__init__(app, app_args, - cmd_name=cmd_name) + super(DisplayCommandBase, self).__init__( + app, app_args, cmd_name=cmd_name + ) self._formatter_plugins = self._load_formatter_plugins() @property @@ -58,7 +58,8 @@ class DisplayCommandBase(command.Command, metaclass=abc.ABCMeta): if formatter_default not in formatter_choices: formatter_default = formatter_choices[0] formatter_group.add_argument( - '-f', '--format', + '-f', + '--format', dest='formatter', action='store', choices=formatter_choices, @@ -66,13 +67,14 @@ class DisplayCommandBase(command.Command, metaclass=abc.ABCMeta): help='the output format, defaults to %s' % formatter_default, ) formatter_group.add_argument( - '-c', '--column', + '-c', + '--column', action='append', default=[], dest='columns', metavar='COLUMN', help='specify the column(s) to include, can be ' - 'repeated to show multiple columns', + 'repeated to show multiple columns', ) for formatter in self._formatter_plugins: formatter.obj.add_argument_group(parser) @@ -99,24 +101,27 @@ class DisplayCommandBase(command.Command, metaclass=abc.ABCMeta): columns_to_include = column_names selector = None else: - columns_to_include = [c for c in column_names - if c in parsed_args.columns] + columns_to_include = [ + c for c in column_names if c in parsed_args.columns + ] if not columns_to_include: - raise ValueError('No recognized column names in %s. ' - 'Recognized columns are %s.' % - (str(parsed_args.columns), str(column_names))) + raise ValueError( + 'No recognized column names in %s. ' + 'Recognized columns are %s.' + % (str(parsed_args.columns), str(column_names)) + ) # Set up argument to compress() - selector = [(c in columns_to_include) - for c in column_names] + selector = [(c in columns_to_include) for c in column_names] return columns_to_include, selector def run(self, parsed_args): parsed_args = self._run_before_hooks(parsed_args) self.formatter = self._formatter_plugins[parsed_args.formatter].obj column_names, data = self.take_action(parsed_args) - column_names, data = self._run_after_hooks(parsed_args, - (column_names, data)) + column_names, data = self._run_after_hooks( + parsed_args, (column_names, data) + ) self.produce_output(parsed_args, column_names, data) return 0 diff --git a/cliff/formatters/base.py b/cliff/formatters/base.py index ca65928b..7fc7b5d1 100644 --- a/cliff/formatters/base.py +++ b/cliff/formatters/base.py @@ -17,7 +17,6 @@ import abc class Formatter(object, metaclass=abc.ABCMeta): - @abc.abstractmethod def add_argument_group(self, parser): """Add any options to the argument parser. @@ -27,8 +26,7 @@ class Formatter(object, metaclass=abc.ABCMeta): class ListFormatter(Formatter, metaclass=abc.ABCMeta): - """Base class for formatters that know how to deal with multiple objects. - """ + """Base class for formatters that know how to deal with multiple objects.""" @abc.abstractmethod def emit_list(self, column_names, data, stdout, parsed_args): @@ -50,8 +48,7 @@ class ListFormatter(Formatter, metaclass=abc.ABCMeta): class SingleFormatter(Formatter, metaclass=abc.ABCMeta): - """Base class for formatters that work with single objects. - """ + """Base class for formatters that work with single objects.""" @abc.abstractmethod def emit_one(self, column_names, data, stdout, parsed_args): diff --git a/cliff/formatters/commaseparated.py b/cliff/formatters/commaseparated.py index 7536817f..b2107e5e 100644 --- a/cliff/formatters/commaseparated.py +++ b/cliff/formatters/commaseparated.py @@ -21,7 +21,6 @@ from cliff import columns class CSVLister(ListFormatter): - QUOTE_MODES = { 'all': csv.QUOTE_ALL, 'minimal': csv.QUOTE_MINIMAL, @@ -50,9 +49,13 @@ class CSVLister(ListFormatter): writer.writerow(column_names) for row in data: writer.writerow( - [(str(c.machine_readable()) - if isinstance(c, columns.FormattableColumn) - else c) - for c in row] + [ + ( + str(c.machine_readable()) + if isinstance(c, columns.FormattableColumn) + else c + ) + for c in row + ] ) return diff --git a/cliff/formatters/json_format.py b/cliff/formatters/json_format.py index 04804321..a65987c8 100644 --- a/cliff/formatters/json_format.py +++ b/cliff/formatters/json_format.py @@ -20,24 +20,27 @@ from cliff import columns class JSONFormatter(base.ListFormatter, base.SingleFormatter): - def add_argument_group(self, parser): group = parser.add_argument_group(title='json formatter') group.add_argument( '--noindent', action='store_true', dest='noindent', - help='whether to disable indenting the JSON' + help='whether to disable indenting the JSON', ) def emit_list(self, column_names, data, stdout, parsed_args): items = [] for item in data: items.append( - {n: (i.machine_readable() - if isinstance(i, columns.FormattableColumn) - else i) - for n, i in zip(column_names, item)} + { + n: ( + i.machine_readable() + if isinstance(i, columns.FormattableColumn) + else i + ) + for n, i in zip(column_names, item) + } ) indent = None if parsed_args.noindent else 2 json.dump(items, stdout, indent=indent) @@ -45,9 +48,11 @@ class JSONFormatter(base.ListFormatter, base.SingleFormatter): def emit_one(self, column_names, data, stdout, parsed_args): one = { - n: (i.machine_readable() + n: ( + i.machine_readable() if isinstance(i, columns.FormattableColumn) - else i) + else i + ) for n, i in zip(column_names, data) } indent = None if parsed_args.noindent else 2 diff --git a/cliff/formatters/shell.py b/cliff/formatters/shell.py index d02ebe0f..226bc271 100644 --- a/cliff/formatters/shell.py +++ b/cliff/formatters/shell.py @@ -20,7 +20,6 @@ import argparse class ShellFormatter(base.SingleFormatter): - def add_argument_group(self, parser): group = parser.add_argument_group( title='shell formatter', @@ -43,15 +42,15 @@ class ShellFormatter(base.SingleFormatter): ) def emit_one(self, column_names, data, stdout, parsed_args): - variable_names = [c.lower().replace(' ', '_') - for c in column_names - ] + variable_names = [c.lower().replace(' ', '_') for c in column_names] desired_columns = parsed_args.variables for name, value in zip(variable_names, data): if name in desired_columns or not desired_columns: - value = (str(value.machine_readable()) - if isinstance(value, columns.FormattableColumn) - else value) + value = ( + str(value.machine_readable()) + if isinstance(value, columns.FormattableColumn) + else value + ) if isinstance(value, str): value = value.replace('"', '\\"') if isinstance(name, str): diff --git a/cliff/formatters/table.py b/cliff/formatters/table.py index 974f56a5..c8e55386 100644 --- a/cliff/formatters/table.py +++ b/cliff/formatters/table.py @@ -42,7 +42,6 @@ def _do_fit(fit_width): class TableFormatter(base.ListFormatter, base.SingleFormatter): - ALIGNMENTS = { int: 'r', str: 'l', @@ -56,18 +55,22 @@ class TableFormatter(base.ListFormatter, base.SingleFormatter): metavar='<integer>', default=int(os.environ.get('CLIFF_MAX_TERM_WIDTH', 0)), type=int, - help=('Maximum display width, <1 to disable. You can also ' - 'use the CLIFF_MAX_TERM_WIDTH environment variable, ' - 'but the parameter takes precedence.'), + help=( + 'Maximum display width, <1 to disable. You can also ' + 'use the CLIFF_MAX_TERM_WIDTH environment variable, ' + 'but the parameter takes precedence.' + ), ) group.add_argument( '--fit-width', action='store_true', default=bool(int(os.environ.get('CLIFF_FIT_WIDTH', 0))), - help=('Fit the table to the display width. ' - 'Implied if --max-width greater than 0. ' - 'Set the environment variable CLIFF_FIT_WIDTH=1 ' - 'to always enable'), + help=( + 'Fit the table to the display width. ' + 'Implied if --max-width greater than 0. ' + 'Set the environment variable CLIFF_FIT_WIDTH=1 ' + 'to always enable' + ), ) group.add_argument( '--print-empty', @@ -109,8 +112,8 @@ class TableFormatter(base.ListFormatter, base.SingleFormatter): # preference to wrapping columns smaller than 8 characters. min_width = 8 self._assign_max_widths( - x, int(parsed_args.max_width), min_width, - parsed_args.fit_width) + x, int(parsed_args.max_width), min_width, parsed_args.fit_width + ) formatted = x.get_string() stdout.write(formatted) @@ -118,8 +121,9 @@ class TableFormatter(base.ListFormatter, base.SingleFormatter): return def emit_one(self, column_names, data, stdout, parsed_args): - x = prettytable.PrettyTable(field_names=('Field', 'Value'), - print_empty=False) + x = prettytable.PrettyTable( + field_names=('Field', 'Value'), print_empty=False + ) x.padding_width = 1 # Align all columns left because the values are # not all the same type. @@ -134,8 +138,8 @@ class TableFormatter(base.ListFormatter, base.SingleFormatter): # the Field column readable. min_width = 16 self._assign_max_widths( - x, int(parsed_args.max_width), min_width, - parsed_args.fit_width) + x, int(parsed_args.max_width), min_width, parsed_args.fit_width + ) formatted = x.get_string() stdout.write(formatted) @@ -144,7 +148,6 @@ class TableFormatter(base.ListFormatter, base.SingleFormatter): @staticmethod def _field_widths(field_names, first_line): - # use the first line +----+-------+ to infer column widths # accounting for padding and dividers widths = [max(0, len(i) - 2) for i in first_line.split('+')[1:-1]] @@ -164,8 +167,9 @@ class TableFormatter(base.ListFormatter, base.SingleFormatter): return usable_total_width, optimal_width @staticmethod - def _build_shrink_fields(usable_total_width, optimal_width, - field_widths, field_names): + def _build_shrink_fields( + usable_total_width, optimal_width, field_widths, field_names + ): shrink_fields = [] shrink_remaining = usable_total_width for field in field_names: @@ -204,12 +208,14 @@ class TableFormatter(base.ListFormatter, base.SingleFormatter): return usable_total_width, optimal_width = TableFormatter._width_info( - term_width, field_count) + term_width, field_count + ) field_widths = TableFormatter._field_widths(x.field_names, first_line) shrink_fields, shrink_remaining = TableFormatter._build_shrink_fields( - usable_total_width, optimal_width, field_widths, x.field_names) + usable_total_width, optimal_width, field_widths, x.field_names + ) shrink_to = shrink_remaining // len(shrink_fields) # make all shrinkable fields size shrink_to apart from the last one diff --git a/cliff/formatters/value.py b/cliff/formatters/value.py index 5889d2b2..e3db2e77 100644 --- a/cliff/formatters/value.py +++ b/cliff/formatters/value.py @@ -18,7 +18,6 @@ from cliff import columns class ValueFormatter(base.ListFormatter, base.SingleFormatter): - def add_argument_group(self, parser): pass @@ -26,17 +25,25 @@ class ValueFormatter(base.ListFormatter, base.SingleFormatter): for row in data: stdout.write( ' '.join( - str(c.machine_readable() + str( + c.machine_readable() if isinstance(c, columns.FormattableColumn) - else c) - for c in row) + '\n') + else c + ) + for c in row + ) + + '\n' + ) return def emit_one(self, column_names, data, stdout, parsed_args): for value in data: - stdout.write('%s\n' % str( - value.machine_readable() - if isinstance(value, columns.FormattableColumn) - else value) + stdout.write( + '%s\n' + % str( + value.machine_readable() + if isinstance(value, columns.FormattableColumn) + else value + ) ) return diff --git a/cliff/formatters/yaml_format.py b/cliff/formatters/yaml_format.py index 5d25fe72..0283bfe6 100644 --- a/cliff/formatters/yaml_format.py +++ b/cliff/formatters/yaml_format.py @@ -29,7 +29,6 @@ def _yaml_friendly(value): class YAMLFormatter(base.ListFormatter, base.SingleFormatter): - def add_argument_group(self, parser): pass diff --git a/cliff/help.py b/cliff/help.py index af30504d..620be3c9 100644 --- a/cliff/help.py +++ b/cliff/help.py @@ -30,13 +30,13 @@ class HelpExit(SystemExit): class HelpAction(argparse.Action): - """Provide a custom action so the -h and --help options to the main app will print a list of the commands. The commands are determined by checking the CommandManager instance, passed in as the "default" value for the action. """ + def __call__(self, parser, namespace, values, option_string=None): app = self.default pager = autopage.argparse.help_pager(app.stdout) @@ -90,15 +90,15 @@ class HelpAction(argparse.Action): class HelpCommand(command.Command): - """print detailed help for another command - """ + """print detailed help for another command""" def get_parser(self, prog_name): parser = super(HelpCommand, self).get_parser(prog_name) - parser.add_argument('cmd', - nargs='*', - help='name of the command', - ) + parser.add_argument( + 'cmd', + nargs='*', + help='name of the command', + ) return parser def take_action(self, parsed_args): @@ -111,9 +111,11 @@ class HelpCommand(command.Command): except ValueError: # Did not find an exact match cmd = parsed_args.cmd[0] - fuzzy_matches = [k[0] for k in self.app.command_manager - if k[0].startswith(cmd) - ] + fuzzy_matches = [ + k[0] + for k in self.app.command_manager + if k[0].startswith(cmd) + ] if not fuzzy_matches: raise self.app.stdout.write('Command "%s" matches:\n' % cmd) @@ -125,15 +127,17 @@ class HelpCommand(command.Command): if 'cmd_name' in inspect.getfullargspec(cmd_factory.__init__).args: kwargs['cmd_name'] = cmd_name cmd = cmd_factory(self.app, self.app_args, **kwargs) - full_name = (cmd_name - if self.app.interactive_mode - else ' '.join([self.app.NAME, cmd_name]) - ) + full_name = ( + cmd_name + if self.app.interactive_mode + else ' '.join([self.app.NAME, cmd_name]) + ) cmd_parser = cmd.get_parser(full_name) pager = autopage.argparse.help_pager(self.app.stdout) with pager as out: - autopage.argparse.use_color_for_parser(cmd_parser, - pager.to_terminal()) + autopage.argparse.use_color_for_parser( + cmd_parser, pager.to_terminal() + ) cmd_parser.print_help(out) else: action = HelpAction(None, None, default=self.app) diff --git a/cliff/interactive.py b/cliff/interactive.py index 0a44481c..ad3c293a 100644 --- a/cliff/interactive.py +++ b/cliff/interactive.py @@ -42,8 +42,9 @@ class InteractiveApp(cmd2.Cmd): doc_header = "Shell commands (type help <topic>):" app_cmd_header = "Application commands (type help <topic>):" - def __init__(self, parent_app, command_manager, stdin, stdout, - errexit=False): + def __init__( + self, parent_app, command_manager, stdin, stdout, errexit=False + ): self.parent_app = parent_app if not hasattr(sys.stdin, 'isatty') or sys.stdin.isatty(): self.prompt = '(%s) ' % parent_app.NAME @@ -117,8 +118,9 @@ class InteractiveApp(cmd2.Cmd): method_name = '_'.join( itertools.chain( ['do'], - itertools.takewhile(lambda x: not x.startswith('-'), - arg_parts) + itertools.takewhile( + lambda x: not x.startswith('-'), arg_parts + ), ) ) # Have the command manager version of the help @@ -160,10 +162,9 @@ class InteractiveApp(cmd2.Cmd): # Override the base class version to filter out # things that look like they should be hidden # from the user. - return [n - for n in cmd2.Cmd.get_names(self) - if not n.startswith('do__') - ] + return [ + n for n in cmd2.Cmd.get_names(self) if not n.startswith('do__') + ] def precmd(self, statement): """Hook method executed just before the command is executed by diff --git a/cliff/lister.py b/cliff/lister.py index eed48753..e7d628b7 100644 --- a/cliff/lister.py +++ b/cliff/lister.py @@ -83,7 +83,8 @@ class Lister(display.DisplayCommandBase, metaclass=abc.ABCMeta): def produce_output(self, parsed_args, column_names, data): if parsed_args.sort_columns and self.need_sort_by_cliff: indexes = [ - column_names.index(c) for c in parsed_args.sort_columns + column_names.index(c) + for c in parsed_args.sort_columns if c in column_names ] reverse = parsed_args.sort_direction == 'desc' @@ -97,7 +98,8 @@ class Lister(display.DisplayCommandBase, metaclass=abc.ABCMeta): # returns from the 'is None' check on the two values are # the same, i.e. both None or both not-None data = sorted( - data, key=lambda k: (k[index] is None, k[index]), + data, + key=lambda k: (k[index] is None, k[index]), reverse=reverse, ) except TypeError: @@ -108,7 +110,8 @@ class Lister(display.DisplayCommandBase, metaclass=abc.ABCMeta): ) columns_to_include, selector = self._generate_columns_and_selector( - parsed_args, column_names, + parsed_args, + column_names, ) if selector: # Generator expression to only return the parts of a row @@ -120,7 +123,10 @@ class Lister(display.DisplayCommandBase, metaclass=abc.ABCMeta): ) self.formatter.emit_list( - columns_to_include, data, self.app.stdout, parsed_args, + columns_to_include, + data, + self.app.stdout, + parsed_args, ) return 0 diff --git a/cliff/show.py b/cliff/show.py index 6273c0ee..41868e35 100644 --- a/cliff/show.py +++ b/cliff/show.py @@ -18,8 +18,7 @@ from . import display class ShowOne(display.DisplayCommandBase, metaclass=abc.ABCMeta): - """Command base class for displaying data about a single object. - """ + """Command base class for displaying data about a single object.""" @property def formatter_namespace(self): @@ -37,13 +36,13 @@ class ShowOne(display.DisplayCommandBase, metaclass=abc.ABCMeta): def produce_output(self, parsed_args, column_names, data): (columns_to_include, selector) = self._generate_columns_and_selector( - parsed_args, column_names) + parsed_args, column_names + ) if selector: data = list(self._compress_iterable(data, selector)) - self.formatter.emit_one(columns_to_include, - data, - self.app.stdout, - parsed_args) + self.formatter.emit_one( + columns_to_include, data, self.app.stdout, parsed_args + ) return 0 def dict2columns(self, data): diff --git a/cliff/sphinxext.py b/cliff/sphinxext.py index 265ccccd..46899700 100644 --- a/cliff/sphinxext.py +++ b/cliff/sphinxext.py @@ -46,7 +46,8 @@ def _format_description(parser): information in their help messages if they so choose. """ for line in statemachine.string2lines( - parser.description, tab_width=4, convert_whitespace=True): + parser.description, tab_width=4, convert_whitespace=True + ): yield line @@ -64,12 +65,15 @@ def _format_usage(parser): # becomes ['--format <FORMAT>'] and not ['--format', '<FORMAT>']. # Yes, they really do use regexes to break apart and rewrap their help # string. Don't ask me why. - part_regexp = re.compile(r""" + part_regexp = re.compile( + r""" \(.*?\)+ | \[.*?\]+ | (?:(?:-\w|--\w+(?:-\w+)*)(?:\s+<?\w[\w-]*>?)?) | \S+ - """, re.VERBOSE) + """, + re.VERBOSE, + ) opt_usage = fmt._format_actions_usage(optionals, groups) pos_usage = fmt._format_actions_usage(positionals, groups) @@ -91,7 +95,8 @@ def _format_epilog(parser): information in their help messages if they so choose. """ for line in statemachine.string2lines( - parser.epilog, tab_width=4, convert_whitespace=True): + parser.epilog, tab_width=4, convert_whitespace=True + ): yield line @@ -104,11 +109,13 @@ def _format_positional_action(action): # the 'option' directive dictates that only option argument names should be # surrounded by angle brackets yield '.. option:: {}'.format( - (action.metavar or action.dest).strip('<>[]() ')) + (action.metavar or action.dest).strip('<>[]() ') + ) if action.help: yield '' for line in statemachine.string2lines( - action.help, tab_width=4, convert_whitespace=True): + action.help, tab_width=4, convert_whitespace=True + ): yield _indent(line) @@ -123,15 +130,17 @@ def _format_optional_action(action): # TODO(stephenfin): At some point, we may wish to provide more # information about the options themselves, for example, if nargs is # specified - option_strings = [' '.join( - [x, action.metavar or '<{}>'.format(action.dest.upper())]) - for x in action.option_strings] + option_strings = [ + ' '.join([x, action.metavar or '<{}>'.format(action.dest.upper())]) + for x in action.option_strings + ] yield '.. option:: {}'.format(', '.join(option_strings)) if action.help: yield '' for line in statemachine.string2lines( - action.help, tab_width=4, convert_whitespace=True): + action.help, tab_width=4, convert_whitespace=True + ): yield _indent(line) @@ -220,8 +229,9 @@ class AutoprogramCliffDirective(rst.Directive): def _get_ignored_opts(self): global_ignored = self.env.config.autoprogram_cliff_ignored local_ignored = self.options.get('ignored', '') - local_ignored = [x.strip() for x in local_ignored.split(',') - if x.strip()] + local_ignored = [ + x.strip() for x in local_ignored.split(',') if x.strip() + ] return list(set(global_ignored + local_ignored)) def _drop_ignored_options(self, parser, ignored_opts): @@ -256,9 +266,10 @@ class AutoprogramCliffDirective(rst.Directive): # find_command expects the value of argv so split to emulate that return manager.find_command(command_name.split())[0] except ValueError: - raise self.error('"{}" is not a valid command in the "{}" ' - 'namespace'.format( - command_name, manager.namespace)) + raise self.error( + '"{}" is not a valid command in the "{}" ' + 'namespace'.format(command_name, manager.namespace) + ) def _load_commands(self): # TODO(sfinucan): We should probably add this wildcarding functionality @@ -267,8 +278,11 @@ class AutoprogramCliffDirective(rst.Directive): command_pattern = self.options.get('command') manager = commandmanager.CommandManager(self.arguments[0]) if command_pattern: - commands = [x for x in manager.commands - if fnmatch.fnmatch(x, command_pattern)] + commands = [ + x + for x in manager.commands + if fnmatch.fnmatch(x, command_pattern) + ] else: commands = manager.commands.keys() @@ -276,12 +290,15 @@ class AutoprogramCliffDirective(rst.Directive): msg = 'No commands found in the "{}" namespace' if command_pattern: msg += ' using the "{}" command name/pattern' - msg += ('. Are you sure this is correct and the application being ' - 'documented is installed?') + msg += ( + '. Are you sure this is correct and the application being ' + 'documented is installed?' + ) raise self.warning(msg.format(self.arguments[0], command_pattern)) - return dict((name, self._load_command(manager, name)) - for name in commands) + return dict( + (name, self._load_command(manager, name)) for name in commands + ) def _generate_app_node(self, app, application_name): ignored_opts = self._get_ignored_opts() @@ -303,8 +320,9 @@ class AutoprogramCliffDirective(rst.Directive): # return [section.children] return section.children - def _generate_nodes_per_command(self, title, command_name, command_class, - ignored_opts): + def _generate_nodes_per_command( + self, title, command_name, command_class, ignored_opts + ): """Generate the relevant Sphinx nodes. This doesn't bother using raw docutils nodes as they simply don't offer @@ -324,7 +342,8 @@ class AutoprogramCliffDirective(rst.Directive): command = command_class(None, None) if not getattr(command, 'app_dist_name', None): command.app_dist_name = ( - self.env.config.autoprogram_cliff_app_dist_name) + self.env.config.autoprogram_cliff_app_dist_name + ) parser = command.get_parser(command_name) ignored_opts = ignored_opts or [] @@ -334,7 +353,8 @@ class AutoprogramCliffDirective(rst.Directive): '', nodes.title(text=title), ids=[nodes.make_id(title)], - names=[nodes.fully_normalize_name(title)]) + names=[nodes.fully_normalize_name(title)], + ) source_name = '<{}>'.format(command.__class__.__name__) result = statemachine.ViewList() @@ -355,16 +375,21 @@ class AutoprogramCliffDirective(rst.Directive): if application_name: command_name = ' '.join([application_name, command_name]) - output.extend(self._generate_nodes_per_command( - title, command_name, command_class, ignored_opts)) + output.extend( + self._generate_nodes_per_command( + title, command_name, command_class, ignored_opts + ) + ) return output def run(self): self.env = self.state.document.settings.env - application_name = (self.options.get('application') - or self.env.config.autoprogram_cliff_application) + application_name = ( + self.options.get('application') + or self.env.config.autoprogram_cliff_application + ) app = self._load_app() if app: diff --git a/cliff/tests/base.py b/cliff/tests/base.py index 7afce023..c213dc62 100644 --- a/cliff/tests/base.py +++ b/cliff/tests/base.py @@ -18,7 +18,6 @@ import fixtures class TestBase(testtools.TestCase): - def setUp(self): super(TestBase, self).setUp() self._stdout_fixture = fixtures.StringStream('stdout') diff --git a/cliff/tests/test__argparse.py b/cliff/tests/test__argparse.py index ab1e9b8f..31caf40b 100644 --- a/cliff/tests/test__argparse.py +++ b/cliff/tests/test__argparse.py @@ -19,7 +19,6 @@ from cliff import _argparse class TestArgparse(unittest.TestCase): - def test_argument_parser(self): _argparse.ArgumentParser(conflict_handler='ignore') diff --git a/cliff/tests/test_app.py b/cliff/tests/test_app.py index bffbb70f..b3a8dc1f 100644 --- a/cliff/tests/test_app.py +++ b/cliff/tests/test_app.py @@ -48,32 +48,28 @@ def make_app(**kwargs): # Register a command that is interrrupted interrupt_command = mock.Mock(name='interrupt_command', spec=c_cmd.Command) interrupt_command_inst = mock.Mock(spec=c_cmd.Command) - interrupt_command_inst.run = mock.Mock( - side_effect=KeyboardInterrupt - ) + interrupt_command_inst.run = mock.Mock(side_effect=KeyboardInterrupt) interrupt_command.return_value = interrupt_command_inst cmd_mgr.add_command('interrupt', interrupt_command) # Register a command that is interrrupted by a broken pipe pipeclose_command = mock.Mock(name='pipeclose_command', spec=c_cmd.Command) pipeclose_command_inst = mock.Mock(spec=c_cmd.Command) - pipeclose_command_inst.run = mock.Mock( - side_effect=BrokenPipeError - ) + pipeclose_command_inst.run = mock.Mock(side_effect=BrokenPipeError) pipeclose_command.return_value = pipeclose_command_inst cmd_mgr.add_command('pipe-close', pipeclose_command) - app = application.App('testing interactive mode', - '1', - cmd_mgr, - stderr=mock.Mock(), # suppress warning messages - **kwargs - ) + app = application.App( + 'testing interactive mode', + '1', + cmd_mgr, + stderr=mock.Mock(), # suppress warning messages + **kwargs + ) return app, command class TestInteractiveMode(base.TestBase): - def test_no_args_triggers_interactive_mode(self): app, command = make_app() app.interact = mock.MagicMock(name='inspect') @@ -110,7 +106,6 @@ class TestInteractiveMode(base.TestBase): class TestInitAndCleanup(base.TestBase): - def test_initialize_app(self): app, command = make_app() app.initialize_app = mock.MagicMock(name='initialize_app') @@ -266,7 +261,6 @@ class TestInitAndCleanup(base.TestBase): class TestOptionParser(base.TestBase): - def test_conflicting_option_should_throw(self): class MyApp(application.App): def __init__(self): @@ -277,10 +271,12 @@ class TestOptionParser(base.TestBase): ) def build_option_parser(self, description, version): - parser = super(MyApp, self).build_option_parser(description, - version) + parser = super(MyApp, self).build_option_parser( + description, version + ) parser.add_argument( - '-h', '--help', + '-h', + '--help', default=self, # tricky help="Show help message and exit.", ) @@ -302,11 +298,11 @@ class TestOptionParser(base.TestBase): def build_option_parser(self, description, version): argparse_kwargs = {'conflict_handler': 'resolve'} parser = super(MyApp, self).build_option_parser( - description, - version, - argparse_kwargs=argparse_kwargs) + description, version, argparse_kwargs=argparse_kwargs + ) parser.add_argument( - '-h', '--help', + '-h', + '--help', default=self, # tricky help="Show help message and exit.", ) @@ -339,7 +335,8 @@ class TestOptionParser(base.TestBase): parser = super(MyApp, self).build_option_parser( description, version, - argparse_kwargs={'allow_abbrev': False}) + argparse_kwargs={'allow_abbrev': False}, + ) parser.add_argument('--endpoint') return parser @@ -350,12 +347,12 @@ class TestOptionParser(base.TestBase): class TestHelpHandling(base.TestBase): - def _test_help(self, deferred_help): app, _ = make_app(deferred_help=deferred_help) with mock.patch.object(app, 'initialize_app') as init: - with mock.patch('cliff.help.HelpAction.__call__', - side_effect=SystemExit(0)) as helper: + with mock.patch( + 'cliff.help.HelpAction.__call__', side_effect=SystemExit(0) + ) as helper: self.assertRaises( SystemExit, app.run, @@ -372,8 +369,9 @@ class TestHelpHandling(base.TestBase): def _test_interrupted_help(self, deferred_help): app, _ = make_app(deferred_help=deferred_help) - with mock.patch('cliff.help.HelpAction.__call__', - side_effect=KeyboardInterrupt): + with mock.patch( + 'cliff.help.HelpAction.__call__', side_effect=KeyboardInterrupt + ): result = app.run(['--help']) self.assertEqual(result, 130) @@ -385,8 +383,9 @@ class TestHelpHandling(base.TestBase): def _test_pipeclose_help(self, deferred_help): app, _ = make_app(deferred_help=deferred_help) - with mock.patch('cliff.help.HelpAction.__call__', - side_effect=BrokenPipeError): + with mock.patch( + 'cliff.help.HelpAction.__call__', side_effect=BrokenPipeError + ): app.run(['--help']) def test_pipeclose_help(self): @@ -415,7 +414,6 @@ class TestHelpHandling(base.TestBase): class TestCommandLookup(base.TestBase): - def test_unknown_cmd(self): app, command = make_app() self.assertEqual(2, app.run(['hell'])) @@ -429,18 +427,21 @@ class TestCommandLookup(base.TestBase): def test_list_matching_commands(self): stdout = io.StringIO() - app = application.App('testing', '1', - test_utils.TestCommandManager( - test_utils.TEST_NAMESPACE), - stdout=stdout) + app = application.App( + 'testing', + '1', + test_utils.TestCommandManager(test_utils.TEST_NAMESPACE), + stdout=stdout, + ) app.NAME = 'test' try: self.assertEqual(2, app.run(['t'])) except SystemExit: pass output = stdout.getvalue() - self.assertIn("test: 't' is not a test command. See 'test --help'.", - output) + self.assertIn( + "test: 't' is not a test command. See 'test --help'.", output + ) self.assertIn('Did you mean one of these?', output) self.assertIn('three word command\n two words\n', output) @@ -484,7 +485,6 @@ class TestCommandLookup(base.TestBase): class TestVerboseMode(base.TestBase): - def test_verbose(self): app, command = make_app() app.clean_up = mock.MagicMock(name='clean_up') @@ -501,7 +501,6 @@ class TestVerboseMode(base.TestBase): class TestIO(base.TestBase): - def test_io_streams(self): cmd_mgr = commandmanager.CommandManager('cliff.tests') io = mock.Mock() @@ -516,14 +515,12 @@ class TestIO(base.TestBase): self.assertIs(sys.stdout, app.stdout) self.assertIs(sys.stderr, app.stderr) - app = application.App('with stdout io stream', 1, cmd_mgr, - stdout=io) + app = application.App('with stdout io stream', 1, cmd_mgr, stdout=io) self.assertIs(sys.stdin, app.stdin) self.assertIs(io, app.stdout) self.assertIs(sys.stderr, app.stderr) - app = application.App('with stderr io stream', 1, cmd_mgr, - stderr=io) + app = application.App('with stderr io stream', 1, cmd_mgr, stderr=io) self.assertIs(sys.stdin, app.stdin) self.assertIs(sys.stdout, app.stdout) self.assertIs(io, app.stderr) diff --git a/cliff/tests/test_columns.py b/cliff/tests/test_columns.py index 364d2581..c2e95d16 100644 --- a/cliff/tests/test_columns.py +++ b/cliff/tests/test_columns.py @@ -16,13 +16,11 @@ from cliff import columns class FauxColumn(columns.FormattableColumn): - def human_readable(self): return 'I made this string myself: {}'.format(self._value) class TestColumns(unittest.TestCase): - def test_machine_readable(self): c = FauxColumn(['list', 'of', 'values']) self.assertEqual(['list', 'of', 'values'], c.machine_readable()) diff --git a/cliff/tests/test_command.py b/cliff/tests/test_command.py index c9513d0f..3cd77024 100644 --- a/cliff/tests/test_command.py +++ b/cliff/tests/test_command.py @@ -18,30 +18,28 @@ from cliff.tests import base class TestCommand(command.Command): - """Description of command. - """ + """Description of command.""" def get_parser(self, prog_name): parser = super(TestCommand, self).get_parser(prog_name) parser.add_argument( 'long_help_argument', help="Create a NIC on the server.\n" - "Specify option multiple times to create multiple NICs. " - "Either net-id or port-id must be provided, but not both.\n" - "net-id: attach NIC to network with this UUID\n" - "port-id: attach NIC to port with this UUID\n" - "v4-fixed-ip: IPv4 fixed address for NIC (optional)\n" - "v6-fixed-ip: IPv6 fixed address for NIC (optional)\n" - "none: (v2.37+) no network is attached\n" - "auto: (v2.37+) the compute service will automatically " - "allocate a network.\n" - "Specifying a --nic of auto or none " - "cannot be used with any other --nic value.", + "Specify option multiple times to create multiple NICs. " + "Either net-id or port-id must be provided, but not both.\n" + "net-id: attach NIC to network with this UUID\n" + "port-id: attach NIC to port with this UUID\n" + "v4-fixed-ip: IPv4 fixed address for NIC (optional)\n" + "v6-fixed-ip: IPv6 fixed address for NIC (optional)\n" + "none: (v2.37+) no network is attached\n" + "auto: (v2.37+) the compute service will automatically " + "allocate a network.\n" + "Specifying a --nic of auto or none " + "cannot be used with any other --nic value.", ) parser.add_argument( 'regular_help_argument', - help="The quick brown fox jumps " - "over the lazy dog.", + help="The quick brown fox jumps " "over the lazy dog.", ) parser.add_argument( '-z', @@ -56,17 +54,15 @@ class TestCommand(command.Command): class TestCommandNoDocstring(command.Command): - def take_action(self, parsed_args): return 42 class TestDescription(base.TestBase): - def test_get_description_docstring(self): cmd = TestCommand(None, None) desc = cmd.get_description() - assert desc == "Description of command.\n " + assert desc == "Description of command." def test_get_description_attribute(self): cmd = TestCommand(None, None) @@ -83,7 +79,6 @@ class TestDescription(base.TestBase): class TestBasicValues(base.TestBase): - def test_get_parser(self): cmd = TestCommand(None, None) parser = cmd.get_parser('NAME') @@ -118,7 +113,6 @@ expected_help_message = """ class TestHelp(base.TestBase): - def test_smart_help_formatter(self): cmd = TestCommand(None, None) parser = cmd.get_parser('NAME') @@ -138,7 +132,6 @@ class TestHelp(base.TestBase): class TestArgumentParser(base.TestBase): - def test_option_name_collision(self): cmd = TestCommand(None, None) parser = cmd.get_parser('NAME') @@ -165,7 +158,8 @@ class TestArgumentParser(base.TestBase): cmd = TestCommand(None, None) parser = cmd.get_parser('NAME') parser.add_argument( - '-z', '--zero', + '-z', + '--zero', dest='zero', default='zero-default', ) @@ -183,7 +177,8 @@ class TestArgumentParser(base.TestBase): cmd = TestCommand(None, None) parser = cmd.get_parser('NAME') parser.add_argument( - '-f', '--foo', + '-f', + '--foo', dest='foo', default='foo', ) @@ -198,12 +193,14 @@ class TestArgumentParser(base.TestBase): cmd.conflict_handler = 'resolve' parser = cmd.get_parser('NAME') parser.add_argument( - '-f', '--foo', + '-f', + '--foo', dest='foo', default='foo', ) parser.add_argument( - '-f', '--foo', + '-f', + '--foo', dest='foo', default='bar', ) diff --git a/cliff/tests/test_command_hooks.py b/cliff/tests/test_command_hooks.py index 63dcbb3d..cec8b579 100644 --- a/cliff/tests/test_command_hooks.py +++ b/cliff/tests/test_command_hooks.py @@ -41,18 +41,18 @@ def make_app(**kwargs): err_command.return_value = err_command_inst cmd_mgr.add_command('error', err_command) - app = application.App('testing command hooks', - '1', - cmd_mgr, - stderr=mock.Mock(), # suppress warning messages - **kwargs - ) + app = application.App( + 'testing command hooks', + '1', + cmd_mgr, + stderr=mock.Mock(), # suppress warning messages + **kwargs + ) return app class TestCommand(command.Command): - """Description of command. - """ + """Description of command.""" def get_parser(self, prog_name): parser = super(TestCommand, self).get_parser(prog_name) @@ -63,23 +63,20 @@ class TestCommand(command.Command): class TestShowCommand(show.ShowOne): - """Description of command. - """ + """Description of command.""" def take_action(self, parsed_args): return (('Name',), ('value',)) class TestListerCommand(lister.Lister): - """Description of command. - """ + """Description of command.""" def take_action(self, parsed_args): return (('Name',), [('value',)]) class TestHook(hooks.CommandHook): - _before_called = False _after_called = False @@ -98,7 +95,6 @@ class TestHook(hooks.CommandHook): class TestChangeHook(hooks.CommandHook): - _before_called = False _after_called = False @@ -121,7 +117,6 @@ class TestChangeHook(hooks.CommandHook): class TestDisplayChangeHook(hooks.CommandHook): - _before_called = False _after_called = False @@ -144,7 +139,6 @@ class TestDisplayChangeHook(hooks.CommandHook): class TestListerChangeHook(hooks.CommandHook): - _before_called = False _after_called = False @@ -167,7 +161,6 @@ class TestListerChangeHook(hooks.CommandHook): class TestCommandLoadHooks(base.TestBase): - def test_no_app_or_name(self): cmd = TestCommand(None, None) self.assertEqual([], cmd._hooks) @@ -183,18 +176,13 @@ class TestCommandLoadHooks(base.TestBase): class TestHooks(base.TestBase): - def setUp(self): super(TestHooks, self).setUp() self.app = make_app() self.cmd = TestCommand(self.app, None, cmd_name='test') self.hook = TestHook(self.cmd) self.mgr = extension.ExtensionManager.make_test_instance( - [extension.Extension( - 'parser-hook', - None, - None, - self.hook)], + [extension.Extension('parser-hook', None, None, self.hook)], ) # Replace the auto-loaded hooks with our explicitly created # manager. @@ -222,18 +210,13 @@ class TestHooks(base.TestBase): class TestChangeHooks(base.TestBase): - def setUp(self): super(TestChangeHooks, self).setUp() self.app = make_app() self.cmd = TestCommand(self.app, None, cmd_name='test') self.hook = TestChangeHook(self.cmd) self.mgr = extension.ExtensionManager.make_test_instance( - [extension.Extension( - 'parser-hook', - None, - None, - self.hook)], + [extension.Extension('parser-hook', None, None, self.hook)], ) # Replace the auto-loaded hooks with our explicitly created # manager. @@ -267,18 +250,13 @@ class TestChangeHooks(base.TestBase): class TestShowOneHooks(base.TestBase): - def setUp(self): super(TestShowOneHooks, self).setUp() self.app = make_app() self.cmd = TestShowCommand(self.app, None, cmd_name='test') self.hook = TestHook(self.cmd) self.mgr = extension.ExtensionManager.make_test_instance( - [extension.Extension( - 'parser-hook', - None, - None, - self.hook)], + [extension.Extension('parser-hook', None, None, self.hook)], ) # Replace the auto-loaded hooks with our explicitly created # manager. @@ -309,18 +287,13 @@ class TestShowOneHooks(base.TestBase): class TestShowOneChangeHooks(base.TestBase): - def setUp(self): super(TestShowOneChangeHooks, self).setUp() self.app = make_app() self.cmd = TestShowCommand(self.app, None, cmd_name='test') self.hook = TestDisplayChangeHook(self.cmd) self.mgr = extension.ExtensionManager.make_test_instance( - [extension.Extension( - 'parser-hook', - None, - None, - self.hook)], + [extension.Extension('parser-hook', None, None, self.hook)], ) # Replace the auto-loaded hooks with our explicitly created # manager. @@ -354,18 +327,13 @@ class TestShowOneChangeHooks(base.TestBase): class TestListerHooks(base.TestBase): - def setUp(self): super(TestListerHooks, self).setUp() self.app = make_app() self.cmd = TestListerCommand(self.app, None, cmd_name='test') self.hook = TestHook(self.cmd) self.mgr = extension.ExtensionManager.make_test_instance( - [extension.Extension( - 'parser-hook', - None, - None, - self.hook)], + [extension.Extension('parser-hook', None, None, self.hook)], ) # Replace the auto-loaded hooks with our explicitly created # manager. @@ -396,18 +364,13 @@ class TestListerHooks(base.TestBase): class TestListerChangeHooks(base.TestBase): - def setUp(self): super(TestListerChangeHooks, self).setUp() self.app = make_app() self.cmd = TestListerCommand(self.app, None, cmd_name='test') self.hook = TestListerChangeHook(self.cmd) self.mgr = extension.ExtensionManager.make_test_instance( - [extension.Extension( - 'parser-hook', - None, - None, - self.hook)], + [extension.Extension('parser-hook', None, None, self.hook)], ) # Replace the auto-loaded hooks with our explicitly created # manager. diff --git a/cliff/tests/test_commandmanager.py b/cliff/tests/test_commandmanager.py index 3426cfb3..7f2fde01 100644 --- a/cliff/tests/test_commandmanager.py +++ b/cliff/tests/test_commandmanager.py @@ -23,7 +23,6 @@ load_tests = testscenarios.load_tests_apply_scenarios class TestLookupAndFind(base.TestBase): - scenarios = [ ('one-word', {'argv': ['one']}), ('two-words', {'argv': ['two', 'words']}), @@ -39,7 +38,6 @@ class TestLookupAndFind(base.TestBase): class TestLookupWithRemainder(base.TestBase): - scenarios = [ ('one', {'argv': ['one', '--opt']}), ('two', {'argv': ['two', 'words', '--opt']}), @@ -54,7 +52,6 @@ class TestLookupWithRemainder(base.TestBase): class TestFindInvalidCommand(base.TestBase): - scenarios = [ ('no-such-command', {'argv': ['a', '-b']}), ('no-command-given', {'argv': ['-b']}), @@ -73,7 +70,6 @@ class TestFindInvalidCommand(base.TestBase): class TestFindUnknownCommand(base.TestBase): - def test(self): mgr = utils.TestCommandManager(utils.TEST_NAMESPACE) try: @@ -85,7 +81,6 @@ class TestFindUnknownCommand(base.TestBase): class TestDynamicCommands(base.TestBase): - def test_add(self): mgr = utils.TestCommandManager(utils.TEST_NAMESPACE) mock_cmd = mock.Mock() @@ -112,13 +107,13 @@ class TestDynamicCommands(base.TestBase): class TestLoad(base.TestBase): - def test_load_commands(self): testcmd = mock.Mock(name='testcmd') testcmd.name.replace.return_value = 'test' mock_get_group_all = mock.Mock(return_value=[testcmd]) - with mock.patch('stevedore.ExtensionManager', - mock_get_group_all) as mock_manager: + with mock.patch( + 'stevedore.ExtensionManager', mock_get_group_all + ) as mock_manager: mgr = commandmanager.CommandManager('test') mock_manager.assert_called_once_with('test') names = [n for n, v in mgr] @@ -128,8 +123,9 @@ class TestLoad(base.TestBase): testcmd = mock.Mock() testcmd.name = 'test_cmd' mock_get_group_all = mock.Mock(return_value=[testcmd]) - with mock.patch('stevedore.ExtensionManager', - mock_get_group_all) as mock_manager: + with mock.patch( + 'stevedore.ExtensionManager', mock_get_group_all + ) as mock_manager: mgr = commandmanager.CommandManager( 'test', convert_underscores=False, @@ -142,8 +138,9 @@ class TestLoad(base.TestBase): testcmd = mock.Mock() testcmd.name = 'test_cmd' mock_get_group_all = mock.Mock(return_value=[testcmd]) - with mock.patch('stevedore.ExtensionManager', - mock_get_group_all) as mock_manager: + with mock.patch( + 'stevedore.ExtensionManager', mock_get_group_all + ) as mock_manager: mgr = commandmanager.CommandManager( 'test', convert_underscores=True, @@ -154,7 +151,6 @@ class TestLoad(base.TestBase): class FauxCommand(command.Command): - def take_action(self, parsed_args): return 0 @@ -164,7 +160,6 @@ class FauxCommand2(FauxCommand): class TestLegacyCommand(base.TestBase): - def test_find_legacy(self): mgr = utils.TestCommandManager(None) mgr.add_command('new name', FauxCommand) @@ -202,7 +197,6 @@ class TestLegacyCommand(base.TestBase): class TestLookupAndFindPartialName(base.TestBase): - scenarios = [ ('one-word', {'argv': ['o']}), ('two-words', {'argv': ['t', 'w']}), @@ -218,45 +212,61 @@ class TestLookupAndFindPartialName(base.TestBase): class TestGetByPartialName(base.TestBase): - def setUp(self): super(TestGetByPartialName, self).setUp() self.commands = { 'resource provider list': 1, 'resource class list': 2, 'server list': 3, - 'service list': 4} + 'service list': 4, + } def test_no_candidates(self): self.assertEqual( - [], commandmanager._get_commands_by_partial_name( - ['r', 'p'], self.commands)) + [], + commandmanager._get_commands_by_partial_name( + ['r', 'p'], self.commands + ), + ) self.assertEqual( - [], commandmanager._get_commands_by_partial_name( - ['r', 'p', 'c'], self.commands)) + [], + commandmanager._get_commands_by_partial_name( + ['r', 'p', 'c'], self.commands + ), + ) def test_multiple_candidates(self): self.assertEqual( - 2, len(commandmanager._get_commands_by_partial_name( - ['se', 'li'], self.commands))) + 2, + len( + commandmanager._get_commands_by_partial_name( + ['se', 'li'], self.commands + ) + ), + ) def test_one_candidate(self): self.assertEqual( ['resource provider list'], commandmanager._get_commands_by_partial_name( - ['r', 'p', 'l'], self.commands)) + ['r', 'p', 'l'], self.commands + ), + ) self.assertEqual( ['resource provider list'], commandmanager._get_commands_by_partial_name( - ['resource', 'provider', 'list'], self.commands)) + ['resource', 'provider', 'list'], self.commands + ), + ) self.assertEqual( ['server list'], commandmanager._get_commands_by_partial_name( - ['serve', 'l'], self.commands)) + ['serve', 'l'], self.commands + ), + ) class FakeCommand(object): - @classmethod def load(cls): return cls @@ -286,7 +296,6 @@ class FakeCommandManager(commandmanager.CommandManager): class TestCommandManagerGroups(base.TestBase): - def test_add_command_group(self): mgr = FakeCommandManager('test') diff --git a/cliff/tests/test_complete.py b/cliff/tests/test_complete.py index 1e7da6be..f7db8ce0 100644 --- a/cliff/tests/test_complete.py +++ b/cliff/tests/test_complete.py @@ -22,19 +22,23 @@ from cliff.tests import base class TestCompletion(base.TestBase): - def test_dictionary(self): sot = complete.CompleteDictionary() - sot.add_command("image delete".split(), - [mock.Mock(option_strings=["1"])]) - sot.add_command("image list".split(), - [mock.Mock(option_strings=["2"])]) - sot.add_command("image create".split(), - [mock.Mock(option_strings=["3"])]) - sot.add_command("volume type create".split(), - [mock.Mock(option_strings=["4"])]) - sot.add_command("volume type delete".split(), - [mock.Mock(option_strings=["5"])]) + sot.add_command( + "image delete".split(), [mock.Mock(option_strings=["1"])] + ) + sot.add_command( + "image list".split(), [mock.Mock(option_strings=["2"])] + ) + sot.add_command( + "image create".split(), [mock.Mock(option_strings=["3"])] + ) + sot.add_command( + "volume type create".split(), [mock.Mock(option_strings=["4"])] + ) + sot.add_command( + "volume type delete".split(), [mock.Mock(option_strings=["5"])] + ) self.assertEqual("image volume", sot.get_commands()) result = sot.get_data() self.assertEqual("image", result[0][0]) @@ -48,12 +52,15 @@ class TestCompletion(base.TestBase): def test_complete_dictionary_subcmd(self): sot = complete.CompleteDictionary() - sot.add_command("image delete".split(), - [mock.Mock(option_strings=["1"])]) - sot.add_command("image list".split(), - [mock.Mock(option_strings=["2"])]) - sot.add_command("image list better".split(), - [mock.Mock(option_strings=["3"])]) + sot.add_command( + "image delete".split(), [mock.Mock(option_strings=["1"])] + ) + sot.add_command( + "image list".split(), [mock.Mock(option_strings=["2"])] + ) + sot.add_command( + "image list better".split(), [mock.Mock(option_strings=["3"])] + ) self.assertEqual("image", sot.get_commands()) result = sot.get_data() self.assertEqual("image", result[0][0]) @@ -81,14 +88,15 @@ class FakeStdout: class TestCompletionAlternatives(base.TestBase): - def given_cmdo_data(self): cmdo = "image server" - data = [("image", "create"), - ("image_create", "--eolus"), - ("server", "meta ssh"), - ("server_meta_delete", "--wilson"), - ("server_ssh", "--sunlight")] + data = [ + ("image", "create"), + ("image_create", "--eolus"), + ("server", "meta ssh"), + ("server_meta_delete", "--wilson"), + ("server_ssh", "--sunlight"), + ] return cmdo, data def then_data(self, content): @@ -117,12 +125,10 @@ class TestCompletionAlternatives(base.TestBase): sot = complete.CompleteCommand(mock.Mock(), mock.Mock()) parser = sot.get_parser('nothing') self.assertEqual("nothing", parser.prog) - self.assertEqual("print bash completion command\n ", - parser.description) + self.assertEqual("print bash completion command", parser.description) class TestCompletionAction(base.TestBase): - def given_complete_command(self): cmd_mgr = commandmanager.CommandManager('cliff.tests') app = application.App('testing', '1', cmd_mgr, stdout=FakeStdout()) @@ -131,8 +137,9 @@ class TestCompletionAction(base.TestBase): return sot, app, cmd_mgr def then_actions_equal(self, actions): - optstr = ' '.join(opt for action in actions - for opt in action.option_strings) + optstr = ' '.join( + opt for action in actions for opt in action.option_strings + ) self.assertEqual('-h --help --name --shell', optstr) def test_complete_command_get_actions(self): diff --git a/cliff/tests/test_formatters_csv.py b/cliff/tests/test_formatters_csv.py index c34a0e01..ccf12dcc 100644 --- a/cliff/tests/test_formatters_csv.py +++ b/cliff/tests/test_formatters_csv.py @@ -23,7 +23,6 @@ from cliff.tests import test_columns class TestCSVFormatter(unittest.TestCase): - def test_commaseparated_list_formatter(self): sf = commaseparated.CSVLister() c = ('a', 'b', 'c') diff --git a/cliff/tests/test_formatters_json.py b/cliff/tests/test_formatters_json.py index c57412ad..065f48c7 100644 --- a/cliff/tests/test_formatters_json.py +++ b/cliff/tests/test_formatters_json.py @@ -22,17 +22,11 @@ from cliff.tests import test_columns class TestJSONFormatter(base.TestBase): - def test_one(self): sf = json_format.JSONFormatter() c = ('a', 'b', 'c', 'd') d = ('A', 'B', 'C', '"escape me"') - expected = { - 'a': 'A', - 'b': 'B', - 'c': 'C', - 'd': '"escape me"' - } + expected = {'a': 'A', 'b': 'B', 'c': 'C', 'd': '"escape me"'} args = mock.Mock() sf.add_argument_group(args) @@ -78,15 +72,11 @@ class TestJSONFormatter(base.TestBase): def test_list(self): sf = json_format.JSONFormatter() c = ('a', 'b', 'c') - d = ( - ('A1', 'B1', 'C1'), - ('A2', 'B2', 'C2'), - ('A3', 'B3', 'C3') - ) + d = (('A1', 'B1', 'C1'), ('A2', 'B2', 'C2'), ('A3', 'B3', 'C3')) expected = [ {'a': 'A1', 'b': 'B1', 'c': 'C1'}, {'a': 'A2', 'b': 'B2', 'c': 'C2'}, - {'a': 'A3', 'b': 'B3', 'c': 'C3'} + {'a': 'A3', 'b': 'B3', 'c': 'C3'}, ] args = mock.Mock() sf.add_argument_group(args) @@ -110,9 +100,7 @@ class TestJSONFormatter(base.TestBase): def test_formattablecolumn_list(self): sf = json_format.JSONFormatter() c = ('a', 'b', 'c') - d = ( - ('A1', 'B1', test_columns.FauxColumn(['the', 'value'])), - ) + d = (('A1', 'B1', test_columns.FauxColumn(['the', 'value'])),) expected = [ {'a': 'A1', 'b': 'B1', 'c': ['the', 'value']}, ] diff --git a/cliff/tests/test_formatters_shell.py b/cliff/tests/test_formatters_shell.py index 896fe108..40e5f3d4 100644 --- a/cliff/tests/test_formatters_shell.py +++ b/cliff/tests/test_formatters_shell.py @@ -22,7 +22,6 @@ from cliff.tests import test_columns class TestShellFormatter(base.TestBase): - def test(self): sf = shell.ShellFormatter() c = ('a', 'b', 'c', 'd') @@ -54,11 +53,13 @@ class TestShellFormatter(base.TestBase): sf = shell.ShellFormatter() c = ('a', 'b', 'c') d = ('A', 'B', test_columns.FauxColumn(['the', 'value'])) - expected = '\n'.join([ - 'a="A"', - 'b="B"', - 'c="[\'the\', \'value\']"\n', - ]) + expected = '\n'.join( + [ + 'a="A"', + 'b="B"', + 'c="[\'the\', \'value\']"\n', + ] + ) output = io.StringIO() args = mock.Mock() args.variables = ['a', 'b', 'c'] @@ -71,8 +72,9 @@ class TestShellFormatter(base.TestBase): sf = shell.ShellFormatter() c = ('a', 'b', 'c', 'd', 'e') d = (True, False, 100, '"esc"', str('"esc"')) - expected = ('a="True"\nb="False"\nc="100"\n' - 'd="\\"esc\\""\ne="\\"esc\\""\n') + expected = ( + 'a="True"\nb="False"\nc="100"\n' 'd="\\"esc\\""\ne="\\"esc\\""\n' + ) output = io.StringIO() args = mock.Mock() args.variables = ['a', 'b', 'c', 'd', 'e'] diff --git a/cliff/tests/test_formatters_table.py b/cliff/tests/test_formatters_table.py index f890ea14..b7360c64 100644 --- a/cliff/tests/test_formatters_table.py +++ b/cliff/tests/test_formatters_table.py @@ -66,13 +66,13 @@ def _table_tester_helper(tags, data, extra_args=None): class TestTableFormatter(base.TestBase): - @mock.patch('cliff.utils.terminal_width') def test(self, tw): tw.return_value = 80 c = ('a', 'b', 'c', 'd') d = ('A', 'B', 'C', 'test\rcarriage\r\nreturn') - expected = textwrap.dedent('''\ + expected = textwrap.dedent( + '''\ +-------+---------------+ | Field | Value | +-------+---------------+ @@ -82,14 +82,15 @@ class TestTableFormatter(base.TestBase): | d | test carriage | | | return | +-------+---------------+ - ''') + ''' + ) self.assertEqual(expected, _table_tester_helper(c, d)) class TestTerminalWidth(base.TestBase): - # Multi-line output when width is restricted to 42 columns - expected_ml_val = textwrap.dedent('''\ + expected_ml_val = textwrap.dedent( + '''\ +-------+--------------------------------+ | Field | Value | +-------+--------------------------------+ @@ -100,10 +101,12 @@ class TestTerminalWidth(base.TestBase): | | dddddddddddddddddddddddddddddd | | | ddddddddddddddddd | +-------+--------------------------------+ - ''') + ''' + ) # Multi-line output when width is restricted to 80 columns - expected_ml_80_val = textwrap.dedent('''\ + expected_ml_80_val = textwrap.dedent( + '''\ +-------+----------------------------------------------------------------------+ | Field | Value | +-------+----------------------------------------------------------------------+ @@ -113,10 +116,12 @@ class TestTerminalWidth(base.TestBase): | d | dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd | | | ddddddddd | +-------+----------------------------------------------------------------------+ - ''') # noqa + ''' + ) # noqa # Single-line output, for when no line length restriction apply - expected_sl_val = textwrap.dedent('''\ + expected_sl_val = textwrap.dedent( + '''\ +-------+-------------------------------------------------------------------------------+ | Field | Value | +-------+-------------------------------------------------------------------------------+ @@ -125,7 +130,8 @@ class TestTerminalWidth(base.TestBase): | c | C | | d | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd | +-------+-------------------------------------------------------------------------------+ - ''') # noqa + ''' + ) # noqa @mock.patch('cliff.utils.terminal_width') def test_table_formatter_no_cli_param(self, tw): @@ -192,15 +198,16 @@ class TestTerminalWidth(base.TestBase): class TestMaxWidth(base.TestBase): - - expected_80 = textwrap.dedent('''\ + expected_80 = textwrap.dedent( + '''\ +--------------------------+---------------------------------------------+ | Field | Value | +--------------------------+---------------------------------------------+ | field_name | the value | | a_really_long_field_name | a value significantly longer than the field | +--------------------------+---------------------------------------------+ - ''') + ''' + ) @mock.patch('cliff.utils.terminal_width') def test_80(self, tw): @@ -215,7 +222,8 @@ class TestMaxWidth(base.TestBase): tw.return_value = 70 c = ('field_name', 'a_really_long_field_name') d = ('the value', 'a value significantly longer than the field') - expected = textwrap.dedent('''\ + expected = textwrap.dedent( + '''\ +--------------------------+-----------------------------------------+ | Field | Value | +--------------------------+-----------------------------------------+ @@ -223,7 +231,8 @@ class TestMaxWidth(base.TestBase): | a_really_long_field_name | a value significantly longer than the | | | field | +--------------------------+-----------------------------------------+ - ''') + ''' + ) self.assertEqual( expected, _table_tester_helper(c, d, extra_args=['--fit-width']), @@ -235,7 +244,8 @@ class TestMaxWidth(base.TestBase): tw.return_value = 50 c = ('field_name', 'a_really_long_field_name') d = ('the value', 'a value significantly longer than the field') - expected = textwrap.dedent('''\ + expected = textwrap.dedent( + '''\ +-----------------------+------------------------+ | Field | Value | +-----------------------+------------------------+ @@ -243,7 +253,8 @@ class TestMaxWidth(base.TestBase): | a_really_long_field_n | a value significantly | | ame | longer than the field | +-----------------------+------------------------+ - ''') + ''' + ) self.assertEqual( expected, _table_tester_helper(c, d, extra_args=['--fit-width']), @@ -255,7 +266,8 @@ class TestMaxWidth(base.TestBase): tw.return_value = 10 c = ('field_name', 'a_really_long_field_name') d = ('the value', 'a value significantly longer than the field') - expected = textwrap.dedent('''\ + expected = textwrap.dedent( + '''\ +------------------+------------------+ | Field | Value | +------------------+------------------+ @@ -265,7 +277,8 @@ class TestMaxWidth(base.TestBase): | | longer than the | | | field | +------------------+------------------+ - ''') + ''' + ) self.assertEqual( expected, _table_tester_helper(c, d, extra_args=['--fit-width']), @@ -273,50 +286,51 @@ class TestMaxWidth(base.TestBase): class TestListFormatter(base.TestBase): - _col_names = ('one', 'two', 'three') - _col_data = [( - 'one one one one one', - 'two two two two', - 'three three')] + _col_data = [('one one one one one', 'two two two two', 'three three')] _expected_mv = { - 80: textwrap.dedent('''\ + 80: textwrap.dedent( + '''\ +---------------------+-----------------+-------------+ | one | two | three | +---------------------+-----------------+-------------+ | one one one one one | two two two two | three three | +---------------------+-----------------+-------------+ - '''), - - 50: textwrap.dedent('''\ + ''' + ), + 50: textwrap.dedent( + '''\ +----------------+-----------------+-------------+ | one | two | three | +----------------+-----------------+-------------+ | one one one | two two two two | three three | | one one | | | +----------------+-----------------+-------------+ - '''), - - 47: textwrap.dedent('''\ + ''' + ), + 47: textwrap.dedent( + '''\ +---------------+---------------+-------------+ | one | two | three | +---------------+---------------+-------------+ | one one one | two two two | three three | | one one | two | | +---------------+---------------+-------------+ - '''), - - 45: textwrap.dedent('''\ + ''' + ), + 45: textwrap.dedent( + '''\ +--------------+--------------+-------------+ | one | two | three | +--------------+--------------+-------------+ | one one one | two two two | three three | | one one | two | | +--------------+--------------+-------------+ - '''), - - 40: textwrap.dedent('''\ + ''' + ), + 40: textwrap.dedent( + '''\ +------------+------------+------------+ | one | two | three | +------------+------------+------------+ @@ -324,9 +338,10 @@ class TestListFormatter(base.TestBase): | one one | two two | three | | one | | | +------------+------------+------------+ - '''), - - 10: textwrap.dedent('''\ + ''' + ), + 10: textwrap.dedent( + '''\ +----------+----------+----------+ | one | two | three | +----------+----------+----------+ @@ -334,7 +349,8 @@ class TestListFormatter(base.TestBase): | one one | two two | three | | one | | | +----------+----------+----------+ - '''), + ''' + ), } @mock.patch('cliff.utils.terminal_width') @@ -344,7 +360,8 @@ class TestListFormatter(base.TestBase): d1 = ('A', 'B', 'C') d2 = ('D', 'E', 'test\rcarriage\r\nreturn') data = [d1, d2] - expected = textwrap.dedent('''\ + expected = textwrap.dedent( + '''\ +---+---+---------------+ | a | b | c | +---+---+---------------+ @@ -352,7 +369,8 @@ class TestListFormatter(base.TestBase): | D | E | test carriage | | | | return | +---+---+---------------+ - ''') + ''' + ) self.assertEqual(expected, _table_tester_helper(c, data)) @mock.patch('cliff.utils.terminal_width') @@ -360,7 +378,8 @@ class TestListFormatter(base.TestBase): tw.return_value = 0 c = ('a', 'b', 'c', 'd') d = ('A', 'B', 'C', test_columns.FauxColumn(['the', 'value'])) - expected = textwrap.dedent('''\ + expected = textwrap.dedent( + '''\ +-------+---------------------------------------------+ | Field | Value | +-------+---------------------------------------------+ @@ -369,7 +388,8 @@ class TestListFormatter(base.TestBase): | c | C | | d | I made this string myself: ['the', 'value'] | +-------+---------------------------------------------+ - ''') + ''' + ) self.assertEqual(expected, _table_tester_helper(c, d)) @mock.patch('cliff.utils.terminal_width') @@ -378,13 +398,15 @@ class TestListFormatter(base.TestBase): c = ('a', 'b', 'c') d1 = ('A', 'B', test_columns.FauxColumn(['the', 'value'])) data = [d1] - expected = textwrap.dedent('''\ + expected = textwrap.dedent( + '''\ +---+---+---------------------------------------------+ | a | b | c | +---+---+---------------------------------------------+ | A | B | I made this string myself: ['the', 'value'] | +---+---+---------------------------------------------+ - ''') + ''' + ) self.assertEqual(expected, _table_tester_helper(c, data)) @mock.patch('cliff.utils.terminal_width') @@ -400,8 +422,9 @@ class TestListFormatter(base.TestBase): def test_max_width_50(self, tw): # resize 1 column width = tw.return_value = 50 - actual = _table_tester_helper(self._col_names, self._col_data, - extra_args=['--fit-width']) + actual = _table_tester_helper( + self._col_names, self._col_data, extra_args=['--fit-width'] + ) self.assertEqual(self._expected_mv[width], actual) self.assertEqual(width, len(actual.splitlines()[0])) @@ -409,8 +432,9 @@ class TestListFormatter(base.TestBase): def test_max_width_45(self, tw): # resize 2 columns width = tw.return_value = 45 - actual = _table_tester_helper(self._col_names, self._col_data, - extra_args=['--fit-width']) + actual = _table_tester_helper( + self._col_names, self._col_data, extra_args=['--fit-width'] + ) self.assertEqual(self._expected_mv[width], actual) self.assertEqual(width, len(actual.splitlines()[0])) @@ -418,8 +442,9 @@ class TestListFormatter(base.TestBase): def test_max_width_40(self, tw): # resize all columns width = tw.return_value = 40 - actual = _table_tester_helper(self._col_names, self._col_data, - extra_args=['--fit-width']) + actual = _table_tester_helper( + self._col_names, self._col_data, extra_args=['--fit-width'] + ) self.assertEqual(self._expected_mv[width], actual) self.assertEqual(width, len(actual.splitlines()[0])) @@ -427,8 +452,9 @@ class TestListFormatter(base.TestBase): def test_max_width_10(self, tw): # resize all columns limited by min_width=8 width = tw.return_value = 10 - actual = _table_tester_helper(self._col_names, self._col_data, - extra_args=['--fit-width']) + actual = _table_tester_helper( + self._col_names, self._col_data, extra_args=['--fit-width'] + ) self.assertEqual(self._expected_mv[width], actual) # 3 columns each 8 wide, plus table spacing and borders expected_width = 11 * 3 + 1 @@ -550,16 +576,18 @@ class TestListFormatter(base.TestBase): def test_env_maxwidth_args_big(self): self.assertEqual( self._expected_mv[80], - _table_tester_helper(self._col_names, self._col_data, - extra_args=args(666)), + _table_tester_helper( + self._col_names, self._col_data, extra_args=args(666) + ), ) @mock.patch.dict(os.environ, {'CLIFF_MAX_TERM_WIDTH': '42'}) def test_env_maxwidth_args_tiny(self): self.assertEqual( self._expected_mv[40], - _table_tester_helper(self._col_names, self._col_data, - extra_args=args(40)), + _table_tester_helper( + self._col_names, self._col_data, extra_args=args(40) + ), ) @mock.patch('cliff.utils.terminal_width') @@ -575,46 +603,35 @@ class TestListFormatter(base.TestBase): tw.return_value = 80 c = ('a', 'b', 'c') data = [] - expected = textwrap.dedent('''\ + expected = textwrap.dedent( + '''\ +---+---+---+ | a | b | c | +---+---+---+ +---+---+---+ - ''') + ''' + ) self.assertEqual( expected, - _table_tester_helper(c, data, - extra_args=['--print-empty']), + _table_tester_helper(c, data, extra_args=['--print-empty']), ) class TestFieldWidths(base.TestBase): - def test(self): tf = table.TableFormatter self.assertEqual( - { - 'a': 1, - 'b': 2, - 'c': 3, - 'd': 10 - }, + {'a': 1, 'b': 2, 'c': 3, 'd': 10}, tf._field_widths( - ('a', 'b', 'c', 'd'), - '+---+----+-----+------------+'), + ('a', 'b', 'c', 'd'), '+---+----+-----+------------+' + ), ) def test_zero(self): tf = table.TableFormatter self.assertEqual( - { - 'a': 0, - 'b': 0, - 'c': 0 - }, - tf._field_widths( - ('a', 'b', 'c'), - '+--+-++'), + {'a': 0, 'b': 0, 'c': 0}, + tf._field_widths(('a', 'b', 'c'), '+--+-++'), ) def test_info(self): diff --git a/cliff/tests/test_formatters_value.py b/cliff/tests/test_formatters_value.py index a0f23622..aa0cd50f 100644 --- a/cliff/tests/test_formatters_value.py +++ b/cliff/tests/test_formatters_value.py @@ -20,7 +20,6 @@ from cliff.tests import test_columns class TestValueFormatter(base.TestBase): - def test(self): sf = value.ValueFormatter() c = ('a', 'b', 'c', 'd') diff --git a/cliff/tests/test_formatters_yaml.py b/cliff/tests/test_formatters_yaml.py index 5d93fd27..5af088ae 100644 --- a/cliff/tests/test_formatters_yaml.py +++ b/cliff/tests/test_formatters_yaml.py @@ -23,7 +23,6 @@ from cliff.tests import test_columns class _toDict: - def __init__(self, **kwargs): self._data = kwargs @@ -40,17 +39,11 @@ class _to_Dict: class TestYAMLFormatter(base.TestBase): - def test_format_one(self): sf = yaml_format.YAMLFormatter() c = ('a', 'b', 'c', 'd') d = ('A', 'B', 'C', '"escape me"') - expected = { - 'a': 'A', - 'b': 'B', - 'c': 'C', - 'd': '"escape me"' - } + expected = {'a': 'A', 'b': 'B', 'c': 'C', 'd': '"escape me"'} output = StringIO() args = mock.Mock() sf.emit_one(c, d, output, args) @@ -81,15 +74,11 @@ class TestYAMLFormatter(base.TestBase): def test_list(self): sf = yaml_format.YAMLFormatter() c = ('a', 'b', 'c') - d = ( - ('A1', 'B1', 'C1'), - ('A2', 'B2', 'C2'), - ('A3', 'B3', 'C3') - ) + d = (('A1', 'B1', 'C1'), ('A2', 'B2', 'C2'), ('A3', 'B3', 'C3')) expected = [ {'a': 'A1', 'b': 'B1', 'c': 'C1'}, {'a': 'A2', 'b': 'B2', 'c': 'C2'}, - {'a': 'A3', 'b': 'B3', 'c': 'C3'} + {'a': 'A3', 'b': 'B3', 'c': 'C3'}, ] output = StringIO() args = mock.Mock() @@ -101,9 +90,7 @@ class TestYAMLFormatter(base.TestBase): def test_formattablecolumn_list(self): sf = yaml_format.YAMLFormatter() c = ('a', 'b', 'c') - d = ( - ('A1', 'B1', test_columns.FauxColumn(['the', 'value'])), - ) + d = (('A1', 'B1', test_columns.FauxColumn(['the', 'value'])),) expected = [ {'a': 'A1', 'b': 'B1', 'c': ['the', 'value']}, ] @@ -124,7 +111,7 @@ class TestYAMLFormatter(base.TestBase): 'a': 'A', 'b': 'B', 'toDict': {"spam": "ham"}, - 'to_dict': {"ham": "eggs"} + 'to_dict': {"ham": "eggs"}, } output = StringIO() args = mock.Mock() @@ -138,12 +125,12 @@ class TestYAMLFormatter(base.TestBase): d = ( ('A1', _toDict(B=1), _to_Dict(C=1)), ('A2', _toDict(B=2), _to_Dict(C=2)), - ('A3', _toDict(B=3), _to_Dict(C=3)) + ('A3', _toDict(B=3), _to_Dict(C=3)), ) expected = [ {'a': 'A1', 'toDict': {'B': 1}, 'to_dict': {'C': 1}}, {'a': 'A2', 'toDict': {'B': 2}, 'to_dict': {'C': 2}}, - {'a': 'A3', 'toDict': {'B': 3}, 'to_dict': {'C': 3}} + {'a': 'A3', 'toDict': {'B': 3}, 'to_dict': {'C': 3}}, ] output = StringIO() args = mock.Mock() diff --git a/cliff/tests/test_help.py b/cliff/tests/test_help.py index c9b0c8b0..0fa74e92 100644 --- a/cliff/tests/test_help.py +++ b/cliff/tests/test_help.py @@ -24,15 +24,17 @@ from cliff.tests import utils class TestHelp(base.TestBase): - def test_show_help_for_command(self): # FIXME(dhellmann): Are commands tied too closely to the app? Or # do commands know too much about apps by using them to get to the # command manager? stdout = io.StringIO() - app = application.App('testing', '1', - utils.TestCommandManager(utils.TEST_NAMESPACE), - stdout=stdout) + app = application.App( + 'testing', + '1', + utils.TestCommandManager(utils.TEST_NAMESPACE), + stdout=stdout, + ) app.NAME = 'test' help_cmd = help.HelpCommand(app, mock.Mock()) parser = help_cmd.get_parser('test') @@ -48,9 +50,12 @@ class TestHelp(base.TestBase): # do commands know too much about apps by using them to get to the # command manager? stdout = io.StringIO() - app = application.App('testing', '1', - utils.TestCommandManager(utils.TEST_NAMESPACE), - stdout=stdout) + app = application.App( + 'testing', + '1', + utils.TestCommandManager(utils.TEST_NAMESPACE), + stdout=stdout, + ) app.NAME = 'test' help_cmd = help.HelpCommand(app, mock.Mock()) parser = help_cmd.get_parser('test') @@ -68,9 +73,12 @@ class TestHelp(base.TestBase): # do commands know too much about apps by using them to get to the # command manager? stdout = io.StringIO() - app = application.App('testing', '1', - utils.TestCommandManager(utils.TEST_NAMESPACE), - stdout=stdout) + app = application.App( + 'testing', + '1', + utils.TestCommandManager(utils.TEST_NAMESPACE), + stdout=stdout, + ) app.NAME = 'test' help_cmd = help.HelpCommand(app, mock.Mock()) parser = help_cmd.get_parser('test') @@ -86,9 +94,12 @@ class TestHelp(base.TestBase): # do commands know too much about apps by using them to get to the # command manager? stdout = io.StringIO() - app = application.App('testing', '1', - utils.TestCommandManager(utils.TEST_NAMESPACE), - stdout=stdout) + app = application.App( + 'testing', + '1', + utils.TestCommandManager(utils.TEST_NAMESPACE), + stdout=stdout, + ) app.NAME = 'test' app.options = mock.Mock() help_cmd = help.HelpCommand(app, mock.Mock()) @@ -113,9 +124,12 @@ class TestHelp(base.TestBase): # do commands know too much about apps by using them to get to the # command manager? stdout = io.StringIO() - app = application.App('testing', '1', - utils.TestCommandManager(utils.TEST_NAMESPACE), - stdout=stdout) + app = application.App( + 'testing', + '1', + utils.TestCommandManager(utils.TEST_NAMESPACE), + stdout=stdout, + ) app.NAME = 'test' try: app.run(['--help']) @@ -126,13 +140,19 @@ class TestHelp(base.TestBase): self.assertIn('three word command', help_output) self.assertNotIn('old cmd', help_output) - @mock.patch.object(commandmanager.EntryPointWrapper, 'load', - side_effect=Exception('Could not load EntryPoint')) + @mock.patch.object( + commandmanager.EntryPointWrapper, + 'load', + side_effect=Exception('Could not load EntryPoint'), + ) def test_show_help_with_ep_load_fail(self, mock_load): stdout = io.StringIO() - app = application.App('testing', '1', - utils.TestCommandManager(utils.TEST_NAMESPACE), - stdout=stdout) + app = application.App( + 'testing', + '1', + utils.TestCommandManager(utils.TEST_NAMESPACE), + stdout=stdout, + ) app.NAME = 'test' app.options = mock.Mock() app.options.debug = False @@ -148,13 +168,19 @@ class TestHelp(base.TestBase): self.assertIn('Could not load', help_output) self.assertNotIn('Exception: Could not load EntryPoint', help_output) - @mock.patch.object(commandmanager.EntryPointWrapper, 'load', - side_effect=Exception('Could not load EntryPoint')) + @mock.patch.object( + commandmanager.EntryPointWrapper, + 'load', + side_effect=Exception('Could not load EntryPoint'), + ) def test_show_help_print_exc_with_ep_load_fail(self, mock_load): stdout = io.StringIO() - app = application.App('testing', '1', - utils.TestCommandManager(utils.TEST_NAMESPACE), - stdout=stdout) + app = application.App( + 'testing', + '1', + utils.TestCommandManager(utils.TEST_NAMESPACE), + stdout=stdout, + ) app.NAME = 'test' app.options = mock.Mock() app.options.debug = True diff --git a/cliff/tests/test_interactive.py b/cliff/tests/test_interactive.py index 041fffd6..75315940 100644 --- a/cliff/tests/test_interactive.py +++ b/cliff/tests/test_interactive.py @@ -23,16 +23,21 @@ class FakeApp(object): class TestInteractive(base.TestBase): - def make_interactive_app(self, errexit, *command_names): fake_command_manager = [(x, None) for x in command_names] - return InteractiveApp(FakeApp, fake_command_manager, - stdin=None, stdout=None, errexit=errexit) + return InteractiveApp( + FakeApp, + fake_command_manager, + stdin=None, + stdout=None, + errexit=errexit, + ) def _test_completenames(self, expecteds, prefix): app = self.make_interactive_app(False, 'hips', 'hippo', 'nonmatching') self.assertEqual( - set(app.completenames(prefix, '', 0, 1)), set(expecteds)) + set(app.completenames(prefix, '', 0, 1)), set(expecteds) + ) def test_cmd2_completenames(self): # cmd2.Cmd define do_help method @@ -56,8 +61,9 @@ class TestInteractive(base.TestBase): self._test_completenames(['history', 'hips', 'hippo'], 'hi') def _test_completedefault(self, expecteds, line, begidx): - command_names = set(['show file', 'show folder', 'show long', - 'list all']) + command_names = set( + ['show file', 'show folder', 'show long', 'list all'] + ) app = self.make_interactive_app(False, *command_names) observeds = app.completedefault(None, line, begidx, None) self.assertEqual(set(expecteds), set(observeds)) diff --git a/cliff/tests/test_lister.py b/cliff/tests/test_lister.py index 5dfa69a4..10bf081d 100644 --- a/cliff/tests/test_lister.py +++ b/cliff/tests/test_lister.py @@ -21,7 +21,6 @@ from cliff.tests import base class FauxFormatter(object): - def __init__(self): self.args = [] self.obj = weakref.proxy(self) @@ -31,7 +30,6 @@ class FauxFormatter(object): class ExerciseLister(lister.Lister): - data = [('a', 'A'), ('b', 'B'), ('c', 'A')] def _load_formatter_plugins(self): @@ -44,22 +42,18 @@ class ExerciseLister(lister.Lister): class ExerciseListerCustomSort(ExerciseLister): - need_sort_by_cliff = False class ExerciseListerNullValues(ExerciseLister): - data = ExerciseLister.data + [(None, None)] class ExerciseListerDifferentTypes(ExerciseLister): - data = ExerciseLister.data + [(1, 0)] class TestLister(base.TestBase): - def test_formatter_args(self): app = mock.Mock() test_lister = ExerciseLister(app, []) @@ -148,7 +142,8 @@ class TestLister(base.TestBase): args = f.args[0] data = list(args[1]) self.assertEqual( - [['a', 'A'], ['c', 'A'], ['b', 'B'], [None, None]], data) + [['a', 'A'], ['c', 'A'], ['b', 'B'], [None, None]], data + ) def test_sort_by_column_with_different_types(self): test_lister = ExerciseListerDifferentTypes(mock.Mock(), []) @@ -164,13 +159,16 @@ class TestLister(base.TestBase): args = f.args[0] data = list(args[1]) # The output should be unchanged - self.assertEqual( - [['a', 'A'], ['b', 'B'], ['c', 'A'], [1, 0]], data) + self.assertEqual([['a', 'A'], ['b', 'B'], ['c', 'A'], [1, 0]], data) # but we should have logged a warning - mock_log.warning.assert_has_calls([ - mock.call("Could not sort on field '%s'; unsortable types", col) - for col in parsed_args.sort_columns - ]) + mock_log.warning.assert_has_calls( + [ + mock.call( + "Could not sort on field '%s'; unsortable types", col + ) + for col in parsed_args.sort_columns + ] + ) def test_sort_by_non_displayed_column(self): test_lister = ExerciseLister(mock.Mock(), []) @@ -181,7 +179,8 @@ class TestLister(base.TestBase): with mock.patch.object(test_lister, 'take_action') as mock_take_action: mock_take_action.return_value = ( - ('Col1', 'Col2'), [['a', 'A'], ['b', 'B'], ['c', 'A']] + ('Col1', 'Col2'), + [['a', 'A'], ['b', 'B'], ['c', 'A']], ) test_lister.run(parsed_args) diff --git a/cliff/tests/test_show.py b/cliff/tests/test_show.py index 41e13b62..fe4eef45 100644 --- a/cliff/tests/test_show.py +++ b/cliff/tests/test_show.py @@ -21,7 +21,6 @@ from cliff.tests import base class FauxFormatter(object): - def __init__(self): self.args = [] self.obj = weakref.proxy(self) @@ -31,7 +30,6 @@ class FauxFormatter(object): class ExerciseShowOne(show.ShowOne): - def _load_formatter_plugins(self): return { 'test': FauxFormatter(), @@ -45,7 +43,6 @@ class ExerciseShowOne(show.ShowOne): class TestShow(base.TestBase): - def test_formatter_args(self): app = mock.Mock() test_show = ExerciseShowOne(app, []) diff --git a/cliff/tests/test_sphinxext.py b/cliff/tests/test_sphinxext.py index 852004c0..2f614bdb 100644 --- a/cliff/tests/test_sphinxext.py +++ b/cliff/tests/test_sphinxext.py @@ -20,7 +20,6 @@ from cliff.tests import base class TestSphinxExtension(base.TestBase): - def test_empty_help(self): """Handle positional and optional actions without help messages.""" parser = argparse.ArgumentParser(prog='hello-world', add_help=False) @@ -28,7 +27,9 @@ class TestSphinxExtension(base.TestBase): parser.add_argument('--language', dest='lang') output = '\n'.join(sphinxext._format_parser(parser)) - self.assertEqual(textwrap.dedent(""" + self.assertEqual( + textwrap.dedent( + """ .. program:: hello-world .. code-block:: shell @@ -37,17 +38,23 @@ class TestSphinxExtension(base.TestBase): .. option:: --language <LANG> .. option:: name - """).lstrip(), output) + """ + ).lstrip(), + output, + ) def test_nonempty_help(self): """Handle positional and optional actions with help messages.""" parser = argparse.ArgumentParser(prog='hello-world', add_help=False) parser.add_argument('name', help='user name') - parser.add_argument('--language', dest='lang', - help='greeting language') + parser.add_argument( + '--language', dest='lang', help='greeting language' + ) output = '\n'.join(sphinxext._format_parser(parser)) - self.assertEqual(textwrap.dedent(""" + self.assertEqual( + textwrap.dedent( + """ .. program:: hello-world .. code-block:: shell @@ -60,18 +67,26 @@ class TestSphinxExtension(base.TestBase): .. option:: name user name - """).lstrip(), output) + """ + ).lstrip(), + output, + ) def test_description_epilog(self): """Handle a parser description, epilog.""" - parser = argparse.ArgumentParser(prog='hello-world', add_help=False, - description='A "Hello, World" app.', - epilog='What am I doing down here?') + parser = argparse.ArgumentParser( + prog='hello-world', + add_help=False, + description='A "Hello, World" app.', + epilog='What am I doing down here?', + ) parser.add_argument('name', action='store') parser.add_argument('--language', dest='lang') output = '\n'.join(sphinxext._format_parser(parser)) - self.assertEqual(textwrap.dedent(""" + self.assertEqual( + textwrap.dedent( + """ A "Hello, World" app. .. program:: hello-world @@ -84,17 +99,25 @@ class TestSphinxExtension(base.TestBase): .. option:: name What am I doing down here? - """).lstrip(), output) + """ + ).lstrip(), + output, + ) def test_flag(self): """Handle a boolean argparse action.""" parser = argparse.ArgumentParser(prog='hello-world', add_help=False) parser.add_argument('name', help='user name') - parser.add_argument('--translate', action='store_true', - help='translate to local language') + parser.add_argument( + '--translate', + action='store_true', + help='translate to local language', + ) output = '\n'.join(sphinxext._format_parser(parser)) - self.assertEqual(textwrap.dedent(""" + self.assertEqual( + textwrap.dedent( + """ .. program:: hello-world .. code-block:: shell @@ -107,7 +130,10 @@ class TestSphinxExtension(base.TestBase): .. option:: name user name - """).lstrip(), output) + """ + ).lstrip(), + output, + ) def test_supressed(self): """Handle a supressed action.""" @@ -116,7 +142,9 @@ class TestSphinxExtension(base.TestBase): parser.add_argument('--variable', help=argparse.SUPPRESS) output = '\n'.join(sphinxext._format_parser(parser)) - self.assertEqual(textwrap.dedent(""" + self.assertEqual( + textwrap.dedent( + """ .. program:: hello-world .. code-block:: shell @@ -126,16 +154,22 @@ class TestSphinxExtension(base.TestBase): .. option:: name user name - """).lstrip(), output) + """ + ).lstrip(), + output, + ) def test_metavar(self): """Handle an option with a metavar.""" parser = argparse.ArgumentParser(prog='hello-world', add_help=False) - parser.add_argument('names', metavar='<NAME>', nargs='+', - help='a user name') + parser.add_argument( + 'names', metavar='<NAME>', nargs='+', help='a user name' + ) output = '\n'.join(sphinxext._format_parser(parser)) - self.assertEqual(textwrap.dedent(""" + self.assertEqual( + textwrap.dedent( + """ .. program:: hello-world .. code-block:: shell @@ -144,29 +178,46 @@ class TestSphinxExtension(base.TestBase): .. option:: NAME a user name - """).lstrip(), output) + """ + ).lstrip(), + output, + ) def test_multiple_opts(self): """Correctly output multiple opts on separate lines.""" parser = argparse.ArgumentParser(prog='hello-world', add_help=False) parser.add_argument('name', help='user name') - parser.add_argument('--language', dest='lang', - help='greeting language') - parser.add_argument('--translate', action='store_true', - help='translate to local language') - parser.add_argument('--write-to-var-log-something-or-other', - action='store_true', - help='a long opt to force wrapping') - parser.add_argument('--required-arg', dest='stuff', required=True, - help='a required argument') + parser.add_argument( + '--language', dest='lang', help='greeting language' + ) + parser.add_argument( + '--translate', + action='store_true', + help='translate to local language', + ) + parser.add_argument( + '--write-to-var-log-something-or-other', + action='store_true', + help='a long opt to force wrapping', + ) + parser.add_argument( + '--required-arg', + dest='stuff', + required=True, + help='a required argument', + ) style_group = parser.add_mutually_exclusive_group(required=True) - style_group.add_argument('--polite', action='store_true', - help='use a polite greeting') - style_group.add_argument('--profane', action='store_true', - help='use a less polite greeting') + style_group.add_argument( + '--polite', action='store_true', help='use a polite greeting' + ) + style_group.add_argument( + '--profane', action='store_true', help='use a less polite greeting' + ) output = '\n'.join(sphinxext._format_parser(parser)) - self.assertEqual(textwrap.dedent(""" + self.assertEqual( + textwrap.dedent( + """ .. program:: hello-world .. code-block:: shell @@ -205,26 +256,36 @@ class TestSphinxExtension(base.TestBase): .. option:: name user name - """).lstrip(), output) + """ + ).lstrip(), + output, + ) def test_various_option_names_with_hyphen(self): """Handle options whose name and/or metavar contain hyphen(s)""" parser = argparse.ArgumentParser(prog='hello-world', add_help=False) - parser.add_argument('--foo-bar', metavar='<foo-bar>', - help='foo bar', required=True) - parser.add_argument('--foo-bar-baz', metavar='<foo-bar-baz>', - help='foo bar baz', required=True) - parser.add_argument('--foo', metavar='<foo>', - help='foo', required=True) - parser.add_argument('--alpha', metavar='<A>', - help='alpha') - parser.add_argument('--alpha-beta', metavar='<A-B>', - help='alpha beta') - parser.add_argument('--alpha-beta-gamma', metavar='<A-B-C>', - help='alpha beta gamma') + parser.add_argument( + '--foo-bar', metavar='<foo-bar>', help='foo bar', required=True + ) + parser.add_argument( + '--foo-bar-baz', + metavar='<foo-bar-baz>', + help='foo bar baz', + required=True, + ) + parser.add_argument( + '--foo', metavar='<foo>', help='foo', required=True + ) + parser.add_argument('--alpha', metavar='<A>', help='alpha') + parser.add_argument('--alpha-beta', metavar='<A-B>', help='alpha beta') + parser.add_argument( + '--alpha-beta-gamma', metavar='<A-B-C>', help='alpha beta gamma' + ) output = '\n'.join(sphinxext._format_parser(parser)) - self.assertEqual(textwrap.dedent(""" + self.assertEqual( + textwrap.dedent( + """ .. program:: hello-world .. code-block:: shell @@ -259,4 +320,7 @@ class TestSphinxExtension(base.TestBase): .. option:: --alpha-beta-gamma <A-B-C> alpha beta gamma - """).lstrip(), output) + """ + ).lstrip(), + output, + ) diff --git a/cliff/tests/test_utils.py b/cliff/tests/test_utils.py index 7650d78d..92bced8c 100644 --- a/cliff/tests/test_utils.py +++ b/cliff/tests/test_utils.py @@ -20,7 +20,6 @@ from cliff import utils class TestTerminalWidth(base.TestBase): - def test(self): width = utils.terminal_width() # Results are specific to the execution environment, so only assert diff --git a/cliff/tests/utils.py b/cliff/tests/utils.py index b9cdba35..b9cf8d33 100644 --- a/cliff/tests/utils.py +++ b/cliff/tests/utils.py @@ -17,7 +17,6 @@ TEST_NAMESPACE = 'cliff.test' class TestParser(object): - def print_help(self, stdout): stdout.write('TestParser') @@ -35,12 +34,10 @@ class TestCommand(Command): class TestDeprecatedCommand(TestCommand): - deprecated = True class TestCommandManager(CommandManager): - def load_commands(self, namespace): if namespace == TEST_NAMESPACE: for key in ('one', 'two words', 'three word command'): diff --git a/cliff/utils.py b/cliff/utils.py index 1a559e32..3874bdb8 100644 --- a/cliff/utils.py +++ b/cliff/utils.py @@ -59,7 +59,6 @@ def damerau_levenshtein(s1, s2, cost): row2[0] = (i + 1) * cost['d'] for j in range(len2): - # substitution sub_cost = row1[j] + (s1[i] != s2[j]) * cost['s'] @@ -70,11 +69,12 @@ def damerau_levenshtein(s1, s2, cost): del_cost = row1[j + 1] + cost['d'] # swap - swp_condition = ((i > 0) and - (j > 0) and - (s1[i - 1] == s2[j]) and - (s1[i] == s2[j - 1]) - ) + swp_condition = ( + (i > 0) + and (j > 0) + and (s1[i - 1] == s2[j]) + and (s1[i] == s2[j - 1]) + ) # min cost if swp_condition: diff --git a/demoapp/cliffdemo/encoding.py b/demoapp/cliffdemo/encoding.py index 4aac5781..99f4b2be 100644 --- a/demoapp/cliffdemo/encoding.py +++ b/demoapp/cliffdemo/encoding.py @@ -6,8 +6,7 @@ from cliff.lister import Lister class Encoding(Lister): - """Show some unicode text - """ + """Show some unicode text""" log = logging.getLogger(__name__) @@ -18,6 +17,5 @@ class Encoding(Lister): ] return ( ('UTF-8', 'Unicode'), - [(repr(t.encode('utf-8')), t) - for t in messages], + [(repr(t.encode('utf-8')), t) for t in messages], ) diff --git a/demoapp/cliffdemo/list.py b/demoapp/cliffdemo/list.py index 3dcee4ab..5481bfb9 100644 --- a/demoapp/cliffdemo/list.py +++ b/demoapp/cliffdemo/list.py @@ -13,6 +13,7 @@ class Files(Lister): log = logging.getLogger(__name__) def take_action(self, parsed_args): - return (('Name', 'Size'), - ((n, os.stat(n).st_size) for n in os.listdir('.')) - ) + return ( + ('Name', 'Size'), + ((n, os.stat(n).st_size) for n in os.listdir('.')), + ) diff --git a/demoapp/cliffdemo/main.py b/demoapp/cliffdemo/main.py index ca5ce228..71b6445d 100644 --- a/demoapp/cliffdemo/main.py +++ b/demoapp/cliffdemo/main.py @@ -5,14 +5,13 @@ from cliff.commandmanager import CommandManager class DemoApp(App): - def __init__(self): super(DemoApp, self).__init__( description='cliff demo app', version='0.1', command_manager=CommandManager('cliff.demo'), deferred_help=True, - ) + ) def initialize_app(self, argv): self.LOG.debug('initialize_app') diff --git a/demoapp/cliffdemo/show.py b/demoapp/cliffdemo/show.py index 9351148c..115b43ab 100644 --- a/demoapp/cliffdemo/show.py +++ b/demoapp/cliffdemo/show.py @@ -16,16 +16,18 @@ class File(ShowOne): def take_action(self, parsed_args): stat_data = os.stat(parsed_args.filename) - columns = ('Name', - 'Size', - 'UID', - 'GID', - 'Modified Time', - ) - data = (parsed_args.filename, - stat_data.st_size, - stat_data.st_uid, - stat_data.st_gid, - stat_data.st_mtime, - ) + columns = ( + 'Name', + 'Size', + 'UID', + 'GID', + 'Modified Time', + ) + data = ( + parsed_args.filename, + stat_data.st_size, + stat_data.st_uid, + stat_data.st_gid, + stat_data.st_mtime, + ) return (columns, data) diff --git a/demoapp/setup.py b/demoapp/setup.py index 5fbd3466..21477ef3 100644 --- a/demoapp/setup.py +++ b/demoapp/setup.py @@ -16,16 +16,12 @@ except IOError: setup( name=PROJECT, version=VERSION, - description='Demo app for cliff', long_description=long_description, - author='Doug Hellmann', author_email='doug.hellmann@gmail.com', - url='https://github.com/openstack/cliff', download_url='https://github.com/openstack/cliff/tarball/master', - classifiers=[ 'Development Status :: 3 - Alpha', 'License :: OSI Approved :: Apache Software License', @@ -35,22 +31,15 @@ setup( 'Intended Audience :: Developers', 'Environment :: Console', ], - platforms=['Any'], - scripts=[], - provides=[], install_requires=['cliff'], - namespace_packages=[], packages=find_packages(), include_package_data=True, - entry_points={ - 'console_scripts': [ - 'cliffdemo = cliffdemo.main:main' - ], + 'console_scripts': ['cliffdemo = cliffdemo.main:main'], 'cliff.demo': [ 'simple = cliffdemo.simple:Simple', 'two_part = cliffdemo.simple:Simple', @@ -66,6 +55,5 @@ setup( 'sample-hook = cliffdemo.hook:Hook', ], }, - zip_safe=False, ) diff --git a/doc/source/conf.py b/doc/source/conf.py index acc977ce..08d7fa1c 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -197,10 +197,8 @@ htmlhelp_basename = 'cliffdoc' latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # 'preamble': '', } @@ -209,8 +207,7 @@ latex_elements = { # (source start file, target name, title, author, # documentclass [howto/manual]). latex_documents = [ - ('index', 'cliff.tex', 'cliff Documentation', - 'Doug Hellmann', 'manual'), + ('index', 'cliff.tex', 'cliff Documentation', 'Doug Hellmann', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -238,10 +235,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'cliff', 'cliff Documentation', - ['Doug Hellmann'], 1) -] +man_pages = [('index', 'cliff', 'cliff Documentation', ['Doug Hellmann'], 1)] # If true, show URL addresses after external links. # man_show_urls = False @@ -253,9 +247,15 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'cliff', 'cliff Documentation', - 'Doug Hellmann', 'cliff', 'One line description of project.', - 'Miscellaneous'), + ( + 'index', + 'cliff', + 'cliff Documentation', + 'Doug Hellmann', + 'cliff', + 'One line description of project.', + 'Miscellaneous', + ), ] # Documents to append as an appendix to all manuals. diff --git a/setup.cfg b/setup.cfg index fd9411d4..501e22f0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -57,4 +57,3 @@ cliff.demo = hooked = cliffdemo.hook:Hooked cliff.demo.hooked = sample-hook = cliffdemo.hook:Hook - diff --git a/setup.py b/setup.py index 77fd783f..886386ef 100644 --- a/setup.py +++ b/setup.py @@ -13,10 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools setuptools.setup( setup_requires=['pbr>=2.0.0'], install_requires=['setuptools'], - pbr=True) + pbr=True, +) diff --git a/tox.ini b/tox.ini index 7b67fc11..7d534a9b 100644 --- a/tox.ini +++ b/tox.ini @@ -59,3 +59,15 @@ commands = coverage combine coverage html -d cover coverage xml -o cover/coverage.xml + +[flake8] +application-import-names = cliff +# E203 Black will put spaces after colons in list comprehensions +# E501 Black takes care of line length for us +# W503 Is supposed to be off by default but in the latest pycodestyle isn't. +# Also, both openstacksdk and Donald Knuth disagree with the rule. Line +# breaks should occur before the binary operator for readability. +ignore = E203, E501, W503 +import-order-style = pep8 +show-source = true +exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build