Made the Shell interpreter statement execution timeout configurable. eric7

Sat, 10 Feb 2024 10:58:48 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 10 Feb 2024 10:58:48 +0100
branch
eric7
changeset 10556
b4a75c77f9cd
parent 10554
cfcfba945421
child 10559
64db35c6e335
child 10562
8e93f1578f99

Made the Shell interpreter statement execution timeout configurable.

src/eric7/Preferences/ConfigurationPages/ShellPage.py file | annotate | diff | comparison | revisions
src/eric7/Preferences/ConfigurationPages/ShellPage.ui file | annotate | diff | comparison | revisions
src/eric7/Preferences/__init__.py file | annotate | diff | comparison | revisions
src/eric7/QScintilla/Shell.py file | annotate | diff | comparison | revisions
--- a/src/eric7/Preferences/ConfigurationPages/ShellPage.py	Fri Feb 09 18:58:42 2024 +0100
+++ b/src/eric7/Preferences/ConfigurationPages/ShellPage.py	Sat Feb 10 10:58:48 2024 +0100
@@ -70,6 +70,8 @@
         self.marginsFont = Preferences.getShell("MarginsFont")
         self.marginsFontSample.setFont(self.marginsFont)
 
+        self.timeoutSpinBox.setValue(Preferences.getShell("CommandExecutionTimeout"))
+
     def save(self):
         """
         Public slot to save the Shell configuration.
@@ -102,6 +104,8 @@
         Preferences.setShell("UseMonospacedFont", self.monospacedCheckBox.isChecked())
         Preferences.setShell("MarginsFont", self.marginsFont)
 
+        Preferences.setShell("CommandExecutionTimeout", self.timeoutSpinBox.value())
+
     @pyqtSlot()
     def on_monospacedFontButton_clicked(self):
         """
--- a/src/eric7/Preferences/ConfigurationPages/ShellPage.ui	Fri Feb 09 18:58:42 2024 +0100
+++ b/src/eric7/Preferences/ConfigurationPages/ShellPage.ui	Sat Feb 10 10:58:48 2024 +0100
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>573</width>
-    <height>465</height>
+    <height>677</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
@@ -116,6 +116,9 @@
         <property name="alignment">
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
         </property>
+        <property name="accelerated">
+         <bool>true</bool>
+        </property>
         <property name="minimum">
          <number>10</number>
         </property>
@@ -265,6 +268,57 @@
     </widget>
    </item>
    <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>Interpreter</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>Statement Execution Timeout:</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QSpinBox" name="timeoutSpinBox">
+        <property name="toolTip">
+         <string>Enter the timeout in seconds after which the shell will not wait for the result of the current statement execution.</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="accelerated">
+         <bool>true</bool>
+        </property>
+        <property name="suffix">
+         <string> s</string>
+        </property>
+        <property name="minimum">
+         <number>5</number>
+        </property>
+        <property name="maximum">
+         <number>600</number>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>289</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
     <widget class="QCheckBox" name="stdOutErrCheckBox">
      <property name="toolTip">
       <string>Select to show debugger stdout and stderr</string>
@@ -291,10 +345,10 @@
  </widget>
  <tabstops>
   <tabstop>shellLinenoCheckBox</tabstop>
+  <tabstop>shellWordWrapCheckBox</tabstop>
   <tabstop>shellACEnabledCheckBox</tabstop>
+  <tabstop>shellCTEnabledCheckBox</tabstop>
   <tabstop>shellSyntaxHighlightingCheckBox</tabstop>
-  <tabstop>shellWordWrapCheckBox</tabstop>
-  <tabstop>shellCTEnabledCheckBox</tabstop>
   <tabstop>rememberCheckBox</tabstop>
   <tabstop>shellHistorySpinBox</tabstop>
   <tabstop>shellHistoryStyleComboBox</tabstop>
@@ -303,6 +357,7 @@
   <tabstop>monospacedFontButton</tabstop>
   <tabstop>monospacedCheckBox</tabstop>
   <tabstop>linenumbersFontButton</tabstop>
+  <tabstop>timeoutSpinBox</tabstop>
   <tabstop>stdOutErrCheckBox</tabstop>
  </tabstops>
  <resources/>
--- a/src/eric7/Preferences/__init__.py	Fri Feb 09 18:58:42 2024 +0100
+++ b/src/eric7/Preferences/__init__.py	Sat Feb 10 10:58:48 2024 +0100
@@ -1369,6 +1369,7 @@
         "MarginsFont": "Sans Serif,10,-1,5,50,0,0,0,0,0",
         "LastVirtualEnvironment": "",
         "StartWithMostRecentlyUsedEnvironment": True,
+        "CommandExecutionTimeout": 15,
     }
 
     # defaults for Qt related stuff
@@ -2891,7 +2892,7 @@
         f = QFont()
         f.fromString(Prefs.settings.value("Shell/" + key, Prefs.shellDefaults[key]))
         return f
-    elif key in ["MaxHistoryEntries"]:
+    elif key in ["MaxHistoryEntries", "CommandExecutionTimeout"]:
         return int(Prefs.settings.value("Shell/" + key, Prefs.shellDefaults[key]))
     elif key in ["HistoryStyle"]:
         return ShellHistoryStyle(
--- a/src/eric7/QScintilla/Shell.py	Fri Feb 09 18:58:42 2024 +0100
+++ b/src/eric7/QScintilla/Shell.py	Sat Feb 10 10:58:48 2024 +0100
@@ -266,6 +266,8 @@
 
         self.clientType = ""
 
+        self.__commandExecutionTimeout = Preferences.getShell("CommandExecutionTimeout")
+
         # Initialize history
         self.__historyLists = {}
         self.__maxHistoryEntries = Preferences.getShell("MaxHistoryEntries")
@@ -1979,10 +1981,24 @@
             else:
                 self.dbs.remoteStatement(self.__getSelectedDebuggerId(), cmd)
                 now = time.monotonic()
-                while self.inCommandExecution and time.monotonic() - now < 10:
-                    # 10 seconds timeout
+                timeDelta = 0
+                while (
+                    self.inCommandExecution
+                    and timeDelta <= self.__commandExecutionTimeout
+                ):
+                    timeDelta = time.monotonic() - now
+                    # configurable timeout
                     with contextlib.suppress(KeyboardInterrupt):
                         QApplication.processEvents()
+                self.inCommandExecution = False
+                if timeDelta > self.__commandExecutionTimeout:
+                    # timeout -> write a hint into the shell window
+                    s = self.tr(
+                        "Execution of the interpreter statement timed out after"
+                        " {0} seconds.\n"
+                    ).format(self.__commandExecutionTimeout)
+                    self.__write(s)
+                    self.__clientStatement(False)
         else:
             if not self.__echoInput:
                 cmd = self.buff
@@ -2189,6 +2205,9 @@
                 self.dbs.clientProcessStderr.disconnect(self.__writeStdErr)
             self.__showStdOutErr = showStdOutErr
 
+        # do some additional configuration parameters
+        self.__commandExecutionTimeout = Preferences.getShell("CommandExecutionTimeout")
+
     @pyqtSlot(list, str)
     def __showCompletions(self, completions, text):
         """

eric ide

mercurial