diff --git a/python/helpers/pycharm/_jb_manage_tasks_provider.py b/python/helpers/pycharm/_jb_manage_tasks_provider.py index 78b312643505..f0c72578ac26 100644 --- a/python/helpers/pycharm/_jb_manage_tasks_provider.py +++ b/python/helpers/pycharm/_jb_manage_tasks_provider.py @@ -4,13 +4,18 @@ This is an entry point of this helper. It fetches data from Django manage commands delegating calles to _parser package report it via _xml module. See _xml module and readme.txt for more info. +One may also add list of commands, separated with comma as argument. This is a list of commands to skip. +Could be useful if you know command may lead to freeze + Module can be called directly, but be sure env var DJANGO_SETTINGS_MODULE is set to something like "mysite.settings" """ + import django from django_manage_commands_provider._parser import parser from django_manage_commands_provider import _xml +import sys __author__ = 'Ilya.Kazakevich' @@ -19,5 +24,6 @@ __author__ = 'Ilya.Kazakevich' if hasattr(django, 'setup'): django.setup() dumper = _xml.XmlDumper() -parser.report_data(dumper) +commands_to_skip = str(sys.argv[1]).split(",") if len(sys.argv) > 1 else [] +parser.report_data(dumper, commands_to_skip) print(dumper.xml) \ No newline at end of file diff --git a/python/helpers/pycharm/django_manage_commands_provider/_parser/parser.py b/python/helpers/pycharm/django_manage_commands_provider/_parser/parser.py index 0e638841070b..d454c39d86c9 100644 --- a/python/helpers/pycharm/django_manage_commands_provider/_parser/parser.py +++ b/python/helpers/pycharm/django_manage_commands_provider/_parser/parser.py @@ -3,33 +3,61 @@ Exports data from optparse or argparse based manage.py commands and reports it to _xml.XmlDumper. This module encapsulates Django semi-public API knowledge, and not very stable because of it. """ -from django.core.exceptions import ImproperlyConfigured -from django.core.management import ManagementUtility, get_commands, BaseCommand - -from django_manage_commands_provider._parser import _optparse, _argparse -from _jb_utils import VersionAgnosticUtils import sys - +import threading +from _jb_utils import VersionAgnosticUtils +from django.core.management import ManagementUtility, get_commands +from django_manage_commands_provider._parser import _optparse, _argparse __author__ = 'Ilya.Kazakevich' -def report_data(dumper): +class _Fetcher(threading.Thread): + def __init__(self, utility, command_name): + super(_Fetcher, self).__init__() + self.result = None + self.__utility = utility + self.__command_name = command_name + self.command_lead_to_exception = False + + def run(self): + try: + self.result = self.__utility.fetch_command(self.__command_name) + except Exception as e: + sys.stderr.write("Error fetching command '{0}': {1}\n".format(self.__command_name, e)) + self.command_lead_to_exception = True + + +def report_data(dumper, commands_to_skip): """ Fetches data from management commands and reports it to dumper. :type dumper _xml.XmlDumper + :type commands_to_skip list + :param commands_to_skip list of commands to skip :param dumper: destination to report """ utility = ManagementUtility() for command_name in get_commands().keys(): - try: - command = utility.fetch_command(command_name) - except Exception as e: - sys.stderr.write("Error fetching command {0}: {1}\n".format(command_name, e)) - continue - assert isinstance(command, BaseCommand) + if command_name in commands_to_skip: + sys.stderr.write("Skipping command '{0}' due to config\n".format(command_name)) + continue + + fetcher = _Fetcher(utility, command_name) + fetcher.daemon = True + fetcher.start() + fetcher.join(2) + command = fetcher.result + if not command: + if fetcher.command_lead_to_exception: + sys.stderr.write("Command '{0}' skipped\n".format(command_name)) + continue + else: + sys.stderr.write( + "Command '{0}' took too long and may freeze everything. Consider adding it to 'skip commands' list\n".format( + command_name)) + sys.exit(1) use_argparse = False try: @@ -44,8 +72,8 @@ def report_data(dumper): continue dumper.start_command(command_name=command_name, - command_help_text=VersionAgnosticUtils().to_unicode(command.usage("")).replace("%prog", command_name)) - module_to_use = _argparse if use_argparse else _optparse # Choose appropriate module: argparse, optparse + command_help_text=VersionAgnosticUtils().to_unicode(command.usage("")).replace("%prog", + command_name)) + module_to_use = _argparse if use_argparse else _optparse # Choose appropriate module: argparse, optparse module_to_use.process_command(dumper, command, parser) dumper.close_command() -