Skip to content

@cmd2.with_argparser: parser's prog value #1414

Closed
@fixeria

Description

@fixeria

In Osmocom, we use cmd2 in pysim — command-line tools for SIM/UICC/USIM/ISIM card analysis and programming. For documentation, we rely on sphinx together with sphinx-argparse to auto-generate docs for each cmd2 command.

This setup has worked well until recently, but we've started seeing artifacts in the generated documentation:

https://ftp.osmocom.org/docs/pysim/master/osmopysim-usermanual.pdf#subsubsection*.56

change_chv

usage: build.py [-h] [--pin-nr PIN_NR] [NEWPIN] [PIN]

Suddenly we're getting build.py instead of the command name (change_chv) in usage.

The usage we're getting when actually running the program looks good:

pySIM-shell (00:MF)> change_chv --help
usage: change_chv [-h] [--pin-nr PIN_NR] [NEWPIN] [PIN]
 
Change PIN code to a new PIN code
 
positional arguments:
  NEWPIN           PIN code value. If none given, CSV file will be queried
  PIN              PIN code value. If none given, CSV file will be queried
 
options:
  -h, --help       show this help message and exit
  --pin-nr PIN_NR  PUK Number, 1=PIN1, 2=PIN2 or custom value (decimal)

Below is definition of the change_chv command:

https://gitea.osmocom.org/sim-card/pysim/src/commit/949c2a2d579943f5286e1f4505be0835f149eab6/pySim-shell.py#L950

@with_default_category('ISO7816 Commands')
class Iso7816Commands(CommandSet):
    # ...
    change_chv_parser = argparse.ArgumentParser()
    change_chv_parser.add_argument('NEWPIN', nargs='?', type=is_decimal,
                                   help='PIN code value. If none given, CSV file will be queried')
    change_chv_parser.add_argument('PIN', nargs='?', type=is_decimal,
                                   help='PIN code value. If none given, CSV file will be queried')
    change_chv_parser.add_argument(
        '--pin-nr', type=int, default=1, help='PUK Number, 1=PIN1, 2=PIN2 or custom value (decimal)')
 
    @cmd2.with_argparser(change_chv_parser)
    def do_change_chv(self, opts):
        """Change PIN code to a new PIN code"""
        new_pin = self.get_code(opts.NEWPIN, "PIN" + str(opts.pin_nr))
        pin = self.get_code(opts.PIN, "PIN" + str(opts.pin_nr))
        (data, sw) = self._cmd.lchan.scc.change_chv(
            opts.pin_nr, h2b(pin), h2b(new_pin))
        self._cmd.poutput("CHV change successful")
 
    print(f'prog={change_chv_parser.prog}') # XXX: debug

I figured out that @cmd2.with_argparser (actually _set_parser_prog()) is in charge of updating the prog attribute.
Sphinx is using this attribute to generate the usage.

  • v2.4.3 was the last version to retain the old behavior (prog=change_chv).
  • v2.5.0 exhibits the new behavior (prog=build.py).

git-bisect pointed out to 8d88c35:

8d88c357ca0764b114c68d8175d2cd33146b83d7 is the first bad commit
commit 8d88c357ca0764b114c68d8175d2cd33146b83d7 (HEAD)
Author: Eric Lin
Date:   Mon Sep 25 17:44:21 2023 -0400
 
    Changed with_argparser() and as_subcommand_to() to accept either an ArgumentParser or a
    factory callable that returns an ArgumentParser.
    Changed Cmd constructor to construct an instance-specific ArgumentParser using either the factory callable
    or by deep-copying the provided ArgumentParser.
    With this change a new argparse instance should be created for each instance of Cmd.
    
    Addresses #1002

Apparently we end up with prog=__name__ after this commit. This looks like a side-effect.

For the record, here's our internal ticket: https://osmocom.org/issues/6776.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions