diff --git a/tools/nid_names.py b/tools/nid_names.py index 0df8c3f147..2c4cce5a23 100644 --- a/tools/nid_names.py +++ b/tools/nid_names.py @@ -163,9 +163,11 @@ def main(argv=None): options = [option for action in parser._actions for option in action.option_strings] arguments = sys.argv[1:] if argv is None else argv args = parser.parse_args(nid_arguments(arguments, options)) + requested_options = {option_name(argument, options) for argument in arguments} + requested_nids = "--nid" in requested_options + if requested_nids and requested_options & {"--name", "--symbol"}: + parser.error("--name/--symbol cannot be combined with --nid") if args.name: - if args.nid: - parser.error("--name/--symbol cannot be combined with --nid") rows = [{"name": name, "nid": compute_nid(name)} for name in args.name] if args.json: print(json.dumps({"symbols": rows}, indent=1)) @@ -174,7 +176,6 @@ def main(argv=None): for row in rows: print("%-40s %s" % (row["name"], row["nid"])) return 0 - requested_nids = any(option_name(argument, options) == "--nid" for argument in arguments) for nid in args.nid or []: if re.fullmatch(r"[A-Za-z0-9+\-]{11}", nid) is None: parser.error(f"invalid NID {nid!r}: expected 11 characters from A-Z, a-z, 0-9, + or -") diff --git a/tools/tests/test_nid_names.py b/tools/tests/test_nid_names.py index 6dd4b20804..213f79c47f 100644 --- a/tools/tests/test_nid_names.py +++ b/tools/tests/test_nid_names.py @@ -94,6 +94,31 @@ class DatabaseCacheTests(unittest.TestCase): class NidArgumentTests(unittest.TestCase): options = ["-h", "--help", "--db", "--nid", "--json"] + def test_name_and_nid_modes_conflict_even_with_empty_filters(self): + for name_option in ("--name", "--symbol", "--na", "--sym"): + for nid_option in ("--nid", "--ni"): + for names, nids in ( + ([name_option], [nid_option]), + ([name_option, "ceilf"], [nid_option]), + ([name_option + "=ceilf"], [nid_option]), + ([name_option], [nid_option, "AAAAAAAAAAA"]), + ([name_option], [nid_option + "=AAAAAAAAAAA"])): + for arguments in (names + nids, nids + names): + with self.subTest(arguments=arguments), \ + contextlib.redirect_stdout(io.StringIO()) as output, \ + contextlib.redirect_stderr(io.StringIO()) as error, \ + patch.object(nid_names, "load_db", return_value={}) as database, \ + patch.object(nid_names, "collect_unknowns", return_value={}) as sources, \ + patch.object(nid_names, "collect_real_names", return_value=set()) as definitions: + with self.assertRaises(SystemExit) as exited: + nid_names.main([*arguments, "--json"]) + self.assertEqual(exited.exception.code, 2) + self.assertIn("--name/--symbol cannot be combined with --nid", error.getvalue()) + self.assertEqual(output.getvalue(), "") + database.assert_not_called() + sources.assert_not_called() + definitions.assert_not_called() + def test_invalid_nids_fail_before_database_or_source_access(self): for nid in ("short", "ABCDEFGHIJKL", "ABCDEFGHIJ/", "ABCDEFGHIJ_", "ABCDEFGHIJ\u00e9", "", "--jsooon"): with self.subTest(nid=nid):