1#!/usr/bin/env python 2 3import os 4import sys 5 6from django.core.management import ManagementUtility 7 8from pycharm_run_utils import import_system_module 9from teamcity import teamcity_presence_env_var 10 11inspect = import_system_module("inspect") 12 13project_directory = sys.argv.pop() 14 15#ensure project directory is given priority when looking for settings files 16sys.path.insert(0, project_directory) 17 18#import settings to prevent circular dependencies later on import django.db 19try: 20 from django.conf import settings 21 apps = settings.INSTALLED_APPS 22except: 23 pass 24 25from django.core import management 26 27try: 28 # setup environment 29 # this stuff was done earlier by setup_environ() which was removed in 1.4 30 sys.path.append(os.path.join(project_directory, os.pardir)) 31 project_name = os.path.basename(project_directory) 32 __import__(project_name) 33except ImportError: 34 # project has custom structure (project directory is not importable) 35 pass 36finally: 37 sys.path.pop() 38 39manage_file = os.getenv('PYCHARM_DJANGO_MANAGE_MODULE') 40if not manage_file: 41 manage_file = 'manage' 42 43try: 44 __import__(manage_file) 45except ImportError as e: 46 print ("Failed to import" + str(manage_file) + " in ["+ ",".join(sys.path) +"] " + str(e)) 47 48settings_file = os.getenv('DJANGO_SETTINGS_MODULE') 49if not settings_file: 50 settings_file = 'settings' 51 52import django 53if django.VERSION >= (1, 7): 54 if not settings.configured: 55 settings.configure() 56 django.setup() 57 58 59def _create_command(): 60 """ 61 62 Creates PycharmTestCommand that inherits real Command class. 63 Wrapped to method to make it is not called when module loaded but only when django fully initialized (lazy) 64 65 """ 66 class PycharmTestCommand(ManagementUtility().fetch_command("test").__class__): 67 def get_runner(self): 68 TEST_RUNNER = 'django_test_runner.run_tests' 69 test_path = TEST_RUNNER.split('.') 70 # Allow for Python 2.5 relative paths 71 if len(test_path) > 1: 72 test_module_name = '.'.join(test_path[:-1]) 73 else: 74 test_module_name = '.' 75 test_module = __import__(test_module_name, {}, {}, test_path[-1]) 76 test_runner = getattr(test_module, test_path[-1]) 77 return test_runner 78 79 def handle(self, *test_labels, **options): 80 # handle south migration in tests 81 commands = management.get_commands() 82 if hasattr(settings, "SOUTH_TESTS_MIGRATE") and not settings.SOUTH_TESTS_MIGRATE: 83 # point at the core syncdb command when creating tests 84 # tests should always be up to date with the most recent model structure 85 commands['syncdb'] = 'django.core' 86 elif 'south' in settings.INSTALLED_APPS: 87 try: 88 from south.management.commands import MigrateAndSyncCommand 89 commands['syncdb'] = MigrateAndSyncCommand() 90 from south.hacks import hacks 91 if hasattr(hacks, "patch_flush_during_test_db_creation"): 92 hacks.patch_flush_during_test_db_creation() 93 except ImportError: 94 commands['syncdb'] = 'django.core' 95 96 verbosity = int(options.get('verbosity', 1)) 97 interactive = options.get('interactive', True) 98 failfast = options.get('failfast', False) 99 TestRunner = self.get_runner() 100 101 if not inspect.ismethod(TestRunner): 102 our_options = {"verbosity": int(verbosity), "interactive": interactive, "failfast": failfast} 103 options.update(our_options) 104 failures = TestRunner(test_labels, **options) 105 else: 106 test_runner = TestRunner(verbosity=verbosity, interactive=interactive, failfast=failfast) 107 failures = test_runner.run_tests(test_labels) 108 109 if failures: 110 sys.exit(bool(failures)) 111 112 return PycharmTestCommand() 113 114 115class PycharmTestManagementUtility(ManagementUtility): 116 def __init__(self, argv=None): 117 ManagementUtility.__init__(self, argv) 118 119 def execute(self): 120 from django_test_runner import is_nosetest 121 if is_nosetest(settings) and "_JB_USE_OLD_RUNNERS" not in os.environ: 122 # New way to run django-nose is to install teamcity-runners plugin 123 # there is no easy way to get qname in 2.7 so string is used 124 name = "teamcity.nose_report.TeamcityReport" 125 126 # emulate TC to enable plugin 127 os.environ.update({teamcity_presence_env_var: "1"}) 128 129 # NOSE_PLUGINS could be list or tuple. Adding teamcity plugin to it 130 try: 131 settings.NOSE_PLUGINS += [name] 132 except TypeError: 133 settings.NOSE_PLUGINS += (name, ) 134 except AttributeError: 135 settings.NOSE_PLUGINS = [name] 136 137 # This file is required to init and monkeypatch new runners 138 # noinspection PyUnresolvedReferences 139 import _jb_runner_tools 140 super(PycharmTestManagementUtility, self).execute() 141 else: 142 _create_command().run_from_argv(self.argv) 143 144 145if __name__ == "__main__": 146 147 try: 148 custom_settings = __import__(settings_file) 149 splitted_settings = settings_file.split('.') 150 if len(splitted_settings) != 1: 151 settings_name = '.'.join(splitted_settings[:-1]) 152 settings_module = __import__(settings_name, globals(), locals(), [splitted_settings[-1]]) 153 custom_settings = getattr(settings_module, splitted_settings[-1]) 154 155 except ImportError: 156 print ("There is no such settings file " + str(settings_file) + "\n") 157 158 try: 159 subcommand = sys.argv[1] 160 except IndexError: 161 subcommand = 'help' # Display help if no arguments were given. 162 163 if subcommand == 'test': 164 utility = PycharmTestManagementUtility(sys.argv) 165 else: 166 utility = ManagementUtility() 167 168 utility.execute() 169