This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: argparse : allow_abbrev behavior between 3.7 and 3.8
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.8
process
Status: closed Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Fox214, paul.j3, petr.viktorin, r1kk3r, rhettinger, xtreak
Priority: normal Keywords:

Created on 2020-08-12 18:10 by r1kk3r, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
msg375276 - (view) Author: (r1kk3r) Date: 2020-08-12 18:10
I looked into changelog and the source code to see if the behavior was wanted but I was not able to see the source of the issue.

import argparse
parser = argparse.ArgumentParser(allow_abbrev=True)
parser.add_argument('-o', type=str, required=True, dest="bla", help="bla")
known_args, rest_of_args = parser.parse_known_args(["-o", "test1", "-object_lto", "test2"])
print(rest_of_args)

Executing with python 3.7.8

With allow_abbrev=True:

['test2']

allow_abbrev=False:

['-object_lto', 'test2']


Executed with python 3.8.5

With allow_abbrev=True:

['test2']

allow_abbrev=False:

['test2']


Is it expected? How do I get the behavior of python 3.7 in python 3.8?
msg375292 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2020-08-13 06:27
Bisection tells me this was introduced with commit b1e4d1b6032d4c82b549233fa08a2c7cfe7e818b in issue26967
msg375848 - (view) Author: (r1kk3r) Date: 2020-08-24 15:02
Another issue:

parser = argparse.ArgumentParser(allow_abbrev=False)
parser.add_argument('-verbose', type=int, required=True, dest="bla", help="bla")
known_args, rest_of_args = parser.parse_known_args(["-v", "-verbose=2"])

With python 3.8.5

test.py: error: argument -verbose: expected one argument

With python 3.7.8

<no error>


This is really annoying. Argparse tries to do "smart" things where it shouldn't. I want it to parse -verbose, I never told him that -v is an alias for -verbose...
msg375870 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2020-08-25 03:18
In your first example:

In [29]: parser = argparse39.ArgumentParser(allow_abbrev=True)                  
In [30]: parser.add_argument('-o');                                             

In [32]: parser.parse_known_args(['-o','test'])                                 
Out[32]: (Namespace(o='test'), [])

In [33]: parser.parse_known_args(['-object','test'])                            
Out[33]: (Namespace(o='bject'), ['test'])

Here the '-object' is interpreted as '-o' flag, with value the rest of the string.  That's normal behavior for a short option.

In [34]: parser.parse_known_args(['-o','test1','-object','test2'])              
Out[34]: (Namespace(o='bject'), ['test2'])

Same thing only '-object' has overwritten the 'test1' value.

In your second example:

In [39]: parser = argparse39.ArgumentParser(allow_abbrev=False)                 
In [40]: parser.add_argument('-verbose');                                       

In [42]: parser.parse_known_args(['-v', '-verbose=2'])                          
usage: ipython3 [-h] [-verbose VERBOSE]
ipython3: error: argument -verbose: expected one argument

Expected uses:

In [46]: parser.parse_known_args(['-verbose','two'])                            
Out[46]: (Namespace(verbose='two'), [])
In [47]: parser.parse_known_args(['-verbose=2'])                                
Out[47]: (Namespace(verbose='2'), [])

The '-ver' is not accepted as abbreviation:

In [48]: parser.parse_known_args(['-ver=2'])                                    
Out[48]: (Namespace(verbose=None), ['-ver=2'])

'allow_abbrev' doesn't have effect because of '-verbose'

If instead I define '--verbose', I can turn the abbrev on/off:

In [49]: parser = argparse39.ArgumentParser(allow_abbrev=False)                 
In [50]: parser.add_argument('--verbose');                                      
In [51]: parser.parse_known_args(['-ver=2'])                                    
Out[51]: (Namespace(verbose=None), ['-ver=2'])
In [52]: parser.parse_known_args(['--ver=2'])                                   
Out[52]: (Namespace(verbose=None), ['--ver=2'])
In [53]: parser.allow_abbrev=True                                               
In [54]: parser.parse_known_args(['--ver=2'])                                   
Out[54]: (Namespace(verbose='2'), [])

There are a lot of variations to examine here.  The original, the 3.7, and 3.8 versions.  abbrev False or True.  Proper long option (--), improper etc.
msg376202 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2020-09-01 18:31
I'm going to close this.  3.8 works as expected/documented, provided we use the normal  double dash protocol for long options.  Single dash is best reserved for single character options, where chaining is allowed.
msg410236 - (view) Author: Steve Fox (Fox214) Date: 2022-01-10 17:54
Fundamentally the use of allow_abbrev=False is now broken (it is allowing abbreviations when already explicitly told not to)

The use of a single - for all options is much older than -- and exists in my unix utilities and many programs have been written to follow this convention, these are now broken in 3.8+

"Changed in version 3.8: In previous versions, allow_abbrev also disabled grouping of short flags such as -vv to mean -v -v"

Does not accurately describe the behavior change, it is more broadly injecting abbreviations when already told not to.
History
Date User Action Args
2022-04-11 14:59:34adminsetgithub: 85706
2022-01-10 17:54:16Fox214setnosy: + Fox214
messages: + msg410236
2020-09-01 18:31:21paul.j3setstatus: open -> closed

messages: + msg376202
stage: resolved
2020-08-25 03:18:27paul.j3setmessages: + msg375870
2020-08-24 15:02:10r1kk3rsetmessages: + msg375848
2020-08-13 08:03:30ned.deilysetnosy: + petr.viktorin
2020-08-13 06:27:22xtreaksetnosy: + xtreak
messages: + msg375292
2020-08-13 03:49:28shihai1991setnosy: + rhettinger, paul.j3
2020-08-12 18:10:13r1kk3rcreate