Патч для ловли присваивания к перзистент атрибутам
by
Anatoly Zaretsky
—
last modified
2007-10-02 01:46
Мой опыт позволяет предложить некое сомнительное приспособление для охоты на такие баги; прилагаемый файл ZODB.Connection.py.diff является патчем к lib/python/ZODB/Connection.py, с помощью которого можно отслеживать, где происходят изменения persistent-объектов. Патч основан на внесении трассировки в код регистрации объекта в менеджере транзакции при первом его измении
Size 1.6 kB - File type text/plainFile contents
--- ZODB/Connection.py 2007-01-14 17:04:10 +0300 +++ ZODB/Connection.py 2007-09-27 19:04:33 +0400 @@ -866,6 +866,20 @@ obj must be an object loaded from this Connection. """ assert obj._p_jar is self + #!!! + try: + from zope.exceptions.exceptionformatter import format_exception + trace = format_exception('', '', FrameToTraceback(sys._getframe(1)), with_filenames=True)[:-1] + trace.reverse() + self._log.info('transaction register %s.%s %s\n%s', + obj.__class__.__module__, obj.__class__.__name__, + oid_repr(obj._p_oid), + (trace[-1] + ''.join(trace[7:-1])).strip()) + del trace + del format_exception + except: + self._log.warning('register: exception while trying to blame persistent assingment') + #!!! if obj._p_oid is None: # The actual complaint here is that an object without # an oid is being registered. I can't think of any way to @@ -1183,3 +1197,20 @@ # a copy of the index here. An alternative would be to ensure that # all callers pass copies. As is, our callers do not make copies. self.index = index.copy() + +#!!! +class FrameToTraceback(object): + def __init__(self, f): + self.tb_frame = f + + @property + def tb_lineno(self): + return self.tb_frame.f_lineno + + @property + def tb_next(self): + next = self.tb_frame.f_back + if next is None: + return None + return FrameToTraceback(next) +#!!!