Skip to content

Commit

Permalink
Fixed #8280 -- Allowed management command discovery for eggs
Browse files Browse the repository at this point in the history
Thanks jdetaeye for the report, bhuztez and jdetaeye for the
initial patches, Tim Graham and Berker Peksag for the reviews.
  • Loading branch information
claudep committed Jan 5, 2015
1 parent d94fe42 commit 6e1c9c6
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 7 deletions.
10 changes: 5 additions & 5 deletions django/core/management/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import collections
from importlib import import_module
import os
import pkgutil
import sys

import django
Expand All @@ -24,11 +25,10 @@ def find_commands(management_dir):
Returns an empty list if no commands are defined.
"""
command_dir = os.path.join(management_dir, 'commands')
try:
return [f[:-3] for f in os.listdir(command_dir)
if not f.startswith('_') and f.endswith('.py')]
except OSError:
return []
# Workaround for a Python 3.2 bug with pkgutil.iter_modules
sys.path_importer_cache.pop(command_dir, None)
return [name for _, name, is_pkg in pkgutil.iter_modules([command_dir])
if not is_pkg and not name.startswith('_')]


def load_command_class(app_name, name):
Expand Down
2 changes: 2 additions & 0 deletions docs/releases/1.8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,8 @@ Management Commands
* Database connections are now always closed after a management command called
from the command line has finished doing its job.

* Commands from alternate package formats like eggs are now also discovered.

* :djadmin:`dumpdata` now has the option :djadminopt:`--output` which allows
specifying the file to which the serialized data is written.

Expand Down
Binary file added tests/user_commands/eggs/basic.egg
Binary file not shown.
17 changes: 15 additions & 2 deletions tests/user_commands/tests.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import os

from django.apps import apps
from django.db import connection
from django.core import management
from django.core.management import BaseCommand, CommandError
from django.core.management import BaseCommand, CommandError, find_commands
from django.core.management.utils import find_command, popen_wrapper
from django.test import SimpleTestCase, ignore_warnings
from django.test.utils import captured_stderr, captured_stdout
from django.test.utils import captured_stderr, captured_stdout, extend_sys_path
from django.utils import translation
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils._os import upath
from django.utils.six import StringIO


Expand Down Expand Up @@ -72,6 +74,17 @@ def test_find_command_without_PATH(self):
if current_path is not None:
os.environ['PATH'] = current_path

def test_discover_commands_in_eggs(self):
"""
Test that management commands can also be loaded from Python eggs.
"""
egg_dir = '%s/eggs' % os.path.dirname(upath(__file__))
egg_name = '%s/basic.egg' % egg_dir
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['commandegg']):
cmds = find_commands(os.path.join(apps.get_app_config('commandegg').path, 'management'))
self.assertEqual(cmds, ['eggcommand'])

def test_call_command_option_parsing(self):
"""
When passing the long option name to call_command, the available option
Expand Down

0 comments on commit 6e1c9c6

Please sign in to comment.