From ce796ad4bae5c47011876778674ad036357febdf Mon Sep 17 00:00:00 2001
From: Adriano Peluso <catonano@gmail.com>
Date: Wed, 5 Apr 2017 15:10:06 +0200
Subject: [PATCH 1/2] fixing the tests on python35

---
 genshi/filters/i18n.py        |  6 ++++--
 genshi/template/astutil.py    | 14 +++++++++++---
 genshi/template/directives.py | 20 ++++++++++++++------
 genshi/template/eval.py       |  5 +++++
 4 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/genshi/filters/i18n.py b/genshi/filters/i18n.py
index 526fda4..5387fcf 100644
--- a/genshi/filters/i18n.py
+++ b/genshi/filters/i18n.py
@@ -1194,8 +1194,10 @@ def extract_from_code(code, gettext_functions):
                 elif arg:
                     strings.append(None)
             [_add(arg) for arg in node.args]
-            _add(node.starargs)
-            _add(node.kwargs)
+            if hasattr(node, 'starargs'):
+                _add(node.starargs)
+            if hasattr(node, 'kwargs'):
+                _add(node.kwargs)
             if len(strings) == 1:
                 strings = strings[0]
             else:
diff --git a/genshi/template/astutil.py b/genshi/template/astutil.py
index f4e1edd..e561846 100644
--- a/genshi/template/astutil.py
+++ b/genshi/template/astutil.py
@@ -151,6 +151,10 @@ class ASTCodeGenerator(object):
         def visit_arg(self, node):
             self._write(node.arg)
 
+    def visit_Starred(self, node):
+        self._write('*')
+        self.visit(node.value)
+
     # FunctionDef(identifier name, arguments args,
     #                           stmt* body, expr* decorator_list)
     def visit_FunctionDef(self, node):
@@ -664,9 +668,13 @@ class ASTCodeGenerator(object):
             if not first:
                 self._write(', ')
             first = False
-            # keyword = (identifier arg, expr value)
-            self._write(keyword.arg)
-            self._write('=')
+            if not keyword.arg:
+                # Python 3.5+ star-star args
+                self._write('**')
+            else:
+                # keyword = (identifier arg, expr value)
+                self._write(keyword.arg)
+                self._write('=')
             self.visit(keyword.value)
         if getattr(node, 'starargs', None):
             if not first:
diff --git a/genshi/template/directives.py b/genshi/template/directives.py
index 7301c2d..6fd0f28 100644
--- a/genshi/template/directives.py
+++ b/genshi/template/directives.py
@@ -266,13 +266,21 @@ class DefDirective(Directive):
         if isinstance(ast, _ast.Call):
             self.name = ast.func.id
             for arg in ast.args:
-                # only names
-                self.args.append(arg.id)
+                if isinstance(arg, _ast.Starred):
+                    # Python 3.5+
+                    self.star_args = arg.value.id
+                else:
+                    # only names
+                    self.args.append(arg.id)
             for kwd in ast.keywords:
-                self.args.append(kwd.arg)
-                exp = Expression(kwd.value, template.filepath,
-                                 lineno, lookup=template.lookup)
-                self.defaults[kwd.arg] = exp
+                if kwd.arg is None:
+                    # Python 3.5+
+                    self.dstar_args = kwd.value.id
+                else:
+                    self.args.append(kwd.arg)
+                    exp = Expression(kwd.value, template.filepath,
+                                     lineno, lookup=template.lookup)
+                    self.defaults[kwd.arg] = exp
             if getattr(ast, 'starargs', None):
                 self.star_args = ast.starargs.id
             if getattr(ast, 'kwargs', None):
diff --git a/genshi/template/eval.py b/genshi/template/eval.py
index d378419..81644a7 100644
--- a/genshi/template/eval.py
+++ b/genshi/template/eval.py
@@ -600,6 +600,11 @@ class TemplateASTTransformer(ASTTransformer):
         finally:
             self.locals.pop()
 
+    # Only used in Python 3.5+
+    def visit_Starred(self, node):
+        node.value = self.visit(node.value)
+        return node
+
     def visit_Name(self, node):
         # If the name refers to a local inside a lambda, list comprehension, or
         # generator expression, leave it alone
-- 
2.12.0