PEP8 and object initialization using long keyword
It seems to me that there is no easy way to use RawDescriptionHelpFormatter
in a module argparse
without breaking PEP8 or cluttering your namespace.
Here's the most obvious way to format it:
parser = argparse.ArgumentParser(prog='PROG', .... formatter_class=argparse.RawDescriptionHelpFormatter)
This violates the condition that lines must not exceed 80 characters
Here's what the example looks like in the documentation argparse
( spoiler: this is really correct, see comments below ):
parser = argparse.ArgumentParser(
prog='PROG',
formatter_class=argparse.RawDescriptionHelpFormatter,
....
This violates PEP8 E128 regarding continuation line indentation.
Here's another possibility:
parser = argparse.ArgumentParser(
prog='PROG',
formatter_class=
argparse.RawDescriptionHelpFormatter,
....
This violates PEP8 E251 regarding spaces around =
for keyboard arguments.
(Of course, this doesn't even say that my character number for the string assumes the token is parser
fired in the first column, which is the best scenario; what if we want to create a parser inside a class and / or a function?)
So the only remaining alternative, as far as I can tell, is to either clutter up the namespace:
from argparse import RawDescriptionHelpFormatter, ArgumentParser
... or use a silly temporary variable (which also clutters the namespace):
rawformatter = argparse.RawDescriptionHelpFormatter parser = argparse.ArgumentParser(prog='PROG', .... formatter_class=rawformatter)
Am I missing something? My guess is that the RawDescriptionHelpFormatter and ArgumentParser directly in the current namespace don't matter much, but that seems like an unnecessary frustration.
source to share
Your second example looks good to me and seems to match "# Hanging indents should add a level". An example is here: http://legacy.python.org/dev/peps/pep-0008/#indentation
Also similar to this similar question / answer: What is E128 PEP8: indented continuation line for visual indentation?
source to share
A couple of other options:
from argparse import RawDescriptionHelpFormatter as formatter
parser = argparse.ArgumentFormatter(prog='PROG')
# you can reassign a parser attribute after initialization
parser.formatter_class = formatter
But there are other inputs for ArgumentParser
that can be long enough to require carrying or assigning to individual variables.
usage = 'PROG [-h] --foo FOO BAR etc'
description = """\
This is a long multiline description
that may require dedenting.
"""
description = textwrap.dedent(description)
parser=Argparse(usage=usage, description=description, formatter_class=formatter)
Take a look at test_argparse.py
to see many ways to define a long and multifaceted parser.
http://bugs.python.org/issue13023 brings up the question of what if you want a few formatting modifications like:
This means that we can either pass argparse.RawDescriptionHelpFormatter or argparse.ArgumentDefaultsHelpFormatter, but not both.
The recommended solution is to subclass the formatter:
class MyFormatter(argparse.RawDescriptionHelpFormatter,
argparse.ArgumentDefaultsHelpformatter):
pass
Another tactic to keep the namespace clean is to wrap the parser definition in a function or module.
http://ipython.org/ipython-doc/2/api/generated/IPython.core.magic_arguments.html
is an example of how IPython
wraps can argparse
create new APIs for their users.
Another parser built on argparse
, plac
first creates a dictionary cfg
:
https://code.google.com/p/plac/source/browse/plac_core.py
def pconf(obj):
...
cfg = dict(description=obj.__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
...
return cfg
def parser_from(obj, **confparams):
...
conf = pconf(obj).copy()
conf.update(confparams)
parser = ArgumentParser(**conf)
source to share