[Zope-Checkins] CVS: Zope3/lib/python/Persistence - Function.py:1.5
Jeremy Hylton
jeremy@zope.com
Mon, 24 Jun 2002 15:18:36 -0400
Update of /cvs-repository/Zope3/lib/python/Persistence
In directory cvs.zope.org:/tmp/cvs-serv31645
Modified Files:
Function.py
Log Message:
Try to cope with function that have module-level side-effects.
=== Zope3/lib/python/Persistence/Function.py 1.4 => 1.5 ===
+import dis
import new
import sys
from Persistence import Persistent
+_STORE_GLOBAL = chr(dis.opname.index("STORE_GLOBAL"))
+
+def has_side_effect(func):
+ return _STORE_GLOBAL in func.func_code.co_code
+
def get_code_args(co):
"""Return args from code object suitable for passing to constructor."""
return (co.co_argcount,
@@ -32,6 +38,7 @@
# base persistent getattr function does not unghostify an
# object on refences to _p_ attributes.
self._pf_func = func
+ self._v_side_effect = has_side_effect(func)
self._pf_module = module
self._pf_code = {}
@@ -54,6 +61,8 @@
# it must be ours
if attr.startswith('_pf_'):
self.__dict__[attr] = value
+ if attr == "_pf_func":
+ self._v_side_effect = has_side_effect(self._pf_func)
else:
setattr(self._pf_func, attr, value)
@@ -78,8 +87,19 @@
# function is executing? It seems like we need to expose
# refcounts at the Python level to guarantee that this will
# work.
-
- return self._pf_func(*args, **kwargs)
+
+ try:
+ return self._pf_func(*args, **kwargs)
+ finally:
+ # If the func has a side-effect, the module must be marked
+ # as changed. We use the conservative approximation that
+ # any function with a STORE_GLOBAL opcode has a
+ # side-effect, regardless of whether a a particular call
+ # of the function actually executes STORE_GLOBAL.
+
+ # XXX Is this sufficient?
+ if self._v_side_effect:
+ self._pf_module._p_changed = 1
def __getstate__(self):
# If func_dict is empty, store None to avoid creating a dict
@@ -119,3 +139,4 @@
if func_dict:
func.func_dict.update(func_dict)
self._pf_func = func
+ self._v_side_effect = has_side_effect(func)