mirror of
https://github.com/django/django.git
synced 2025-11-17 18:48:15 +00:00
Fixed #36321 -- Added argparse suggest_on_error support for Python 3.14.
When running Django management commands on Python 3.14, argparse's suggest_on_error feature is now enabled. This provides helpful suggestions for mistyped subparser names and argument choices.
This commit is contained in:
parent
e395caf7f7
commit
987d418ae2
4 changed files with 14 additions and 69 deletions
|
|
@ -15,7 +15,7 @@ from django.core import checks
|
|||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.management.color import color_style, no_style
|
||||
from django.db import DEFAULT_DB_ALIAS, connections
|
||||
from django.utils.version import PY314
|
||||
from django.utils.version import PY314, PY315
|
||||
|
||||
ALL_CHECKS = "__all__"
|
||||
|
||||
|
|
@ -58,8 +58,7 @@ class CommandParser(ArgumentParser):
|
|||
):
|
||||
self.missing_args_message = missing_args_message
|
||||
self.called_from_command_line = called_from_command_line
|
||||
# Enable suggest_on_error for Python 3.14+
|
||||
if PY314 and called_from_command_line:
|
||||
if PY314 and not PY315:
|
||||
kwargs.setdefault("suggest_on_error", True)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ PY311 = sys.version_info >= (3, 11)
|
|||
PY312 = sys.version_info >= (3, 12)
|
||||
PY313 = sys.version_info >= (3, 13)
|
||||
PY314 = sys.version_info >= (3, 14)
|
||||
PY315 = sys.version_info >= (3, 15)
|
||||
|
||||
|
||||
def get_version(version=None):
|
||||
|
|
|
|||
|
|
@ -225,10 +225,9 @@ Logging
|
|||
Management Commands
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Management commands now use argparse's ``suggest_on_error`` feature when
|
||||
running on Python 3.14+. This provides helpful suggestions when command-line
|
||||
arguments are misspelled. For example, ``--verbositty`` will suggest
|
||||
``--verbosity``.
|
||||
* Management commands now set :class:`~argparse.ArgumentParser`\'s
|
||||
``suggest_on_error`` argument to ``True`` by default on Python 3.14, enabling
|
||||
suggestions for mistyped subcommand names and argument choices.
|
||||
|
||||
Migrations
|
||||
~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ from django.db import connection
|
|||
from django.test import SimpleTestCase, override_settings
|
||||
from django.test.utils import captured_stderr, extend_sys_path
|
||||
from django.utils import translation
|
||||
from django.utils.version import PY314
|
||||
from django.utils.version import PY314, PY315
|
||||
|
||||
from .management.commands import dance
|
||||
from .utils import AssertFormatterFailureCaughtContext
|
||||
|
|
@ -456,79 +456,25 @@ class CommandTests(SimpleTestCase):
|
|||
self.assertIn("Working...", out.getvalue())
|
||||
self.assertIs(mocked_flush.called, True)
|
||||
|
||||
|
||||
class SuggestOnErrorTests(SimpleTestCase):
|
||||
"""
|
||||
Tests for argparse suggest_on_error feature on Python 3.14+.
|
||||
"""
|
||||
|
||||
def test_parser_kwargs_suggest_on_error_on_python_314_plus(self):
|
||||
@unittest.skipUnless(PY314 and not PY315, "Requires Python 3.14")
|
||||
def test_suggest_on_error_defaults_true(self):
|
||||
"""
|
||||
CommandParser sets suggest_on_error=True on Python 3.14+.
|
||||
CommandParser sets suggest_on_error=True on Python 3.14.
|
||||
"""
|
||||
command = BaseCommand()
|
||||
command._called_from_command_line = True # ADD THIS LINE
|
||||
parser = command.create_parser("prog_name", "subcommand")
|
||||
self.assertTrue(parser.suggest_on_error)
|
||||
|
||||
if PY314:
|
||||
self.assertTrue(
|
||||
getattr(parser, "suggest_on_error", False),
|
||||
"Parser should have suggest_on_error=True on Python 3.14+",
|
||||
)
|
||||
|
||||
@unittest.skipUnless(PY314, "Requires Python 3.14+")
|
||||
def test_custom_suggest_on_error_respected(self):
|
||||
@unittest.skipUnless(PY314 and not PY315, "Requires Python 3.14")
|
||||
def test_suggest_on_error_custom(self):
|
||||
"""
|
||||
Explicit suggest_on_error=False is respected.
|
||||
"""
|
||||
command = BaseCommand()
|
||||
command._called_from_command_line = True # ADD THIS LINE
|
||||
parser = command.create_parser(
|
||||
"prog_name", "subcommand", suggest_on_error=False
|
||||
)
|
||||
self.assertFalse(
|
||||
parser.suggest_on_error,
|
||||
"Explicit suggest_on_error=False is respected",
|
||||
)
|
||||
|
||||
@unittest.skipUnless(PY314, "Requires Python 3.14+")
|
||||
def test_misspelled_option_suggests_correct_option(self):
|
||||
"""
|
||||
On Python 3.14+, misspelled options trigger suggestions when available.
|
||||
"""
|
||||
command = BaseCommand()
|
||||
command._called_from_command_line = True
|
||||
parser = command.create_parser("django-admin", "test")
|
||||
|
||||
err = StringIO()
|
||||
with mock.patch("sys.stderr", err):
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
parser.parse_args(["--verbositty", "2"])
|
||||
self.assertEqual(cm.exception.code, 2)
|
||||
|
||||
error_output = err.getvalue().lower()
|
||||
# Ensure it failed for the right reason
|
||||
self.assertIn("unrecognized arguments", error_output)
|
||||
|
||||
# On Python 3.14+, suggestions *may* appear depending on environment
|
||||
if "did you mean" in error_output:
|
||||
self.assertIn("--verbosity", error_output)
|
||||
|
||||
def test_suggest_on_error_works_with_management_commands(self):
|
||||
"""
|
||||
Management commands have suggest_on_error on Python 3.14+.
|
||||
"""
|
||||
from .management.commands.dance import Command as DanceCommand
|
||||
|
||||
dance_cmd = DanceCommand()
|
||||
dance_cmd._called_from_command_line = True # ADD THIS LINE
|
||||
parser = dance_cmd.create_parser("django-admin", "dance")
|
||||
|
||||
if PY314:
|
||||
self.assertTrue(
|
||||
getattr(parser, "suggest_on_error", False),
|
||||
"Management command parsers should have suggest_on_error=True",
|
||||
)
|
||||
self.assertFalse(parser.suggest_on_error)
|
||||
|
||||
|
||||
class CommandRunTests(AdminScriptTestCase):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue