mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Infrastructure to detect mem leaks in the edit metadata dialog
This commit is contained in:
parent
3a1fd7af56
commit
acbbc16bf3
@ -154,15 +154,17 @@ class EditMetadataAction(InterfaceAction):
|
||||
d.view_format.connect(lambda
|
||||
fmt:self.gui.iactions['View'].view_format(row_list[current_row],
|
||||
fmt))
|
||||
if d.exec_() != d.Accepted:
|
||||
d.view_format.disconnect()
|
||||
ret = d.exec_()
|
||||
d.break_cycles()
|
||||
if ret != d.Accepted:
|
||||
break
|
||||
d.view_format.disconnect()
|
||||
|
||||
changed.add(d.id)
|
||||
if d.row_delta == 0:
|
||||
break
|
||||
current_row += d.row_delta
|
||||
|
||||
|
||||
if changed:
|
||||
self.gui.library_view.model().refresh_ids(list(changed))
|
||||
current = self.gui.library_view.currentIndex()
|
||||
|
@ -293,7 +293,8 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
||||
finally:
|
||||
self.fetch_cover_button.setEnabled(True)
|
||||
self.unsetCursor()
|
||||
self.pi.stop()
|
||||
if self.pi is not None:
|
||||
self.pi.stop()
|
||||
|
||||
|
||||
# }}}
|
||||
@ -442,7 +443,6 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
||||
ResizableDialog.__init__(self, window)
|
||||
self.cover_fetcher = None
|
||||
self.bc_box.layout().setAlignment(self.cover, Qt.AlignCenter|Qt.AlignHCenter)
|
||||
self.cancel_all = False
|
||||
base = unicode(self.author_sort.toolTip())
|
||||
self.ok_aus_tooltip = '<p>' + textwrap.fill(base+'<br><br>'+
|
||||
_(' The green color indicates that the current '
|
||||
@ -573,7 +573,6 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
||||
QObject.connect(self.series, SIGNAL('editTextChanged(QString)'), self.enable_series_index)
|
||||
self.series.lineEdit().editingFinished.connect(self.increment_series_index)
|
||||
|
||||
self.show()
|
||||
pm = QPixmap()
|
||||
if cover:
|
||||
pm.loadFromData(cover)
|
||||
@ -593,6 +592,8 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
||||
self.original_author = unicode(self.authors.text()).strip()
|
||||
self.original_title = unicode(self.title.text()).strip()
|
||||
|
||||
self.show()
|
||||
|
||||
def create_custom_column_editors(self):
|
||||
w = self.central_widget.widget(1)
|
||||
layout = w.layout()
|
||||
@ -907,3 +908,65 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
||||
dynamic.set('metasingle_window_geometry', bytes(self.saveGeometry()))
|
||||
dynamic.set('metasingle_splitter_state',
|
||||
bytes(self.splitter.saveState()))
|
||||
|
||||
def break_cycles(self):
|
||||
try:
|
||||
self.view_format.disconnect()
|
||||
except:
|
||||
pass # Fails if view format was never connected
|
||||
self.view_format = None
|
||||
self.db = None
|
||||
self.pi = None
|
||||
self.cover_data = self.cpixmap = None
|
||||
|
||||
if __name__ == '__main__':
|
||||
from calibre.library import db
|
||||
from PyQt4.Qt import QApplication
|
||||
from calibre.utils.mem import memory
|
||||
import gc
|
||||
|
||||
|
||||
app = QApplication([])
|
||||
db = db()
|
||||
|
||||
# Initialize all Qt Objects once
|
||||
d = MetadataSingleDialog(None, 4, db)
|
||||
d.break_cycles()
|
||||
d.reject()
|
||||
del d
|
||||
|
||||
for i in range(3):
|
||||
gc.collect()
|
||||
before = memory()
|
||||
|
||||
gc.collect()
|
||||
d = MetadataSingleDialog(None, 4, db)
|
||||
d.break_cycles()
|
||||
d.reject()
|
||||
del d
|
||||
|
||||
for i in range(3):
|
||||
gc.collect()
|
||||
print 'Used memory:', memory(before)/1024.**2, 'MB'
|
||||
gc.collect()
|
||||
|
||||
'''
|
||||
nmap, omap = {}, {}
|
||||
for x in objects:
|
||||
omap[id(x)] = x
|
||||
for x in nobjects:
|
||||
nmap[id(x)] = x
|
||||
|
||||
new_ids = set(nmap.keys()) - set(omap.keys())
|
||||
print "New ids:", len(new_ids)
|
||||
for i in new_ids:
|
||||
o = nmap[i]
|
||||
if o is objects:
|
||||
continue
|
||||
print repr(o)[:1050]
|
||||
refs = gc.get_referrers(o)
|
||||
for r in refs:
|
||||
if r is objects or r is nobjects:
|
||||
continue
|
||||
print '\t', r
|
||||
'''
|
||||
|
55
src/calibre/utils/mem.py
Normal file
55
src/calibre/utils/mem.py
Normal file
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
## {{{ http://code.activestate.com/recipes/286222/ (r1)
|
||||
import os
|
||||
|
||||
_proc_status = '/proc/%d/status' % os.getpid()
|
||||
|
||||
_scale = {'kB': 1024.0, 'mB': 1024.0*1024.0,
|
||||
'KB': 1024.0, 'MB': 1024.0*1024.0}
|
||||
|
||||
def _VmB(VmKey):
|
||||
'''Private.
|
||||
'''
|
||||
global _proc_status, _scale
|
||||
# get pseudo file /proc/<pid>/status
|
||||
try:
|
||||
t = open(_proc_status)
|
||||
v = t.read()
|
||||
t.close()
|
||||
except:
|
||||
return 0.0 # non-Linux?
|
||||
# get VmKey line e.g. 'VmRSS: 9999 kB\n ...'
|
||||
i = v.index(VmKey)
|
||||
v = v[i:].split(None, 3) # whitespace
|
||||
if len(v) < 3:
|
||||
return 0.0 # invalid format?
|
||||
# convert Vm value to bytes
|
||||
return float(v[1]) * _scale[v[2]]
|
||||
|
||||
|
||||
def memory(since=0.0):
|
||||
'''Return memory usage in bytes.
|
||||
'''
|
||||
return _VmB('VmSize:') - since
|
||||
|
||||
|
||||
def resident(since=0.0):
|
||||
'''Return resident memory usage in bytes.
|
||||
'''
|
||||
return _VmB('VmRSS:') - since
|
||||
|
||||
|
||||
def stacksize(since=0.0):
|
||||
'''Return stack size in bytes.
|
||||
'''
|
||||
return _VmB('VmStk:') - since
|
||||
## end of http://code.activestate.com/recipes/286222/ }}}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user