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 #4978
........
This commit is contained in:
Benjamin Peterson 2010-02-06 19:16:33 +00:00
parent c54b62141f
commit 004f3dcaa5
3 changed files with 55 additions and 12 deletions

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""Doctest for method/function calls. """Doctest for method/function calls.
We're going the use these types for extra testing We're going the use these types for extra testing
@ -252,11 +253,30 @@ TypeError if te dictionary is not empty
""" """
import unittest
from test import test_support from test import test_support
class UnicodeKeywordArgsTest(unittest.TestCase):
def test_unicode_keywords(self):
def f(a):
return a
self.assertEqual(f(**{u'a': 4}), 4)
self.assertRaises(TypeError, f, **{u'stören': 4})
self.assertRaises(TypeError, f, **{u'someLongString':2})
try:
f(a=4, **{u'a': 4})
except TypeError:
pass
else:
self.fail("duplicate arguments didn't raise")
def test_main(): def test_main():
from test import test_extcall # self import from test import test_extcall # self import
test_support.run_doctest(test_extcall, True) test_support.run_doctest(test_extcall, True)
test_support.run_unittest(UnicodeKeywordArgsTest)
if __name__ == '__main__': if __name__ == '__main__':
test_main() test_main()

View File

@ -17,6 +17,8 @@ Core and Builtins
library would return a bogus result; on Solaris, it was possible to crash library would return a bogus result; on Solaris, it was possible to crash
the interpreter. Patch by Stefan Krah. the interpreter. Patch by Stefan Krah.
- Issue #4978: Passing keyword arguments as unicode strings is now allowed.
- Issue #7819: Check sys.call_tracing() arguments types. - Issue #7819: Check sys.call_tracing() arguments types.
- Issue #7788: Fix an interpreter crash produced by deleting a list - Issue #7788: Fix an interpreter crash produced by deleting a list

View File

@ -145,6 +145,7 @@ static void reset_exc_info(PyThreadState *);
static void format_exc_check_arg(PyObject *, char *, PyObject *); static void format_exc_check_arg(PyObject *, char *, PyObject *);
static PyObject * string_concatenate(PyObject *, PyObject *, static PyObject * string_concatenate(PyObject *, PyObject *,
PyFrameObject *, unsigned char *); PyFrameObject *, unsigned char *);
static PyObject * kwd_as_string(PyObject *);
#define NAME_ERROR_MSG \ #define NAME_ERROR_MSG \
"name '%.200s' is not defined" "name '%.200s' is not defined"
@ -2831,7 +2832,8 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
PyObject *keyword = kws[2*i]; PyObject *keyword = kws[2*i];
PyObject *value = kws[2*i + 1]; PyObject *value = kws[2*i + 1];
int j; int j;
if (keyword == NULL || !PyString_Check(keyword)) { if (keyword == NULL || !(PyString_Check(keyword) ||
PyUnicode_Check(keyword))) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%.200s() keywords must be strings", "%.200s() keywords must be strings",
PyString_AsString(co->co_name)); PyString_AsString(co->co_name));
@ -2860,11 +2862,15 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
goto fail; goto fail;
if (j >= co->co_argcount) { if (j >= co->co_argcount) {
if (kwdict == NULL) { if (kwdict == NULL) {
PyErr_Format(PyExc_TypeError, PyObject *kwd_str = kwd_as_string(keyword);
"%.200s() got an unexpected " if (kwd_str) {
"keyword argument '%.400s'", PyErr_Format(PyExc_TypeError,
PyString_AsString(co->co_name), "%.200s() got an unexpected "
PyString_AsString(keyword)); "keyword argument '%.400s'",
PyString_AsString(co->co_name),
PyString_AsString(kwd_str));
Py_DECREF(kwd_str);
}
goto fail; goto fail;
} }
PyDict_SetItem(kwdict, keyword, value); PyDict_SetItem(kwdict, keyword, value);
@ -2872,12 +2878,16 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
} }
kw_found: kw_found:
if (GETLOCAL(j) != NULL) { if (GETLOCAL(j) != NULL) {
PyErr_Format(PyExc_TypeError, PyObject *kwd_str = kwd_as_string(keyword);
"%.200s() got multiple " if (kwd_str) {
"values for keyword " PyErr_Format(PyExc_TypeError,
"argument '%.400s'", "%.200s() got multiple "
PyString_AsString(co->co_name), "values for keyword "
PyString_AsString(keyword)); "argument '%.400s'",
PyString_AsString(co->co_name),
PyString_AsString(kwd_str));
Py_DECREF(kwd_str);
}
goto fail; goto fail;
} }
Py_INCREF(value); Py_INCREF(value);
@ -3004,6 +3014,17 @@ fail: /* Jump here from prelude on failure */
} }
static PyObject *
kwd_as_string(PyObject *kwd) {
if (PyString_Check(kwd)) {
Py_INCREF(kwd);
return kwd;
}
else
return _PyUnicode_AsDefaultEncodedString(kwd, "replace");
}
/* Implementation notes for set_exc_info() and reset_exc_info(): /* Implementation notes for set_exc_info() and reset_exc_info():
- Below, 'exc_ZZZ' stands for 'exc_type', 'exc_value' and - Below, 'exc_ZZZ' stands for 'exc_type', 'exc_value' and