]> granicus.if.org Git - python/commitdiff
Implement the frame evaluation API aspect of PEP 523.
authorBrett Cannon <brett@python.org>
Mon, 5 Sep 2016 22:33:46 +0000 (15:33 -0700)
committerBrett Cannon <brett@python.org>
Mon, 5 Sep 2016 22:33:46 +0000 (15:33 -0700)
Doc/whatsnew/3.6.rst
Include/ceval.h
Include/pystate.h
Misc/NEWS
Python/ceval.c
Python/pystate.c

index 031bf797b8f6519378eae7b55050698a012938ac..085bca31dd48a3d2f2461d7e26fe7328e14fd95d 100644 (file)
@@ -97,6 +97,34 @@ Windows improvements:
 New Features
 ============
 
+.. _pep-523:
+
+PEP 523: Adding a frame evaluation API to CPython
+=================================================
+
+While Python provides extensive support to customize how code
+executes, one place it has not done so is in the evaluation of frame
+objects. If you wanted some way to intercept frame evaluation in
+Python there really wasn't any way without directly manipulating
+function pointers for defined functions.
+
+:pep:`523` changes this by providing an API to make frame
+evaluation pluggable at the C level. This will allow for tools such
+as debuggers and JITs to intercept frame evaluation before the
+execution of Python code begins. This enables the use of alternative
+evaluation implementations for Python code, tracking frame
+evaluation, etc.
+
+This API is not part of the limited C API and is marked as private to
+signal that usage of this API is expected to be limited and only
+applicable to very select, low-level use-cases.
+
+.. seealso::
+
+    :pep:`523` - Adding a frame evaluation API to CPython
+       PEP written by Brett Cannon and Dino Viehland.
+
+
 .. _pep-519:
 
 PEP 519: Adding a file system path protocol
index 73b4ca632821e26fc7e9e184b1cbcbce889b927b..7607f75dcabc82fb9d242ce4100fa21f32039a44 100644 (file)
@@ -119,6 +119,9 @@ PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *);
 PyAPI_FUNC(PyObject *) PyEval_GetCallStats(PyObject *);
 PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *);
 PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc);
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(struct _frame *f, int exc);
+#endif
 
 /* Interface for threads.
 
index f08618cc00f67ef822c1b0f2b8c6c172c8171081..5a067736e37a5a2f59e640b91b7e3cf2c41a918e 100644 (file)
@@ -12,10 +12,13 @@ extern "C" {
 
 struct _ts; /* Forward */
 struct _is; /* Forward */
+struct _frame; /* Forward declaration for PyFrameObject. */
 
 #ifdef Py_LIMITED_API
 typedef struct _is PyInterpreterState;
 #else
+typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
+
 typedef struct _is {
 
     struct _is *next;
@@ -42,14 +45,14 @@ typedef struct _is {
 
     PyObject *builtins_copy;
     PyObject *import_func;
+    /* Initialized to PyEval_EvalFrameDefault(). */
+    _PyFrameEvalFunction eval_frame;
 } PyInterpreterState;
 #endif
 
 
 /* State unique per thread */
 
-struct _frame; /* Avoid including frameobject.h */
-
 #ifndef Py_LIMITED_API
 /* Py_tracefunc return -1 when raising an exception, or 0 for success. */
 typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *);
index f9abe29807b55fa641cc96c19ce9a713c9fec8df..c411531341bd0be0210cd9a2ea1dbfa01791a16b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -17,7 +17,9 @@ Core and Builtins
   restriction: in beta 2, backslashes will only be disallowed inside
   the braces (where the expressions are). This is a breaking change
   from the 3.6 alpha releases.
-  
+
+- Implement the frame evaluation part of PEP 523.
+
 - Issue #27870: A left shift of zero by a large integer no longer attempts
   to allocate large amounts of memory.
 
index 5a542f006391d39682062cf96179c372d2c44505..05563a001c22a1e60539288f4f74c1d55d2005e8 100644 (file)
@@ -796,6 +796,13 @@ PyEval_EvalFrame(PyFrameObject *f) {
 
 PyObject *
 PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
+{
+    PyThreadState *tstate = PyThreadState_GET();
+    return tstate->interp->eval_frame(f, throwflag);
+}
+
+PyObject *
+_PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
 {
 #ifdef DXPAIRS
     int lastopcode = 0;
index 25110b287ffacce97b728da304977ad3ef69906f..61bda2a9fbb08bf9f785818f34a95aadf09ce9bf 100644 (file)
@@ -91,6 +91,7 @@ PyInterpreterState_New(void)
         interp->fscodec_initialized = 0;
         interp->importlib = NULL;
         interp->import_func = NULL;
+        interp->eval_frame = _PyEval_EvalFrameDefault;
 #ifdef HAVE_DLOPEN
 #if HAVE_DECL_RTLD_NOW
         interp->dlopenflags = RTLD_NOW;