Repository: django/django
File: tests/user_commands/tests.py (Python)

Code before:
            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",
            )


class CommandRunTests(AdminScriptTestCase):
    """
    Tests that need to run by simulating the command line, not by call_command.
    """

    def test_script_prefix_set_in_commands(self):
        self.write_settings(

Review comment (bug):
This test was not testing the correct output, or expecting the right correction. `suggest_on_error` does not affect mistyped options. It affects mistyped option *choices* and subparser names.

The way I'm testing it manually is:

```
$ python -m django check --fail-level EROR
...
__main__.py check: error: argument --fail-level: invalid choice: 'EROR', maybe you meant 'ERROR'? (choose from CRITICAL, ERROR, WARNING, INFO, DEBUG)
```

Note the "maybe you meant 'ERROR'?"

I don't think argparse *has* any feature to suggest for mistyped options at current. Did you see this assertion pass on any environment?

Code after:
        self.assertEqual(out.strip(), "/PREFIX/some/url/")

    def test_disallowed_abbreviated_options(self):
        """
        To avoid conflicts with custom options, commands don't allow
        abbreviated forms of the --setting and --pythonpath options.
        """
        self.write_settings("settings.py", apps=["user_commands"])
        out, err = self.run_manage(["set_option", "--set", "foo"])
        self.assertNoOutput(err)
        self.assertEqual(out.strip(), "Set foo")

    def test_skip_checks(self):
        self.write_settings(
            "settings.py",
            apps=["django.contrib.staticfiles", "user_commands"],
            sdict={
                # (staticfiles.E001) The STATICFILES_DIRS setting is not a
                # tuple or list.
                "STATICFILES_DIRS": '"foo"',
            },
        )
        out, err = self.run_manage(["set_option", "--skip-checks", "--set", "foo"])
        self.assertNoOutput(err)
        self.assertEqual(out.strip(), "Set foo")

    def test_subparser_error_formatting(self):
        self.write_settings("settings.py", apps=["user_commands"])
        out, err = self.run_manage(["subparser", "foo", "twelve"])
        self.maxDiff = None
        self.assertNoOutput(out)
        err_lines = err.splitlines()
        self.assertEqual(len(err_lines), 2)
        self.assertEqual(
            err_lines[1],
            "manage.py subparser foo: error: argument bar: invalid int value: 'twelve'",
        )

    def test_subparser_non_django_error_formatting(self):
        self.write_settings("settings.py", apps=["user_commands"])
        out, err = self.run_manage(["subparser_vanilla", "foo", "seven"])
        self.assertNoOutput(out)
        err_lines = err.splitlines()
        self.assertEqual(len(err_lines), 2)
        self.assertEqual(
            err_lines[1],
            "manage.py subparser_vanilla foo: error: argument bar: invalid int value: "
            "'seven'",
        )