From d63c5024dc8e4931b0766feafb5207ec02af9f52 Mon Sep 17 00:00:00 2001 From: Lon Hohberger Date: Mon, 22 Jan 2024 11:48:20 -0500 Subject: [PATCH] jira: Render list items with commas in quotes When you have a component or name with a comma, simply joining the list together does not provide output you could quote and use as input, and makes it confusing where the component name begins and ends without looking at the component list. So, for example, one can see: "component1, desc1", component2, component3 ... in the output instead of: component1, desc1, component2, component3 ... when looking at issues, in addition to: $ jirate field TEST-1 set components '"component1, desc1", component2' --- jirate/decor.py | 10 ++++++++++ jirate/jira_cli.py | 6 +++--- jirate/jira_fields.py | 8 ++++---- jirate/tests/__init__.py | 6 +++--- jirate/tests/test_decor.py | 19 +++++++++++++++++-- jirate/tests/test_render.py | 3 ++- 6 files changed, 39 insertions(+), 13 deletions(-) diff --git a/jirate/decor.py b/jirate/decor.py index f99a05b..a8557b2 100644 --- a/jirate/decor.py +++ b/jirate/decor.py @@ -81,6 +81,16 @@ def parse_params(arg): return ret +def comma_separated(item_list): + out = [] + for item in item_list: + if item and ',' in item: + out.append(f'"{item}"') + else: + out.append(item) + return ', '.join(out) + + def truncate(arg, maxlen): if arg and maxlen and len(arg) > maxlen: arg = arg[:maxlen - 1] + '…' diff --git a/jirate/jira_cli.py b/jirate/jira_cli.py index c046188..0191925 100644 --- a/jirate/jira_cli.py +++ b/jirate/jira_cli.py @@ -16,7 +16,7 @@ from jirate.args import ComplicatedArgs, GenericArgs from jirate.jboard import JiraProject, get_jira -from jirate.decor import md_print, pretty_date, color_string, hbar_under, hbar, hbar_over, nym, vsep_print, vseparator, parse_params, truncate, render_matrix +from jirate.decor import md_print, pretty_date, color_string, hbar_under, hbar, hbar_over, nym, vsep_print, vseparator, parse_params, truncate, render_matrix, comma_separated from jirate.decor import pretty_print # NOQA from jirate.config import get_config from jirate.jira_fields import apply_field_renderers, render_issue_fields, max_field_width, render_field_data @@ -290,7 +290,7 @@ def issue_fields(args): values.append(val['value']) else: values.append(val['id']) - fvalue = ', '.join(values) + fvalue = comma_separated(values) vsep_print(' ', fname, nlen, fvalue) return (0, False) @@ -399,7 +399,7 @@ def print_creation_fields(metadata): values.append(val['value']) else: values.append(val['id']) - fvalue = ', '.join(values) + fvalue = comma_separated(values) vsep_print(' ', fname, nlen, req, 1, fvalue) diff --git a/jirate/jira_fields.py b/jirate/jira_fields.py index c4f22fe..b866a1f 100644 --- a/jirate/jira_fields.py +++ b/jirate/jira_fields.py @@ -2,7 +2,7 @@ import re # NOQA from collections import OrderedDict -from jirate.decor import pretty_date, vsep_print +from jirate.decor import pretty_date, vsep_print, comma_separated # @@ -10,7 +10,7 @@ # suppressed. # def _list_of_key(field, key): - return ', '.join([item[key] for item in field]) + return comma_separated([item[key] for item in field]) def string(field, fields): @@ -21,7 +21,7 @@ def auto_field(field, fields): if isinstance(field, str): return field if isinstance(field, list): - return ', '.join([str(item) for item in field]) + return comma_separated([str(item) for item in field]) if isinstance(field, dict): for key in ['name', 'value']: if key in field: @@ -61,7 +61,7 @@ def user_list(field, fields): def array(field, fields): - return ', '.join(field) + return comma_separated(field) def value_list(field, fields): diff --git a/jirate/tests/__init__.py b/jirate/tests/__init__.py index d38a949..3b3d59b 100644 --- a/jirate/tests/__init__.py +++ b/jirate/tests/__init__.py @@ -281,7 +281,7 @@ 'timeZone': 'America/New_York'}, 'attachment': [], 'comment': [], - 'components': [], + 'components': [{'name': 'food, pork'}, {'name': 'food, carrot'}], 'created': '2023-08-03T10:28:48.366+0000', 'description': 'Test Description 1', 'duedate': '2024-01-30', @@ -358,7 +358,7 @@ {'name': 'Version2', 'value': 'version_two'}], 'customfield_1234571': [{'key': 'user1', 'name': 'user-one', 'displayName': 'One', 'emailAddress': 'one@two.com'}, {'key': 'user2', 'name': 'two@other.eml', 'displayName': 'Two', 'emailAddress': 'two@two.com'}], - 'customfield_1234572': ['one', 'two', 'three'], + 'customfield_1234572': ['one', 'two', 'three, and four'], 'customfield_1234573': [{'name': 'group1'}, {'name': 'group2'}], 'customfield_1234574': ['one', 2.0], 'customfield_1234575': '2022-08-01', @@ -389,7 +389,7 @@ 'assignee': None, 'attachment': [], 'comment': [], - 'components': ['porkchop'], + 'components': [], 'created': '2023-08-03T10:28:48.366+0000', 'customfield_1234567': None, 'customfield_1234568': None, diff --git a/jirate/tests/test_decor.py b/jirate/tests/test_decor.py index 2bceb07..e4ea03a 100644 --- a/jirate/tests/test_decor.py +++ b/jirate/tests/test_decor.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -from jirate.decor import truncate, parse_params +from jirate.decor import truncate, parse_params, comma_separated def test_parse_simple(): @@ -9,7 +9,7 @@ def test_parse_simple(): def test_parse_commas(): assert parse_params('arg,barg') == ['arg', 'barg'] - assert parse_params('"Comma,Test, ", 2') == ['Comma,Test,', "2"] + assert parse_params('"Comma, Test, ", 2') == ['Comma, Test,', "2"] def test_parse_spaces(): @@ -30,3 +30,18 @@ def test_truncate_identity(): def test_truncate_exceed(): assert truncate('abc', 3) == 'abc' assert truncate('abcd', 3) == 'ab…' + + +def test_comma_separated(): + str_val = 'one, two, "three, and four"' + list_val = ['one', 'two', 'three, and four'] + + assert comma_separated(list_val) == str_val + + +def test_parse_and_unparse(): + str_val = 'one, two, "three, and four"' + list_val = ['one', 'two', 'three, and four'] + + assert parse_params(comma_separated(list_val)) == list_val + assert comma_separated(parse_params(str_val)) == str_val diff --git a/jirate/tests/test_render.py b/jirate/tests/test_render.py index 7ebb579..f16fc15 100644 --- a/jirate/tests/test_render.py +++ b/jirate/tests/test_render.py @@ -69,6 +69,7 @@ def test_render_code_override(): field_test_params = 'field_id,field_name,value' field_test_info = [ + pytest.param('components', 'Component/s', '"food, pork", "food, carrot"'), # Fixed in build (string) pytest.param('customfield_1234567', 'Fixed in Build', 'test-build-1'), @@ -86,7 +87,7 @@ def test_render_code_override(): pytest.param('customfield_1234571', 'Array of Users', 'user-one, two@other.eml'), # Array of strings - pytest.param('customfield_1234572', 'Array of Strings', 'one, two, three'), + pytest.param('customfield_1234572', 'Array of Strings', 'one, two, "three, and four"'), # Array of groups (name?), pytest.param('customfield_1234573', 'Array of Groups', 'group1, group2'),