summaryrefslogtreecommitdiffstats
path: root/debuginfo-tests/dexter/dex/utils/ExtArgParse.py
diff options
context:
space:
mode:
authorJeremy Morse <jeremy.morse@sony.com>2019-10-31 13:41:24 +0000
committerJeremy Morse <jeremy.morse@sony.com>2019-10-31 13:49:47 +0000
commitf78c236efda85af1e526ac35ed535ef4786450e3 (patch)
tree1ff1609178e085f58b46dfcbce21fd6b2ef40025 /debuginfo-tests/dexter/dex/utils/ExtArgParse.py
parentefacf2ce55d698e5df8173f0d4dacbc7d3c7fd34 (diff)
downloadbcm5719-llvm-f78c236efda85af1e526ac35ed535ef4786450e3.tar.gz
bcm5719-llvm-f78c236efda85af1e526ac35ed535ef4786450e3.zip
Import Dexter to debuginfo-tests
Dexter (Debug Experience Tester) is a test-driver for our debug info integration tests, reading a set of debug experience expectations and comparing them with the actual behaviour of a program under a debugger. More about Dexter can be found in the RFC: http://lists.llvm.org/pipermail/llvm-dev/2019-October/135773.html and the phab review in D68708. Not all the debuginfo tests have been transformed into Dexter tests, and we look forwards to doing that incrementally. This commit mostly aims to flush out buildbots that are running debuginfo-tests but don't have python 3 installed, possibly green-dragon and some windows bots.
Diffstat (limited to 'debuginfo-tests/dexter/dex/utils/ExtArgParse.py')
-rw-r--r--debuginfo-tests/dexter/dex/utils/ExtArgParse.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/debuginfo-tests/dexter/dex/utils/ExtArgParse.py b/debuginfo-tests/dexter/dex/utils/ExtArgParse.py
new file mode 100644
index 00000000000..9fa08fb066e
--- /dev/null
+++ b/debuginfo-tests/dexter/dex/utils/ExtArgParse.py
@@ -0,0 +1,148 @@
+# DExTer : Debugging Experience Tester
+# ~~~~~~ ~ ~~ ~ ~~
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+"""Extended Argument Parser. Extends the argparse module with some extra
+functionality, to hopefully aid user-friendliness.
+"""
+
+import argparse
+import difflib
+import unittest
+
+from dex.utils import PrettyOutput
+from dex.utils.Exceptions import Error
+
+# re-export all of argparse
+for argitem in argparse.__all__:
+ vars()[argitem] = getattr(argparse, argitem)
+
+
+def _did_you_mean(val, possibles):
+ close_matches = difflib.get_close_matches(val, possibles)
+ did_you_mean = ''
+ if close_matches:
+ did_you_mean = 'did you mean {}?'.format(' or '.join(
+ "<y>'{}'</>".format(c) for c in close_matches[:2]))
+ return did_you_mean
+
+
+def _colorize(message):
+ lines = message.splitlines()
+ for i, line in enumerate(lines):
+ lines[i] = lines[i].replace('usage:', '<g>usage:</>')
+ if line.endswith(':'):
+ lines[i] = '<g>{}</>'.format(line)
+ return '\n'.join(lines)
+
+
+class ExtArgumentParser(argparse.ArgumentParser):
+ def error(self, message):
+ """Use the Dexception Error mechanism (including auto-colored output).
+ """
+ raise Error('{}\n\n{}'.format(message, self.format_usage()))
+
+ # pylint: disable=redefined-builtin
+ def _print_message(self, message, file=None):
+ if message:
+ if file and file.name == '<stdout>':
+ file = PrettyOutput.stdout
+ else:
+ file = PrettyOutput.stderr
+
+ self.context.o.auto(message, file)
+
+ # pylint: enable=redefined-builtin
+
+ def format_usage(self):
+ return _colorize(super(ExtArgumentParser, self).format_usage())
+
+ def format_help(self):
+ return _colorize(super(ExtArgumentParser, self).format_help() + '\n\n')
+
+ @property
+ def _valid_visible_options(self):
+ """A list of all non-suppressed command line flags."""
+ return [
+ item for sublist in vars(self)['_actions']
+ for item in sublist.option_strings
+ if sublist.help != argparse.SUPPRESS
+ ]
+
+ def parse_args(self, args=None, namespace=None):
+ """Add 'did you mean' output to errors."""
+ args, argv = self.parse_known_args(args, namespace)
+ if argv:
+ errors = []
+ for arg in argv:
+ if arg in self._valid_visible_options:
+ error = "unexpected argument: <y>'{}'</>".format(arg)
+ else:
+ error = "unrecognized argument: <y>'{}'</>".format(arg)
+ dym = _did_you_mean(arg, self._valid_visible_options)
+ if dym:
+ error += ' ({})'.format(dym)
+ errors.append(error)
+ self.error('\n '.join(errors))
+
+ return args
+
+ def add_argument(self, *args, **kwargs):
+ """Automatically add the default value to help text."""
+ if 'default' in kwargs:
+ default = kwargs['default']
+ if default is None:
+ default = kwargs.pop('display_default', None)
+
+ if (default and isinstance(default, (str, int, float))
+ and default != argparse.SUPPRESS):
+ assert (
+ 'choices' not in kwargs or default in kwargs['choices']), (
+ "default value '{}' is not one of allowed choices: {}".
+ format(default, kwargs['choices']))
+ if 'help' in kwargs and kwargs['help'] != argparse.SUPPRESS:
+ assert isinstance(kwargs['help'], str), type(kwargs['help'])
+ kwargs['help'] = ('{} (default:{})'.format(
+ kwargs['help'], default))
+
+ super(ExtArgumentParser, self).add_argument(*args, **kwargs)
+
+ def __init__(self, context, *args, **kwargs):
+ self.context = context
+ super(ExtArgumentParser, self).__init__(*args, **kwargs)
+
+
+class TestExtArgumentParser(unittest.TestCase):
+ def test_did_you_mean(self):
+ parser = ExtArgumentParser(None)
+ parser.add_argument('--foo')
+ parser.add_argument('--qoo', help=argparse.SUPPRESS)
+ parser.add_argument('jam', nargs='?')
+
+ parser.parse_args(['--foo', '0'])
+
+ expected = (r"^unrecognized argument\: <y>'\-\-doo'</>\s+"
+ r"\(did you mean <y>'\-\-foo'</>\?\)\n"
+ r"\s*<g>usage:</>")
+ with self.assertRaisesRegex(Error, expected):
+ parser.parse_args(['--doo'])
+
+ parser.add_argument('--noo')
+
+ expected = (r"^unrecognized argument\: <y>'\-\-doo'</>\s+"
+ r"\(did you mean <y>'\-\-noo'</> or <y>'\-\-foo'</>\?\)\n"
+ r"\s*<g>usage:</>")
+ with self.assertRaisesRegex(Error, expected):
+ parser.parse_args(['--doo'])
+
+ expected = (r"^unrecognized argument\: <y>'\-\-bar'</>\n"
+ r"\s*<g>usage:</>")
+ with self.assertRaisesRegex(Error, expected):
+ parser.parse_args(['--bar'])
+
+ expected = (r"^unexpected argument\: <y>'\-\-foo'</>\n"
+ r"\s*<g>usage:</>")
+ with self.assertRaisesRegex(Error, expected):
+ parser.parse_args(['--', 'x', '--foo'])
OpenPOWER on IntegriCloud