Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
42d7186
Basic prototype for frame proxy
gaogaotiantian Feb 7, 2024
7eeab1b
Fix some lint and remove oprun check
gaogaotiantian Feb 8, 2024
60e70e7
Not entirely work yet
gaogaotiantian Feb 8, 2024
1454ce4
Fix a bug
gaogaotiantian Feb 8, 2024
0045274
Change code style and add GC
gaogaotiantian Feb 13, 2024
de73bc9
Clean up code
gaogaotiantian Feb 13, 2024
ca92393
Disable all fast/local functions
gaogaotiantian Mar 1, 2024
ff886ff
Update tests for the new f_locals
gaogaotiantian Mar 2, 2024
9690a2d
Comment out the pop for now
gaogaotiantian Mar 2, 2024
6e9848a
Convert f_locals to dict first
gaogaotiantian Mar 2, 2024
b84b0df
Add static to static functions, add interface for new C API
gaogaotiantian Apr 24, 2024
bebff28
Add some tests and a few methods
gaogaotiantian Apr 26, 2024
d846de9
Implement all methods
gaogaotiantian Apr 27, 2024
d00a742
Make f_extra_locals extra lazy
gaogaotiantian Apr 27, 2024
1a4344d
Merge branch 'main' into pep667
gaogaotiantian Apr 27, 2024
f720e12
Fix typo
gaogaotiantian Apr 27, 2024
64d3772
Remove print debugging
gaogaotiantian Apr 27, 2024
2eadbf0
Fix some styling issue
gaogaotiantian Apr 27, 2024
cbae199
Update generated files for cAPI
gaogaotiantian Apr 27, 2024
9e7edf8
Remove f_fast_as_locals and useless calls for sys.settrace
gaogaotiantian Apr 27, 2024
523cb75
📜🤖 Added by blurb_it.
blurb-it[bot] Apr 27, 2024
4b83311
Add the new type to static types
gaogaotiantian Apr 27, 2024
ae2db7c
Remove internal APIs for fast locals
gaogaotiantian Apr 27, 2024
bf45c02
Add extra tests for closure
gaogaotiantian Apr 27, 2024
026e15e
Add the type to globals-to-fix
gaogaotiantian Apr 27, 2024
f42980d
Add CAapi test
gaogaotiantian Apr 27, 2024
e693ad0
Polish lint
gaogaotiantian Apr 27, 2024
5dd045b
Apply some simple changes
gaogaotiantian Apr 28, 2024
30ecd4d
Update Misc/NEWS.d/next/Core and Builtins/2024-04-27-21-44-40.gh-issu…
gaogaotiantian Apr 28, 2024
f35c5e3
Abstract the key index part
gaogaotiantian Apr 28, 2024
5844fb4
Fix error handling
gaogaotiantian Apr 28, 2024
06277f9
Make key index work better
gaogaotiantian Apr 28, 2024
e1c3f56
Add comments for GetHiddenLocals
gaogaotiantian Apr 30, 2024
b672d84
Add global test
gaogaotiantian Apr 30, 2024
3e32572
Remove unsupported methods
gaogaotiantian May 2, 2024
8dc4664
Support non-string keys
gaogaotiantian May 2, 2024
652f641
Use static function for setitem
gaogaotiantian May 2, 2024
f29e6a3
Fix the list comp
gaogaotiantian May 3, 2024
e0ca4fe
Fix mapping check
gaogaotiantian May 3, 2024
f78156a
Fix frame_getlocals
gaogaotiantian May 3, 2024
4503145
Fix test error
gaogaotiantian May 3, 2024
cdac22c
Change the new ref for getcode
gaogaotiantian May 3, 2024
49287ff
Avoid creating the frame object if possible
gaogaotiantian May 3, 2024
378aacf
Remove a single blank line
gaogaotiantian May 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Support non-string keys
  • Loading branch information
gaogaotiantian committed May 2, 2024
commit 8dc46642fa98feb1ff0b14c3da392b52e90ec971
14 changes: 8 additions & 6 deletions Lib/test/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ def test_as_dict(self):
self.assertEqual(d.setdefault('new', 5), 5)
self.assertEqual(d['new'], 5)

with self.assertRaises(KeyError):
d['non_exist']

def test_as_number(self):
x = 1
y = 2
Expand All @@ -345,6 +348,11 @@ def test_as_number(self):
with self.assertRaises(TypeError):
_ = d | [3]

def test_non_string_key(self):
d = sys._getframe().f_locals
d[1] = 2
self.assertEqual(d[1], 2)

def test_write_with_hidden(self):
def f():
f_locals = [sys._getframe().f_locals for b in [0]][0]
Expand Down Expand Up @@ -391,12 +399,6 @@ def test_unsupport(self):
with self.assertRaises(TypeError):
copy.deepcopy(d)

with self.assertRaises(TypeError):
d.get(1)

with self.assertRaises(TypeError):
d.setdefault(1, 'x')


class TestFrameCApi(unittest.TestCase):
def test_basic(self):
Expand Down
104 changes: 50 additions & 54 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ framelocalsproxy_getkeyindex(PyFrameObject *frame, PyObject* key, bool read)
* - if read == true, returns the index if the value is not NULL
* - if read == false, returns the index if the value is not hidden
*/

assert(PyUnicode_CheckExact(key));

PyCodeObject *co = PyFrame_GetCode(frame);
int found_key = false;

Expand Down Expand Up @@ -388,11 +391,13 @@ framelocalsproxy_getitem(PyObject *self, PyObject *key)
PyFrameObject* frame = ((PyFrameLocalsProxyObject*)self)->frame;
PyCodeObject* co = PyFrame_GetCode(frame);

int i = framelocalsproxy_getkeyindex(frame, key, true);
if (i >= 0) {
PyObject *value = framelocalsproxy_getval(frame, co, i);
assert(value != NULL);
return Py_NewRef(value);
if (PyUnicode_CheckExact(key)) {
int i = framelocalsproxy_getkeyindex(frame, key, true);
if (i >= 0) {
PyObject *value = framelocalsproxy_getval(frame, co, i);
assert(value != NULL);
return Py_NewRef(value);
}
}

// Okay not in the fast locals, try extra locals
Expand Down Expand Up @@ -422,34 +427,35 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
return -1;
}

int i = framelocalsproxy_getkeyindex(frame, key, false);

if (i >= 0) {
_PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
if (PyUnicode_CheckExact(key)) {
int i = framelocalsproxy_getkeyindex(frame, key, false);
if (i >= 0) {
_PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);

PyObject *oldvalue = fast[i];
PyObject *cell = NULL;
if (kind == CO_FAST_FREE) {
// The cell was set when the frame was created from
// the function's closure.
assert(oldvalue != NULL && PyCell_Check(oldvalue));
cell = oldvalue;
} else if (kind & CO_FAST_CELL && oldvalue != NULL) {
if (PyCell_Check(oldvalue)) {
PyObject *oldvalue = fast[i];
PyObject *cell = NULL;
if (kind == CO_FAST_FREE) {
// The cell was set when the frame was created from
// the function's closure.
assert(oldvalue != NULL && PyCell_Check(oldvalue));
cell = oldvalue;
} else if (kind & CO_FAST_CELL && oldvalue != NULL) {
if (PyCell_Check(oldvalue)) {
cell = oldvalue;
}
}
}
if (cell != NULL) {
oldvalue = PyCell_GET(cell);
if (value != oldvalue) {
PyCell_SET(cell, Py_XNewRef(value));
Py_XDECREF(oldvalue);
if (cell != NULL) {
oldvalue = PyCell_GET(cell);
if (value != oldvalue) {
PyCell_SET(cell, Py_XNewRef(value));
Py_XDECREF(oldvalue);
}
} else if (value != oldvalue) {
Py_XSETREF(fast[i], Py_NewRef(value));
}
} else if (value != oldvalue) {
Py_XSETREF(fast[i], Py_NewRef(value));
Py_XDECREF(value);
return 0;
}
Py_XDECREF(value);
return 0;
}

// Okay not in the fast locals, try extra locals
Expand All @@ -473,21 +479,21 @@ static PyObject*
framelocalsproxy_contains(PyObject *self, PyObject *key)
{
PyFrameObject *frame = ((PyFrameLocalsProxyObject*)self)->frame;
int i = framelocalsproxy_getkeyindex(frame, key, true);

if (i >= 0) {
PyObject *value = framelocalsproxy_getval(frame, PyFrame_GetCode(frame), i);
assert(value != NULL);
Py_RETURN_TRUE;
} else {
PyObject *extra = ((PyFrameObject*)frame)->f_extra_locals;
if (extra != NULL) {
int result = PyDict_Contains(extra, key);
if (result < 0) {
return NULL;
} else if (result > 0) {
Py_RETURN_TRUE;
}

if (PyUnicode_CheckExact(key)) {
int i = framelocalsproxy_getkeyindex(frame, key, true);
if (i >= 0) {
Py_RETURN_TRUE;
}
}

PyObject *extra = ((PyFrameObject*)frame)->f_extra_locals;
if (extra != NULL) {
int result = PyDict_Contains(extra, key);
if (result < 0) {
return NULL;
} else if (result > 0) {
Py_RETURN_TRUE;
}
}

Expand Down Expand Up @@ -520,12 +526,7 @@ framelocalsproxy_get(PyObject* self, PyObject *const *args, Py_ssize_t nargs)
default_value = args[1];
}

if (!PyUnicode_CheckExact(key)) {
PyErr_SetString(PyExc_TypeError, "key must be a string");
return NULL;
}

PyObject *result = framelocalsproxy_getitem(self, args[0]);
PyObject *result = framelocalsproxy_getitem(self, key);

if (result == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyError)) {
Expand Down Expand Up @@ -553,11 +554,6 @@ framelocalsproxy_setdefault(PyObject* self, PyObject *const *args, Py_ssize_t na
default_value = args[1];
}

if (!PyUnicode_CheckExact(key)) {
PyErr_SetString(PyExc_TypeError, "key must be a string");
return NULL;
}

PyObject *result = framelocalsproxy_getitem(self, key);

if (result == NULL) {
Expand Down