From 196b2827759da3c80617418cbcdcb51f2d8ce1bc Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Fri, 8 Aug 2008 12:27:40 +0000 Subject: [PATCH] Fixed #5825 -- Modified the custom command loader to allow for explicit specification of the project name, even if the project directory isn't in the python path. This brings custom command loading into alignment with application loading. Thanks to jdetaeye@frepple.com for the original report, and to abozanich for the patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8227 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/management/__init__.py | 14 ++ tests/regressiontests/admin_scripts/tests.py | 133 +++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py index 5e01ccbbe9..1e8017e77f 100644 --- a/django/core/management/__init__.py +++ b/django/core/management/__init__.py @@ -37,7 +37,21 @@ def find_management_module(app_name): parts = app_name.split('.') parts.append('management') parts.reverse() + part = parts.pop() path = None + + # When using manage.py, the project module is added to the path, + # loaded, then removed from the path. This means that + # testproject.testapp.models can be loaded in future, even if + # testproject isn't in the path. When looking for the management + # module, we need look for the case where the project name is part + # of the app_name but the project directory itself isn't on the path. + try: + f, path, descr = find_module(part,path) + except ImportError,e: + if os.path.basename(os.getcwd()) != part: + raise e + while parts: part = parts.pop() f, path, descr = find_module(part, path and [path] or None) diff --git a/tests/regressiontests/admin_scripts/tests.py b/tests/regressiontests/admin_scripts/tests.py index f1b167eec7..0c3fc1435e 100644 --- a/tests/regressiontests/admin_scripts/tests.py +++ b/tests/regressiontests/admin_scripts/tests.py @@ -231,6 +231,72 @@ class DjangoAdminDefaultSettings(AdminScriptTestCase): self.assertNoOutput(out) self.assertOutput(err, "Unknown command: 'noargs_command'") +class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase): + """A series of tests for django-admin.py when using a settings.py file that + contains the test application specified using a full path. + """ + def setUp(self): + self.write_settings('settings.py', ['django.contrib.auth', 'django.contrib.contenttypes', 'regressiontests.admin_scripts']) + + def tearDown(self): + self.remove_settings('settings.py') + + def test_builtin_command(self): + "fulldefault: django-admin builtin commands fail with an import error when no settings provided" + args = ['sqlall','admin_scripts'] + out, err = self.run_django_admin(args) + self.assertNoOutput(out) + self.assertOutput(err, 'environment variable DJANGO_SETTINGS_MODULE is undefined') + + def test_builtin_with_settings(self): + "fulldefault: django-admin builtin commands fail if user app isn't on path" + args = ['sqlall','--settings=settings', 'admin_scripts'] + out, err = self.run_django_admin(args) + self.assertNoOutput(out) + self.assertOutput(err, 'ImportError: No module named regressiontests') + + def test_builtin_with_environment(self): + "fulldefault: django-admin builtin commands fail if user app isn't on path" + args = ['sqlall','admin_scripts'] + out, err = self.run_django_admin(args,'settings') + self.assertNoOutput(out) + self.assertOutput(err, 'ImportError: No module named regressiontests') + + def test_builtin_with_bad_settings(self): + "fulldefault: django-admin builtin commands fail if settings file (from argument) doesn't exist" + args = ['sqlall','--settings=bad_settings', 'admin_scripts'] + out, err = self.run_django_admin(args) + self.assertNoOutput(out) + self.assertOutput(err, "Could not import settings 'bad_settings'") + + def test_builtin_with_bad_environment(self): + "fulldefault: django-admin builtin commands fail if settings file (from environment) doesn't exist" + args = ['sqlall','admin_scripts'] + out, err = self.run_django_admin(args,'bad_settings') + self.assertNoOutput(out) + self.assertOutput(err, "Could not import settings 'bad_settings'") + + def test_custom_command(self): + "fulldefault: django-admin can't execute user commands" + args = ['noargs_command'] + out, err = self.run_django_admin(args) + self.assertNoOutput(out) + self.assertOutput(err, "Unknown command: 'noargs_command'") + + def test_custom_command_with_settings(self): + "fulldefault: django-admin can't execute user commands, even if settings are provided as argument" + args = ['noargs_command', '--settings=settings'] + out, err = self.run_django_admin(args) + self.assertNoOutput(out) + self.assertOutput(err, "Unknown command: 'noargs_command'") + + def test_custom_command_with_environment(self): + "fulldefault: django-admin can't execute user commands, even if settings are provided in environment" + args = ['noargs_command'] + out, err = self.run_django_admin(args,'settings') + self.assertNoOutput(out) + self.assertOutput(err, "Unknown command: 'noargs_command'") + class DjangoAdminMinimalSettings(AdminScriptTestCase): """A series of tests for django-admin.py when using a settings.py file that doesn't contain the test application. @@ -530,6 +596,73 @@ class ManageDefaultSettings(AdminScriptTestCase): self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:NoArgsCommand") + +class ManageFullPathDefaultSettings(AdminScriptTestCase): + """A series of tests for manage.py when using a settings.py file that + contains the test application specified using a full path. + """ + def setUp(self): + self.write_settings('settings.py', ['django.contrib.auth', 'django.contrib.contenttypes', 'regressiontests.admin_scripts']) + + def tearDown(self): + self.remove_settings('settings.py') + + def test_builtin_command(self): + "fulldefault: manage.py builtin commands succeed when default settings are appropriate" + args = ['sqlall','admin_scripts'] + out, err = self.run_manage(args) + self.assertNoOutput(err) + self.assertOutput(out, 'CREATE TABLE') + + def test_builtin_with_settings(self): + "fulldefault: manage.py builtin commands succeed if settings are provided as argument" + args = ['sqlall','--settings=settings', 'admin_scripts'] + out, err = self.run_manage(args) + self.assertNoOutput(err) + self.assertOutput(out, 'CREATE TABLE') + + def test_builtin_with_environment(self): + "fulldefault: manage.py builtin commands succeed if settings are provided in the environment" + args = ['sqlall','admin_scripts'] + out, err = self.run_manage(args,'settings') + self.assertNoOutput(err) + self.assertOutput(out, 'CREATE TABLE') + + def test_builtin_with_bad_settings(self): + "fulldefault: manage.py builtin commands succeed if settings file (from argument) doesn't exist" + args = ['sqlall','--settings=bad_settings', 'admin_scripts'] + out, err = self.run_manage(args) + self.assertNoOutput(out) + self.assertOutput(err, "Could not import settings 'bad_settings'") + + def test_builtin_with_bad_environment(self): + "fulldefault: manage.py builtin commands fail if settings file (from environment) doesn't exist" + args = ['sqlall','admin_scripts'] + out, err = self.run_manage(args,'bad_settings') + self.assertNoOutput(err) + self.assertOutput(out, 'CREATE TABLE') + + def test_custom_command(self): + "fulldefault: manage.py can execute user commands when default settings are appropriate" + args = ['noargs_command'] + out, err = self.run_manage(args) + self.assertNoOutput(err) + self.assertOutput(out, "EXECUTE:NoArgsCommand") + + def test_custom_command_with_settings(self): + "fulldefault: manage.py can execute user commands when settings are provided as argument" + args = ['noargs_command', '--settings=settings'] + out, err = self.run_manage(args) + self.assertNoOutput(err) + self.assertOutput(out, "EXECUTE:NoArgsCommand") + + def test_custom_command_with_environment(self): + "fulldefault: manage.py can execute user commands when settings are provided in environment" + args = ['noargs_command'] + out, err = self.run_manage(args,'settings') + self.assertNoOutput(err) + self.assertOutput(out, "EXECUTE:NoArgsCommand") + class ManageMinimalSettings(AdminScriptTestCase): """A series of tests for manage.py when using a settings.py file that doesn't contain the test application.