summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2016-09-05 22:33:46 (GMT)
committerBrett Cannon <brett@python.org>2016-09-05 22:33:46 (GMT)
commit3cebf9387279d8b21369f55e205392199ad9b1a2 (patch)
tree3ab40b5c47ee4876a46d2ca6920b402a0e63cd16
parent625cb379f7e77457ca5be94e175d4b71a1d8989f (diff)
downloadcpython-3cebf9387279d8b21369f55e205392199ad9b1a2.zip
cpython-3cebf9387279d8b21369f55e205392199ad9b1a2.tar.gz
cpython-3cebf9387279d8b21369f55e205392199ad9b1a2.tar.bz2
Implement the frame evaluation API aspect of PEP 523.
-rw-r--r--Doc/whatsnew/3.6.rst28
-rw-r--r--Include/ceval.h3
-rw-r--r--Include/pystate.h7
-rw-r--r--Misc/NEWS4
-rw-r--r--Python/ceval.c7
-rw-r--r--Python/pystate.c1
6 files changed, 47 insertions, 3 deletions
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
index 031bf79..085bca3 100644
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -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
diff --git a/Include/ceval.h b/Include/ceval.h
index 73b4ca6..7607f75 100644
--- a/Include/ceval.h
+++ b/Include/ceval.h
@@ -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.
diff --git a/Include/pystate.h b/Include/pystate.h
index f08618c..5a06773 100644
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -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 *);
diff --git a/Misc/NEWS b/Misc/NEWS
index f9abe29..c411531 100644
--- 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.
diff --git a/Python/ceval.c b/Python/ceval.c
index 5a542f0..05563a0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -797,6 +797,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;
#endif
diff --git a/Python/pystate.c b/Python/pystate.c
index 25110b2..61bda2a 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -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;