mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-18594: Slow commands may freeze manage.py, fixing it
* Give each command 2 seconds to complete * Kill it and report if it fails * Give user ability to skip such commands
This commit is contained in:
@@ -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)
|
||||
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user