Opened 3 weeks ago

Closed 13 days ago

Last modified 10 days ago

#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: master
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 Changed 3 weeks ago by Carlton Gibson

Triage Stage: UnreviewedAccepted
Type: BugNew feature
Version: 2.0master

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

...this option is only available in Python 3.5 and above.

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.)

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.

Yes, probably not a biggie but could you add a note to the Breaking changes section in 2.1.txt.

Last edited 3 weeks ago by Carlton Gibson (previous) (diff)

comment:3 Changed 13 days ago by Ryan P Kilby

Thanks for the review Carlton. Added a note to the misc backwards incompatibility section.

comment:4 Changed 13 days ago by Tim Graham <timograham@…>

Resolution: fixed
Status: newclosed

In 2dcc5d62:

Fixed #29392 -- Disallowed use of abbreviated forms of --settings and --pythonpath management command options.

Note: See TracTickets for help on using tickets.
Back to Top