mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	gh-106307: C API: Add PyMapping_GetOptionalItem() function (GH-106308)
Also add PyMapping_GetOptionalItemString() function.
This commit is contained in:
		
							parent
							
								
									b444bfb0a3
								
							
						
					
					
						commit
						4bf43710d1
					
				
					 15 changed files with 739 additions and 896 deletions
				
			
		|  | @ -33,6 +33,36 @@ See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and | ||||||
|    See also :c:func:`PyObject_GetItem`. |    See also :c:func:`PyObject_GetItem`. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | .. c:function:: int PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) | ||||||
|  | 
 | ||||||
|  |    Variant of :c:func:`PyObject_GetItem` which doesn't raise | ||||||
|  |    :exc:`KeyError` if the key is not found. | ||||||
|  | 
 | ||||||
|  |    If the key is found, return ``1`` and set *\*result* to a new | ||||||
|  |    :term:`strong reference` to the corresponding value. | ||||||
|  |    If the key is not found, return ``0`` and set *\*result* to ``NULL``; | ||||||
|  |    the :exc:`KeyError` is silenced. | ||||||
|  |    If an error other than :exc:`KeyError` is raised, return ``-1`` and | ||||||
|  |    set *\*result* to ``NULL``. | ||||||
|  | 
 | ||||||
|  |    .. versionadded:: 3.13 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | .. c:function:: int PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) | ||||||
|  | 
 | ||||||
|  |    Variant of :c:func:`PyMapping_GetItemString` which doesn't raise | ||||||
|  |    :exc:`KeyError` if the key is not found. | ||||||
|  | 
 | ||||||
|  |    If the key is found, return ``1`` and set *\*result* to a new | ||||||
|  |    :term:`strong reference` to the corresponding value. | ||||||
|  |    If the key is not found, return ``0`` and set *\*result* to ``NULL``; | ||||||
|  |    the :exc:`KeyError` is silenced. | ||||||
|  |    If an error other than :exc:`KeyError` is raised, return ``-1`` and | ||||||
|  |    set *\*result* to ``NULL``. | ||||||
|  | 
 | ||||||
|  |    .. versionadded:: 3.13 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| .. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) | .. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) | ||||||
| 
 | 
 | ||||||
|    Map the string *key* to the value *v* in object *o*.  Returns ``-1`` on |    Map the string *key* to the value *v* in object *o*.  Returns ``-1`` on | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								Doc/data/stable_abi.dat
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Doc/data/stable_abi.dat
									
										
									
										generated
									
									
									
								
							|  | @ -370,6 +370,8 @@ var,PyLong_Type,3.2,, | ||||||
| var,PyMap_Type,3.2,, | var,PyMap_Type,3.2,, | ||||||
| function,PyMapping_Check,3.2,, | function,PyMapping_Check,3.2,, | ||||||
| function,PyMapping_GetItemString,3.2,, | function,PyMapping_GetItemString,3.2,, | ||||||
|  | function,PyMapping_GetOptionalItem,3.13,, | ||||||
|  | function,PyMapping_GetOptionalItemString,3.13,, | ||||||
| function,PyMapping_HasKey,3.2,, | function,PyMapping_HasKey,3.2,, | ||||||
| function,PyMapping_HasKeyString,3.2,, | function,PyMapping_HasKeyString,3.2,, | ||||||
| function,PyMapping_Items,3.2,, | function,PyMapping_Items,3.2,, | ||||||
|  |  | ||||||
|  | @ -742,6 +742,14 @@ New Features | ||||||
|   should not be treated as a failure. |   should not be treated as a failure. | ||||||
|   (Contributed by Serhiy Storchaka in :gh:`106521`.) |   (Contributed by Serhiy Storchaka in :gh:`106521`.) | ||||||
| 
 | 
 | ||||||
|  | * Add :c:func:`PyMapping_GetOptionalItem` and | ||||||
|  |   :c:func:`PyMapping_GetOptionalItemString`: variants of | ||||||
|  |   :c:func:`PyObject_GetItem` and :c:func:`PyMapping_GetItemString` which don't | ||||||
|  |   raise :exc:`KeyError` if the key is not found. | ||||||
|  |   These variants are more convenient and faster if the missing key should not | ||||||
|  |   be treated as a failure. | ||||||
|  |   (Contributed by Serhiy Storchaka in :gh:`106307`.) | ||||||
|  | 
 | ||||||
| * If Python is built in :ref:`debug mode <debug-build>` or :option:`with | * If Python is built in :ref:`debug mode <debug-build>` or :option:`with | ||||||
|   assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and |   assertions <--with-assertions>`, :c:func:`PyTuple_SET_ITEM` and | ||||||
|   :c:func:`PyList_SET_ITEM` now check the index argument with an assertion. |   :c:func:`PyList_SET_ITEM` now check the index argument with an assertion. | ||||||
|  |  | ||||||
|  | @ -840,6 +840,21 @@ PyAPI_FUNC(PyObject *) PyMapping_Items(PyObject *o); | ||||||
| PyAPI_FUNC(PyObject *) PyMapping_GetItemString(PyObject *o, | PyAPI_FUNC(PyObject *) PyMapping_GetItemString(PyObject *o, | ||||||
|                                                const char *key); |                                                const char *key); | ||||||
| 
 | 
 | ||||||
|  | /* Variants of PyObject_GetItem() and PyMapping_GetItemString() which don't
 | ||||||
|  |    raise KeyError if the key is not found. | ||||||
|  | 
 | ||||||
|  |    If the key is found, return 1 and set *result to a new strong | ||||||
|  |    reference to the corresponding value. | ||||||
|  |    If the key is not found, return 0 and set *result to NULL; | ||||||
|  |    the KeyError is silenced. | ||||||
|  |    If an error other than KeyError is raised, return -1 and | ||||||
|  |    set *result to NULL. | ||||||
|  | */ | ||||||
|  | #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000 | ||||||
|  | PyAPI_FUNC(int) PyMapping_GetOptionalItem(PyObject *, PyObject *, PyObject **); | ||||||
|  | PyAPI_FUNC(int) PyMapping_GetOptionalItemString(PyObject *, const char *, PyObject **); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /* Map the string 'key' to the value 'v' in the mapping 'o'.
 | /* Map the string 'key' to the value 'v' in the mapping 'o'.
 | ||||||
|    Returns -1 on failure. |    Returns -1 on failure. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								Lib/test/test_stable_abi_ctypes.py
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Lib/test/test_stable_abi_ctypes.py
									
										
									
										generated
									
									
									
								
							|  | @ -398,6 +398,8 @@ SYMBOL_NAMES = ( | ||||||
|     "PyMap_Type", |     "PyMap_Type", | ||||||
|     "PyMapping_Check", |     "PyMapping_Check", | ||||||
|     "PyMapping_GetItemString", |     "PyMapping_GetItemString", | ||||||
|  |     "PyMapping_GetOptionalItem", | ||||||
|  |     "PyMapping_GetOptionalItemString", | ||||||
|     "PyMapping_HasKey", |     "PyMapping_HasKey", | ||||||
|     "PyMapping_HasKeyString", |     "PyMapping_HasKeyString", | ||||||
|     "PyMapping_Items", |     "PyMapping_Items", | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | Add :c:func:`PyMapping_GetOptionalItem` function. | ||||||
|  | @ -2440,3 +2440,7 @@ | ||||||
|     added = '3.13' |     added = '3.13' | ||||||
| [function.PyObject_GetOptionalAttrString] | [function.PyObject_GetOptionalAttrString] | ||||||
|     added = '3.13' |     added = '3.13' | ||||||
|  | [function.PyMapping_GetOptionalItem] | ||||||
|  |     added = '3.13' | ||||||
|  | [function.PyMapping_GetOptionalItemString] | ||||||
|  |     added = '3.13' | ||||||
|  |  | ||||||
|  | @ -240,15 +240,10 @@ parse_filter_spec_lzma(_lzma_state *state, PyObject *spec) | ||||||
|     /* First, fill in default values for all the options using a preset.
 |     /* First, fill in default values for all the options using a preset.
 | ||||||
|        Then, override the defaults with any values given by the caller. */ |        Then, override the defaults with any values given by the caller. */ | ||||||
| 
 | 
 | ||||||
|     preset_obj = PyMapping_GetItemString(spec, "preset"); |     if (PyMapping_GetOptionalItemString(spec, "preset", &preset_obj) < 0) { | ||||||
|     if (preset_obj == NULL) { |         return NULL; | ||||||
|         if (PyErr_ExceptionMatches(PyExc_KeyError)) { |     } | ||||||
|             PyErr_Clear(); |     if (preset_obj != NULL) { | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             return NULL; |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         int ok = uint32_converter(preset_obj, &preset); |         int ok = uint32_converter(preset_obj, &preset); | ||||||
|         Py_DECREF(preset_obj); |         Py_DECREF(preset_obj); | ||||||
|         if (!ok) { |         if (!ok) { | ||||||
|  | @ -345,11 +340,12 @@ lzma_filter_converter(_lzma_state *state, PyObject *spec, void *ptr) | ||||||
|                         "Filter specifier must be a dict or dict-like object"); |                         "Filter specifier must be a dict or dict-like object"); | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|     id_obj = PyMapping_GetItemString(spec, "id"); |     if (PyMapping_GetOptionalItemString(spec, "id", &id_obj) < 0) { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|     if (id_obj == NULL) { |     if (id_obj == NULL) { | ||||||
|         if (PyErr_ExceptionMatches(PyExc_KeyError)) |         PyErr_SetString(PyExc_ValueError, | ||||||
|             PyErr_SetString(PyExc_ValueError, |                         "Filter specifier must have an \"id\" entry"); | ||||||
|                             "Filter specifier must have an \"id\" entry"); |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|     f->id = PyLong_AsUnsignedLongLong(id_obj); |     f->id = PyLong_AsUnsignedLongLong(id_obj); | ||||||
|  |  | ||||||
|  | @ -4438,16 +4438,13 @@ save(PickleState *st, PicklerObject *self, PyObject *obj, int pers_save) | ||||||
|                PyObject_GetItem and _PyObject_GetAttrId used below. */ |                PyObject_GetItem and _PyObject_GetAttrId used below. */ | ||||||
|             Py_INCREF(reduce_func); |             Py_INCREF(reduce_func); | ||||||
|         } |         } | ||||||
|     } else { |  | ||||||
|         reduce_func = PyObject_GetItem(self->dispatch_table, |  | ||||||
|                                        (PyObject *)type); |  | ||||||
|         if (reduce_func == NULL) { |  | ||||||
|             if (PyErr_ExceptionMatches(PyExc_KeyError)) |  | ||||||
|                 PyErr_Clear(); |  | ||||||
|             else |  | ||||||
|                 goto error; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |     else if (PyMapping_GetOptionalItem(self->dispatch_table, (PyObject *)type, | ||||||
|  |                                        &reduce_func) < 0) | ||||||
|  |     { | ||||||
|  |         goto error; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (reduce_func != NULL) { |     if (reduce_func != NULL) { | ||||||
|         reduce_value = _Pickle_FastCall(reduce_func, Py_NewRef(obj)); |         reduce_value = _Pickle_FastCall(reduce_func, Py_NewRef(obj)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -199,6 +199,30 @@ PyObject_GetItem(PyObject *o, PyObject *key) | ||||||
|     return type_error("'%.200s' object is not subscriptable", o); |     return type_error("'%.200s' object is not subscriptable", o); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int | ||||||
|  | PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result) | ||||||
|  | { | ||||||
|  |     if (PyDict_CheckExact(obj)) { | ||||||
|  |         *result = PyDict_GetItemWithError(obj, key);  /* borrowed */ | ||||||
|  |         if (*result) { | ||||||
|  |             Py_INCREF(*result); | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |         return PyErr_Occurred() ? -1 : 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     *result = PyObject_GetItem(obj, key); | ||||||
|  |     if (*result) { | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |     assert(PyErr_Occurred()); | ||||||
|  |     if (!PyErr_ExceptionMatches(PyExc_KeyError)) { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |     PyErr_Clear(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int | int | ||||||
| PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value) | PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value) | ||||||
| { | { | ||||||
|  | @ -2366,6 +2390,22 @@ PyMapping_GetItemString(PyObject *o, const char *key) | ||||||
|     return r; |     return r; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int | ||||||
|  | PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result) | ||||||
|  | { | ||||||
|  |     if (key == NULL) { | ||||||
|  |         null_error(); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |     PyObject *okey = PyUnicode_FromString(key); | ||||||
|  |     if (okey == NULL) { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |     int rc = PyMapping_GetOptionalItem(obj, okey, result); | ||||||
|  |     Py_DECREF(okey); | ||||||
|  |     return rc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int | int | ||||||
| PyMapping_SetItemString(PyObject *o, const char *key, PyObject *value) | PyMapping_SetItemString(PyObject *o, const char *key, PyObject *value) | ||||||
| { | { | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								PC/python3dll.c
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								PC/python3dll.c
									
										
									
										generated
									
									
									
								
							|  | @ -352,6 +352,8 @@ EXPORT_FUNC(PyLong_FromVoidPtr) | ||||||
| EXPORT_FUNC(PyLong_GetInfo) | EXPORT_FUNC(PyLong_GetInfo) | ||||||
| EXPORT_FUNC(PyMapping_Check) | EXPORT_FUNC(PyMapping_Check) | ||||||
| EXPORT_FUNC(PyMapping_GetItemString) | EXPORT_FUNC(PyMapping_GetItemString) | ||||||
|  | EXPORT_FUNC(PyMapping_GetOptionalItem) | ||||||
|  | EXPORT_FUNC(PyMapping_GetOptionalItemString) | ||||||
| EXPORT_FUNC(PyMapping_HasKey) | EXPORT_FUNC(PyMapping_HasKey) | ||||||
| EXPORT_FUNC(PyMapping_HasKeyString) | EXPORT_FUNC(PyMapping_HasKeyString) | ||||||
| EXPORT_FUNC(PyMapping_Items) | EXPORT_FUNC(PyMapping_Items) | ||||||
|  |  | ||||||
|  | @ -1086,26 +1086,11 @@ dummy_func( | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         inst(LOAD_BUILD_CLASS, ( -- bc)) { |         inst(LOAD_BUILD_CLASS, ( -- bc)) { | ||||||
|             if (PyDict_CheckExact(BUILTINS())) { |             ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0, error); | ||||||
|                 bc = _PyDict_GetItemWithError(BUILTINS(), |             if (bc == NULL) { | ||||||
|                                               &_Py_ID(__build_class__)); |                 _PyErr_SetString(tstate, PyExc_NameError, | ||||||
|                 if (bc == NULL) { |                                  "__build_class__ not found"); | ||||||
|                     if (!_PyErr_Occurred(tstate)) { |                 ERROR_IF(true, error); | ||||||
|                         _PyErr_SetString(tstate, PyExc_NameError, |  | ||||||
|                                          "__build_class__ not found"); |  | ||||||
|                     } |  | ||||||
|                     ERROR_IF(true, error); |  | ||||||
|                 } |  | ||||||
|                 Py_INCREF(bc); |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 bc = PyObject_GetItem(BUILTINS(), &_Py_ID(__build_class__)); |  | ||||||
|                 if (bc == NULL) { |  | ||||||
|                     if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) |  | ||||||
|                         _PyErr_SetString(tstate, PyExc_NameError, |  | ||||||
|                                          "__build_class__ not found"); |  | ||||||
|                     ERROR_IF(true, error); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1280,25 +1265,9 @@ dummy_func( | ||||||
| 
 | 
 | ||||||
|         op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) { |         op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) { | ||||||
|             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); |             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); | ||||||
|             if (PyDict_CheckExact(mod_or_class_dict)) { |             if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { | ||||||
|                 v = PyDict_GetItemWithError(mod_or_class_dict, name); |                 Py_DECREF(mod_or_class_dict); | ||||||
|                 if (v != NULL) { |                 goto error; | ||||||
|                     Py_INCREF(v); |  | ||||||
|                 } |  | ||||||
|                 else if (_PyErr_Occurred(tstate)) { |  | ||||||
|                     Py_DECREF(mod_or_class_dict); |  | ||||||
|                     goto error; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 v = PyObject_GetItem(mod_or_class_dict, name); |  | ||||||
|                 if (v == NULL) { |  | ||||||
|                     if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { |  | ||||||
|                         Py_DECREF(mod_or_class_dict); |  | ||||||
|                         goto error; |  | ||||||
|                     } |  | ||||||
|                     _PyErr_Clear(tstate); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             Py_DECREF(mod_or_class_dict); |             Py_DECREF(mod_or_class_dict); | ||||||
|             if (v == NULL) { |             if (v == NULL) { | ||||||
|  | @ -1310,28 +1279,14 @@ dummy_func( | ||||||
|                     goto error; |                     goto error; | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
|                     if (PyDict_CheckExact(BUILTINS())) { |                     if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { | ||||||
|                         v = PyDict_GetItemWithError(BUILTINS(), name); |                         goto error; | ||||||
|                         if (v == NULL) { |  | ||||||
|                             if (!_PyErr_Occurred(tstate)) { |  | ||||||
|                                 format_exc_check_arg( |  | ||||||
|                                         tstate, PyExc_NameError, |  | ||||||
|                                         NAME_ERROR_MSG, name); |  | ||||||
|                             } |  | ||||||
|                             goto error; |  | ||||||
|                         } |  | ||||||
|                         Py_INCREF(v); |  | ||||||
|                     } |                     } | ||||||
|                     else { |                     if (v == NULL) { | ||||||
|                         v = PyObject_GetItem(BUILTINS(), name); |                         format_exc_check_arg( | ||||||
|                         if (v == NULL) { |                                     tstate, PyExc_NameError, | ||||||
|                             if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { |                                     NAME_ERROR_MSG, name); | ||||||
|                                 format_exc_check_arg( |                         goto error; | ||||||
|                                             tstate, PyExc_NameError, |  | ||||||
|                                             NAME_ERROR_MSG, name); |  | ||||||
|                             } |  | ||||||
|                             goto error; |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -1381,19 +1336,14 @@ dummy_func( | ||||||
|                 /* Slow-path if globals or builtins is not a dict */ |                 /* Slow-path if globals or builtins is not a dict */ | ||||||
| 
 | 
 | ||||||
|                 /* namespace 1: globals */ |                 /* namespace 1: globals */ | ||||||
|                 v = PyObject_GetItem(GLOBALS(), name); |                 ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &v) < 0, error); | ||||||
|                 if (v == NULL) { |                 if (v == NULL) { | ||||||
|                     ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error); |  | ||||||
|                     _PyErr_Clear(tstate); |  | ||||||
| 
 |  | ||||||
|                     /* namespace 2: builtins */ |                     /* namespace 2: builtins */ | ||||||
|                     v = PyObject_GetItem(BUILTINS(), name); |                     ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0, error); | ||||||
|                     if (v == NULL) { |                     if (v == NULL) { | ||||||
|                         if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { |                         format_exc_check_arg( | ||||||
|                             format_exc_check_arg( |                                     tstate, PyExc_NameError, | ||||||
|                                         tstate, PyExc_NameError, |                                     NAME_ERROR_MSG, name); | ||||||
|                                         NAME_ERROR_MSG, name); |  | ||||||
|                         } |  | ||||||
|                         ERROR_IF(true, error); |                         ERROR_IF(true, error); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | @ -1466,25 +1416,9 @@ dummy_func( | ||||||
|             assert(class_dict); |             assert(class_dict); | ||||||
|             assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); |             assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); | ||||||
|             name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); |             name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); | ||||||
|             if (PyDict_CheckExact(class_dict)) { |             if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) { | ||||||
|                 value = PyDict_GetItemWithError(class_dict, name); |                 Py_DECREF(class_dict); | ||||||
|                 if (value != NULL) { |                 goto error; | ||||||
|                     Py_INCREF(value); |  | ||||||
|                 } |  | ||||||
|                 else if (_PyErr_Occurred(tstate)) { |  | ||||||
|                     Py_DECREF(class_dict); |  | ||||||
|                     goto error; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 value = PyObject_GetItem(class_dict, name); |  | ||||||
|                 if (value == NULL) { |  | ||||||
|                     if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { |  | ||||||
|                         Py_DECREF(class_dict); |  | ||||||
|                         goto error; |  | ||||||
|                     } |  | ||||||
|                     _PyErr_Clear(tstate); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             Py_DECREF(class_dict); |             Py_DECREF(class_dict); | ||||||
|             if (!value) { |             if (!value) { | ||||||
|  | @ -1622,10 +1556,8 @@ dummy_func( | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 /* do the same if locals() is not a dict */ |                 /* do the same if locals() is not a dict */ | ||||||
|                 ann_dict = PyObject_GetItem(LOCALS(), &_Py_ID(__annotations__)); |                 ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error); | ||||||
|                 if (ann_dict == NULL) { |                 if (ann_dict == NULL) { | ||||||
|                     ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error); |  | ||||||
|                     _PyErr_Clear(tstate); |  | ||||||
|                     ann_dict = PyDict_New(); |                     ann_dict = PyDict_New(); | ||||||
|                     ERROR_IF(ann_dict == NULL, error); |                     ERROR_IF(ann_dict == NULL, error); | ||||||
|                     err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), |                     err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), | ||||||
|  |  | ||||||
							
								
								
									
										482
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										482
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										872
									
								
								Python/generated_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										872
									
								
								Python/generated_cases.c.h
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -249,16 +249,7 @@ import_get_module(PyThreadState *tstate, PyObject *name) | ||||||
| 
 | 
 | ||||||
|     PyObject *m; |     PyObject *m; | ||||||
|     Py_INCREF(modules); |     Py_INCREF(modules); | ||||||
|     if (PyDict_CheckExact(modules)) { |     (void)PyMapping_GetOptionalItem(modules, name, &m); | ||||||
|         m = PyDict_GetItemWithError(modules, name);  /* borrowed */ |  | ||||||
|         Py_XINCREF(m); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         m = PyObject_GetItem(modules, name); |  | ||||||
|         if (m == NULL && _PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { |  | ||||||
|             _PyErr_Clear(tstate); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     Py_DECREF(modules); |     Py_DECREF(modules); | ||||||
|     return m; |     return m; | ||||||
| } | } | ||||||
|  | @ -322,18 +313,7 @@ import_add_module(PyThreadState *tstate, PyObject *name) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PyObject *m; |     PyObject *m; | ||||||
|     if (PyDict_CheckExact(modules)) { |     if (PyMapping_GetOptionalItem(modules, name, &m) < 0) { | ||||||
|         m = Py_XNewRef(PyDict_GetItemWithError(modules, name)); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         m = PyObject_GetItem(modules, name); |  | ||||||
|         // For backward-compatibility we copy the behavior
 |  | ||||||
|         // of PyDict_GetItemWithError().
 |  | ||||||
|         if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { |  | ||||||
|             _PyErr_Clear(tstate); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     if (_PyErr_Occurred(tstate)) { |  | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|     if (m != NULL && PyModule_Check(m)) { |     if (m != NULL && PyModule_Check(m)) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Serhiy Storchaka
						Serhiy Storchaka