Files
openide/python/helpers/pycharm/django_test_manage.py
Alexander Koshevoy 98d818cf53 Fix "ValueError: Empty module name" when project dir (first argument of django_test_manage.py) ends in a slash
Note that `os.path.basename(path)` returns an empty string (`''`) when `path` ends in a slash.

GitOrigin-RevId: e400e794d5e0de0cf29ab6796ffac5972f50eb53
2022-02-08 23:25:31 +00:00

169 lines
5.4 KiB
Python

#!/usr/bin/env python
import os
import sys
from django.core.management import ManagementUtility
from pycharm_run_utils import import_system_module
from teamcity import teamcity_presence_env_var
inspect = import_system_module("inspect")
project_directory = sys.argv.pop()
#ensure project directory is given priority when looking for settings files
sys.path.insert(0, project_directory)
#import settings to prevent circular dependencies later on import django.db
try:
from django.conf import settings
apps = settings.INSTALLED_APPS
except:
pass
from django.core import management
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(os.path.normpath(project_directory))
__import__(project_name)
except ImportError:
# project has custom structure (project directory is not importable)
pass
finally:
sys.path.pop()
manage_file = os.getenv('PYCHARM_DJANGO_MANAGE_MODULE')
if not manage_file:
manage_file = 'manage'
try:
__import__(manage_file)
except ImportError as e:
print ("Failed to import" + str(manage_file) + " in ["+ ",".join(sys.path) +"] " + str(e))
settings_file = os.getenv('DJANGO_SETTINGS_MODULE')
if not settings_file:
settings_file = 'settings'
import django
if django.VERSION >= (1, 7):
if not settings.configured:
settings.configure()
django.setup()
def _create_command():
"""
Creates PycharmTestCommand that inherits real Command class.
Wrapped to method to make it is not called when module loaded but only when django fully initialized (lazy)
"""
class PycharmTestCommand(ManagementUtility().fetch_command("test").__class__):
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
commands = 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
commands['syncdb'] = 'django.core'
elif 'south' in settings.INSTALLED_APPS:
try:
from south.management.commands import MigrateAndSyncCommand
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:
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):
our_options = {"verbosity": int(verbosity), "interactive": interactive, "failfast": failfast}
options.update(our_options)
failures = TestRunner(test_labels, **options)
else:
test_runner = TestRunner(verbosity=verbosity, interactive=interactive, failfast=failfast)
failures = test_runner.run_tests(test_labels)
if failures:
sys.exit(bool(failures))
return PycharmTestCommand()
class PycharmTestManagementUtility(ManagementUtility):
def __init__(self, argv=None):
ManagementUtility.__init__(self, argv)
def execute(self):
from django_test_runner import is_nosetest
if is_nosetest(settings):
# New way to run django-nose is to install teamcity-runners plugin
# there is no easy way to get qname in 2.7 so string is used
name = "teamcity.nose_report.TeamcityReport"
# emulate TC to enable plugin
os.environ.update({teamcity_presence_env_var: "1"})
# NOSE_PLUGINS could be list or tuple. Adding teamcity plugin to it
try:
settings.NOSE_PLUGINS += [name]
except TypeError:
settings.NOSE_PLUGINS += (name, )
except AttributeError:
settings.NOSE_PLUGINS = [name]
# This file is required to init and monkeypatch new runners
# noinspection PyUnresolvedReferences
import _jb_runner_tools
super(PycharmTestManagementUtility, self).execute()
else:
_create_command().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()