mirror of https://github.com/python/cpython
Add new PyFrame_GetLasti C-API function (GH-32413)
This commit is contained in:
parent
f4b328e2bb
commit
5b4a4b6f09
|
@ -78,6 +78,17 @@ See also :ref:`Reflection <reflection>`.
|
|||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. c:function:: int PyFrame_GetLasti(PyFrameObject *frame)
|
||||
|
||||
Get the *frame*'s ``f_lasti`` attribute (:class:`dict`).
|
||||
|
||||
Returns -1 if ``frame.f_lasti`` is ``None``.
|
||||
|
||||
*frame* must not be ``NULL``.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. c:function:: PyObject* PyFrame_GetLocals(PyFrameObject *frame)
|
||||
|
||||
Get the *frame*'s ``f_locals`` attribute (:class:`dict`).
|
||||
|
|
|
@ -1121,7 +1121,7 @@ New Features
|
|||
|
||||
* Add new functions to get frame object attributes:
|
||||
:c:func:`PyFrame_GetBuiltins`, :c:func:`PyFrame_GetGenerator`,
|
||||
:c:func:`PyFrame_GetGlobals`.
|
||||
:c:func:`PyFrame_GetGlobals`, :c:func:`PyFrame_GetLasti`.
|
||||
|
||||
Porting to Python 3.11
|
||||
----------------------
|
||||
|
@ -1246,9 +1246,9 @@ Porting to Python 3.11
|
|||
* ``f_gen``: use :c:func:`PyFrame_GetGenerator`.
|
||||
* ``f_globals``: use :c:func:`PyFrame_GetGlobals`.
|
||||
* ``f_iblock``: removed.
|
||||
* ``f_lasti``: use ``PyObject_GetAttrString((PyObject*)frame, "f_lasti")``.
|
||||
* ``f_lasti``: use :c:func:`PyFrame_GetLasti`.
|
||||
Code using ``f_lasti`` with ``PyCode_Addr2Line()`` should use
|
||||
:c:func:`PyFrame_GetLineNumber` instead.
|
||||
:c:func:`PyFrame_GetLineNumber` instead; it may be faster.
|
||||
* ``f_lineno``: use :c:func:`PyFrame_GetLineNumber`
|
||||
* ``f_locals``: use :c:func:`PyFrame_GetLocals`.
|
||||
* ``f_stackdepth``: removed.
|
||||
|
|
|
@ -29,3 +29,4 @@ PyAPI_FUNC(PyObject *) PyFrame_GetGlobals(PyFrameObject *frame);
|
|||
PyAPI_FUNC(PyObject *) PyFrame_GetBuiltins(PyFrameObject *frame);
|
||||
|
||||
PyAPI_FUNC(PyObject *) PyFrame_GetGenerator(PyFrameObject *frame);
|
||||
PyAPI_FUNC(int) PyFrame_GetLasti(PyFrameObject *frame);
|
||||
|
|
|
@ -1102,6 +1102,7 @@ class Test_FrameAPI(unittest.TestCase):
|
|||
self.assertEqual(frame.f_locals, _testcapi.frame_getlocals(frame))
|
||||
self.assertIs(frame.f_globals, _testcapi.frame_getglobals(frame))
|
||||
self.assertIs(frame.f_builtins, _testcapi.frame_getbuiltins(frame))
|
||||
self.assertEqual(frame.f_lasti, _testcapi.frame_getlasti(frame))
|
||||
|
||||
def test_frame_get_generator(self):
|
||||
gen = self.getgenframe()
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Add ``PyFrame_GetLasti`` C-API function to access frame object's ``lasti``
|
||||
attribute safely from C code.
|
|
@ -5893,6 +5893,21 @@ frame_getbuiltins(PyObject *self, PyObject *frame)
|
|||
return PyFrame_GetBuiltins((PyFrameObject *)frame);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
frame_getlasti(PyObject *self, PyObject *frame)
|
||||
{
|
||||
if (!PyFrame_Check(frame)) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a frame");
|
||||
return NULL;
|
||||
}
|
||||
int lasti = PyFrame_GetLasti((PyFrameObject *)frame);
|
||||
if (lasti < 0) {
|
||||
assert(lasti == -1);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return PyLong_FromLong(lasti);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *negative_dictoffset(PyObject *, PyObject *);
|
||||
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
|
||||
|
@ -6186,6 +6201,7 @@ static PyMethodDef TestMethods[] = {
|
|||
{"frame_getglobals", frame_getglobals, METH_O, NULL},
|
||||
{"frame_getgenerator", frame_getgenerator, METH_O, NULL},
|
||||
{"frame_getbuiltins", frame_getbuiltins, METH_O, NULL},
|
||||
{"frame_getlasti", frame_getlasti, METH_O, NULL},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
|
@ -880,7 +880,7 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
|
|||
// This only works when opcode is a non-quickened form:
|
||||
assert(_PyOpcode_Deopt[opcode] == opcode);
|
||||
int check_oparg = 0;
|
||||
for (_Py_CODEUNIT *instruction = _PyCode_CODE(frame->f_code);
|
||||
for (_Py_CODEUNIT *instruction = _PyCode_CODE(frame->f_code);
|
||||
instruction < frame->prev_instr; instruction++)
|
||||
{
|
||||
int check_opcode = _PyOpcode_Deopt[_Py_OPCODE(*instruction)];
|
||||
|
@ -1135,6 +1135,16 @@ PyFrame_GetBuiltins(PyFrameObject *frame)
|
|||
return frame_getbuiltins(frame, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
PyFrame_GetLasti(PyFrameObject *frame)
|
||||
{
|
||||
int lasti = _PyInterpreterFrame_LASTI(frame->f_frame);
|
||||
if (lasti < 0) {
|
||||
return -1;
|
||||
}
|
||||
return lasti*2;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyFrame_GetGenerator(PyFrameObject *frame)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue