Skip to content

Commit 004f3dc

Browse files
committed
Merged revisions 68805 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r68805 | benjamin.peterson | 2009-01-20 08:21:16 -0600 (Tue, 20 Jan 2009) | 1 line allow unicode keyword arguments for the ** syntax python#4978 ........
1 parent c54b621 commit 004f3dc

3 files changed

Lines changed: 55 additions & 12 deletions

File tree

‎Lib/test/test_extcall.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
"""Doctest for method/function calls.
23
34
We're going the use these types for extra testing
@@ -252,11 +253,30 @@
252253
253254
"""
254255

256+
import unittest
255257
from test import test_support
256258

259+
260+
class UnicodeKeywordArgsTest(unittest.TestCase):
261+
262+
def test_unicode_keywords(self):
263+
def f(a):
264+
return a
265+
self.assertEqual(f(**{u'a': 4}), 4)
266+
self.assertRaises(TypeError, f, **{u'stören': 4})
267+
self.assertRaises(TypeError, f, **{u'someLongString':2})
268+
try:
269+
f(a=4, **{u'a': 4})
270+
except TypeError:
271+
pass
272+
else:
273+
self.fail("duplicate arguments didn't raise")
274+
275+
257276
def test_main():
258277
from test import test_extcall # self import
259278
test_support.run_doctest(test_extcall, True)
279+
test_support.run_unittest(UnicodeKeywordArgsTest)
260280

261281
if __name__ == '__main__':
262282
test_main()

‎Misc/NEWS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Core and Builtins
1717
library would return a bogus result; on Solaris, it was possible to crash
1818
the interpreter. Patch by Stefan Krah.
1919

20+
- Issue #4978: Passing keyword arguments as unicode strings is now allowed.
21+
2022
- Issue #7819: Check sys.call_tracing() arguments types.
2123

2224
- Issue #7788: Fix an interpreter crash produced by deleting a list

‎Python/ceval.c‎

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ static void reset_exc_info(PyThreadState *);
145145
static void format_exc_check_arg(PyObject *, char *, PyObject *);
146146
static PyObject * string_concatenate(PyObject *, PyObject *,
147147
PyFrameObject *, unsigned char *);
148+
static PyObject * kwd_as_string(PyObject *);
148149

149150
#define NAME_ERROR_MSG \
150151
"name '%.200s' is not defined"
@@ -2831,7 +2832,8 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
28312832
PyObject *keyword = kws[2*i];
28322833
PyObject *value = kws[2*i + 1];
28332834
int j;
2834-
if (keyword == NULL || !PyString_Check(keyword)) {
2835+
if (keyword == NULL || !(PyString_Check(keyword) ||
2836+
PyUnicode_Check(keyword))) {
28352837
PyErr_Format(PyExc_TypeError,
28362838
"%.200s() keywords must be strings",
28372839
PyString_AsString(co->co_name));
@@ -2860,24 +2862,32 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
28602862
goto fail;
28612863
if (j >= co->co_argcount) {
28622864
if (kwdict == NULL) {
2863-
PyErr_Format(PyExc_TypeError,
2864-
"%.200s() got an unexpected "
2865-
"keyword argument '%.400s'",
2866-
PyString_AsString(co->co_name),
2867-
PyString_AsString(keyword));
2865+
PyObject *kwd_str = kwd_as_string(keyword);
2866+
if (kwd_str) {
2867+
PyErr_Format(PyExc_TypeError,
2868+
"%.200s() got an unexpected "
2869+
"keyword argument '%.400s'",
2870+
PyString_AsString(co->co_name),
2871+
PyString_AsString(kwd_str));
2872+
Py_DECREF(kwd_str);
2873+
}
28682874
goto fail;
28692875
}
28702876
PyDict_SetItem(kwdict, keyword, value);
28712877
continue;
28722878
}
28732879
kw_found:
28742880
if (GETLOCAL(j) != NULL) {
2875-
PyErr_Format(PyExc_TypeError,
2876-
"%.200s() got multiple "
2877-
"values for keyword "
2878-
"argument '%.400s'",
2879-
PyString_AsString(co->co_name),
2880-
PyString_AsString(keyword));
2881+
PyObject *kwd_str = kwd_as_string(keyword);
2882+
if (kwd_str) {
2883+
PyErr_Format(PyExc_TypeError,
2884+
"%.200s() got multiple "
2885+
"values for keyword "
2886+
"argument '%.400s'",
2887+
PyString_AsString(co->co_name),
2888+
PyString_AsString(kwd_str));
2889+
Py_DECREF(kwd_str);
2890+
}
28812891
goto fail;
28822892
}
28832893
Py_INCREF(value);
@@ -3004,6 +3014,17 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
30043014
}
30053015

30063016

3017+
static PyObject *
3018+
kwd_as_string(PyObject *kwd) {
3019+
if (PyString_Check(kwd)) {
3020+
Py_INCREF(kwd);
3021+
return kwd;
3022+
}
3023+
else
3024+
return _PyUnicode_AsDefaultEncodedString(kwd, "replace");
3025+
}
3026+
3027+
30073028
/* Implementation notes for set_exc_info() and reset_exc_info():
30083029
30093030
- Below, 'exc_ZZZ' stands for 'exc_type', 'exc_value' and

0 commit comments

Comments
 (0)