Mon, 16 Oct 2017 19:39:57 +0200
Added a timeout configuration value to the completions cache after which completions will be removed from the cache.
--- 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)