views:

140

answers:

3

I'm writing unit tests for a function that takes both an *args and a **kwargs argument. A reasonable use-case for this function is using keyword arguments after the *args argment, i.e. of the form

def f(a, *b, **c):
    print a, b, c

f(1, *(2, 3, 4), keyword=13)

Now this only became legal in Python 2.6; in earlier versions the above line is a syntax error and so won't even compile to byte-code.

My question is: How can I test the functionality provided in the newer Python version and still have the tests run for older Python versions?

I should point out that the function itself works fine for earlier Python versions, it is only some invocations that are syntax errors before Python 2.6. The various methods I've seen for checking the Python version don't work for this as it doesn't get past the compilation stage.

I would prefer not to have to split the tests into multiple files if at all possible.

+2  A: 

One approach might be to use eval() or exec along with a test for the current version of Python. This will defer compilation to runtime, where you can control whether compilation actually happens or not.

Greg Hewgill
Greg, eval() real?
Unkwntech
I would say using `eval()` is perfectly appropriate for unit test code that may be run on any version of Python.
Greg Hewgill
+11  A: 

I don't think you should be testing whether Python works correctly; instead, focus on testing your own code. In doing so, it is perfectly possible to write the specific invocation in a way that works for all Python versions, namely:

f(1, *(2,3,4), **{'keyword':13})
Martin v. Löwis
Thanks, this solves my problem. I was too focussed on getting the code I had written to work and didn't realise that the new invocation method had an equivalent in earlier Pythons.
Scott Griffiths
+1  A: 

Why do you want to use such syntax? I mean, this 2.6 feature does not bring any real advantage other than shortcut.

a = [2,3,4]
a.insert(0, 1)
kw = {'keyword'='test'}
f(*a, **kw)
iElectric