-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
gh-94936: C getters: co_varnames, co_cellvars, co_freevars #95008
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Added :c:func:`PyCode_GetVarnames`, :c:func:`PyCode_GetCellvars` and | ||
:c:func:`PyCode_GetFreevars` for accessing ``co_varnames``, ``co_cellvars`` | ||
and ``co_freevars`` respectively via the C API. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5932,21 +5932,79 @@ test_code_api(PyObject *self, PyObject *Py_UNUSED(args)) | |
if (co == NULL) { | ||
return NULL; | ||
} | ||
PyObject *co_code = PyCode_GetCode(co); | ||
if (co_code == NULL) { | ||
Py_DECREF(co); | ||
return NULL; | ||
} | ||
assert(PyBytes_CheckExact(co_code)); | ||
if (PyObject_Length(co_code) == 0) { | ||
PyErr_SetString(PyExc_ValueError, "empty co_code"); | ||
Py_DECREF(co); | ||
/* co_code */ | ||
{ | ||
PyObject *co_code = PyCode_GetCode(co); | ||
if (co_code == NULL) { | ||
goto fail; | ||
} | ||
assert(PyBytes_CheckExact(co_code)); | ||
if (PyObject_Length(co_code) == 0) { | ||
PyErr_SetString(PyExc_ValueError, "empty co_code"); | ||
Py_DECREF(co_code); | ||
goto fail; | ||
} | ||
Py_DECREF(co_code); | ||
return NULL; | ||
} | ||
/* co_varnames */ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make more sense to expose the functions here, and test them in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be better, but I'm fine with these tests. |
||
PyObject *co_varnames = PyCode_GetVarnames(co); | ||
if (co_varnames == NULL) { | ||
goto fail; | ||
} | ||
if (!PyTuple_CheckExact(co_varnames)) { | ||
PyErr_SetString(PyExc_TypeError, "co_varnames not tuple"); | ||
Py_DECREF(co_varnames); | ||
goto fail; | ||
} | ||
if (PyTuple_GET_SIZE(co_varnames) != 0) { | ||
PyErr_SetString(PyExc_ValueError, "non-empty co_varnames"); | ||
Py_DECREF(co_varnames); | ||
goto fail; | ||
} | ||
Py_DECREF(co_varnames); | ||
} | ||
/* co_cellvars */ | ||
{ | ||
PyObject *co_cellvars = PyCode_GetCellvars(co); | ||
if (co_cellvars == NULL) { | ||
goto fail; | ||
} | ||
if (!PyTuple_CheckExact(co_cellvars)) { | ||
PyErr_SetString(PyExc_TypeError, "co_cellvars not tuple"); | ||
Py_DECREF(co_cellvars); | ||
goto fail; | ||
} | ||
if (PyTuple_GET_SIZE(co_cellvars) != 0) { | ||
PyErr_SetString(PyExc_ValueError, "non-empty co_cellvars"); | ||
Py_DECREF(co_cellvars); | ||
goto fail; | ||
} | ||
Py_DECREF(co_cellvars); | ||
} | ||
/* co_freevars */ | ||
{ | ||
PyObject *co_freevars = PyCode_GetFreevars(co); | ||
if (co_freevars == NULL) { | ||
goto fail; | ||
} | ||
if (!PyTuple_CheckExact(co_freevars)) { | ||
PyErr_SetString(PyExc_TypeError, "co_freevars not tuple"); | ||
Py_DECREF(co_freevars); | ||
goto fail; | ||
} | ||
if (PyTuple_GET_SIZE(co_freevars) != 0) { | ||
PyErr_SetString(PyExc_ValueError, "non-empty co_freevars"); | ||
Py_DECREF(co_freevars); | ||
goto fail; | ||
} | ||
Py_DECREF(co_freevars); | ||
} | ||
Py_DECREF(co); | ||
Py_DECREF(co_code); | ||
Py_RETURN_NONE; | ||
fail: | ||
Py_DECREF(co); | ||
return NULL; | ||
} | ||
|
||
static int | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1400,18 +1400,36 @@ _PyCode_GetVarnames(PyCodeObject *co) | |
return get_localsplus_names(co, CO_FAST_LOCAL, co->co_nlocals); | ||
} | ||
|
||
PyObject * | ||
PyCode_GetVarnames(PyCodeObject *code) | ||
{ | ||
return _PyCode_GetVarnames(code); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the advantage of separate wrapper functions rather than just removing the leading There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I concur wuth @gvanrossum, unless it's implemented as a static inline function, I see no advantage, but that's not the case here. Just rename _PyCode_GetVarnames() to PyCode_GetVarnames(). Same remark for the 2 other functions. |
||
} | ||
|
||
PyObject * | ||
_PyCode_GetCellvars(PyCodeObject *co) | ||
{ | ||
return get_localsplus_names(co, CO_FAST_CELL, co->co_ncellvars); | ||
} | ||
|
||
PyObject * | ||
PyCode_GetCellvars(PyCodeObject *code) | ||
{ | ||
return _PyCode_GetCellvars(code); | ||
} | ||
|
||
PyObject * | ||
_PyCode_GetFreevars(PyCodeObject *co) | ||
{ | ||
return get_localsplus_names(co, CO_FAST_FREE, co->co_nfreevars); | ||
} | ||
|
||
PyObject * | ||
PyCode_GetFreevars(PyCodeObject *code) | ||
{ | ||
return _PyCode_GetFreevars(code); | ||
} | ||
|
||
static void | ||
deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len) | ||
{ | ||
|
Uh oh!
There was an error while loading. Please reload this page.