Skip to content

Instantly share code, notes, and snippets.

@kklimonda
Last active April 26, 2018 10:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kklimonda/5323714 to your computer and use it in GitHub Desktop.
Save kklimonda/5323714 to your computer and use it in GitHub Desktop.
A custom django_test_manage.py for PyCharm 2.7 that adds support for running Django tests for projects that use Buildout. Two things had to be done. First, python egg paths from the buildout script have to be added. Some AST magic does that. Second, the working directory gets mangled because "manage.py" script resides in <<project root>>/bin, so…
#!/usr/bin/env python
import os
def _inject_buildout_modules(buildout_script):
import sys
import ast
with open(buildout_script, 'r') as fh:
content = fh.read()
tree = ast.parse(content)
for item in tree.body:
if isinstance(item, ast.Assign) and isinstance(item.value, ast.List):
modules = item.value.elts
module_paths = [module.s for module in modules]
sys.path[0:0] = module_paths
buildout_script = os.getenv('PYCHARM_BUILDOUT_SCRIPT', None)
if buildout_script:
_inject_buildout_modules(buildout_script)
from django.core.management import ManagementUtility
import inspect
import sys
project_directory = sys.argv.pop()
sys.path.insert(0, project_directory)
try:
# setup environment
# this stuff was done earlier by setup_environ() which was removed in 1.4
sys.path.append(os.path.join(project_directory, os.pardir))
project_name = os.path.basename(project_directory)
__import__(project_name)
sys.path.pop()
except ImportError:
# project has custom structure (project directory is not importable)
pass
os.chdir(project_directory)
manage_file = os.getenv('PYCHARM_DJANGO_MANAGE_MODULE')
if not manage_file:
manage_file = 'manage'
try:
__import__(manage_file)
except ImportError:
print ("There is no such manage file " + str(manage_file) + "\n")
os.chdir('..')
settings_file = os.getenv('DJANGO_SETTINGS_MODULE')
if not settings_file:
settings_file = 'settings'
from django.core import management
from django.core.management.commands.test import Command
from django.conf import settings
class PycharmTestCommand(Command):
def get_runner(self):
TEST_RUNNER = 'django_test_runner.run_tests'
test_path = TEST_RUNNER.split('.')
# Allow for Python 2.5 relative paths
if len(test_path) > 1:
test_module_name = '.'.join(test_path[:-1])
else:
test_module_name = '.'
test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1])
return test_runner
def handle(self, *test_labels, **options):
# handle south migration in tests
management.get_commands()
if hasattr(settings, "SOUTH_TESTS_MIGRATE") and not settings.SOUTH_TESTS_MIGRATE:
# point at the core syncdb command when creating tests
# tests should always be up to date with the most recent model structure
management._commands['syncdb'] = 'django.core'
elif 'south' in settings.INSTALLED_APPS:
try:
from south.management.commands import MigrateAndSyncCommand
management._commands['syncdb'] = MigrateAndSyncCommand()
from south.hacks import hacks
if hasattr(hacks, "patch_flush_during_test_db_creation"):
hacks.patch_flush_during_test_db_creation()
except ImportError:
management._commands['syncdb'] = 'django.core'
verbosity = int(options.get('verbosity', 1))
interactive = options.get('interactive', True)
failfast = options.get('failfast', False)
TestRunner = self.get_runner()
if not inspect.ismethod(TestRunner):
failures = TestRunner(test_labels, verbosity=verbosity, interactive=interactive, failfast=failfast)
else:
test_runner = TestRunner(verbosity=verbosity, interactive=interactive, failfast=failfast)
failures = test_runner.run_tests(test_labels)
if failures:
sys.exit(bool(failures))
class PycharmTestManagementUtility(ManagementUtility):
def __init__(self, argv=None):
ManagementUtility.__init__(self, argv)
def execute(self):
PycharmTestCommand().run_from_argv(self.argv)
if __name__ == "__main__":
try:
custom_settings = __import__(settings_file)
splitted_settings = settings_file.split('.')
if len(splitted_settings) != 1:
settings_name = '.'.join(splitted_settings[:-1])
settings_module = __import__(settings_name, globals(), locals(), [splitted_settings[-1]])
custom_settings = getattr(settings_module, splitted_settings[-1])
except ImportError:
print ("There is no such settings file " + str(settings_file) + "\n")
try:
subcommand = sys.argv[1]
except IndexError:
subcommand = 'help' # Display help if no arguments were given.
if subcommand == 'test':
utility = PycharmTestManagementUtility(sys.argv)
else:
utility = ManagementUtility()
utility.execute()
@malteos
Copy link

malteos commented Apr 26, 2018

Thanks for sharing. How can this be added into PyCharm without overriding the existing django_test_manage.py?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment