Added a timeout configuration value to the completions cache after which completions will be removed from the cache.

Mon, 16 Oct 2017 19:39:57 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 16 Oct 2017 19:39:57 +0200
changeset 5909
21d90a3abc7c
parent 5908
4d08fb83a844
child 5910
3f0255a8786a

Added a timeout configuration value to the completions cache after which completions will be removed from the cache.

E5Utilities/E5Cache.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/EditorAutocompletionPage.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/EditorAutocompletionPage.ui file | annotate | diff | comparison | revisions
Preferences/__init__.py file | annotate | diff | comparison | revisions
QScintilla/Editor.py file | annotate | diff | comparison | revisions
--- a/E5Utilities/E5Cache.py	Mon Oct 16 19:11:25 2017 +0200
+++ b/E5Utilities/E5Cache.py	Mon Oct 16 19:39:57 2017 +0200
@@ -9,6 +9,8 @@
 
 from __future__ import unicode_literals
 
+from PyQt5.QtCore import QDateTime, QTimer
+
 
 # TODO: add timeout for cached entries
 class E5Cache(object):
@@ -32,10 +34,16 @@
         
         # internal objects
         self.__keyList = []
-        self.__store = {}
+        self.__store = {}           # stores the cache entries
+        self.__accesStore = {}      # stores the last access date and times
         self.__hits = 0
         self.__misses = 0
         self.__maxsize = 0
+        self.__maxCacheTime = 0     # 0 seconds means aging is disabled
+        
+        self.__cacheTimer = QTimer()
+        self.__cacheTimer.setSingleShot(True)
+        self.__cacheTimer.timeout.connect(self.__pruneCache)
     
     def __moveLast(self, key):
         """
@@ -55,6 +63,7 @@
             self.__keyList[:-self.__size], self.__keyList[-self.__size:]
         for key in removeList:
             del self.__store[key]
+            del self.__accesStore[key]
     
     def getSize(self):
         """
@@ -78,6 +87,30 @@
         self.__size = newSize
         self.__adjustToSize()
     
+    def getMaximumCacheTime(self):
+        """
+        Public method to get the maximum time entries may exist in the cache.
+        
+        @return maximum cache time in seconds
+        @rtype int
+        """
+        return self.__maxCacheTime
+    
+    def setMaximumCacheTime(self, time):
+        """
+        Public method to set the maximum time entries may exist in the cache.
+        
+        @param time maximum cache time in seconds
+        @type int
+        """
+        if time != self.__maxCacheTime:
+            self.__cacheTimer.stop()
+            self.__pruneCache()
+            self.__maxCacheTime = time
+            if self.__maxCacheTime > 0:
+                self.__cacheTimer.setInterval(self.__maxCacheTime * 1000)
+                self.__cacheTimer.start()
+    
     def get(self, key):
         """
         Public method to get an entry from the cache given its key.
@@ -93,6 +126,7 @@
         if key in self.__store:
             self.__hits += 1
             self.__moveLast(key)
+            self.__accesStore[key] = QDateTime.currentDateTimeUtc()
             return self.__store[key]
         else:
             self.__misses += 1
@@ -115,6 +149,7 @@
         else:
             self.__keyList.append(key)
         self.__store[key] = item
+        self.__accesStore[key] = QDateTime.currentDateTimeUtc()
         
         self.__adjustToSize()
         
@@ -129,6 +164,7 @@
         """
         if key in self.__store:
             del self.__store[key]
+            del self.__accesStore[key]
             self.__keyList.remove(key)
     
     def clear(self):
@@ -137,6 +173,7 @@
         """
         self.__keyList = []
         self.__store = {}
+        self.__accesStore = {}
     
     def reset(self):
         """
@@ -172,3 +209,19 @@
             "maxsize": self.__maxsize,
             "currsize": self.length(),
         }
+    
+    def __pruneCache(self):
+        """
+        Private slot to prune outdated cache entries and restart the timer.
+        """
+        if self.__maxCacheTime > 0:
+            current = QDateTime.currentDateTimeUtc()
+            
+            keysToBeDeleted = []
+            for key, lastAccessTime in self.__accesStore.items():
+                if lastAccessTime.secsTo(current) > self.__maxCacheTime:
+                    keysToBeDeleted.append(key)
+            for key in keysToBeDeleted:
+                self.remove(key)
+        
+            self.__cacheTimer.start()
--- a/Preferences/ConfigurationPages/EditorAutocompletionPage.py	Mon Oct 16 19:11:25 2017 +0200
+++ b/Preferences/ConfigurationPages/EditorAutocompletionPage.py	Mon Oct 16 19:39:57 2017 +0200
@@ -43,6 +43,8 @@
             Preferences.getEditor("AutoCompletionTimeout"))
         self.acCacheSizeSpinBox.setValue(
             Preferences.getEditor("AutoCompletionCacheSize"))
+        self.acCacheTimeSpinBox.setValue(
+            Preferences.getEditor("AutoCompletionCacheTime"))
         
     def save(self):
         """
@@ -70,6 +72,9 @@
         Preferences.setEditor(
             "AutoCompletionCacheSize",
             self.acCacheSizeSpinBox.value())
+        Preferences.setEditor(
+            "AutoCompletionCacheTime",
+            self.acCacheTimeSpinBox.value())
     
 
 def create(dlg):
--- a/Preferences/ConfigurationPages/EditorAutocompletionPage.ui	Mon Oct 16 19:11:25 2017 +0200
+++ b/Preferences/ConfigurationPages/EditorAutocompletionPage.ui	Mon Oct 16 19:39:57 2017 +0200
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>506</width>
-    <height>398</height>
+    <height>498</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
@@ -53,7 +53,7 @@
       <string>General</string>
      </property>
      <layout class="QGridLayout" name="gridLayout_2">
-      <item row="0" column="0">
+      <item row="0" column="0" colspan="2">
        <widget class="QCheckBox" name="acCaseSensitivityCheckBox">
         <property name="toolTip">
          <string>Select this to have case sensitive auto-completion lists</string>
@@ -63,7 +63,7 @@
         </property>
        </widget>
       </item>
-      <item row="0" column="1">
+      <item row="0" column="2" colspan="2">
        <widget class="QCheckBox" name="acReplaceWordCheckBox">
         <property name="toolTip">
          <string>Select this, if the word to the right should be replaced by the selected entry</string>
@@ -73,7 +73,7 @@
         </property>
        </widget>
       </item>
-      <item row="1" column="0">
+      <item row="1" column="0" colspan="2">
        <widget class="QCheckBox" name="acReversedCheckBox">
         <property name="toolTip">
          <string>Select to show completions of type 'public' first</string>
@@ -83,133 +83,183 @@
         </property>
        </widget>
       </item>
-      <item row="2" column="0" colspan="2">
-       <layout class="QGridLayout" name="gridLayout">
-        <item row="0" column="0">
-         <widget class="QLabel" name="textLabel1_2">
-          <property name="text">
-           <string>Threshold:</string>
+      <item row="2" column="0">
+       <widget class="QLabel" name="textLabel1_2">
+        <property name="text">
+         <string>Threshold:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1" colspan="3">
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QSlider" name="acThresholdSlider">
+          <property name="toolTip">
+           <string>Move to set the threshold for display of an autocompletion list</string>
           </property>
-         </widget>
-        </item>
-        <item row="0" column="1" colspan="2">
-         <layout class="QHBoxLayout" name="horizontalLayout">
-          <item>
-           <widget class="QSlider" name="acThresholdSlider">
-            <property name="toolTip">
-             <string>Move to set the threshold for display of an autocompletion list</string>
-            </property>
-            <property name="maximum">
-             <number>10</number>
-            </property>
-            <property name="value">
-             <number>2</number>
-            </property>
-            <property name="orientation">
-             <enum>Qt::Horizontal</enum>
-            </property>
-            <property name="tickInterval">
-             <number>1</number>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QLCDNumber" name="lCDNumber4">
-            <property name="toolTip">
-             <string>Displays the selected autocompletion threshold</string>
-            </property>
-            <property name="digitCount">
-             <number>2</number>
-            </property>
-            <property name="segmentStyle">
-             <enum>QLCDNumber::Flat</enum>
-            </property>
-            <property name="value" stdset="0">
-             <double>2.000000000000000</double>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </item>
-        <item row="1" column="0">
-         <widget class="QLabel" name="label">
-          <property name="text">
-           <string>Time to wait until completion:</string>
+          <property name="maximum">
+           <number>10</number>
+          </property>
+          <property name="value">
+           <number>2</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="tickInterval">
+           <number>1</number>
           </property>
          </widget>
         </item>
-        <item row="1" column="1">
-         <widget class="QSpinBox" name="acTimeoutSpinBox">
+        <item>
+         <widget class="QLCDNumber" name="lCDNumber4">
           <property name="toolTip">
-           <string>Enter the time in milliseconds after which a list with completion proposals shall be shown</string>
-          </property>
-          <property name="alignment">
-           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-          </property>
-          <property name="correctionMode">
-           <enum>QAbstractSpinBox::CorrectToNearestValue</enum>
-          </property>
-          <property name="suffix">
-           <string> ms</string>
-          </property>
-          <property name="minimum">
-           <number>0</number>
-          </property>
-          <property name="maximum">
-           <number>999</number>
-          </property>
-          <property name="singleStep">
-           <number>10</number>
-          </property>
-         </widget>
-        </item>
-        <item row="1" column="2">
-         <spacer name="horizontalSpacer">
-          <property name="orientation">
-           <enum>Qt::Horizontal</enum>
+           <string>Displays the selected autocompletion threshold</string>
           </property>
-          <property name="sizeHint" stdset="0">
-           <size>
-            <width>68</width>
-            <height>20</height>
-           </size>
-          </property>
-         </spacer>
-        </item>
-        <item row="2" column="0">
-         <widget class="QLabel" name="label_2">
-          <property name="text">
-           <string>Completions Cache Size:</string>
+          <property name="digitCount">
+           <number>2</number>
           </property>
-         </widget>
-        </item>
-        <item row="2" column="1">
-         <widget class="QSpinBox" name="acCacheSizeSpinBox">
-          <property name="toolTip">
-           <string>Enter the maximum number of entries to be kept in the completions cache</string>
-          </property>
-          <property name="alignment">
-           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+          <property name="segmentStyle">
+           <enum>QLCDNumber::Flat</enum>
           </property>
-          <property name="correctionMode">
-           <enum>QAbstractSpinBox::CorrectToNearestValue</enum>
-          </property>
-          <property name="suffix">
-           <string> entries</string>
-          </property>
-          <property name="minimum">
-           <number>0</number>
-          </property>
-          <property name="maximum">
-           <number>999</number>
-          </property>
-          <property name="singleStep">
-           <number>10</number>
+          <property name="value" stdset="0">
+           <double>2.000000000000000</double>
           </property>
          </widget>
         </item>
        </layout>
       </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>Time to wait until completion:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1" colspan="2">
+       <widget class="QSpinBox" name="acTimeoutSpinBox">
+        <property name="toolTip">
+         <string>Enter the time in milliseconds after which a list with completion proposals shall be shown</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+        <property name="correctionMode">
+         <enum>QAbstractSpinBox::CorrectToNearestValue</enum>
+        </property>
+        <property name="suffix">
+         <string> ms</string>
+        </property>
+        <property name="minimum">
+         <number>0</number>
+        </property>
+        <property name="maximum">
+         <number>999</number>
+        </property>
+        <property name="singleStep">
+         <number>10</number>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="3">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>192</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="4" column="0" colspan="4">
+       <widget class="QGroupBox" name="groupBox_2">
+        <property name="title">
+         <string>Completions Cache</string>
+        </property>
+        <layout class="QGridLayout" name="gridLayout">
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string>Size:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1">
+          <widget class="QSpinBox" name="acCacheSizeSpinBox">
+           <property name="toolTip">
+            <string>Enter the maximum number of entries to be kept in the completions cache</string>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+           </property>
+           <property name="correctionMode">
+            <enum>QAbstractSpinBox::CorrectToNearestValue</enum>
+           </property>
+           <property name="suffix">
+            <string> entries</string>
+           </property>
+           <property name="minimum">
+            <number>0</number>
+           </property>
+           <property name="maximum">
+            <number>999</number>
+           </property>
+           <property name="singleStep">
+            <number>10</number>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="2">
+          <spacer name="horizontalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>271</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item row="1" column="0">
+          <widget class="QLabel" name="label_3">
+           <property name="text">
+            <string>Timeout:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="1">
+          <widget class="QSpinBox" name="acCacheTimeSpinBox">
+           <property name="toolTip">
+            <string>Enter the time in seconds after which a cached completion entry should be removed from the completions cache</string>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+           </property>
+           <property name="correctionMode">
+            <enum>QAbstractSpinBox::CorrectToNearestValue</enum>
+           </property>
+           <property name="suffix">
+            <string> s</string>
+           </property>
+           <property name="minimum">
+            <number>0</number>
+           </property>
+           <property name="maximum">
+            <number>3600</number>
+           </property>
+           <property name="singleStep">
+            <number>60</number>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
--- a/Preferences/__init__.py	Mon Oct 16 19:11:25 2017 +0200
+++ b/Preferences/__init__.py	Mon Oct 16 19:39:57 2017 +0200
@@ -421,6 +421,7 @@
         "AutoCompletionFillups": False,
         "AutoCompletionReversedList": False,
         "AutoCompletionCacheSize": 100,
+        "AutoCompletionCacheTime": 300,     # 5 minutes
         
         "CallTipsEnabled": False,
         "CallTipsVisible": 0,
@@ -2076,7 +2077,8 @@
                  "FoldingStyle", "WarnFilesize", "EdgeMode", "EdgeColumn",
                  "CaretWidth", "AutoCompletionSource",
                  "AutoCompletionThreshold", "AutoCompletionTimeout",
-                 "AutoCompletionCacheSize", "CallTipsVisible", "CallTipsStyle",
+                 "AutoCompletionCacheSize", "AutoCompletionCacheTime",
+                 "CallTipsVisible", "CallTipsStyle",
                  "MarkOccurrencesTimeout", "AutoSpellCheckChunkSize",
                  "SpellCheckingMinWordSize", "PostScriptLevel", "EOLMode",
                  "ZoomFactor", "WhitespaceSize", "OnlineSyntaxCheckInterval",
--- a/QScintilla/Editor.py	Mon Oct 16 19:11:25 2017 +0200
+++ b/QScintilla/Editor.py	Mon Oct 16 19:39:57 2017 +0200
@@ -390,6 +390,8 @@
         self.__acCompletions = set()
         self.__acCache = E5Cache(
             size=Preferences.getEditor("AutoCompletionCacheSize"))
+        self.__acCache.setMaximumCacheTime(
+            Preferences.getEditor("AutoCompletionCacheTime"))
         self.__acTimer = QTimer(self)
         self.__acTimer.setSingleShot(True)
         self.__acTimer.setInterval(
@@ -4061,6 +4063,8 @@
         # set the auto-completion function
         self.__acCache.setSize(
             Preferences.getEditor("AutoCompletionCacheSize"))
+        self.__acCache.setMaximumCacheTime(
+            Preferences.getEditor("AutoCompletionCacheTime"))
         acTimeout = Preferences.getEditor("AutoCompletionTimeout")
         if acTimeout != self.__acTimer.interval:
             self.__acTimer.setInterval(acTimeout)

eric ide

mercurial