Calling multiple key value argument functions, does not work when the dict's keys are in unicode

36 views
Skip to first unread message

Jan Flyborg

unread,
Aug 29, 2012, 2:46:28 PM8/29/12
to cython...@googlegroups.com
Hi,

I don't know if this is a known limitation (honestly I haven't made much effort googling around either), but the following works in Python 2.7, but not in Cython:

    def foo(*a, **k):
        print k

    dict = {u"arg1": "Hello World!"}

    foo(**dict)

When executed I get the following output just as expected:

    {u'arg1': 'Hello World!'}

But when compiled with Cython 0.16 and 0.17b3, I get the following:

    TypeError: foo() keywords must be strings

The culprit seems to be the unicode value for the dict's key. If changed to an ordinary string it works.

Jan Flyborg

Stefan Behnel

unread,
Aug 29, 2012, 3:21:40 PM8/29/12
to cython...@googlegroups.com
Jan Flyborg, 29.08.2012 20:46:
Hmm, yes, that was changed in CPython 2.6. It was explicitly forbidden
before. I'll see if I can adapt the keyword type checking code in Cython.

Thanks for the report!

Stefan

Stefan Behnel

unread,
Aug 29, 2012, 5:49:07 PM8/29/12
to cython...@googlegroups.com
Stefan Behnel, 29.08.2012 21:21:
I pushed a fix here:

https://github.com/cython/cython/commit/a8f70e2210b9a36c3b67ce5f426000c62473b62e

Note that this doesn't currently work in PyPy. It checks keyword types on
the caller side instead of the callee side (as CPython and Cython do).

Stefan

Jan Flyborg

unread,
Aug 29, 2012, 6:35:40 PM8/29/12
to cython...@googlegroups.com
Thank you. I'll try it out tomorrow.

I just found another problem in the same area. The same caveat applies for this one too (i.e I don't know if it is a known limitation or not, so please bare with me).

If you define a simple module test.py, like this:

    def foo(arg):
        print arg

And you call it like this from another module in CPython 2.7

    import test
    d = {"arg": "Hello World!"}
    test.foo(**d)

You get the result:

    Hello World!

However, if you compile test.py with Cython, and call it in the same way, you get:

    TypeError: foo() takes no keyword arguments

A simple workaround is probably to make 'arg' a keyword argument (haven't tried it), but this does not seem to be in line with how CPython works.

-- Jan Flyborg

Stefan Behnel

unread,
Aug 29, 2012, 11:58:10 PM8/29/12
to cython...@googlegroups.com
Jan Flyborg, 30.08.2012 00:35:
> If you define a simple module test.py, like this:
>
> def foo(arg):
> print arg
>
> And you call it like this from another module in CPython 2.7
>
> import test
> d = {"arg": "Hello World!"}
> test.foo(**d)
>
> You get the result:
>
> Hello World!
>
> However, if you compile test.py with Cython, and call it in the same way,
> you get:
>
> TypeError: foo() takes no keyword arguments
>
> A simple workaround is probably to make 'arg' a keyword argument (haven't
> tried it), but this does not seem to be in line with how CPython works.

Yes, that's a known optimisation. It's simply faster not to accept keyword
arguments for one-arg functions, and the use case of passing them is so
rare that we chose to optimise against it.

You can enable support with a compiler directive:

http://docs.cython.org/src/reference/compilation.html?highlight=always_allow_keywords#compiler-directives

Stefan

Jan Flyborg

unread,
Aug 30, 2012, 6:49:45 AM8/30/12
to cython...@googlegroups.com
Thank you once again. It worked like a charm when I added this compiler directive.

-- Jan Flyborg

Reply all
Reply to author
Forward
0 new messages