I am building a command-line program that uses argparse.
In the (assumed-to-be) rare case of a wrong call, argparse will show a description string supplied when creating the ArgumentParser.
I want this description to show the version number of my program.
I want to extract this from the pyproject.toml file via tomllib.
Since this is an expensive operation (and even more so since I want to learn how to do it), I would like the description string to be evaluated lazily: only when it is actually to be printed.
I have not yet found a way to do it even though I am willing to build a one-trick-pony object specialized for this particular value:
collections.UserStringcould provide the lazy evaluation (via overriding__getattribute__for thedataattribute), but, alas, some code inargparseusesre.sub()on it, which appears to checkisinstance(x, str), which aUserStringdoes not fulfill.- a subclass of
strcan override any operation done on a string — but not perform lazy evaluation for a plain use of the entire string. (Is this true?) - if
ArgumentParserwould usestr(description)instead ofdescriptionwhen it is about to print the description, one could supply an object that performs the lazy evaluation in its__str__method. But, alas,ArgumentParserdoes not do this.
Is there any approach that does the job?
>Solution :
In a roundabout way: don’t set description, and only set it just before ArgumentParser would format the help.
import argparse
import time
class MyArgParser(argparse.ArgumentParser):
def format_help(self):
if not self.description:
print("Now thinking hard...")
time.sleep(3)
self.description = "An application!"
return super().format_help()
ap = MyArgParser()
ap.add_argument("--foo", help="foo")
args = ap.parse_args()
print(args)
This program is fast when run without arguments, or with --foo=bar, and takes its sweet time when you run with --help.