fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/42310?usp=email )
Change subject: global_platform: install_cap_parser: argument groups cannot be nested ......................................................................
global_platform: install_cap_parser: argument groups cannot be nested
pySim-shell currently does not work on systems with Python 3.14+:
File ".../pysim/pySim/global_platform/__init__.py", line 868, in AddlShellCommands install_cap_parser_inst_prm_g_grp = install_cap_parser_inst_prm_g.add_argument_group() File "/usr/lib/python3.14/argparse.py", line 1794, in add_argument_group raise ValueError('argument groups cannot be nested') ValueError('argument groups cannot be nested')
The problem is that install_cap_parser creates a nested group inside of mutually exclusive group. argparse never supported group nesting properly, so it has been deprecated since Python 3.11, and eventually got removed in Python 3.14.
Remove group nesting, adjust the usage string, and implement the mutual exclusiveness/inclusiveness manually in do_install_cap().
Change-Id: Idddf72d5a745345e134b23f2f01e0257d0667579 --- M pySim/global_platform/__init__.py 1 file changed, 27 insertions(+), 15 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/10/42310/1
diff --git a/pySim/global_platform/__init__.py b/pySim/global_platform/__init__.py index 8a99677..1c0d521 100644 --- a/pySim/global_platform/__init__.py +++ b/pySim/global_platform/__init__.py @@ -859,22 +859,28 @@ _rsp_hex, _sw = self._cmd.lchan.scc.send_apdu_checksw(cmd_hex) self._cmd.poutput("Loaded a total of %u bytes in %u blocks. Don't forget install_for_install (and make selectable) now!" % (total_size, block_nr))
- install_cap_parser = argparse.ArgumentParser() + install_cap_parser = argparse.ArgumentParser(usage='%(prog)s FILE (--install-parameters | --install-parameters-*)') install_cap_parser.add_argument('cap_file', type=str, metavar='FILE', help='JAVA-CARD CAP file to install') - install_cap_parser_inst_prm_g = install_cap_parser.add_mutually_exclusive_group() - install_cap_parser_inst_prm_g.add_argument('--install-parameters', type=is_hexstr, default=None, - help='install Parameters (GPC_SPE_034, section 11.5.2.3.7, table 11-49)') - install_cap_parser_inst_prm_g_grp = install_cap_parser_inst_prm_g.add_argument_group() - install_cap_parser_inst_prm_g_grp.add_argument('--install-parameters-volatile-memory-quota', - type=int, default=None, - help='volatile memory quota (GPC_SPE_034, section 11.5.2.3.7, table 11-49)') - install_cap_parser_inst_prm_g_grp.add_argument('--install-parameters-non-volatile-memory-quota', - type=int, default=None, - help='non volatile memory quota (GPC_SPE_034, section 11.5.2.3.7, table 11-49)') - install_cap_parser_inst_prm_g_grp.add_argument('--install-parameters-stk', - type=is_hexstr, default=None, - help='Load Parameters (ETSI TS 102 226, section 8.2.1.3.2.1)') + # Ideally, the parser should enforce that: + # * either the `--install-parameters` is given alone, + # * or all `--install-parameters-*` are given together. + # We tried to achieve this using mutually exclusive groups (add_mutually_exclusive_group). + # However, group nesting was never supported, often failed to work correctly, and was unintentionally + # exposed through inheritance. It has been deprecated since version 3.11, removed in version 3.14. + # Hence, we have to implement the enforcement manually. + install_cap_parser_inst_prm_grp = install_cap_parser.add_argument_group('Install Parameters') + install_cap_parser_inst_prm_grp.add_argument('--install-parameters', type=is_hexstr, default=None, + help='install Parameters (GPC_SPE_034, section 11.5.2.3.7, table 11-49)') + install_cap_parser_inst_prm_grp.add_argument('--install-parameters-volatile-memory-quota', + type=int, default=None, + help='volatile memory quota (GPC_SPE_034, section 11.5.2.3.7, table 11-49)') + install_cap_parser_inst_prm_grp.add_argument('--install-parameters-non-volatile-memory-quota', + type=int, default=None, + help='non volatile memory quota (GPC_SPE_034, section 11.5.2.3.7, table 11-49)') + install_cap_parser_inst_prm_grp.add_argument('--install-parameters-stk', + type=is_hexstr, default=None, + help='Load Parameters (ETSI TS 102 226, section 8.2.1.3.2.1)')
@cmd2.with_argparser(install_cap_parser) def do_install_cap(self, opts): @@ -888,9 +894,15 @@ load_file_aid = cap.get_loadfile_aid() module_aid = cap.get_applet_aid() application_aid = module_aid - if opts.install_parameters: + # `--install-parameters` and `--install-parameters-*` are mutually exclusive + if opts.install_parameters is not None: install_parameters = opts.install_parameters; else: + # `--install-parameters-*` are mutually inclusive + if opts.install_parameters_non_volatile_memory_quota is None or \ + opts.install_parameters_volatile_memory_quota is None or \ + opts.install_parameters_stk is None: + raise ValueError("Either --install-parameters alone, or all --install-parameters-* must be specified") install_parameters = gen_install_parameters(opts.install_parameters_non_volatile_memory_quota, opts.install_parameters_volatile_memory_quota, opts.install_parameters_stk)