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
_PyStackRef * 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 );
@@ -202,6 +203,10 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
202
203
PyObject * extra = frame -> f_extra_locals ;
203
204
204
205
if (extra == NULL ) {
206
+ if (value == NULL ) {
207
+ _PyErr_SetKeyError (key );
208
+ return -1 ;
209
+ }
205
210
extra = PyDict_New ();
206
211
if (extra == NULL ) {
207
212
return -1 ;
@@ -211,7 +216,11 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
211
216
212
217
assert (PyDict_Check (extra ));
213
218
214
- return PyDict_SetItem (extra , key , value );
219
+ if (value == NULL ) {
220
+ return PyDict_DelItem (extra , key );
221
+ } else {
222
+ return PyDict_SetItem (extra , key , value );
223
+ }
215
224
}
216
225
217
226
static int
@@ -676,6 +685,59 @@ framelocalsproxy_setdefault(PyObject* self, PyObject *const *args, Py_ssize_t na
676
685
return result ;
677
686
}
678
687
688
+ static PyObject *
689
+ framelocalsproxy_pop (PyObject * self , PyObject * const * args , Py_ssize_t nargs )
690
+ {
691
+ if (!_PyArg_CheckPositional ("pop" , nargs , 1 , 2 )) {
692
+ return NULL ;
693
+ }
694
+
695
+ PyObject * key = args [0 ];
696
+ PyObject * default_value = NULL ;
697
+
698
+ if (nargs == 2 ) {
699
+ default_value = args [1 ];
700
+ }
701
+
702
+ PyFrameObject * frame = ((PyFrameLocalsProxyObject * )self )-> frame ;
703
+
704
+ int i = framelocalsproxy_getkeyindex (frame , key , false);
705
+ if (i == -2 ) {
706
+ return NULL ;
707
+ }
708
+
709
+ if (i >= 0 ) {
710
+ PyErr_SetString (PyExc_ValueError , "cannot remove local variables from FrameLocalsProxy" );
711
+ return NULL ;
712
+ }
713
+
714
+ PyObject * result = NULL ;
715
+
716
+ if (frame -> f_extra_locals == NULL ) {
717
+ if (default_value != NULL ) {
718
+ return Py_XNewRef (default_value );
719
+ } else {
720
+ _PyErr_SetKeyError (key );
721
+ return NULL ;
722
+ }
723
+ }
724
+
725
+ if (PyDict_Pop (frame -> f_extra_locals , key , & result ) < 0 ) {
726
+ return NULL ;
727
+ }
728
+
729
+ if (result == NULL ) {
730
+ if (default_value != NULL ) {
731
+ return Py_XNewRef (default_value );
732
+ } else {
733
+ _PyErr_SetKeyError (key );
734
+ return NULL ;
735
+ }
736
+ }
737
+
738
+ return result ;
739
+ }
740
+
679
741
static PyObject *
680
742
framelocalsproxy_copy (PyObject * self , PyObject * Py_UNUSED (ignored ))
681
743
{
@@ -743,6 +805,8 @@ static PyMethodDef framelocalsproxy_methods[] = {
743
805
NULL },
744
806
{"get" , _PyCFunction_CAST (framelocalsproxy_get ), METH_FASTCALL ,
745
807
NULL },
808
+ {"pop" , _PyCFunction_CAST (framelocalsproxy_pop ), METH_FASTCALL ,
809
+ NULL },
746
810
{"setdefault" , _PyCFunction_CAST (framelocalsproxy_setdefault ), METH_FASTCALL ,
747
811
NULL },
748
812
{NULL , NULL } /* sentinel */
0 commit comments