diff options
| author | John Anderson <sontek@gmail.com> | 2014-12-25 20:49:00 -0800 |
|---|---|---|
| committer | John Anderson <sontek@gmail.com> | 2014-12-25 20:49:00 -0800 |
| commit | a99d2d7e17f4c87d9307215a2ad8d583e74c3a50 (patch) | |
| tree | 2030a07c3449e185a167288305d7b06e3b8aa7d1 | |
| parent | c966a9283c2c6515848e8a5f4f7c34e0fba733a8 (diff) | |
| download | pyramid-a99d2d7e17f4c87d9307215a2ad8d583e74c3a50.tar.gz pyramid-a99d2d7e17f4c87d9307215a2ad8d583e74c3a50.tar.bz2 pyramid-a99d2d7e17f4c87d9307215a2ad8d583e74c3a50.zip | |
Add the --format flag
| -rw-r--r-- | pyramid/scripts/proutes.py | 106 | ||||
| -rw-r--r-- | pyramid/tests/test_scripts/test_proutes.py | 94 |
2 files changed, 183 insertions, 17 deletions
diff --git a/pyramid/scripts/proutes.py b/pyramid/scripts/proutes.py index fce90c0c1..917d9af71 100644 --- a/pyramid/scripts/proutes.py +++ b/pyramid/scripts/proutes.py @@ -4,7 +4,7 @@ import sys import textwrap from pyramid.paster import bootstrap -from pyramid.compat import string_types +from pyramid.compat import (string_types, configparser) from pyramid.interfaces import ( IRouteRequest, IViewClassifier, @@ -35,14 +35,22 @@ def _get_pattern(route): return pattern -def _get_print_format(max_name, max_pattern, max_view, max_method): - fmt = '%-{0}s %-{1}s %-{2}s %-{3}s'.format( - max_name + PAD, - max_pattern + PAD, - max_view + PAD, - max_method + PAD, - ) - return fmt +def _get_print_format(fmt, max_name, max_pattern, max_view, max_method): + print_fmt = '' + max_map = { + 'name': max_name, + 'pattern': max_pattern, + 'view': max_view, + 'method': max_method, + } + sizes = [] + + for index, col in enumerate(fmt): + size = max_map[col] + PAD + print_fmt += '{{%s: <{%s}}} ' % (col, index) + sizes.append(size) + + return print_fmt.format(*sizes) def _get_request_methods(route_request_methods, view_request_methods): @@ -230,7 +238,7 @@ class PRoutesCommand(object): bootstrap = (bootstrap,) stdout = sys.stdout usage = '%prog config_uri' - + ConfigParser = configparser.ConfigParser # testing parser = optparse.OptionParser( usage, description=textwrap.dedent(description) @@ -239,9 +247,49 @@ class PRoutesCommand(object): action='store', type='string', dest='glob', default='', help='Display routes matching glob pattern') + parser.add_option('-f', '--format', + action='store', type='string', dest='format', + default='', help=('Choose which columns to display, this ' + 'will override the format key in the ' + '[proutes] ini section')) + def __init__(self, argv, quiet=False): self.options, self.args = self.parser.parse_args(argv[1:]) self.quiet = quiet + self.available_formats = [ + 'name', 'pattern', 'view', 'method' + ] + self.column_format = self.available_formats + + def validate_formats(self, formats): + invalid_formats = [] + for fmt in formats: + if fmt not in self.available_formats: + invalid_formats.append(fmt) + + msg = ( + 'You provided invalid formats %s, ' + 'Available formats are %s' + ) + + if invalid_formats: + msg = msg % (invalid_formats, self.available_formats) + self.out(msg) + return False + + return True + + def proutes_file_config(self, filename): + config = self.ConfigParser() + config.read(filename) + try: + items = config.items('proutes') + for k, v in items: + if 'format' == k: + self.column_format = [x.strip() for x in v.split('\n')] + + except configparser.NoSectionError: + return def out(self, msg): # pragma: no cover if not self.quiet: @@ -261,6 +309,16 @@ class PRoutesCommand(object): env = self.bootstrap[0](config_uri, options=parse_vars(self.args[1:])) registry = env['registry'] mapper = self._get_mapper(registry) + self.proutes_file_config(config_uri) + + if self.options.format: + columns = self.options.format.split(',') + self.column_format = [x.strip() for x in columns] + + is_valid = self.validate_formats(self.column_format) + + if is_valid is False: + return 2 if mapper is None: return 0 @@ -275,10 +333,17 @@ class PRoutesCommand(object): if len(routes) == 0: return 0 - mapped_routes = [ - ('Name', 'Pattern', 'View', 'Method'), - ('----', '-------', '----', '------') - ] + mapped_routes = [{ + 'name': 'Name', + 'pattern': 'Pattern', + 'view': 'View', + 'method': 'Method' + },{ + 'name': '----', + 'pattern': '-------', + 'view': '----', + 'method': '------' + }] for route in routes: route_data = get_route_data(route, registry) @@ -302,12 +367,19 @@ class PRoutesCommand(object): if len(method) > max_method: max_method = len(method) - mapped_routes.append((name, pattern, view, method)) + mapped_routes.append({ + 'name': name, + 'pattern': pattern, + 'view': view, + 'method': method + }) - fmt = _get_print_format(max_name, max_pattern, max_view, max_method) + fmt = _get_print_format( + self.column_format, max_name, max_pattern, max_view, max_method + ) for route in mapped_routes: - self.out(fmt % route) + self.out(fmt.format(**route)) return 0 diff --git a/pyramid/tests/test_scripts/test_proutes.py b/pyramid/tests/test_scripts/test_proutes.py index 4622383be..d51baaa01 100644 --- a/pyramid/tests/test_scripts/test_proutes.py +++ b/pyramid/tests/test_scripts/test_proutes.py @@ -20,6 +20,7 @@ class TestPRoutesCommand(unittest.TestCase): cmd = self._getTargetClass()([]) cmd.bootstrap = (dummy.DummyBootstrap(),) cmd.args = ('/foo/bar/myapp.ini#myapp',) + return cmd def _makeRegistry(self): @@ -572,6 +573,99 @@ class TestPRoutesCommand(unittest.TestCase): ] self.assertEqual(compare_to, expected) + def test_good_format(self): + from pyramid.renderers import null_renderer as nr + from pyramid.config import not_ + + def view1(context, request): return 'view1' + + config = self._makeConfig(autocommit=True) + config.add_route('foo', '/a/b') + config.add_view( + route_name='foo', + view=view1, + renderer=nr, + request_method=not_('POST') + ) + + command = self._makeOne() + command.options.glob = '*foo*' + command.options.format = 'method,name' + L = [] + command.out = L.append + command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),) + result = command.run() + self.assertEqual(result, 0) + self.assertEqual(len(L), 3) + compare_to = L[-1].split() + expected = ['!POST,*', 'foo'] + + self.assertEqual(compare_to, expected) + self.assertEqual(L[0].split(), ['Method', 'Name']) + + def test_bad_format(self): + from pyramid.renderers import null_renderer as nr + from pyramid.config import not_ + + def view1(context, request): return 'view1' + + config = self._makeConfig(autocommit=True) + config.add_route('foo', '/a/b') + config.add_view( + route_name='foo', + view=view1, + renderer=nr, + request_method=not_('POST') + ) + + command = self._makeOne() + command.options.glob = '*foo*' + command.options.format = 'predicates,name,pattern' + L = [] + command.out = L.append + command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),) + expected = ( + "You provided invalid formats ['predicates'], " + "Available formats are ['name', 'pattern', 'view', 'method']" + ) + result = command.run() + self.assertEqual(result, 2) + self.assertEqual(L[0], expected) + + def test_config_format_ini(self): + from pyramid.renderers import null_renderer as nr + from pyramid.config import not_ + + def view1(context, request): return 'view1' + + config = self._makeConfig(autocommit=True) + config.add_route('foo', '/a/b') + config.add_view( + route_name='foo', + view=view1, + renderer=nr, + request_method=not_('POST') + ) + + command = self._makeOne() + command.options.glob = '*foo*' + command.options.format = 'method,name' + L = [] + command.out = L.append + command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),) + config_factory = dummy.DummyConfigParserFactory() + command.ConfigParser = config_factory + config_factory.items = [('format', 'method\name')] + + result = command.run() + self.assertEqual(result, 0) + self.assertEqual(len(L), 3) + compare_to = L[-1].split() + expected = ['!POST,*', 'foo'] + + self.assertEqual(compare_to, expected) + self.assertEqual(L[0].split(), ['Method', 'Name']) + class Test_main(unittest.TestCase): def _callFUT(self, argv): from pyramid.scripts.proutes import main |
