classification
Title: Support comments in argparse fromfile_prefix_chars files
Type: enhancement Stage:
Components: Library (Lib) Versions:
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: eric.smith, nabelekt, paul.j3, rhettinger
Priority: normal Keywords:

Created on 2020-12-18 19:15 by nabelekt, last changed 2020-12-19 20:34 by nabelekt.

Messages (7)
msg383321 - (view) Author: Thomas Nabelek (nabelekt) Date: 2020-12-18 19:15
For input argument files, specified with the fromfile_prefix_chars argument to argparse.ArgumentParser, argparse should ignore lines beginning with '#' so that comments can be used in those files.
msg383330 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2020-12-18 22:43
I think you could achieve this by overriding convert_arg_line_to_args.

If this were baked in to argparse, there would need to be an argument to argparse.ArgumentParser to turn on this behavior, with the default being to not support comments. That's because enabling this by default would be a non backward compatible change.

Personally, I think argparse.ArgumentParser is already too complex, and this shouldn't be added.
msg383353 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2020-12-19 02:04
https://docs.python.org/3/library/argparse.html#customizing-file-parsing

in the docs describes how to customize the @file reading.  This particular extension handles several strings on a line, but that's not the limit of what you could do.

You can also read a file before parsing and construct a custom `argv` list, as described in https://docs.python.org/3/library/argparse.html#beyond-sys-argv
msg383396 - (view) Author: Thomas Nabelek (nabelekt) Date: 2020-12-19 19:50
While overloading convert_arg_line_to_args may work, I think that @file reading is kind of the odd ball out in not recognizing '#' as the beginning of a comment.

Besides, I'm not sure that overloading just convert_arg_line_to_args is sufficient. Here is what I have:


import argparse
import re


class ArgumentParserCustom(argparse.ArgumentParser):
    
    def convert_arg_line_to_args(self, arg_line):
    
        if re.match(r'(\s+)?#', arg_line):  # Look for any number of whitespace characters up to a `#` character
            return ['']
        else:
            return [arg_line]


If I return [''], I get:
  "error: unrecognized arguments:".

If I return [None], I get:
  File "C:\Users\tnabelek\AppData\Local\Programs\Python\Python38-32\lib\argparse.py", line 1771, in parse_args
    self.error(msg % ' '.join(argv))
TypeError: sequence item 0: expected str instance, NoneType found


Is there a better solution?
msg383397 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2020-12-19 19:53
Have you tried returning an empty list?
msg383398 - (view) Author: Thomas Nabelek (nabelekt) Date: 2020-12-19 19:59
Oh, yes, returning [] does work. Thanks guys.
msg383401 - (view) Author: Thomas Nabelek (nabelekt) Date: 2020-12-19 20:34
For anyone else, here is my implementation. I decided not to do anything to support comments on the same lines as arguments.


import argparse
import re

# Override argparse's convert_arg_line_to_args method to allow for comments and empty lines

class ArgumentParserCustom(argparse.ArgumentParser):
    
    def convert_arg_line_to_args(self, arg_line):
    
        if (re.match(r'^[\s]*#', arg_line) or   # Look for any number of whitespace characters up to a `#` character
            re.match(r'^[\s]*$', arg_line)):  # Look for lines containing nothing or just whitespace
            return []
        else:
            return [arg_line]
History
Date User Action Args
2020-12-19 20:34:04nabelektsetmessages: + msg383401
2020-12-19 19:59:21nabelektsetmessages: + msg383398
2020-12-19 19:53:36eric.smithsetmessages: + msg383397
2020-12-19 19:50:55nabelektsetmessages: + msg383396
2020-12-19 02:04:37paul.j3setmessages: + msg383353
2020-12-18 22:43:44eric.smithsetnosy: + rhettinger, paul.j3, eric.smith
messages: + msg383330
2020-12-18 19:15:45nabelektcreate