#29392 closed New feature (fixed)
Command parsing does not handle options that conflict with `--settings`/`--pythonpath`
Reported by: | Ryan P Kilby | Owned by: | nobody |
---|---|---|---|
Component: | Core (Management commands) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
Argparse performs prefix matching when arguments are unambiguous (e.g., --set=my.settings
and --settings=my.settings
are both valid). Since --settings
and --pythonpath
are parsed before the command is fetched, conflicting/ambiguous command options are not checked. For example, if I have a command for getting/setting config values, the result of using the --set
option is:
$ python manage.py config --set foo bar Traceback (most recent call last): File "manage.py", line 20, in <module> execute_from_command_line(sys.argv) File ".venv/lib/python3.6/site-packages/django/core/management/__init__.py", line 364, in execute_from_command_line utility.execute() File ".venv/lib/python3.6/site-packages/django/core/management/__init__.py", line 308, in execute settings.INSTALLED_APPS File ".venv/lib/python3.6/site-packages/django/conf/__init__.py", line 56, in __getattr__ self._setup(name) File ".venv/lib/python3.6/site-packages/django/conf/__init__.py", line 41, in _setup self._wrapped = Settings(settings_module) File ".venv/lib/python3.6/site-packages/django/conf/__init__.py", line 110, in __init__ mod = importlib.import_module(self.SETTINGS_MODULE) File "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 978, in _gcd_import File "<frozen importlib._bootstrap>", line 961, in _find_and_load File "<frozen importlib._bootstrap>", line 948, in _find_and_load_unlocked ModuleNotFoundError: No module named 'foo'
One solution would be to set allow_abbrev to False
, which would disable prefix matching. However, this option is only available in Python 3.5 and above. Also, this might be considered a breaking change if users are expecting to be able to use the abbreviated option names, but I don't know if that's really a concern.
Change History (3)
comment:1 by , 7 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Type: | Bug → New feature |
Version: | 2.0 → master |
comment:3 by , 7 years ago
Thanks for the review Carlton. Added a note to the misc backwards incompatibility section.
Hi Ryan. Thanks for the report. This seems reasonable.
Interestingly, with the patch, if you pass an abbreviation to second parser you get the error you'd expect:
manage.py config: error: ambiguous option: --se could match --set, --settings
Right. For that reason lets call this a New Feature and roll it into 2.1, where we don't have to worry about compat. (This has existed for ≈forever so I can't see the harm in holding off slightly.)
Yes, probably not a biggie but could you add a note to the Breaking changes section in
2.1.txt
.