Skip to content

Commit

Permalink
Add management commands from MODULES and SUBMODULES to help
Browse files Browse the repository at this point in the history
  • Loading branch information
mikicz committed Sep 30, 2024
1 parent 9bf5ce4 commit fe6e55d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
46 changes: 46 additions & 0 deletions src/management_commands/core.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from __future__ import annotations

import contextlib
import importlib
import pkgutil
from contextlib import suppress

from django.apps.registry import apps
Expand Down Expand Up @@ -27,6 +30,49 @@ def import_command_class(dotted_path: str) -> type[BaseCommand]:
return command_class


def _discover_commands_in_module(module: str) -> list[str]:
commands: list[str] = []
try:
files_in_dir = [
name
for _, name, is_pkg in pkgutil.iter_modules(
importlib.import_module(module).__path__,
)
if not is_pkg and not name.startswith("_")
]
except ImportError: # module doesn't exist
return commands

for file in files_in_dir:
with (
contextlib.suppress(CommandImportError),
contextlib.suppress(CommandTypeError),
):
import_command_class(f"{module}.{file}.Command")
commands.append(file)

return commands


def get_commands_from_modules_and_submodules() -> dict[str, list[str]]:
commands = {}
for module in settings.MODULES:
if module_commands := _discover_commands_in_module(module):
commands[module] = module_commands

for app in apps.get_app_configs():
for submodule in settings.SUBMODULES:
if app.name == "django.core" or submodule == "management.commands":
continue

if module_commands := _discover_commands_in_module(
f"{app.name}.{submodule}",
):
commands[app.name] = module_commands

return commands


def get_command_paths(name: str, app_label: str | None = None) -> list[str]:
if not app_label:
app_names = [
Expand Down
17 changes: 16 additions & 1 deletion src/management_commands/management.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
from __future__ import annotations

import itertools
import sys
from typing import TYPE_CHECKING

from django.core.management import ManagementUtility as BaseManagementUtility
from django.core.management.color import color_style

from .conf import settings
from .core import import_command_class, load_command_class
from .core import (
get_commands_from_modules_and_submodules,
import_command_class,
load_command_class,
)

if TYPE_CHECKING:
from django.core.management.base import BaseCommand
Expand Down Expand Up @@ -43,11 +48,21 @@ def main_help_text(self, commands_only: bool = False) -> str:
if (aliases := settings.ALIASES)
else []
)
modules = get_commands_from_modules_and_submodules()
modules_usage = (
[
style.NOTICE(f"[django-management-commands: {module}]"),
*[f" {file}" for file in modules[module]],
"",
]
for module in modules
)

usage_list = usage.split("\n")
usage_list.append("")
usage_list.extend(commands_usage)
usage_list.extend(aliases_usage)
usage_list.extend(itertools.chain(*modules_usage))

return "\n".join(usage_list)

Expand Down

0 comments on commit fe6e55d

Please sign in to comment.