From e2cc2530fc6d54ebc975c01a4ff887ce12f0a736 Mon Sep 17 00:00:00 2001 From: Pavel Aharoni Date: Wed, 29 Mar 2017 13:35:45 +0300 Subject: [SDC-6] sdc-distribution-client 1707 rebasing Change-Id: I322a05fd79beb6ba4fee4d32afffecf531b86e98 Signed-off-by: Pavel Aharoni --- .../cliff-2.4.0-py2.7.egg/cliff/app.py | 423 +++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 jython-tosca-parser/src/main/resources/Lib/site-packages/cliff-2.4.0-py2.7.egg/cliff/app.py (limited to 'jython-tosca-parser/src/main/resources/Lib/site-packages/cliff-2.4.0-py2.7.egg/cliff/app.py') diff --git a/jython-tosca-parser/src/main/resources/Lib/site-packages/cliff-2.4.0-py2.7.egg/cliff/app.py b/jython-tosca-parser/src/main/resources/Lib/site-packages/cliff-2.4.0-py2.7.egg/cliff/app.py new file mode 100644 index 0000000..2c2f219 --- /dev/null +++ b/jython-tosca-parser/src/main/resources/Lib/site-packages/cliff-2.4.0-py2.7.egg/cliff/app.py @@ -0,0 +1,423 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Application base class. +""" + +import codecs +import inspect +import locale +import logging +import logging.handlers +import os +import six +import sys + +from cliff import argparse +from . import complete +from . import help +from . import utils + + +logging.getLogger('cliff').addHandler(logging.NullHandler()) + + +class App(object): + """Application base class. + + :param description: one-liner explaining the program purpose + :paramtype description: str + :param version: application version number + :paramtype version: str + :param command_manager: plugin loader + :paramtype command_manager: cliff.commandmanager.CommandManager + :param stdin: Standard input stream + :paramtype stdin: readable I/O stream + :param stdout: Standard output stream + :paramtype stdout: writable I/O stream + :param stderr: Standard error output stream + :paramtype stderr: writable I/O stream + :param interactive_app_factory: callable to create an + interactive application + :paramtype interactive_app_factory: cliff.interactive.InteractiveApp + :param deferred_help: True - Allow subcommands to accept --help with + allowing to defer help print after initialize_app + :paramtype deferred_help: bool + """ + + NAME = os.path.splitext(os.path.basename(sys.argv[0]))[0] + LOG = logging.getLogger(NAME) + + CONSOLE_MESSAGE_FORMAT = '%(message)s' + 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. + """ + self.command_manager = command_manager + self.command_manager.add_command('help', help.HelpCommand) + self.command_manager.add_command('complete', complete.CompleteCommand) + self._set_streams(stdin, stdout, stderr) + self.interactive_app_factory = interactive_app_factory + self.deferred_help = deferred_help + self.parser = self.build_option_parser(description, version) + self.interactive_mode = False + self.interpreter = None + + def _set_streams(self, stdin, stdout, stderr): + try: + locale.setlocale(locale.LC_ALL, '') + except locale.Error: + pass + + # Unicode must be encoded/decoded for text I/O streams, the + # correct encoding for the stream must be selected and it must + # be capable of handling the set of characters in the stream + # or Python will raise a codec error. The correct codec is + # selected based on the locale. Python2 uses the locales + # encoding but only when the I/O stream is attached to a + # terminal (TTY) otherwise it uses the default ASCII + # encoding. The effect is internationalized text written to + # the terminal works as expected but if command line output is + # redirected (file or pipe) the ASCII codec is used and the + # program aborts with a codec error. + # + # The default I/O streams stdin, stdout and stderr can be + # wrapped in a codec based on the locale thus assuring the + # users desired encoding is always used no matter the I/O + # destination. Python3 does this by default. + # + # If the caller supplies an I/O stream we use it unmodified on + # the assumption the caller has taken all responsibility for + # the stream. But with Python2 if the caller allows us to + # default the I/O streams to sys.stdin, sys.stdout and + # sys.stderr we apply the locales encoding just as Python3 + # would do. We also check to make sure the main Python program + # has not already already wrapped sys.stdin, sys.stdout and + # sys.stderr as this is a common recommendation. + + if six.PY2: + encoding = locale.getpreferredencoding() + if encoding: + if not (stdin or isinstance(sys.stdin, codecs.StreamReader)): + stdin = codecs.getreader(encoding)(sys.stdin) + + if not (stdout or isinstance(sys.stdout, codecs.StreamWriter)): + stdout = codecs.getwriter(encoding)(sys.stdout) + + if not (stderr or isinstance(sys.stderr, codecs.StreamWriter)): + stderr = codecs.getwriter(encoding)(sys.stderr) + + self.stdin = stdin or sys.stdin + self.stdout = stdout or sys.stdout + self.stderr = stderr or sys.stderr + + 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 + the parser with more global options. + + :param description: full description of the application + :paramtype description: str + :param version: version number for the application + :paramtype version: str + :param argparse_kwargs: extra keyword argument passed to the + ArgumentParser constructor + :paramtype extra_kwargs: dict + """ + argparse_kwargs = argparse_kwargs or {} + parser = argparse.ArgumentParser( + description=description, + add_help=False, + **argparse_kwargs + ) + parser.add_argument( + '--version', + action='version', + version='%(prog)s {0}'.format(version), + ) + verbose_group = parser.add_mutually_exclusive_group() + verbose_group.add_argument( + '-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', + action='store_const', + dest='verbose_level', + const=0, + help='Suppress output except warnings and errors.', + ) + parser.add_argument( + '--log-file', + action='store', + default=None, + help='Specify a file to log output. Disabled by default.', + ) + if self.deferred_help: + parser.add_argument( + '-h', '--help', + dest='deferred_help', + action='store_true', + help="Show help message and exit.", + ) + else: + parser.add_argument( + '-h', '--help', + action=help.HelpAction, + nargs=0, + default=self, # tricky + help="Show help message and exit.", + ) + parser.add_argument( + '--debug', + default=False, + action='store_true', + help='Show tracebacks on errors.', + ) + return parser + + def configure_logging(self): + """Create logging handlers for any log output. + """ + root_logger = logging.getLogger('') + root_logger.setLevel(logging.DEBUG) + + # Set up logging to a file + if self.options.log_file: + file_handler = logging.FileHandler( + filename=self.options.log_file, + ) + formatter = logging.Formatter(self.LOG_FILE_MESSAGE_FORMAT) + file_handler.setFormatter(formatter) + root_logger.addHandler(file_handler) + + # 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.setLevel(console_level) + formatter = logging.Formatter(self.CONSOLE_MESSAGE_FORMAT) + console.setFormatter(formatter) + root_logger.addHandler(console) + return + + def print_help_if_requested(self): + """Print help and exits if deferred help is enabled and requested. + + '--help' shows the help message and exits: + * without calling initialize_app if not self.deferred_help (default), + * after initialize_app call if self.deferred_help, + * during initialize_app call if self.deferred_help and subclass calls + explicitly this method in initialize_app. + """ + if self.deferred_help and self.options.deferred_help: + action = help.HelpAction(None, None, default=self) + action(self.parser, self.options, None, None) + + def run(self, argv): + """Equivalent to the main program for the application. + + :param argv: input arguments and options + :paramtype argv: list of str + """ + try: + self.options, remainder = self.parser.parse_known_args(argv) + self.configure_logging() + self.interactive_mode = not remainder + if self.deferred_help and self.options.deferred_help and remainder: + # When help is requested and `remainder` has any values disable + # `deferred_help` and instead allow the help subcommand to + # handle the request during run_subcommand(). This turns + # "app foo bar --help" into "app help foo bar". However, when + # `remainder` is empty use print_help_if_requested() to allow + # for an early exit. + # Disabling `deferred_help` here also ensures that + # print_help_if_requested will not fire if called by a subclass + # during its initialize_app(). + self.options.deferred_help = False + remainder.insert(0, "help") + self.initialize_app(remainder) + self.print_help_if_requested() + except Exception as err: + if hasattr(self, 'options'): + debug = self.options.debug + else: + debug = True + if debug: + self.LOG.exception(err) + raise + else: + self.LOG.error(err) + return 1 + result = 1 + if self.interactive_mode: + result = self.interact() + else: + result = self.run_subcommand(remainder) + return result + + # FIXME(dhellmann): Consider moving these command handling methods + # to a separate class. + def initialize_app(self, argv): + """Hook for subclasses to take global initialization action + after the arguments are parsed but before a command is run. + Invoked only once, even in interactive mode. + + :param argv: List of arguments, including the subcommand to run. + Empty for interactive mode. + """ + return + + def prepare_to_run_command(self, cmd): + """Perform any preliminary work needed to run a command. + + :param cmd: command processor being invoked + :paramtype cmd: cliff.command.Command + """ + return + + def clean_up(self, cmd, result, err): + """Hook run after a command is done to shutdown the app. + + :param cmd: command processor being invoked + :paramtype cmd: cliff.command.Command + :param result: return value of cmd + :paramtype result: int + :param err: exception or None + :paramtype err: Exception + """ + return + + def interact(self): + # Defer importing .interactive as cmd2 is a slow import + from .interactive import InteractiveApp + + 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.cmdloop() + return 0 + + def get_fuzzy_matches(self, cmd): + """return fuzzy matches of unknown command + """ + + sep = '_' + if self.command_manager.convert_underscores: + sep = ' ' + all_cmds = [k[0] for k in self.command_manager] + dist = [] + for candidate in sorted(all_cmds): + prefix = candidate.split(sep)[0] + # Give prefix match a very good score + if candidate.startswith(cmd): + dist.append((0, candidate)) + continue + # Levenshtein distance + dist.append((utils.damerau_levenshtein(cmd, prefix, utils.COST)+1, + candidate)) + + matches = [] + match_distance = 0 + for distance, candidate in sorted(dist): + if distance > match_distance: + if match_distance: + # we copied all items with minimum distance, we are done + break + # we copied all items with distance=0, + # now we match all candidates at the minimum distance + match_distance = distance + matches.append(candidate) + + return matches + + def run_subcommand(self, argv): + try: + subcommand = self.command_manager.find_command(argv) + except ValueError as err: + # If there was no exact match, try to find a fuzzy match + the_cmd = argv[0] + fuzzy_matches = self.get_fuzzy_matches(the_cmd) + if fuzzy_matches: + 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('Did you mean one of these?\n') + for match in fuzzy_matches: + self.stdout.write(' %s\n' % match) + else: + if self.options.debug: + raise + else: + self.LOG.error(err) + return 2 + cmd_factory, cmd_name, sub_argv = subcommand + kwargs = {} + if 'cmd_name' in inspect.getargspec(cmd_factory.__init__).args: + kwargs['cmd_name'] = cmd_name + cmd = cmd_factory(self, self.options, **kwargs) + err = None + result = 1 + try: + self.prepare_to_run_command(cmd) + full_name = (cmd_name + if self.interactive_mode + else ' '.join([self.NAME, cmd_name]) + ) + cmd_parser = cmd.get_parser(full_name) + parsed_args = cmd_parser.parse_args(sub_argv) + result = cmd.run(parsed_args) + except Exception as err: + if self.options.debug: + self.LOG.exception(err) + else: + self.LOG.error(err) + try: + self.clean_up(cmd, result, err) + except Exception as err2: + if self.options.debug: + self.LOG.exception(err2) + else: + self.LOG.error('Could not clean up: %s', err2) + if self.options.debug: + raise + else: + try: + self.clean_up(cmd, result, None) + except Exception as err3: + if self.options.debug: + self.LOG.exception(err3) + else: + self.LOG.error('Could not clean up: %s', err3) + return result -- cgit 1.2.3-korg