Anonymous + varargs: possible serious breakage -- please confirm!

Hi -- after updating my CVS tree today with Python 2.1a1, i ran the tests and test_inspect failed. This revealed that the format of code.co_varnames has changed. At first i tried to update the inspect.py module to check the Python version number and track the change, but now i believe this is actually symptomatic of a real interpreter problem. Consider the function: def f(a, (b, c), *d): x = 1 print a, b, c, d, x Whereas in Python 1.5.2: f.func_code.co_argcount = 2 f.func_code.co_nlocals = 6 f.func_code.co_names = ('x', 'a', 'b', 'c', 'd') f.func_code.co_varnames = ('a', '.2', 'd', 'b', 'c', 'x') In Python 2.1a1: f.func_code.co_argcount = 2 f.func_code.co_nlocals = 6 f.func_code.co_names = ('b', 'c', 'x', 'a', 'd') f.func_code.co_varnames = ('a', '.2', 'b', 'c', 'd', 'x') Notice how the ordering of the variable names has changed. I went and looked at the CO_VARARGS clause in eval_code2 to see if it put the varargs and kwdict arguments in different slots, but it appears unchanged! It still puts varargs at locals[co_argcount] and kwdict at locals[co_argcount + 1]. Please try: >>> def f(a, (b, c), *d): ... x = 1 ... print a, b, c, d, x ... >>> f(1, (2, 3), 4) 1 2 3 Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in f UnboundLocalError: local variable 'd' referenced before assignment >>> In Python 1.5.2, this prints "1 2 3 (4,)" as expected. I only have 1.5.2 and 2.1a1 to test. I hope this problem isn't present in 2.0... Note that test_inspect was the only test to fail! It might be the only test that checks anonymous and *varargs at the same time. (Yet another reason to put inspect in the core...) I did recently check in additions to test_extcall that made the test much beefier -- but that only tested combinations of regular, keyword, varargs, and kwdict arguments; it neglected to test anonymous (tuple) arguments as well. -- ?!ng

On Wed, Jan 24, 2001 at 12:33:43PM -0800, Ka-Ping Yee wrote:
Please try:
>>> def f(a, (b, c), *d): ... x = 1 ... print a, b, c, d, x ... >>> f(1, (2, 3), 4) 1 2 3 Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in f UnboundLocalError: local variable 'd' referenced before assignment >>>
In Python 1.5.2, this prints "1 2 3 (4,)" as expected.
I only have 1.5.2 and 2.1a1 to test. I hope this problem isn't present in 2.0...
It isn't present in 2.0. This is probably related to Jeremy's changes in the call mechanism or the compiler track, though Jeremy himself is the best person to claim that for sure :)
Note that test_inspect was the only test to fail! It might be the only test that checks anonymous and *varargs at the same time. (Yet another reason to put inspect in the core...)
Well, this is not an inspect-specific test, so it shouldn't *be* in test_inspect, it should be in test_extcall :) -- Thomas Wouters <thomas@xs4all.net> Hi! I'm a .signature virus! copy me into your .signature file to help me spread!

"TW" == Thomas Wouters <thomas@xs4all.net> writes:
TW> On Wed, Jan 24, 2001 at 12:33:43PM -0800, Ka-Ping Yee wrote:
Please try:
def f(a, (b, c), *d): ... x = 1 ... print a, b, c, d, x ... f(1, (2, 3), 4) 1 2 3 Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in f UnboundLocalError: local variable 'd' referenced before assignment
In Python 1.5.2, this prints "1 2 3 (4,)" as expected.
I only have 1.5.2 and 2.1a1 to test. I hope this problem isn't present in 2.0...
TW> It isn't present in 2.0. This is probably related to Jeremy's TW> changes in the call mechanism or the compiler track, though TW> Jeremy himself is the best person to claim that for sure :) The bug is in the compiler. It creates varnames while it is parsing the argument list. While I got the handling of the anonymous tuples right, I forgot to insert *varargs or **kwargs in varnames *before* the names defined in the tuple. I will fix it real soon now.
Note that test_inspect was the only test to fail! It might be the only test that checks anonymous and *varargs at the same time. (Yet another reason to put inspect in the core...)
TW> Well, this is not an inspect-specific test, so it shouldn't *be* TW> in test_inspect, it should be in test_extcall :) It should probably be in test_grammar. The ext call mechanism is only invoked when the caller uses a form like 'f(*arg)'. Perhaps the name "ext call" isn't very clear. Jeremy
participants (3)
-
Jeremy Hylton
-
Ka-Ping Yee
-
Thomas Wouters