| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 1af025d commit 6932c3e
11 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -302,7 +302,7 @@ PyAPI_FUNC(int) _PyEval_ExceptionGroupMatch(_PyInterpreterFrame *, PyObject* exc | |||
| 302 | 302 | PyAPI_FUNC(void) _PyEval_FormatAwaitableError(PyThreadState *tstate, PyTypeObject *type, int oparg); | |
| 303 | 303 | PyAPI_FUNC(void) _PyEval_FormatExcCheckArg(PyThreadState *tstate, PyObject *exc, const char *format_str, PyObject *obj); | |
| 304 | 304 | PyAPI_FUNC(void) _PyEval_FormatExcUnbound(PyThreadState *tstate, PyCodeObject *co, int oparg); | |
| 305 | - PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs); | ||
| 305 | + PyAPI_FUNC(void) _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs, PyObject *dupkey); | ||
| 306 | 306 | PyAPI_FUNC(PyObject *) _PyEval_ImportFrom(PyThreadState *, PyObject *, PyObject *); | |
| 307 | 307 | ||
| 308 | 308 | PyAPI_FUNC(PyObject *) _PyEval_LazyImportName( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,7 +55,7 @@ extern Py_ssize_t _PyDict_SizeOf_LockHeld(PyDictObject *); | |||
| 55 | 55 | of a key wins, if override is 2, a KeyError with conflicting key as | |
| 56 | 56 | argument is raised. | |
| 57 | 57 | */ | |
| 58 | - PyAPI_FUNC(int) _PyDict_MergeEx(PyObject *mp, PyObject *other, int override); | ||
| 58 | + PyAPI_FUNC(int) _PyDict_MergeUniq(PyObject *mp, PyObject *other, PyObject **dupkey); | ||
| 59 | 59 | ||
| 60 | 60 | extern void _PyDict_DebugMallocStats(FILE *out); | |
| 61 | 61 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -634,11 +634,11 @@ def test_errors_in_keys(): | |||
| 634 | 634 | ... | |
| 635 | 635 | AttributeError: some error | |
| 636 | 636 | ||
| 637 | - >>> exc = TypeError('some error') | ||
| 637 | + >>> exc = KeyError('some error') | ||
| 638 | 638 | >>> f(**D()) | |
| 639 | 639 | Traceback (most recent call last): | |
| 640 | 640 | ... | |
| 641 | - TypeError: some error | ||
| 641 | + KeyError: 'some error' | ||
| 642 | 642 | """ | |
| 643 | 643 | ||
| 644 | 644 | def test_errors_in_keys_next(): | |
@@ -666,11 +666,11 @@ def test_errors_in_keys_next(): | |||
| 666 | 666 | ... | |
| 667 | 667 | AttributeError: some error | |
| 668 | 668 | ||
| 669 | - >>> exc = TypeError('some error') | ||
| 669 | + >>> exc = KeyError('some error') | ||
| 670 | 670 | >>> f(**D()) | |
| 671 | 671 | Traceback (most recent call last): | |
| 672 | 672 | ... | |
| 673 | - TypeError: some error | ||
| 673 | + KeyError: 'some error' | ||
| 674 | 674 | """ | |
| 675 | 675 | ||
| 676 | 676 | def test_errors_in_getitem(): | |
@@ -694,11 +694,11 @@ def test_errors_in_getitem(): | |||
| 694 | 694 | ... | |
| 695 | 695 | AttributeError: some error | |
| 696 | 696 | ||
| 697 | - >>> exc = TypeError('some error') | ||
| 697 | + >>> exc = KeyError('some error') | ||
| 698 | 698 | >>> f(**D()) | |
| 699 | 699 | Traceback (most recent call last): | |
| 700 | 700 | ... | |
| 701 | - TypeError: some error | ||
| 701 | + KeyError: 'some error' | ||
| 702 | 702 | """ | |
| 703 | 703 | ||
| 704 | 704 | import doctest | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -681,11 +681,11 @@ def test_errors_in_keys(): | |||
| 681 | 681 | ... | |
| 682 | 682 | AttributeError: some error | |
| 683 | 683 | ||
| 684 | - >>> exc = TypeError('some error') | ||
| 684 | + >>> exc = KeyError('some error') | ||
| 685 | 685 | >>> {**D()} | |
| 686 | 686 | Traceback (most recent call last): | |
| 687 | 687 | ... | |
| 688 | - TypeError: some error | ||
| 688 | + KeyError: 'some error' | ||
| 689 | 689 | """ | |
| 690 | 690 | ||
| 691 | 691 | def test_errors_in_keys_next(): | |
@@ -712,11 +712,11 @@ def test_errors_in_keys_next(): | |||
| 712 | 712 | ... | |
| 713 | 713 | AttributeError: some error | |
| 714 | 714 | ||
| 715 | - >>> exc = TypeError('some error') | ||
| 715 | + >>> exc = KeyError('some error') | ||
| 716 | 716 | >>> {**D()} | |
| 717 | 717 | Traceback (most recent call last): | |
| 718 | 718 | ... | |
| 719 | - TypeError: some error | ||
| 719 | + KeyError: 'some error' | ||
| 720 | 720 | """ | |
| 721 | 721 | ||
| 722 | 722 | def test_errors_in_getitem(): | |
@@ -739,11 +739,11 @@ def test_errors_in_getitem(): | |||
| 739 | 739 | ... | |
| 740 | 740 | AttributeError: some error | |
| 741 | 741 | ||
| 742 | - >>> exc = TypeError('some error') | ||
| 742 | + >>> exc = KeyError('some error') | ||
| 743 | 743 | >>> {**D()} | |
| 744 | 744 | Traceback (most recent call last): | |
| 745 | 745 | ... | |
| 746 | - TypeError: some error | ||
| 746 | + KeyError: 'some error' | ||
| 747 | 747 | """ | |
| 748 | 748 | ||
| 749 | 749 | __test__ = {'doctests' : doctests} | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,3 +1,3 @@ | |||
| 1 | - :exc:`AttributeError`\ s raised in :meth:`!keys` or :meth:`!__getitem__` | ||
| 1 | + :exc:`AttributeError`\ s and :exc:`KeyError`\ s raised in :meth:`!keys` or :meth:`!__getitem__` | ||
| 2 | 2 | during dictionary unpacking (``{**mymapping}`` or ``func(**mymapping)``) are | |
| 3 | 3 | no longer masked by :exc:`TypeError`. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -139,7 +139,7 @@ As a consequence of this, split keys have a maximum size of 16. | |||
| 139 | 139 | static PyObject* frozendict_new(PyTypeObject *type, PyObject *args, | |
| 140 | 140 | PyObject *kwds); | |
| 141 | 141 | static PyObject* dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds); | |
| 142 | - static int dict_merge(PyObject *a, PyObject *b, int override); | ||
| 142 | + static int dict_merge(PyObject *a, PyObject *b, int override, PyObject **dupkey); | ||
| 143 | 143 | static int dict_contains(PyObject *op, PyObject *key); | |
| 144 | 144 | static int dict_merge_from_seq2(PyObject *d, PyObject *seq2, int override); | |
| 145 | 145 | ||
@@ -3391,7 +3391,7 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value) | |||
| 3391 | 3391 | Py_DECREF(d); | |
| 3392 | 3392 | return NULL; | |
| 3393 | 3393 | } | |
| 3394 | - if (dict_merge(copy, d, 1) < 0) { | ||
| 3394 | + if (dict_merge(copy, d, 1, NULL) < 0) { | ||
| 3395 | 3395 | Py_DECREF(d); | |
| 3396 | 3396 | Py_DECREF(copy); | |
| 3397 | 3397 | return NULL; | |
@@ -3887,14 +3887,14 @@ static int | |||
| 3887 | 3887 | dict_update_arg(PyObject *self, PyObject *arg) | |
| 3888 | 3888 | { | |
| 3889 | 3889 | if (PyAnyDict_CheckExact(arg)) { | |
| 3890 | - return dict_merge(self, arg, 1); | ||
| 3890 | + return dict_merge(self, arg, 1, NULL); | ||
| 3891 | 3891 | } | |
| 3892 | 3892 | int has_keys = PyObject_HasAttrWithError(arg, &_Py_ID(keys)); | |
| 3893 | 3893 | if (has_keys < 0) { | |
| 3894 | 3894 | return -1; | |
| 3895 | 3895 | } | |
| 3896 | 3896 | if (has_keys) { | |
| 3897 | - return dict_merge(self, arg, 1); | ||
| 3897 | + return dict_merge(self, arg, 1, NULL); | ||
| 3898 | 3898 | } | |
| 3899 | 3899 | return dict_merge_from_seq2(self, arg, 1); | |
| 3900 | 3900 | } | |
@@ -3915,7 +3915,7 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, | |||
| 3915 | 3915 | ||
| 3916 | 3916 | if (result == 0 && kwds != NULL) { | |
| 3917 | 3917 | if (PyArg_ValidateKeywordArguments(kwds)) | |
| 3918 | - result = dict_merge(self, kwds, 1); | ||
| 3918 | + result = dict_merge(self, kwds, 1, NULL); | ||
| 3919 | 3919 | else | |
| 3920 | 3920 | result = -1; | |
| 3921 | 3921 | } | |
@@ -4059,7 +4059,7 @@ PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override) | |||
| 4059 | 4059 | } | |
| 4060 | 4060 | ||
| 4061 | 4061 | static int | |
| 4062 | - dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override) | ||
| 4062 | + dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override, PyObject **dupkey) | ||
| 4063 | 4063 | { | |
| 4064 | 4064 | assert(can_modify_dict(mp)); | |
| 4065 | 4065 | ASSERT_DICT_LOCKED(other); | |
@@ -4068,10 +4068,10 @@ dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override) | |||
| 4068 | 4068 | /* a.update(a) or a.update({}); nothing to do */ | |
| 4069 | 4069 | return 0; | |
| 4070 | 4070 | if (mp->ma_used == 0) { | |
| 4071 | - /* Since the target dict is empty, PyDict_GetItem() | ||
| 4072 | - * always returns NULL. Setting override to 1 | ||
| 4073 | - * skips the unnecessary test. | ||
| 4074 | - */ | ||
| 4071 | + /* Since the target dict is empty, _PyDict_Contains_KnownHash() | ||
| 4072 | + * always returns 0. Setting override to 1 | ||
| 4073 | + * skips the unnecessary test. | ||
| 4074 | + */ | ||
| 4075 | 4075 | override = 1; | |
| 4076 | 4076 | PyDictKeysObject *okeys = other->ma_keys; | |
| 4077 | 4077 | ||
@@ -4131,11 +4131,10 @@ dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override) | |||
| 4131 | 4131 | err = insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value)); | |
| 4132 | 4132 | } | |
| 4133 | 4133 | else if (err > 0) { | |
| 4134 | - if (override != 0) { | ||
| 4135 | - _PyErr_SetKeyError(key); | ||
| 4134 | + if (dupkey != NULL) { | ||
| 4135 | + *dupkey = key; | ||
| 4136 | 4136 | Py_DECREF(value); | |
| 4137 | - Py_DECREF(key); | ||
| 4138 | - return -1; | ||
| 4137 | + return -2; | ||
| 4139 | 4138 | } | |
| 4140 | 4139 | err = 0; | |
| 4141 | 4140 | } | |
@@ -4155,7 +4154,7 @@ dict_dict_merge(PyDictObject *mp, PyDictObject *other, int override) | |||
| 4155 | 4154 | } | |
| 4156 | 4155 | ||
| 4157 | 4156 | static int | |
| 4158 | - dict_merge(PyObject *a, PyObject *b, int override) | ||
| 4157 | + dict_merge(PyObject *a, PyObject *b, int override, PyObject **dupkey) | ||
| 4159 | 4158 | { | |
| 4160 | 4159 | assert(a != NULL); | |
| 4161 | 4160 | assert(b != NULL); | |
@@ -4167,7 +4166,7 @@ dict_merge(PyObject *a, PyObject *b, int override) | |||
| 4167 | 4166 | PyDictObject *other = (PyDictObject*)b; | |
| 4168 | 4167 | int res; | |
| 4169 | 4168 | Py_BEGIN_CRITICAL_SECTION2(a, b); | |
| 4170 | - res = dict_dict_merge((PyDictObject *)a, other, override); | ||
| 4169 | + res = dict_dict_merge((PyDictObject *)a, other, override, dupkey); | ||
| 4171 | 4170 | ASSERT_CONSISTENT(a); | |
| 4172 | 4171 | Py_END_CRITICAL_SECTION2(); | |
| 4173 | 4172 | return res; | |
@@ -4202,15 +4201,18 @@ dict_merge(PyObject *a, PyObject *b, int override) | |||
| 4202 | 4201 | status = dict_contains(a, key); | |
| 4203 | 4202 | if (status != 0) { | |
| 4204 | 4203 | if (status > 0) { | |
| 4205 | - if (override == 0) { | ||
| 4204 | + if (dupkey == NULL) { | ||
| 4206 | 4205 | Py_DECREF(key); | |
| 4207 | 4206 | continue; | |
| 4208 | 4207 | } | |
| 4209 | - _PyErr_SetKeyError(key); | ||
| 4208 | + *dupkey = key; | ||
| 4209 | + res = -2; | ||
| 4210 | + } | ||
| 4211 | + else { | ||
| 4212 | + Py_DECREF(key); | ||
| 4213 | + res = -1; | ||
| 4210 | 4214 | } | |
| 4211 | - Py_DECREF(key); | ||
| 4212 | 4215 | Py_DECREF(iter); | |
| 4213 | - res = -1; | ||
| 4214 | 4216 | goto slow_exit; | |
| 4215 | 4217 | } | |
| 4216 | 4218 | } | |
@@ -4246,7 +4248,7 @@ dict_merge(PyObject *a, PyObject *b, int override) | |||
| 4246 | 4248 | } | |
| 4247 | 4249 | ||
| 4248 | 4250 | static int | |
| 4249 | - dict_merge_api(PyObject *a, PyObject *b, int override) | ||
| 4251 | + dict_merge_api(PyObject *a, PyObject *b, int override, PyObject **dupkey) | ||
| 4250 | 4252 | { | |
| 4251 | 4253 | /* We accept for the argument either a concrete dictionary object, | |
| 4252 | 4254 | * or an abstract "mapping" object. For the former, we can do | |
@@ -4262,26 +4264,26 @@ dict_merge_api(PyObject *a, PyObject *b, int override) | |||
| 4262 | 4264 | } | |
| 4263 | 4265 | return -1; | |
| 4264 | 4266 | } | |
| 4265 | - return dict_merge(a, b, override); | ||
| 4267 | + return dict_merge(a, b, override, dupkey); | ||
| 4266 | 4268 | } | |
| 4267 | 4269 | ||
| 4268 | 4270 | int | |
| 4269 | 4271 | PyDict_Update(PyObject *a, PyObject *b) | |
| 4270 | 4272 | { | |
| 4271 | - return dict_merge_api(a, b, 1); | ||
| 4273 | + return dict_merge_api(a, b, 1, NULL); | ||
| 4272 | 4274 | } | |
| 4273 | 4275 | ||
| 4274 | 4276 | int | |
| 4275 | 4277 | PyDict_Merge(PyObject *a, PyObject *b, int override) | |
| 4276 | 4278 | { | |
| 4277 | 4279 | /* XXX Deprecate override not in (0, 1). */ | |
| 4278 | - return dict_merge_api(a, b, override != 0); | ||
| 4280 | + return dict_merge_api(a, b, override != 0, NULL); | ||
| 4279 | 4281 | } | |
| 4280 | 4282 | ||
| 4281 | 4283 | int | |
| 4282 | - _PyDict_MergeEx(PyObject *a, PyObject *b, int override) | ||
| 4284 | + _PyDict_MergeUniq(PyObject *a, PyObject *b, PyObject **dupkey) | ||
| 4283 | 4285 | { | |
| 4284 | - return dict_merge_api(a, b, override); | ||
| 4286 | + return dict_merge_api(a, b, 2, dupkey); | ||
| 4285 | 4287 | } | |
| 4286 | 4288 | ||
| 4287 | 4289 | /*[clinic input] | |
@@ -4421,7 +4423,7 @@ copy_lock_held(PyObject *o, int as_frozendict) | |||
| 4421 | 4423 | } | |
| 4422 | 4424 | if (copy == NULL) | |
| 4423 | 4425 | return NULL; | |
| 4424 | - if (dict_merge(copy, o, 1) == 0) | ||
| 4426 | + if (dict_merge(copy, o, 1, NULL) == 0) | ||
| 4425 | 4427 | return copy; | |
| 4426 | 4428 | Py_DECREF(copy); | |
| 4427 | 4429 | return NULL; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2416,10 +2416,12 @@ dummy_func( | |||
| 2416 | 2416 | PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); | |
| 2417 | 2417 | PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); | |
| 2418 | 2418 | PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); | |
| 2419 | + PyObject *dupkey = NULL; | ||
| 2419 | 2420 | ||
| 2420 | - int err = _PyDict_MergeEx(dict_o, update_o, 2); | ||
| 2421 | + int err = _PyDict_MergeUniq(dict_o, update_o, &dupkey); | ||
| 2421 | 2422 | if (err < 0) { | |
| 2422 | - _PyEval_FormatKwargsError(tstate, callable_o, update_o); | ||
| 2423 | + _PyEval_FormatKwargsError(tstate, callable_o, update_o, dupkey); | ||
| 2424 | + Py_XDECREF(dupkey); | ||
| 2423 | 2425 | ERROR_NO_POP(); | |
| 2424 | 2426 | } | |
| 2425 | 2427 | u = update; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3456,9 +3456,18 @@ _Py_Check_ArgsIterable(PyThreadState *tstate, PyObject *func, PyObject *args) | |||
| 3456 | 3456 | } | |
| 3457 | 3457 | ||
| 3458 | 3458 | void | |
| 3459 | - _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs) | ||
| 3460 | - { | ||
| 3461 | - /* _PyDict_MergeEx raises attribute | ||
| 3459 | + _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwargs, PyObject *dupkey) | ||
| 3460 | + { | ||
| 3461 | + if (dupkey != NULL) { | ||
| 3462 | + PyObject *funcstr = _PyObject_FunctionStr(func); | ||
| 3463 | + _PyErr_Format( | ||
| 3464 | + tstate, PyExc_TypeError, | ||
| 3465 | + "%V got multiple values for keyword argument '%S'", | ||
| 3466 | + funcstr, "finction", dupkey); | ||
| 3467 | + Py_XDECREF(funcstr); | ||
| 3468 | + return; | ||
| 3469 | + } | ||
| 3470 | + /* _PyDict_MergeUniq raises attribute | ||
| 3462 | 3471 | * error (percolated from an attempt | |
| 3463 | 3472 | * to get 'keys' attribute) instead of | |
| 3464 | 3473 | * a type error if its second argument | |
@@ -3478,27 +3487,6 @@ _PyEval_FormatKwargsError(PyThreadState *tstate, PyObject *func, PyObject *kwarg | |||
| 3478 | 3487 | _PyErr_ChainExceptions1Tstate(tstate, exc); | |
| 3479 | 3488 | } | |
| 3480 | 3489 | } | |
| 3481 | - else if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { | ||
| 3482 | - PyObject *exc = _PyErr_GetRaisedException(tstate); | ||
| 3483 | - PyObject *args = PyException_GetArgs(exc); | ||
| 3484 | - if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1) { | ||
| 3485 | - _PyErr_Clear(tstate); | ||
| 3486 | - PyObject *funcstr = _PyObject_FunctionStr(func); | ||
| 3487 | - if (funcstr != NULL) { | ||
| 3488 | - PyObject *key = PyTuple_GET_ITEM(args, 0); | ||
| 3489 | - _PyErr_Format( | ||
| 3490 | - tstate, PyExc_TypeError, | ||
| 3491 | - "%U got multiple values for keyword argument '%S'", | ||
| 3492 | - funcstr, key); | ||
| 3493 | - Py_DECREF(funcstr); | ||
| 3494 | - } | ||
| 3495 | - Py_XDECREF(exc); | ||
| 3496 | - } | ||
| 3497 | - else { | ||
| 3498 | - _PyErr_SetRaisedException(tstate, exc); | ||
| 3499 | - } | ||
| 3500 | - Py_DECREF(args); | ||
| 3501 | - } | ||
| 3502 | 3490 | } | |
| 3503 | 3491 | ||
| 3504 | 3492 | void | |
| Back | FazBrowse Home | New Git URL |
0 commit comments