mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Debugger speedups not found notification (PY-24310)
Replace filter in output console with new notification.
This commit is contained in:
-4
@@ -5,7 +5,6 @@ import com.intellij.execution.filters.InputFilter;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.jetbrains.python.debugger.PyRunCythonExtensionsFilter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -21,9 +20,6 @@ public class PyEduConsoleInputFilterProvider implements ConsoleInputFilterProvid
|
||||
if (outputType.equals(ConsoleViewContentType.SYSTEM_OUTPUT) && !text.contains("exit code")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (text.startsWith(PyRunCythonExtensionsFilter.WARNING_MESSAGE_BEGIN)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (text.startsWith("pydev debugger")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ CMD_INPUT_REQUESTED = 147
|
||||
CMD_GET_DESCRIPTION = 148
|
||||
|
||||
CMD_PROCESS_CREATED = 149
|
||||
CMD_SHOW_CYTHON_WARNING = 150
|
||||
|
||||
CMD_VERSION = 501
|
||||
CMD_RETURN = 502
|
||||
@@ -204,6 +205,7 @@ ID_TO_MEANING = {
|
||||
'148': 'CMD_GET_DESCRIPTION',
|
||||
|
||||
'149': 'CMD_PROCESS_CREATED',
|
||||
'150': 'CMD_SHOW_CYTHON_WARNING',
|
||||
|
||||
'501': 'CMD_VERSION',
|
||||
'502': 'CMD_RETURN',
|
||||
@@ -590,6 +592,12 @@ class NetCommandFactory:
|
||||
cmdText = '<process/>'
|
||||
return NetCommand(CMD_PROCESS_CREATED, 0, cmdText)
|
||||
|
||||
def make_show_cython_warning_message(self):
|
||||
try:
|
||||
return NetCommand(CMD_SHOW_CYTHON_WARNING, 0, '')
|
||||
except:
|
||||
return self.make_error_message(0, get_exception_traceback_str())
|
||||
|
||||
def make_custom_frame_created_message(self, frameId, frameDescription):
|
||||
frameDescription = pydevd_xml.make_valid_xml_value(frameDescription)
|
||||
cmdText = '<xml><thread name="%s" id="%s"/></xml>' % (frameDescription, frameId)
|
||||
@@ -828,7 +836,6 @@ class NetCommandFactory:
|
||||
except:
|
||||
return self.make_error_message(0, get_exception_traceback_str())
|
||||
|
||||
|
||||
def make_exit_message(self):
|
||||
try:
|
||||
net = NetCommand(CMD_EXIT, 0, '')
|
||||
|
||||
@@ -105,6 +105,7 @@ USE_LIB_COPY = SUPPORT_GEVENT and \
|
||||
|
||||
|
||||
INTERACTIVE_MODE_AVAILABLE = sys.platform in ('darwin', 'win32') or os.getenv('DISPLAY') is not None
|
||||
SHOW_CYTHON_WARNING = False
|
||||
|
||||
|
||||
def protect_libraries_from_patching():
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
from _pydevd_bundle.pydevd_constants import CYTHON_SUPPORTED
|
||||
from _pydevd_bundle.pydevd_constants import CYTHON_SUPPORTED, SHOW_CYTHON_WARNING
|
||||
|
||||
|
||||
use_cython = os.getenv('PYDEVD_USE_CYTHON', None)
|
||||
@@ -34,6 +34,7 @@ def delete_old_compiled_extensions():
|
||||
log_error_once("warning: failed to delete old cython speedups. Please delete all *.so files from the directories "
|
||||
"\"%s\" and \"%s\"" % (_pydevd_bundle_dir, _pydevd_frame_eval_dir))
|
||||
|
||||
show_tracing_warning = False
|
||||
|
||||
if use_cython == 'YES':
|
||||
# We must import the cython version if forcing cython
|
||||
@@ -65,8 +66,11 @@ elif use_cython is None:
|
||||
from _pydevd_bundle.pydevd_trace_dispatch_regular import trace_dispatch, global_cache_skips, global_cache_frame_skips # @UnusedImport
|
||||
from _pydev_bundle.pydev_monkey import log_error_once
|
||||
|
||||
log_error_once("warning: Debugger speedups using cython not found. Run '\"%s\" \"%s\" build_ext --inplace' to build." % (
|
||||
sys.executable, os.path.join(dirname, 'setup_cython.py')))
|
||||
if SHOW_CYTHON_WARNING:
|
||||
log_error_once("warning: Debugger speedups using cython not found. Run '\"%s\" \"%s\" build_ext --inplace' to build." % (
|
||||
sys.executable, os.path.join(dirname, 'setup_cython.py')))
|
||||
else:
|
||||
show_tracing_warning = True
|
||||
|
||||
else:
|
||||
raise RuntimeError('Unexpected value for PYDEVD_USE_CYTHON: %s (accepted: YES, NO)' % (use_cython,))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from _pydevd_bundle.pydevd_constants import SHOW_CYTHON_WARNING
|
||||
|
||||
IS_PY36 = False
|
||||
if sys.version_info[0] == 3 and sys.version_info[1] == 6:
|
||||
IS_PY36 = True
|
||||
@@ -9,6 +11,7 @@ frame_eval_func = None
|
||||
stop_frame_eval = None
|
||||
enable_cache_frames_without_breaks = None
|
||||
dummy_trace_dispatch = None
|
||||
show_frame_eval_warning = False
|
||||
|
||||
USE_FRAME_EVAL = os.environ.get('PYDEVD_USE_FRAME_EVAL', None)
|
||||
|
||||
@@ -24,5 +27,9 @@ else:
|
||||
from _pydev_bundle.pydev_monkey import log_error_once
|
||||
|
||||
dirname = os.path.dirname(os.path.dirname(__file__))
|
||||
log_error_once("warning: Debugger speedups using cython not found. Run '\"%s\" \"%s\" build_ext --inplace' to build." % (
|
||||
sys.executable, os.path.join(dirname, 'setup_cython.py')))
|
||||
|
||||
if SHOW_CYTHON_WARNING:
|
||||
log_error_once("warning: Debugger speedups using cython not found. Run '\"%s\" \"%s\" build_ext --inplace' to build." % (
|
||||
sys.executable, os.path.join(dirname, 'setup_cython.py')))
|
||||
else:
|
||||
show_frame_eval_warning = True
|
||||
|
||||
@@ -35,8 +35,9 @@ from _pydevd_bundle.pydevd_comm import CMD_SET_BREAK, CMD_SET_NEXT_STATEMENT, CM
|
||||
from _pydevd_bundle.pydevd_custom_frames import CustomFramesContainer, custom_frames_container_init
|
||||
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame
|
||||
from _pydevd_bundle.pydevd_kill_all_pydevd_threads import kill_all_pydev_threads
|
||||
from _pydevd_bundle.pydevd_trace_dispatch import trace_dispatch as _trace_dispatch, global_cache_skips, global_cache_frame_skips
|
||||
from _pydevd_frame_eval.pydevd_frame_eval_main import frame_eval_func, stop_frame_eval, enable_cache_frames_without_breaks, dummy_trace_dispatch
|
||||
from _pydevd_bundle.pydevd_trace_dispatch import trace_dispatch as _trace_dispatch, global_cache_skips, global_cache_frame_skips, show_tracing_warning
|
||||
from _pydevd_frame_eval.pydevd_frame_eval_main import frame_eval_func, stop_frame_eval, enable_cache_frames_without_breaks, \
|
||||
dummy_trace_dispatch, show_frame_eval_warning
|
||||
from _pydevd_bundle.pydevd_utils import save_main_module
|
||||
from pydevd_concurrency_analyser.pydevd_concurrency_logger import ThreadingLogger, AsyncioLogger, send_message, cur_time
|
||||
from pydevd_concurrency_analyser.pydevd_thread_wrappers import wrap_threads
|
||||
@@ -905,6 +906,10 @@ class PyDB:
|
||||
# we need all data to be sent to IDE even after program finishes
|
||||
CheckOutputThread(self).start()
|
||||
|
||||
if show_tracing_warning or show_frame_eval_warning:
|
||||
cmd = self.cmd_factory.make_show_cython_warning_message()
|
||||
self.writer.add_command(cmd)
|
||||
|
||||
|
||||
def patch_threads(self):
|
||||
try:
|
||||
|
||||
@@ -39,5 +39,7 @@ public interface IPyDebugProcess extends PyFrameAccessor {
|
||||
|
||||
void consoleInputRequested(boolean isStarted);
|
||||
|
||||
void showCythonWarning();
|
||||
|
||||
XDebugSession getSession();
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ public abstract class AbstractCommand<T> {
|
||||
public static final int INPUT_REQUESTED = 147;
|
||||
|
||||
public static final int PROCESS_CREATED = 149;
|
||||
public static final int SHOW_CYTHON_WARNING = 150;
|
||||
|
||||
public static final int ERROR = 901;
|
||||
|
||||
@@ -206,6 +207,10 @@ public abstract class AbstractCommand<T> {
|
||||
return command == INPUT_REQUESTED;
|
||||
}
|
||||
|
||||
public static boolean isShowWarningCommand(final int command) {
|
||||
return command == SHOW_CYTHON_WARNING;
|
||||
}
|
||||
|
||||
public static boolean isExitEvent(final int command) {
|
||||
return command == EXIT;
|
||||
}
|
||||
|
||||
@@ -474,6 +474,9 @@ public class RemoteDebugger implements ProcessDebugger {
|
||||
else if (ProcessCreatedCommand.isProcessCreatedCommand(frame.getCommand())) {
|
||||
onProcessCreatedEvent();
|
||||
}
|
||||
else if (AbstractCommand.isShowWarningCommand(frame.getCommand())) {
|
||||
myDebugProcess.showCythonWarning();
|
||||
}
|
||||
else {
|
||||
placeResponse(frame.getSequence(), frame);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.execution.filters.TextConsoleBuilder;
|
||||
import com.intellij.execution.ui.ConsoleView;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.jetbrains.python.debugger.PyRunCythonExtensionsFilter;
|
||||
import com.jetbrains.python.run.PythonTracebackFilter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -53,7 +52,6 @@ public class PyDebugConsoleBuilder extends TextConsoleBuilder {
|
||||
protected ConsoleView createConsole() {
|
||||
PythonDebugLanguageConsoleView consoleView = new PythonDebugLanguageConsoleView(myProject, mySdk);
|
||||
consoleView.addMessageFilter(new PythonTracebackFilter(myProject));
|
||||
consoleView.addMessageFilter(new PyRunCythonExtensionsFilter(myProject));
|
||||
return consoleView;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.debugger;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.RunManager;
|
||||
import com.intellij.execution.RunnerAndConfigurationSettings;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.execution.process.*;
|
||||
import com.intellij.execution.util.ExecUtil;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.help.HelpManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
|
||||
import com.jetbrains.python.sdk.PythonEnvUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class PyCythonExtensionWarning {
|
||||
private static final Logger LOG = Logger.getInstance("com.jetbrains.python.debugger.PyCythonExtensionWarning");
|
||||
public static final String ERROR_TITLE = "Compile Cython Extensions Error";
|
||||
private static final String CYTHON_WARNING_GROUP_ID = "CythonWarning";
|
||||
private static final String WARNING_MESSAGE = "Cython extension speed ups Python debugging <br/>" +
|
||||
"<a href=\"install\">Install</a> " +
|
||||
"<a href=\"docs\">How does it work</a>";
|
||||
public static final String SETUP_CYTHON_PATH = "pydev/setup_cython.py";
|
||||
public static final String[] CYTHON_ARGS = {"build_ext", "--inplace"};
|
||||
|
||||
|
||||
public static void showCythonExtensionWarning(@NotNull Project project) {
|
||||
Notification notification =
|
||||
new Notification(CYTHON_WARNING_GROUP_ID, "Python Debugger Extension Available", WARNING_MESSAGE,
|
||||
NotificationType.INFORMATION, createListener(project));
|
||||
notification.notify(project);
|
||||
}
|
||||
|
||||
private static NotificationListener.Adapter createListener(@NotNull Project project) {
|
||||
return new NotificationListener.Adapter() {
|
||||
@Override
|
||||
protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
switch (event.getDescription()) {
|
||||
case "install":
|
||||
compileCythonExtension(project);
|
||||
notification.expire();
|
||||
return;
|
||||
case "docs":
|
||||
// TODO: help id for cython speedups help page
|
||||
HelpManager.getInstance().invokeHelp("");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void showErrorDialog(Project project, String message) {
|
||||
Messages.showMessageDialog(project, message, ERROR_TITLE, null);
|
||||
}
|
||||
|
||||
private static void compileCythonExtension(@NotNull Project project) {
|
||||
try {
|
||||
final RunManager runManager = RunManager.getInstance(project);
|
||||
final RunnerAndConfigurationSettings selectedConfiguration = runManager.getSelectedConfiguration();
|
||||
if (selectedConfiguration == null) {
|
||||
throw new ExecutionException("Python Run Configuration should be selected");
|
||||
}
|
||||
final RunConfiguration configuration = selectedConfiguration.getConfiguration();
|
||||
if (!(configuration instanceof AbstractPythonRunConfiguration)) {
|
||||
throw new ExecutionException("Python Run Configuration should be selected");
|
||||
}
|
||||
AbstractPythonRunConfiguration runConfiguration = (AbstractPythonRunConfiguration)configuration;
|
||||
final String sdkPath = runConfiguration.getSdkHome();
|
||||
final String helpersPath = PythonHelpersLocator.getHelpersRoot().getPath();
|
||||
|
||||
final List<String> cmdline = new ArrayList<>();
|
||||
cmdline.add(sdkPath);
|
||||
cmdline.add(FileUtil.join(helpersPath, FileUtil.toSystemDependentName(SETUP_CYTHON_PATH)));
|
||||
cmdline.addAll(Arrays.asList(CYTHON_ARGS));
|
||||
LOG.info("Compile Cython Extensions " + StringUtil.join(cmdline, " "));
|
||||
|
||||
final Map<String, String> environment = new HashMap<>(System.getenv());
|
||||
PythonEnvUtil.setPythonUnbuffered(environment);
|
||||
PythonEnvUtil.setPythonDontWriteBytecode(environment);
|
||||
if (sdkPath != null) {
|
||||
PythonEnvUtil.resetHomePathChanges(sdkPath, environment);
|
||||
}
|
||||
GeneralCommandLine commandLine = new GeneralCommandLine(cmdline).withEnvironment(environment);
|
||||
|
||||
final boolean canCreate = FileUtil.ensureCanCreateFile(new File(helpersPath));
|
||||
final boolean useSudo = !canCreate && !SystemInfo.isWindows;
|
||||
Process process;
|
||||
if (useSudo) {
|
||||
process = ExecUtil.sudo(commandLine, "Please enter your password to compile cython extensions: ");
|
||||
}
|
||||
else {
|
||||
process = commandLine.createProcess();
|
||||
}
|
||||
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Compile Cython Extensions") {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
final CapturingProcessHandler handler =
|
||||
new CapturingProcessHandler(process, commandLine.getCharset(), commandLine.getCommandLineString());
|
||||
handler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
if (outputType == ProcessOutputTypes.STDOUT || outputType == ProcessOutputTypes.STDERR) {
|
||||
for (String line : StringUtil.splitByLines(event.getText())) {
|
||||
if (isSignificantOutput(line)) {
|
||||
indicator.setText2(line.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSignificantOutput(String line) {
|
||||
return line.trim().length() > 3;
|
||||
}
|
||||
});
|
||||
final ProcessOutput result = handler.runProcessWithProgressIndicator(indicator);
|
||||
final int exitCode = result.getExitCode();
|
||||
if (exitCode != 0) {
|
||||
final String message = StringUtil.isEmptyOrSpaces(result.getStdout()) && StringUtil.isEmptyOrSpaces(result.getStderr())
|
||||
? "Permission denied"
|
||||
: "Non-zero exit code (" + exitCode + "): \n" + result.getStderr();
|
||||
UIUtil.invokeLaterIfNeeded(() -> showErrorDialog(project, message));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException | ExecutionException e) {
|
||||
showErrorDialog(project, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,6 +119,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
|
||||
private PyStackFrame myConsoleContextFrame = null;
|
||||
private PyReferrersLoader myReferrersProvider;
|
||||
private final List<PyFrameListener> myFrameListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
private boolean isCythonWarningShown = false;
|
||||
|
||||
public PyDebugProcess(@NotNull XDebugSession session,
|
||||
@NotNull ServerSocket serverSocket,
|
||||
@@ -382,6 +383,14 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showCythonWarning() {
|
||||
if (!isCythonWarningShown) {
|
||||
PyCythonExtensionWarning.showCythonExtensionWarning(getSession().getProject());
|
||||
isCythonWarningShown = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void afterConnect() {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.debugger;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.RunManager;
|
||||
import com.intellij.execution.RunnerAndConfigurationSettings;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.execution.filters.Filter;
|
||||
import com.intellij.execution.filters.HyperlinkInfo;
|
||||
import com.intellij.execution.process.*;
|
||||
import com.intellij.execution.util.ExecUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
|
||||
import com.jetbrains.python.sdk.PythonEnvUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class PyRunCythonExtensionsFilter implements Filter {
|
||||
public static final String ERROR_TITLE = "Compile Cython Extensions Error";
|
||||
public static final String WARNING_MESSAGE_BEGIN = "warning: Debugger speedups using cython not found. Run \'";
|
||||
public static final String WARNING_MESSAGE_END = "\' to build.";
|
||||
public static final String SETUP_CYTHON_PATH = "pydev/setup_cython.py";
|
||||
public static final String[] CYTHON_ARGS = {"build_ext", "--inplace"};
|
||||
private static final Logger LOG = Logger.getInstance("com.jetbrains.python.debugger.PyRunCythonExtensionsFilter");
|
||||
private final @NotNull Project myProject;
|
||||
private volatile boolean isApplied = false;
|
||||
|
||||
public PyRunCythonExtensionsFilter(@NotNull Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Result applyFilter(String line, int entireLength) {
|
||||
final int indexOfWarning = line.indexOf(WARNING_MESSAGE_BEGIN);
|
||||
if (indexOfWarning != -1) {
|
||||
final int indexOfLinkBeginning = indexOfWarning + WARNING_MESSAGE_BEGIN.length();
|
||||
final int textStartOffset = entireLength - line.length();
|
||||
final int indexOfLinkEnd = line.indexOf(WARNING_MESSAGE_END);
|
||||
return new Result(textStartOffset + indexOfLinkBeginning, textStartOffset + indexOfLinkEnd, new DebuggerExtensionsHyperlinkInfo());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void showErrorDialog(String message) {
|
||||
Messages.showMessageDialog(myProject, message, ERROR_TITLE, null);
|
||||
}
|
||||
|
||||
private class DebuggerExtensionsHyperlinkInfo implements HyperlinkInfo {
|
||||
@Override
|
||||
public void navigate(Project project) {
|
||||
try {
|
||||
if (isApplied) {
|
||||
return;
|
||||
}
|
||||
final RunManager runManager = RunManager.getInstance(myProject);
|
||||
final RunnerAndConfigurationSettings selectedConfiguration = runManager.getSelectedConfiguration();
|
||||
if (selectedConfiguration == null) {
|
||||
throw new ExecutionException("Python Run Configuration should be selected");
|
||||
}
|
||||
final RunConfiguration configuration = selectedConfiguration.getConfiguration();
|
||||
if (!(configuration instanceof AbstractPythonRunConfiguration)) {
|
||||
throw new ExecutionException("Python Run Configuration should be selected");
|
||||
}
|
||||
AbstractPythonRunConfiguration runConfiguration = (AbstractPythonRunConfiguration)configuration;
|
||||
final String sdkPath = runConfiguration.getSdkHome();
|
||||
final String helpersPath = PythonHelpersLocator.getHelpersRoot().getPath();
|
||||
|
||||
final List<String> cmdline = new ArrayList<>();
|
||||
cmdline.add(sdkPath);
|
||||
cmdline.add(FileUtil.join(helpersPath, FileUtil.toSystemDependentName(SETUP_CYTHON_PATH)));
|
||||
cmdline.addAll(Arrays.asList(CYTHON_ARGS));
|
||||
LOG.info("Compile Cython Extensions " + StringUtil.join(cmdline, " "));
|
||||
|
||||
final Map<String, String> environment = new HashMap<>(System.getenv());
|
||||
PythonEnvUtil.setPythonUnbuffered(environment);
|
||||
PythonEnvUtil.setPythonDontWriteBytecode(environment);
|
||||
if (sdkPath != null) {
|
||||
PythonEnvUtil.resetHomePathChanges(sdkPath, environment);
|
||||
}
|
||||
GeneralCommandLine commandLine = new GeneralCommandLine(cmdline).withEnvironment(environment);
|
||||
|
||||
final boolean canCreate = FileUtil.ensureCanCreateFile(new File(helpersPath));
|
||||
final boolean useSudo = !canCreate && !SystemInfo.isWindows;
|
||||
Process process;
|
||||
if (useSudo) {
|
||||
process = ExecUtil.sudo(commandLine, "Please enter your password to compile cython extensions: ");
|
||||
}
|
||||
else {
|
||||
process = commandLine.createProcess();
|
||||
}
|
||||
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(myProject, "Compile Cython Extensions") {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
isApplied = true;
|
||||
final CapturingProcessHandler handler =
|
||||
new CapturingProcessHandler(process, commandLine.getCharset(), commandLine.getCommandLineString());
|
||||
handler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
if (outputType == ProcessOutputTypes.STDOUT || outputType == ProcessOutputTypes.STDERR) {
|
||||
for (String line : StringUtil.splitByLines(event.getText())) {
|
||||
if (isSignificantOutput(line)) {
|
||||
indicator.setText2(line.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSignificantOutput(String line) {
|
||||
return line.trim().length() > 3;
|
||||
}
|
||||
});
|
||||
final ProcessOutput result = handler.runProcessWithProgressIndicator(indicator);
|
||||
final int exitCode = result.getExitCode();
|
||||
if (exitCode != 0) {
|
||||
final String message = StringUtil.isEmptyOrSpaces(result.getStdout()) && StringUtil.isEmptyOrSpaces(result.getStderr())
|
||||
? "Permission denied"
|
||||
: "Non-zero exit code (" + exitCode + "): \n" + result.getStderr();
|
||||
UIUtil.invokeLaterIfNeeded(() -> showErrorDialog(message));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException | ExecutionException e) {
|
||||
showErrorDialog(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user