5
5
#include "pycore_code.h" // CO_FAST_LOCAL, etc.
6
6
#include "pycore_function.h" // _PyFunction_FromConstructor()
7
7
#include "pycore_moduleobject.h" // _PyModule_GetDict()
8
+ #include "pycore_modsupport.h" // _PyArg_CheckPositional()
8
9
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
9
10
#include "pycore_opcode_metadata.h" // _PyOpcode_Deopt, _PyOpcode_Caches
10
11
@@ -158,16 +159,16 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
158
159
PyObject * * fast = _PyFrame_GetLocalsArray (frame -> f_frame );
159
160
PyCodeObject * co = _PyFrame_GetCode (frame -> f_frame );
160
161
161
- if (value == NULL ) {
162
- PyErr_SetString (PyExc_TypeError , "cannot remove variables from FrameLocalsProxy" );
163
- return -1 ;
164
- }
165
-
166
162
int i = framelocalsproxy_getkeyindex (frame , key , false);
167
163
if (i == -2 ) {
168
164
return -1 ;
169
165
}
170
166
if (i >= 0 ) {
167
+ if (value == NULL ) {
168
+ PyErr_SetString (PyExc_ValueError , "cannot remove local variables from FrameLocalsProxy" );
169
+ return -1 ;
170
+ }
171
+
171
172
_Py_Executors_InvalidateDependency (PyInterpreterState_Get (), co , 1 );
172
173
173
174
_PyLocals_Kind kind = _PyLocals_GetKind (co -> co_localspluskinds , i );
@@ -200,6 +201,10 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
200
201
PyObject * extra = frame -> f_extra_locals ;
201
202
202
203
if (extra == NULL ) {
204
+ if (value == NULL ) {
205
+ _PyErr_SetKeyError (key );
206
+ return -1 ;
207
+ }
203
208
extra = PyDict_New ();
204
209
if (extra == NULL ) {
205
210
return -1 ;
@@ -209,7 +214,11 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
209
214
210
215
assert (PyDict_Check (extra ));
211
216
212
- return PyDict_SetItem (extra , key , value );
217
+ if (value == NULL ) {
218
+ return PyDict_DelItem (extra , key );
219
+ } else {
220
+ return PyDict_SetItem (extra , key , value );
221
+ }
213
222
}
214
223
215
224
static int
@@ -674,6 +683,59 @@ framelocalsproxy_setdefault(PyObject* self, PyObject *const *args, Py_ssize_t na
674
683
return result ;
675
684
}
676
685
686
+ static PyObject *
687
+ framelocalsproxy_pop (PyObject * self , PyObject * const * args , Py_ssize_t nargs )
688
+ {
689
+ if (!_PyArg_CheckPositional ("pop" , nargs , 1 , 2 )) {
690
+ return NULL ;
691
+ }
692
+
693
+ PyObject * key = args [0 ];
694
+ PyObject * default_value = NULL ;
695
+
696
+ if (nargs == 2 ) {
697
+ default_value = args [1 ];
698
+ }
699
+
700
+ PyFrameObject * frame = ((PyFrameLocalsProxyObject * )self )-> frame ;
701
+
702
+ int i = framelocalsproxy_getkeyindex (frame , key , false);
703
+ if (i == -2 ) {
704
+ return NULL ;
705
+ }
706
+
707
+ if (i >= 0 ) {
708
+ PyErr_SetString (PyExc_ValueError , "cannot remove local variables from FrameLocalsProxy" );
709
+ return NULL ;
710
+ }
711
+
712
+ PyObject * result = NULL ;
713
+
714
+ if (frame -> f_extra_locals == NULL ) {
715
+ if (default_value != NULL ) {
716
+ return Py_XNewRef (default_value );
717
+ } else {
718
+ _PyErr_SetKeyError (key );
719
+ return NULL ;
720
+ }
721
+ }
722
+
723
+ if (PyDict_Pop (frame -> f_extra_locals , key , & result ) < 0 ) {
724
+ return NULL ;
725
+ }
726
+
727
+ if (result == NULL ) {
728
+ if (default_value != NULL ) {
729
+ return Py_XNewRef (default_value );
730
+ } else {
731
+ _PyErr_SetKeyError (key );
732
+ return NULL ;
733
+ }
734
+ }
735
+
736
+ return result ;
737
+ }
738
+
677
739
static PyObject *
678
740
framelocalsproxy_copy (PyObject * self , PyObject * Py_UNUSED (ignored ))
679
741
{
@@ -741,6 +803,8 @@ static PyMethodDef framelocalsproxy_methods[] = {
741
803
NULL },
742
804
{"get" , _PyCFunction_CAST (framelocalsproxy_get ), METH_FASTCALL ,
743
805
NULL },
806
+ {"pop" , _PyCFunction_CAST (framelocalsproxy_pop ), METH_FASTCALL ,
807
+ NULL },
744
808
{"setdefault" , _PyCFunction_CAST (framelocalsproxy_setdefault ), METH_FASTCALL ,
745
809
NULL },
746
810
{NULL , NULL } /* sentinel */
0 commit comments