From fb98bf58c4c1a8b38511545c74e52a6b7a304521 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Tue, 5 May 2015 23:31:11 -0700 Subject: [PATCH] *args and **kwargs no longer have own args in Python 3.5 Python 3.5's PEP 448 ("Additional Unpacking Generalizations") allows the iterable- and dictionary- unpacking operators to be used more than once; the implementation (see https://hg.python.org/cpython/rev/a65f685ba8c0) gets rid of the optional `starargs` and `kwargs` arguments to `ast.Call` and `ast.ClassDef`, instead using `ast.Starred` and `ast.keyword` objects inside of the normal `args` and `keywords` lists, respectively. This commit allows Hy's `apply` to work correctly with this revised AST when running under Python 3.5. --- hy/compiler.py | 20 ++++++++++++++++++-- tests/native_tests/language.hy | 9 ++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/hy/compiler.py b/hy/compiler.py index 31fba2b..7f9dbe2 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1554,12 +1554,28 @@ class HyASTCompiler(object): stargs = expr.pop(0) if stargs is not None: stargs = self.compile(stargs) - ret.expr.starargs = stargs.force_expr + if PY35: + stargs_expr = stargs.force_expr + ret.expr.args.append( + ast.Starred(stargs_expr, ast.Load(), + lineno=stargs_expr.lineno, + col_offset=stargs_expr.col_offset) + ) + else: + ret.expr.starargs = stargs.force_expr ret = stargs + ret if expr: kwargs = self.compile(expr.pop(0)) - ret.expr.kwargs = kwargs.force_expr + if PY35: + kwargs_expr = kwargs.force_expr + ret.expr.keywords.append( + ast.keyword(None, kwargs_expr, + lineno=kwargs_expr.lineno, + col_offset=kwargs_expr.col_offset) + ) + else: + ret.expr.kwargs = kwargs.force_expr ret = kwargs + ret return ret diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 2d4a909..37bfd05 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -4,7 +4,7 @@ [operator [or_]]) (import sys) -(import [hy._compat [PY33 PY34]]) +(import [hy._compat [PY33 PY34 PY35]]) (defn test-sys-argv [] "NATIVE: test sys.argv" @@ -1047,8 +1047,11 @@ (defn test-disassemble [] "NATIVE: Test the disassemble function" - (assert (= (disassemble '(do (leaky) (leaky) (macros))) - "Module(\n body=[\n Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),\n Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),\n Expr(value=Call(func=Name(id='macros'), args=[], keywords=[], starargs=None, kwargs=None))])")) + (if PY35 + (assert (= (disassemble '(do (leaky) (leaky) (macros))) + "Module(\n body=[Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[])),\n Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[])),\n Expr(value=Call(func=Name(id='macros'), args=[], keywords=[]))])")) + (assert (= (disassemble '(do (leaky) (leaky) (macros))) + "Module(\n body=[\n Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),\n Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),\n Expr(value=Call(func=Name(id='macros'), args=[], keywords=[], starargs=None, kwargs=None))])"))) (assert (= (disassemble '(do (leaky) (leaky) (macros)) true) "leaky()\nleaky()\nmacros()")))