#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 , 8 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, --settingsRight. 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.