Skip to content

Commit 1c47ea1

Browse files
committed
Add support for configurable output columns
Add a '--column' option to all list commands. This allows users to configure what columns are output. How this works is currently quite dumb but that can be improved in the future. Signed-off-by: Stephen Finucane <stephen@that.guru> Closes: #29
1 parent d054c75 commit 1c47ea1

File tree

9 files changed

+96
-48
lines changed

9 files changed

+96
-48
lines changed

git_pw/api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ def new_func(ctx, *args, **kwargs):
284284
if not param.multiple:
285285
continue
286286

287+
if param.name in ('headers'):
288+
continue
289+
287290
value = list(kwargs[param.name] or [])
288291
if value and len(value) > 1 and value != param.default:
289292
msg = ('The `--%s` filter was specified multiple times. '

git_pw/bundle.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
LOG = logging.getLogger(__name__)
1414

15+
_list_headers = ('ID', 'Name', 'Owner', 'Public')
16+
1517

1618
def _get_bundle(bundle_id):
1719
"""Fetch bundle by ID or name.
@@ -123,10 +125,10 @@ def _format_patch(patch):
123125
@click.option('--sort', metavar='FIELD', default='name', type=click.Choice(
124126
['id', '-id', 'name', '-name']),
125127
help='Sort output on given field.')
126-
@utils.format_options
128+
@utils.format_options(headers=_list_headers)
127129
@click.argument('name', required=False)
128130
@api.validate_multiple_filter_support
129-
def list_cmd(owner, limit, page, sort, fmt, name):
131+
def list_cmd(owner, limit, page, sort, fmt, headers, name):
130132
"""List bundles.
131133
132134
List bundles on the Patchwork instance.
@@ -154,13 +156,21 @@ def list_cmd(owner, limit, page, sort, fmt, name):
154156

155157
# Format and print output
156158

157-
headers = ['ID', 'Name', 'Owner', 'Public']
159+
output = []
160+
161+
for bundle in bundles:
162+
item = [
163+
bundle.get('id'),
164+
utils.trim(bundle.get('name') or ''),
165+
bundle.get('owner').get('username'),
166+
'yes' if bundle.get('public') else 'no',
167+
]
168+
169+
output.append([])
170+
for idx, header in enumerate(_list_headers):
171+
if header not in headers:
172+
continue
158173

159-
output = [[
160-
bundle.get('id'),
161-
utils.trim(bundle.get('name') or ''),
162-
bundle.get('owner').get('username'),
163-
'yes' if bundle.get('public') else 'no',
164-
] for bundle in bundles]
174+
output[-1].append(item[idx])
165175

166176
utils.echo_via_pager(output, headers, fmt=fmt)

git_pw/patch.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
LOG = logging.getLogger(__name__)
1515

16+
_list_headers = ('ID', 'Date', 'Name', 'Submitter', 'State', 'Archived',
17+
'Delegate')
18+
1619

1720
@click.command(name='apply', context_settings=dict(
1821
ignore_unknown_options=True,
@@ -199,11 +202,11 @@ def update_cmd(patch_ids, commit_ref, state, delegate, archived, fmt):
199202
@click.option('--sort', metavar='FIELD', default='-date', type=click.Choice(
200203
['id', '-id', 'name', '-name', 'date', '-date']),
201204
help='Sort output on given field.')
202-
@utils.format_options
205+
@utils.format_options(headers=_list_headers)
203206
@click.argument('name', required=False)
204207
@api.validate_multiple_filter_support
205208
def list_cmd(state, submitter, delegate, archived, limit, page, sort, fmt,
206-
name):
209+
headers, name):
207210
"""List patches.
208211
209212
List patches on the Patchwork instance.
@@ -243,19 +246,25 @@ def list_cmd(state, submitter, delegate, archived, limit, page, sort, fmt,
243246

244247
# Format and print output
245248

246-
headers = ['ID', 'Date', 'Name', 'Submitter', 'State', 'Archived',
247-
'Delegate']
248-
249-
output = [[
250-
patch.get('id'),
251-
arrow.get(patch.get('date')).humanize(),
252-
utils.trim(patch.get('name')),
253-
'%s (%s)' % (patch.get('submitter').get('name'),
254-
patch.get('submitter').get('email')),
255-
patch.get('state'),
256-
'yes' if patch.get('archived') else 'no',
257-
(patch.get('delegate').get('username')
258-
if patch.get('delegate') else ''),
259-
] for patch in patches]
249+
output = []
250+
251+
for patch in patches:
252+
item = [
253+
patch.get('id'),
254+
arrow.get(patch.get('date')).humanize(),
255+
utils.trim(patch.get('name')),
256+
'%s (%s)' % (patch.get('submitter').get('name'),
257+
patch.get('submitter').get('email')),
258+
patch.get('state'),
259+
'yes' if patch.get('archived') else 'no',
260+
(patch.get('delegate') or {}).get('username', ''),
261+
]
262+
263+
output.append([])
264+
for idx, header in enumerate(_list_headers):
265+
if header not in headers:
266+
continue
267+
268+
output[-1].append(item[idx])
260269

261270
utils.echo_via_pager(output, headers, fmt=fmt)

git_pw/series.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
LOG = logging.getLogger(__name__)
1515

16+
_list_headers = ('ID', 'Date', 'Name', 'Version', 'Submitter')
17+
1618

1719
@click.command(name='apply', context_settings=dict(
1820
ignore_unknown_options=True,
@@ -110,10 +112,10 @@ def _format_submission(submission):
110112
@click.option('--sort', metavar='FIELD', default='-date', type=click.Choice(
111113
['id', '-id', 'name', '-name', 'date', '-date']),
112114
help='Sort output on given field.')
113-
@utils.format_options
115+
@utils.format_options(headers=_list_headers)
114116
@click.argument('name', required=False)
115117
@api.validate_multiple_filter_support
116-
def list_cmd(submitter, limit, page, sort, fmt, name):
118+
def list_cmd(submitter, limit, page, sort, fmt, headers, name):
117119
"""List series.
118120
119121
List series on the Patchwork instance.
@@ -141,15 +143,23 @@ def list_cmd(submitter, limit, page, sort, fmt, name):
141143

142144
# Format and print output
143145

144-
headers = ['ID', 'Date', 'Name', 'Version', 'Submitter']
146+
output = []
147+
148+
for series_ in series:
149+
item = [
150+
series_.get('id'),
151+
arrow.get(series_.get('date')).humanize(),
152+
utils.trim(series_.get('name') or ''),
153+
series_.get('version'),
154+
'%s (%s)' % (series_.get('submitter').get('name'),
155+
series_.get('submitter').get('email'))
156+
]
157+
158+
output.append([])
159+
for idx, header in enumerate(_list_headers):
160+
if header not in headers:
161+
continue
145162

146-
output = [[
147-
series_.get('id'),
148-
arrow.get(series_.get('date')).humanize(),
149-
utils.trim(series_.get('name') or ''),
150-
series_.get('version'),
151-
'%s (%s)' % (series_.get('submitter').get('name'),
152-
series_.get('submitter').get('email'))
153-
] for series_ in series]
163+
output[-1].append(item[idx])
154164

155165
utils.echo_via_pager(output, headers, fmt=fmt)

git_pw/utils.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,23 @@ def echo(output, headers, fmt):
149149
click.echo(_tabulate(output, headers, fmt))
150150

151151

152-
def format_options(f):
152+
def format_options(original_function=None, headers=None):
153153
"""Shared output format options."""
154-
f = click.option('--format', '-f', 'fmt', envvar='PW_FORMAT',
155-
default=None,
156-
type=click.Choice(['simple', 'table', 'csv']),
157-
help='Output format. Defaults to table.')(f)
158154

159-
return f
155+
def _format_options(f):
156+
f = click.option('--format', '-f', 'fmt', envvar='PW_FORMAT',
157+
default=None,
158+
type=click.Choice(['simple', 'table', 'csv']),
159+
help='Output format. Defaults to table.')(f)
160+
161+
if headers:
162+
f = click.option('--column', '-c', 'headers', metavar='COLUMN',
163+
multiple=True, default=headers,
164+
type=click.Choice(headers),
165+
help='Columns to be included in output.')(f)
166+
return f
167+
168+
if original_function:
169+
return _format_options(original_function)
170+
171+
return _format_options

releasenotes/notes/issue-29-884269fdf35f64b2.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ features:
77
- ``table`` (default)
88
- ``simple`` (a version of table with less markup)
99
- ``csv`` (comma-separated output)
10+
- |
11+
All list comands now take a ``--column``/``-c`` parameter, which can be
12+
used to control what columns are output. This can be specified multiples
13+
times. All columns are output by default.

tests/test_bundle.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,11 +216,11 @@ def test_list_with_formatting(self, mock_echo, mock_index, mock_version):
216216

217217
runner = CLIRunner()
218218
result = runner.invoke(bundle.list_cmd, [
219-
'--format', 'simple'])
219+
'--format', 'simple', '--column', 'ID', '--column', 'Name'])
220220

221221
assert result.exit_code == 0, result
222222

223-
mock_echo.assert_called_once_with(mock.ANY, mock.ANY,
223+
mock_echo.assert_called_once_with(mock.ANY, ('ID', 'Name'),
224224
fmt='simple')
225225

226226
def test_list_with_filters(self, mock_echo, mock_index, mock_version):

tests/test_patch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,11 @@ def test_list_with_formatting(self, mock_echo, mock_index, mock_version):
313313

314314
runner = CLIRunner()
315315
result = runner.invoke(patch.list_cmd, [
316-
'--format', 'simple'])
316+
'--format', 'simple', '--column', 'ID', '--column', 'Name'])
317317

318318
assert result.exit_code == 0, result
319319

320-
mock_echo.assert_called_once_with(mock.ANY, mock.ANY,
320+
mock_echo.assert_called_once_with(mock.ANY, ('ID', 'Name'),
321321
fmt='simple')
322322

323323
def test_list_with_filters(self, mock_echo, mock_index, mock_version):

tests/test_series.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,11 @@ def test_list_with_formatting(self, mock_echo, mock_index, mock_version):
171171

172172
runner = CLIRunner()
173173
result = runner.invoke(series.list_cmd, [
174-
'--format', 'simple'])
174+
'--format', 'simple', '--column', 'ID', '--column', 'Name'])
175175

176176
assert result.exit_code == 0, result
177177

178-
mock_echo.assert_called_once_with(mock.ANY, mock.ANY,
178+
mock_echo.assert_called_once_with(mock.ANY, ('ID', 'Name'),
179179
fmt='simple')
180180

181181
def test_list_with_filters(self, mock_echo, mock_index, mock_version):

0 commit comments

Comments
 (0)