laforge submitted this change.

View Change

Approvals: dexter: Looks good to me, approved; Verified Jenkins Builder: Verified
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 enforcement manually in do_install_cap().

Change-Id: Idddf72d5a745345e134b23f2f01e0257d0667579
---
M pySim/global_platform/__init__.py
1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/pySim/global_platform/__init__.py b/pySim/global_platform/__init__.py
index 810387b..6ff4b28 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 distinct `--install-parameters-*` are optionally given instead.
+ # 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,17 @@
load_file_aid = cap.get_loadfile_aid()
module_aid = cap.get_applet_aid()
application_aid = module_aid
- if opts.install_parameters:
+ if opts.install_parameters is not None:
+ # `--install-parameters` and `--install-parameters-*` are mutually exclusive
+ # make sure that none of `--install-parameters-*` is given; abort otherwise
+ if any(p is not None for p in [opts.install_parameters_non_volatile_memory_quota,
+ opts.install_parameters_volatile_memory_quota,
+ opts.install_parameters_stk]):
+ self.install_cap_parser.error('arguments --install-parameters-* are '
+ 'not allowed with --install-parameters')
install_parameters = opts.install_parameters;
else:
+ # `--install-parameters-*` are all optional
install_parameters = gen_install_parameters(opts.install_parameters_non_volatile_memory_quota,
opts.install_parameters_volatile_memory_quota,
opts.install_parameters_stk)

To view, visit change 42310. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Idddf72d5a745345e134b23f2f01e0257d0667579
Gerrit-Change-Number: 42310
Gerrit-PatchSet: 5
Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier@sysmocom.de>
Gerrit-Reviewer: laforge <laforge@osmocom.org>