[Zope-Checkins] CVS: Zope/lib/python/Products/PythonScripts - PythonScript.py:1.40.2.1

Shane Hathaway shane@cvs.zope.org
Fri, 8 Mar 2002 11:42:12 -0500


Update of /cvs-repository/Zope/lib/python/Products/PythonScripts
In directory cvs.zope.org:/tmp/cvs-serv2444

Modified Files:
      Tag: shane-better-tracebacks-branch
	PythonScript.py 
Log Message:
Added traceback supplements to PythonScripts and added comments about
the possible weaknesses of the current way functions are used.


=== Zope/lib/python/Products/PythonScripts/PythonScript.py 1.40 => 1.40.2.1 ===
              '_getitem_': guarded_getitem,
              '_write_': full_write_guard,
-             '_print_': RestrictedPython.PrintCollector
+             '_print_': RestrictedPython.PrintCollector,
              }
         l = {}
         exec code in g, l
@@ -286,15 +286,24 @@
                 # Got a cached value.
                 return result
 
-        __traceback_info__ = bound_names, args, kw, self.func_defaults
+        #__traceback_info__ = bound_names, args, kw, self.func_defaults
 
         f = self._v_f
         if f is None:
+            __traceback_supplement__ = (
+                PythonScriptTracebackSupplement, self)
             raise RuntimeError, '%s %s has errors.' % (self.meta_type, self.id)
+
         if bound_names is not None:
-            # Updating func_globals directly *should* be thread-safe.
+            # XXX This causes the whole acquisition chain
+            # to be held by self._v_f.  I think we really should
+            # use new.function() instead, similar to
+            # CMFCore.FSPythonScript.  new.function() takes
+            # about 8 microseconds on a 1 GHz Athlon. - Shane
             f.func_globals.update(bound_names)
-    
+        f.func_globals['__traceback_supplement__'] = (
+            PythonScriptTracebackSupplement, self, -1)
+
         # Execute the function in a new security context.
         security=getSecurityManager()
         security.addContext(self)
@@ -466,6 +475,15 @@
         if RESPONSE is not None:
             RESPONSE.setHeader('Content-Type', 'text/plain')
         return self.read()
+
+
+class PythonScriptTracebackSupplement:
+    """Implementation of Products.ErrorReporter.ITracebackSupplement"""
+    def __init__(self, script, line=0):
+        self.manageable_object = script
+        # If line is set to -1, it means to use tb_lineno.
+        self.line = line
+
 
 _first_indent = re.compile('(?m)^ *(?! |$)')
 _nonempty_line = re.compile('(?m)^(.*\S.*)$')