Skip to content

Commit f95ff31

Browse files
committed
cli: Add --field-json=JSONSTRING
This is similar to the `--field` option for interacting with custom bugzilla fields, but it takes a full JSON string as input. This lets users set complex values like arrays, dict mappings, that otherwise were not settable with plain `--field` Fixes: #163 Signed-off-by: Cole Robinson <[email protected]>
1 parent 41f3570 commit f95ff31

8 files changed

Lines changed: 49 additions & 11 deletions

File tree

bugzilla/_cli.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@ def _parser_add_bz_fields(rootp, command):
263263
"the raw name used by the bugzilla instance. For example, if your "
264264
"bugzilla instance has a custom field cf_my_field, do:\n"
265265
" --field cf_my_field=VALUE")
266+
p.add_argument('--field-json',
267+
metavar="JSONSTRING", action="append", dest="field_jsons",
268+
help="Specify --field data as a JSON string. Example: --field-json "
269+
'\'{"cf_my_field": "VALUE", "cf_array_field": [1, 2]}\'')
266270

267271
if not cmd_modify:
268272
_parser_add_output_options(rootp)
@@ -436,15 +440,28 @@ def setup_parser():
436440
# Command routines #
437441
####################
438442

439-
def _merge_field_opts(query, fields, parser):
443+
def _merge_field_opts(query, fields, field_jsons, parser):
444+
values = {}
445+
440446
# Add any custom fields if specified
441-
for f in fields:
447+
for f in (fields or []):
442448
try:
443449
f, v = f.split('=', 1)
444-
query[f] = v
450+
values[f] = v
445451
except Exception:
446452
parser.error("Invalid field argument provided: %s" % (f))
447453

454+
for j in (field_jsons or []):
455+
try:
456+
jvalues = json.loads(j)
457+
values.update(jvalues)
458+
except Exception as e:
459+
parser.error("Invalid field-json value=%s: %s" % (j, e))
460+
461+
if values:
462+
log.debug("parsed --field* values: %s", values)
463+
query.update(values)
464+
448465

449466
def _do_query(bz, opt, parser):
450467
q = {}
@@ -599,8 +616,7 @@ def _do_query(bz, opt, parser):
599616
kwopts["tags"] = opt.tags
600617

601618
built_query = bz.build_query(**kwopts)
602-
if opt.fields:
603-
_merge_field_opts(built_query, opt.fields, parser)
619+
_merge_field_opts(built_query, opt.fields, opt.field_jsons, parser)
604620

605621
built_query.update(q)
606622
q = built_query
@@ -907,8 +923,7 @@ def parse_multi(val):
907923
kwopts["comment_private"] = opt.private
908924

909925
ret = bz.build_createbug(**kwopts)
910-
if opt.fields:
911-
_merge_field_opts(ret, opt.fields, parser)
926+
_merge_field_opts(ret, opt.fields, opt.field_jsons, parser)
912927

913928
b = bz.createbug(ret)
914929
b.refresh()
@@ -1049,8 +1064,7 @@ def _do_modify(bz, parser, opt):
10491064
if not v[0] and not v[1]:
10501065
del wbmap[k]
10511066

1052-
if opt.fields:
1053-
_merge_field_opts(update, opt.fields, parser)
1067+
_merge_field_opts(update, opt.fields, opt.field_jsons, parser)
10541068

10551069
log.debug("update bug dict=%s", update)
10561070
log.debug("update whiteboard dict=%s", wbmap)

man/bugzilla.rst

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,13 +416,22 @@ RHBZ 'Fixed in version' field
416416
``--field``
417417
^^^^^^^^^^^
418418

419-
**Syntax:** ``--field`` FIELD`` VALUE
419+
**Syntax:** ``--field`` FIELD=VALUE
420420

421421
Manually specify a bugzilla API field. FIELD is the raw name used
422422
by the bugzilla instance. For example if your bugzilla instance has a
423423
custom field cf_my_field, do: --field cf_my_field=VALUE
424424

425425

426+
``--field-json``
427+
^^^^^^^^^^^^^^^^
428+
429+
**Syntax:** ``--field-json`` JSONSTRING
430+
431+
Specify --field data as a JSON string. Example:
432+
--field-json '{"cf_my_field": "VALUE", "cf_array_field": [1, 2]}'
433+
434+
426435

427436
Output options
428437
==============

tests/data/mockargs/test_modify5.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
'bar': 'foo',
55
'blocks': {'add': ['1234'], 'remove': ['1235'], 'set': []},
66
'cc': {'add': ['[email protected]'], 'remove': ['[email protected]']},
7+
'cf_blah': {'1': 2},
78
'cf_devel_whiteboard': 'DEVBOARD',
89
'cf_internal_whiteboard': 'INTBOARD',
910
'cf_qa_whiteboard': 'QABOARD',
11+
'cf_verified': ['Tested'],
1012
'comment_tags': ['FOOTAG'],
1113
'depends_on': {'add': ['2234'], 'remove': ['2235'], 'set': []},
1214
'groups': {'add': ['foogroup']},

tests/data/mockargs/test_new2.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
'assigned_to': '[email protected]',
33
'blocks': ['12345', '6789'],
44
5+
'cf_blah': {'1': 2},
6+
'cf_verified': ['Tested'],
57
'comment_is_private': True,
68
'comment_tags': ['FOO'],
79
'component': 'FOOCOMP',

tests/data/mockargs/test_query6.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{'BAR': 'WIBBLE',
22
'FOO': '1',
33
'bug_status': ['VERIFIED', 'RELEASE_PENDING', 'CLOSED'],
4+
'cf_blah': {'1': 2},
5+
'cf_verified': ['Tested'],
46
'include_fields': ['assigned_to',
57
'blocks',
68
'component',

tests/test_cli_modify.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def test_modify(run_cli):
8585
cmd += "--devel_whiteboard =DEVBOARD --internal_whiteboard =INTBOARD "
8686
cmd += "--qa_whiteboard =QABOARD "
8787
cmd += "--comment-tag FOOTAG --field bar=foo "
88+
cmd += '--field-json \'{"cf_verified": ["Tested"], "cf_blah": {"1": 2}}\' '
8889
cmd += "--minor-update "
8990
fakebz = tests.mockbackend.make_bz(rhbz=True,
9091
bug_update_args="data/mockargs/test_modify5.txt",

tests/test_cli_new.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def test_new(run_cli):
4141
cmd += "--assignee [email protected] --qa_contact [email protected] "
4242
cmd += "--comment-tag FOO "
4343
cmd += "--field foo=bar "
44+
cmd += '--field-json \'{"cf_verified": ["Tested"], "cf_blah": {"1": 2}}\' '
4445

4546
fakebz = tests.mockbackend.make_bz(
4647
bug_create_args="data/mockargs/test_new2.txt",

tests/test_cli_query.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@
1515
#################################
1616

1717
def test_query(run_cli):
18-
# bad field option
18+
# bad --field option
1919
fakebz = tests.mockbackend.make_bz()
2020
cmd = "bugzilla query --field FOO"
2121
out = run_cli(cmd, fakebz, expectfail=True)
2222
assert "Invalid field argument" in out
2323

24+
# bad --field-json option
25+
fakebz = tests.mockbackend.make_bz()
26+
cmd = "bugzilla query --field-json='{1: 2}'"
27+
out = run_cli(cmd, fakebz, expectfail=True)
28+
assert "Invalid field-json" in out
29+
2430
# Simple query with some comma opts
2531
cmd = "bugzilla query "
2632
cmd += "--product foo --component foo,bar --bug_id 1234,2480"
@@ -104,6 +110,7 @@ def test_query(run_cli):
104110
# Test --status EOL and --oneline, and some --field usage
105111
cmd = "bugzilla query --status EOL --oneline "
106112
cmd += "--field FOO=1 --field=BAR=WIBBLE "
113+
cmd += '--field-json \'{"cf_verified": ["Tested"], "cf_blah": {"1": 2}}\' '
107114
fakebz = tests.mockbackend.make_bz(
108115
bug_search_args="data/mockargs/test_query6.txt",
109116
bug_search_return="data/mockreturn/test_getbug_rhel.txt",

0 commit comments

Comments
 (0)