Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 62359) +++ Python/ceval.c (working copy) @@ -2756,7 +2756,9 @@ PyObject *keyword = kws[2*i]; PyObject *value = kws[2*i + 1]; int j; - if (keyword == NULL || !PyString_Check(keyword)) { + if (keyword == NULL || + !PyString_Check(keyword) && + !PyUnicode_Check(keyword)) { PyErr_Format(PyExc_TypeError, "%.200s() keywords must be strings", PyString_AsString(co->co_name)); Index: Python/getargs.c =================================================================== --- Python/getargs.c (revision 62359) +++ Python/getargs.c (working copy) @@ -1473,7 +1473,7 @@ while (PyDict_Next(keywords, &pos, &key, &value)) { int match = 0; char *ks; - if (!PyString_Check(key)) { + if (!PyString_Check(key) && !PyUnicode_Check(key)) { PyErr_SetString(PyExc_TypeError, "keywords must be strings"); return cleanreturn(0, freelist); Index: Lib/test/test_extcall.py =================================================================== --- Lib/test/test_extcall.py (revision 62359) +++ Lib/test/test_extcall.py (working copy) @@ -52,6 +52,14 @@ >>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9)) (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5} +Unicode keys in ** dict + + >>> h(1, **{u'a':2, u'h':3}) + 1 2 3 + >>> f(1, 2, 3, **{u'a':4, u'b':5}) + (1, 2, 3) {u'a': 4, u'b': 5} + + Examples with invalid arguments (TypeErrors). We're also testing the function names in the exception messages. @@ -62,6 +70,11 @@ ... TypeError: e() got an unexpected keyword argument 'c' + >>> e(**{u'c':4}) + Traceback (most recent call last): + ... + TypeError: e() got an unexpected keyword argument 'c' + >>> g() Traceback (most recent call last): ... @@ -250,6 +263,15 @@ ... TypeError: id() takes no keyword arguments +Test passing unicode keys to C function + + >>> from datetime import date + >>> date(1, 2, **{u'day': 3}) + datetime.date(1, 2, 3) + >>> date(1, 2, **{u'day': 3, u'x': 4}) + Traceback (most recent call last): + ... + TypeError: function takes at most 3 arguments (4 given) """ from test import test_support