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 replaces \$ with $ (if in commandline)
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.3
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: ezio.melotti, pitrou, r.david.murray, telmich
Priority: normal Keywords:

Created on 2013-10-29 09:43 by telmich, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (6)
msg201614 - (view) Author: (telmich) Date: 2013-10-29 09:43
When using argparse and the string \$ occurs on the commandline, it is converted to $. This as definitely wrong and renders argparse useless, if the input needs to be trusted (i.e. defitinely the same as given into it)'

Example code:

import sys 
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('test', nargs='*')
result = parser.parse_args(sys.argv[1:])

print("args = %s" % " ".join(sys.argv))
print("result = %s" % result)

Reproduce problem:

[10:41] bento:~% python3 argparse-test.py ps1  "PS1='[\t] \[\033[1m\]\h\[\033[0m\]:\w\$ '"
] \[\]\h\[\]:\w\$ '"args = argparse-test.py ps1 PS1='[\t] \[\033[1m\]\h\[\033[0m\]:\w$ '
result = Namespace(test=['ps1', "PS1='[\\t] \\[\\033[1m\\]\\h\\[\\033[0m\\]:\\w$ '"])

[10:40] bento:cdist% python --version
Python 3.3.2
msg201616 - (view) Author: (telmich) Date: 2013-10-29 09:45
Background information:

cdist is written in python 3 and makes heavy use of argparse.
One common task is to run a cdist type with some arguments, which
in the end configure a remote system.

We triggered the bug by running

__line ps1 --file /etc/bash.bashrc --line "PS1='[\t] \[\033[1m\]\h\[\033[0m\]:\w\$ '"

which should have ensured that the line is found in /etc/bash.bashrc.

But in reality we found

PS1='[\t] \[\033[1m\]\h\[\033[0m\]:\w$ '

instead of

PS1='[\t] \[\033[1m\]\h\[\033[0m\]:\w\$ '

This is a rather nasty bug, as you would not suspect argparse doing that and dig through all your code looking for errors.
msg201617 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2013-10-29 09:49
I don't think this is related to argparse:
$ echo 'import sys; print(sys.argv)' > issue19430.py
$ python issue19430.py ps1 --file /etc/bash.bashrc --line "PS1='[\t] \[\033[1m\]\h\[\033[0m\]:\w\$ '"
['issue19430.py', 'ps1', '--file', '/etc/bash.bashrc', '--line', "PS1='[\\t] \\[\\033[1m\\]\\h\\[\\033[0m\\]:\\w$ '"]
$ python issue19430.py "\$"
['issue19430.py', '$']
$ python issue19430.py '\$'
['issue19430.py', '\\$']
msg201621 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-10-29 10:51
Indeed, this sounds very much like the shell doing the unescaping, rather than argparse.
(I wonder why argparse would special-case $, anyway)
msg201628 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-10-29 12:17
Indeed, you can see in the original posting that the \ is already gone from the dollar in sys.argv, so argparse has nothing to do with it.

And it is indeed the shell doing the unescaping:

rdmurray@session:~>cat test.sh
#!/bin/bash
echo "$@"
rdmurray@session:~>bash test.sh "abc [\t] \$"
abc [\t] $
rdmurray@session:~>bash test.sh 'abc [\t] \$'
abc [\t] \$
rdmurray@session:~>bash test.sh 'abc [\t] \$'
abc [\t] \$
rdmurray@session:~>bash test.sh "'abc [\t] \$'"
'abc [\t] $'
rdmurray@session:~>bash test.sh "'abc [\t] \\$'"
'abc [\t] \$'
rdmurray@session:~>bash test.sh "'abc [\t] \\$foo'"
'abc [\t] \'
rdmurray@session:~>bash test.sh '"abc [\t] \\\$foo"'
"abc [\t] \\\$foo"
rdmurray@session:~>bash test.sh '"abc [\t] \$foo"'  
"abc [\t] \$foo"

The shell treats $ specially because $ has a special meaning inside double quotes (variable substitution), so it presumably unescapes it as part of the double quote string processing.  You have to escape both the backslash and the $ if you want a literal '\$' to wind up in argv, when the outer level of quoting is double quotes.
msg201631 - (view) Author: (telmich) Date: 2013-10-29 12:44
sorry for the noise, it was too early in the morning!
History
Date User Action Args
2022-04-11 14:57:52adminsetgithub: 63629
2013-10-29 12:44:17telmichsetmessages: + msg201631
2013-10-29 12:17:20r.david.murraysetmessages: - msg201627
2013-10-29 12:17:04r.david.murraysetmessages: + msg201628
2013-10-29 12:14:47r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg201627

resolution: not a bug
stage: resolved
2013-10-29 10:51:47pitrousetnosy: + pitrou
messages: + msg201621
2013-10-29 09:49:56ezio.melottisetnosy: + ezio.melotti
messages: + msg201617
2013-10-29 09:45:56telmichsetmessages: + msg201616
2013-10-29 09:43:29telmichsettitle: argparse replaces \$ to is passed -> argparse replaces \$ with $ (if in commandline)
2013-10-29 09:43:13telmichcreate