r43341 - in python/trunk: Lib/test/test_grammar.py Lib/test/test_inspect.py Python/ast.c

Author: neal.norwitz Date: Mon Mar 27 10:58:23 2006 New Revision: 43341 Modified: python/trunk/Lib/test/test_grammar.py python/trunk/Lib/test/test_inspect.py python/trunk/Python/ast.c Log: Fix SF bug #1458903 with AST compiler. def foo((x)): was getting recognized as requiring tuple unpacking which is not correct. Add tests for this case and the proper way to unpack a tuple of one: def foo((x,)): test_inpsect was incorrect before. I'm not sure why it was passing, but that has been corrected with a test for both functions above. This means the test (and therefore inspect.getargspec()) are broken in 2.4. Modified: python/trunk/Lib/test/test_grammar.py ============================================================================== --- python/trunk/Lib/test/test_grammar.py (original) +++ python/trunk/Lib/test/test_grammar.py Mon Mar 27 10:58:23 2006 @@ -255,6 +255,10 @@ d22v(*(1, 2, 3, 4)) d22v(1, 2, *(3, 4, 5)) d22v(1, *(2, 3), **{'d': 4}) +def d31v((x)): pass +d31v(1) +def d32v((x,)): pass +d32v((1,)) ### lambdef: 'lambda' [varargslist] ':' test print 'lambdef' Modified: python/trunk/Lib/test/test_inspect.py ============================================================================== --- python/trunk/Lib/test/test_inspect.py (original) +++ python/trunk/Lib/test/test_inspect.py Mon Mar 27 10:58:23 2006 @@ -304,10 +304,12 @@ self.assertArgSpecEquals(A.m, ['self']) def test_getargspec_sublistofone(self): - def sublistOfOne((foo)): return 1 - + def sublistOfOne((foo,)): return 1 self.assertArgSpecEquals(sublistOfOne, [['foo']]) + def fakeSublistOfOne((foo)): return 1 + self.assertArgSpecEquals(fakeSublistOfOne, ['foo']) + def test_classify_oldstyle(self): class A: def s(): pass Modified: python/trunk/Python/ast.c ============================================================================== --- python/trunk/Python/ast.c (original) +++ python/trunk/Python/ast.c Mon Mar 27 10:58:23 2006 @@ -645,10 +645,17 @@ goto error; } if (NCH(ch) == 3) { - asdl_seq_SET(args, k++, - compiler_complex_args(c, CHILD(ch, 1))); - } - else if (TYPE(CHILD(ch, 0)) == NAME) { + ch = CHILD(ch, 1); + /* def foo((x)): is not complex, special case. */ + if (NCH(ch) != 1) { + /* We have complex arguments, setup for unpacking. */ + asdl_seq_SET(args, k++, compiler_complex_args(c, ch)); + } else { + /* def foo((x)): setup for checking NAME below. */ + ch = CHILD(ch, 0); + } + } + if (TYPE(CHILD(ch, 0)) == NAME) { expr_ty name; if (!strcmp(STR(CHILD(ch, 0)), "None")) { ast_error(CHILD(ch, 0), "assignment to None");

neal.norwitz wrote:
Author: neal.norwitz Date: Mon Mar 27 10:58:23 2006 New Revision: 43341
Modified: python/trunk/Lib/test/test_grammar.py python/trunk/Lib/test/test_inspect.py python/trunk/Python/ast.c Log: Fix SF bug #1458903 with AST compiler.
def foo((x)): was getting recognized as requiring tuple unpacking which is not correct.
Add tests for this case and the proper way to unpack a tuple of one: def foo((x,)):
test_inpsect was incorrect before. I'm not sure why it was passing, but that has been corrected with a test for both functions above. This means the test (and therefore inspect.getargspec()) are broken in 2.4.
This raises the question of why "def foo((x))" is allowed in the first place. It has no effect, and can really be confusing. The language ref doesn't tell anything about tuple unpacking arguments other than the grammar rules. Georg

On 3/27/06, Georg Brandl <g.brandl@gmx.net> wrote:
This raises the question of why "def foo((x))" is allowed in the first place. It has no effect, and can really be confusing.
For the same reason you can write these: x = (1) (x) = 1 for (x) in range(10): ... return (1) if (x): ... IOW you should always be allowed to add redundant parentheses.
The language ref doesn't tell anything about tuple unpacking arguments other than the grammar rules.
Please suggest improved language. -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On 3/27/06, neal.norwitz <python-checkins@python.org> wrote:
Author: neal.norwitz Date: Mon Mar 27 10:58:23 2006 New Revision: 43341
Modified: python/trunk/Lib/test/test_grammar.py python/trunk/Lib/test/test_inspect.py python/trunk/Python/ast.c Log: Fix SF bug #1458903 with AST compiler.
def foo((x)): was getting recognized as requiring tuple unpacking which is not correct.
Add tests for this case and the proper way to unpack a tuple of one: def foo((x,)):
test_inpsect was incorrect before. I'm not sure why it was passing, but that has been corrected with a test for both functions above. This means the test (and therefore inspect.getargspec()) are broken in 2.4.
This is an interesting case (after a fashion). I can't find any text in the language reference that explains what def f((x)): means. The grammar production that handles this case is fplist, but there's no comment about how to interpret an fplist of length 1. As Georg mentions in the bug report, old versions of Python did pseudo-unpacking if you wrapped arguments in parentheses. It did assign to a temporary variable, but didn't call unpack sequence on them. I presume this code was what lead to the confusion in inspect. Jeremy
Modified: python/trunk/Lib/test/test_grammar.py ============================================================================== --- python/trunk/Lib/test/test_grammar.py (original) +++ python/trunk/Lib/test/test_grammar.py Mon Mar 27 10:58:23 2006 @@ -255,6 +255,10 @@ d22v(*(1, 2, 3, 4)) d22v(1, 2, *(3, 4, 5)) d22v(1, *(2, 3), **{'d': 4}) +def d31v((x)): pass +d31v(1) +def d32v((x,)): pass +d32v((1,))
### lambdef: 'lambda' [varargslist] ':' test print 'lambdef'
Modified: python/trunk/Lib/test/test_inspect.py ============================================================================== --- python/trunk/Lib/test/test_inspect.py (original) +++ python/trunk/Lib/test/test_inspect.py Mon Mar 27 10:58:23 2006 @@ -304,10 +304,12 @@ self.assertArgSpecEquals(A.m, ['self'])
def test_getargspec_sublistofone(self): - def sublistOfOne((foo)): return 1 - + def sublistOfOne((foo,)): return 1 self.assertArgSpecEquals(sublistOfOne, [['foo']])
+ def fakeSublistOfOne((foo)): return 1 + self.assertArgSpecEquals(fakeSublistOfOne, ['foo']) + def test_classify_oldstyle(self): class A: def s(): pass
Modified: python/trunk/Python/ast.c ============================================================================== --- python/trunk/Python/ast.c (original) +++ python/trunk/Python/ast.c Mon Mar 27 10:58:23 2006 @@ -645,10 +645,17 @@ goto error; } if (NCH(ch) == 3) { - asdl_seq_SET(args, k++, - compiler_complex_args(c, CHILD(ch, 1))); - } - else if (TYPE(CHILD(ch, 0)) == NAME) { + ch = CHILD(ch, 1); + /* def foo((x)): is not complex, special case. */ + if (NCH(ch) != 1) { + /* We have complex arguments, setup for unpacking. */ + asdl_seq_SET(args, k++, compiler_complex_args(c, ch)); + } else { + /* def foo((x)): setup for checking NAME below. */ + ch = CHILD(ch, 0); + } + } + if (TYPE(CHILD(ch, 0)) == NAME) { expr_ty name; if (!strcmp(STR(CHILD(ch, 0)), "None")) { ast_error(CHILD(ch, 0), "assignment to None"); _______________________________________________ Python-checkins mailing list Python-checkins@python.org http://mail.python.org/mailman/listinfo/python-checkins

Well, obviously (:-) the intention was that def f((x)): is the same as def f(x): just like the expression (x) is the same as the expression x. It doesn't become a tuple unless there's a comma (or unless it's an empty tuple). Which reminds me -- what does def f(()): do? --Guido On 4/6/06, Jeremy Hylton <jeremy@alum.mit.edu> wrote:
On 3/27/06, neal.norwitz <python-checkins@python.org> wrote:
Author: neal.norwitz Date: Mon Mar 27 10:58:23 2006 New Revision: 43341
Modified: python/trunk/Lib/test/test_grammar.py python/trunk/Lib/test/test_inspect.py python/trunk/Python/ast.c Log: Fix SF bug #1458903 with AST compiler.
def foo((x)): was getting recognized as requiring tuple unpacking which is not correct.
Add tests for this case and the proper way to unpack a tuple of one: def foo((x,)):
test_inpsect was incorrect before. I'm not sure why it was passing, but that has been corrected with a test for both functions above. This means the test (and therefore inspect.getargspec()) are broken in 2.4.
This is an interesting case (after a fashion). I can't find any text in the language reference that explains what def f((x)): means. The grammar production that handles this case is fplist, but there's no comment about how to interpret an fplist of length 1.
As Georg mentions in the bug report, old versions of Python did pseudo-unpacking if you wrapped arguments in parentheses. It did assign to a temporary variable, but didn't call unpack sequence on them. I presume this code was what lead to the confusion in inspect.
Jeremy
Modified: python/trunk/Lib/test/test_grammar.py ============================================================================== --- python/trunk/Lib/test/test_grammar.py (original) +++ python/trunk/Lib/test/test_grammar.py Mon Mar 27 10:58:23 2006 @@ -255,6 +255,10 @@ d22v(*(1, 2, 3, 4)) d22v(1, 2, *(3, 4, 5)) d22v(1, *(2, 3), **{'d': 4}) +def d31v((x)): pass +d31v(1) +def d32v((x,)): pass +d32v((1,))
### lambdef: 'lambda' [varargslist] ':' test print 'lambdef'
Modified: python/trunk/Lib/test/test_inspect.py ============================================================================== --- python/trunk/Lib/test/test_inspect.py (original) +++ python/trunk/Lib/test/test_inspect.py Mon Mar 27 10:58:23 2006 @@ -304,10 +304,12 @@ self.assertArgSpecEquals(A.m, ['self'])
def test_getargspec_sublistofone(self): - def sublistOfOne((foo)): return 1 - + def sublistOfOne((foo,)): return 1 self.assertArgSpecEquals(sublistOfOne, [['foo']])
+ def fakeSublistOfOne((foo)): return 1 + self.assertArgSpecEquals(fakeSublistOfOne, ['foo']) + def test_classify_oldstyle(self): class A: def s(): pass
Modified: python/trunk/Python/ast.c ============================================================================== --- python/trunk/Python/ast.c (original) +++ python/trunk/Python/ast.c Mon Mar 27 10:58:23 2006 @@ -645,10 +645,17 @@ goto error; } if (NCH(ch) == 3) { - asdl_seq_SET(args, k++, - compiler_complex_args(c, CHILD(ch, 1))); - } - else if (TYPE(CHILD(ch, 0)) == NAME) { + ch = CHILD(ch, 1); + /* def foo((x)): is not complex, special case. */ + if (NCH(ch) != 1) { + /* We have complex arguments, setup for unpacking. */ + asdl_seq_SET(args, k++, compiler_complex_args(c, ch)); + } else { + /* def foo((x)): setup for checking NAME below. */ + ch = CHILD(ch, 0); + } + } + if (TYPE(CHILD(ch, 0)) == NAME) { expr_ty name; if (!strcmp(STR(CHILD(ch, 0)), "None")) { ast_error(CHILD(ch, 0), "assignment to None"); _______________________________________________ Python-checkins mailing list Python-checkins@python.org http://mail.python.org/mailman/listinfo/python-checkins
_______________________________________________ Python-checkins mailing list Python-checkins@python.org http://mail.python.org/mailman/listinfo/python-checkins
-- --Guido van Rossum (home page: http://www.python.org/~guido/)

On 4/6/06, Guido van Rossum <guido@python.org> wrote:
Well, obviously (:-) the intention was that def f((x)): is the same as def f(x): just like the expression (x) is the same as the expression x. It doesn't become a tuple unless there's a comma (or unless it's an empty tuple). Which reminds me -- what does def f(()): do?
Syntax error. The fplist has to have at least one fpdef. Jeremy
--Guido
On 4/6/06, Jeremy Hylton <jeremy@alum.mit.edu> wrote:
On 3/27/06, neal.norwitz <python-checkins@python.org> wrote:
Author: neal.norwitz Date: Mon Mar 27 10:58:23 2006 New Revision: 43341
Modified: python/trunk/Lib/test/test_grammar.py python/trunk/Lib/test/test_inspect.py python/trunk/Python/ast.c Log: Fix SF bug #1458903 with AST compiler.
def foo((x)): was getting recognized as requiring tuple unpacking which is not correct.
Add tests for this case and the proper way to unpack a tuple of one: def foo((x,)):
test_inpsect was incorrect before. I'm not sure why it was passing, but that has been corrected with a test for both functions above. This means the test (and therefore inspect.getargspec()) are broken in 2.4.
This is an interesting case (after a fashion). I can't find any text in the language reference that explains what def f((x)): means. The grammar production that handles this case is fplist, but there's no comment about how to interpret an fplist of length 1.
As Georg mentions in the bug report, old versions of Python did pseudo-unpacking if you wrapped arguments in parentheses. It did assign to a temporary variable, but didn't call unpack sequence on them. I presume this code was what lead to the confusion in inspect.
Jeremy
Modified: python/trunk/Lib/test/test_grammar.py ============================================================================== --- python/trunk/Lib/test/test_grammar.py (original) +++ python/trunk/Lib/test/test_grammar.py Mon Mar 27 10:58:23 2006 @@ -255,6 +255,10 @@ d22v(*(1, 2, 3, 4)) d22v(1, 2, *(3, 4, 5)) d22v(1, *(2, 3), **{'d': 4}) +def d31v((x)): pass +d31v(1) +def d32v((x,)): pass +d32v((1,))
### lambdef: 'lambda' [varargslist] ':' test print 'lambdef'
Modified: python/trunk/Lib/test/test_inspect.py ============================================================================== --- python/trunk/Lib/test/test_inspect.py (original) +++ python/trunk/Lib/test/test_inspect.py Mon Mar 27 10:58:23 2006 @@ -304,10 +304,12 @@ self.assertArgSpecEquals(A.m, ['self'])
def test_getargspec_sublistofone(self): - def sublistOfOne((foo)): return 1 - + def sublistOfOne((foo,)): return 1 self.assertArgSpecEquals(sublistOfOne, [['foo']])
+ def fakeSublistOfOne((foo)): return 1 + self.assertArgSpecEquals(fakeSublistOfOne, ['foo']) + def test_classify_oldstyle(self): class A: def s(): pass
Modified: python/trunk/Python/ast.c ============================================================================== --- python/trunk/Python/ast.c (original) +++ python/trunk/Python/ast.c Mon Mar 27 10:58:23 2006 @@ -645,10 +645,17 @@ goto error; } if (NCH(ch) == 3) { - asdl_seq_SET(args, k++, - compiler_complex_args(c, CHILD(ch, 1))); - } - else if (TYPE(CHILD(ch, 0)) == NAME) { + ch = CHILD(ch, 1); + /* def foo((x)): is not complex, special case. */ + if (NCH(ch) != 1) { + /* We have complex arguments, setup for unpacking. */ + asdl_seq_SET(args, k++, compiler_complex_args(c, ch)); + } else { + /* def foo((x)): setup for checking NAME below. */ + ch = CHILD(ch, 0); + } + } + if (TYPE(CHILD(ch, 0)) == NAME) { expr_ty name; if (!strcmp(STR(CHILD(ch, 0)), "None")) { ast_error(CHILD(ch, 0), "assignment to None"); _______________________________________________ Python-checkins mailing list Python-checkins@python.org http://mail.python.org/mailman/listinfo/python-checkins
_______________________________________________ Python-checkins mailing list Python-checkins@python.org http://mail.python.org/mailman/listinfo/python-checkins
-- --Guido van Rossum (home page: http://www.python.org/~guido/)

"Guido van Rossum" <guido@python.org> writes:
Well, obviously (:-) the intention was that def f((x)): is the same as def f(x): just like the expression (x) is the same as the expression x.
Though many moons ago bytecodehacks.macro exploited the fact that they are compiled differently :) Cheers, mwh -- This makes it possible to pass complex object hierarchies to a C coder who thinks computer science has made no worthwhile advancements since the invention of the pointer. -- Gordon McMillan, 30 Jul 1998
participants (5)
-
Georg Brandl
-
Guido van Rossum
-
Jeremy Hylton
-
Michael Hudson
-
neal.norwitz