1 |
commit: 76b894c6c0001477235be97558d329e29ce8327f |
2 |
Author: Cédric Krier <cedk <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Jul 30 21:41:09 2017 +0000 |
4 |
Commit: Cédric Krier <cedk <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Jul 30 21:41:09 2017 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=76b894c6 |
7 |
|
8 |
dev-python/genshi: Add Python3 support by applying patches |
9 |
|
10 |
Gentoo-Bug: 616308 |
11 |
|
12 |
Package-Manager: Portage-2.3.6, Repoman-2.3.1 |
13 |
|
14 |
...enshi-0.7-fix_tests_failure_with_python27.patch | 25 ++ |
15 |
dev-python/genshi/files/genshi-0.7-issue566.patch | 57 ++++ |
16 |
dev-python/genshi/files/genshi-0.7-issue582.patch | 364 +++++++++++++++++++++ |
17 |
dev-python/genshi/files/genshi-0.7-issue602.patch | 114 +++++++ |
18 |
dev-python/genshi/genshi-0.7-r1.ebuild | 46 +++ |
19 |
5 files changed, 606 insertions(+) |
20 |
|
21 |
diff --git a/dev-python/genshi/files/genshi-0.7-fix_tests_failure_with_python27.patch b/dev-python/genshi/files/genshi-0.7-fix_tests_failure_with_python27.patch |
22 |
new file mode 100644 |
23 |
index 00000000000..4f3467d6481 |
24 |
--- /dev/null |
25 |
+++ b/dev-python/genshi/files/genshi-0.7-fix_tests_failure_with_python27.patch |
26 |
@@ -0,0 +1,25 @@ |
27 |
+From 7f3552a9373fadd2d37ff592769ba6c65755eea5 Mon Sep 17 00:00:00 2001 |
28 |
+From: SVN-Git Migration <python-modules-team@×××××××××××××××××××.org> |
29 |
+Date: Thu, 8 Oct 2015 09:13:47 -0700 |
30 |
+Subject: Skip test which still fails in Python 2.7.6. |
31 |
+ |
32 |
+Author: Barry Warsaw <barry@××××××.org>, Arnaud Fontaine <arnau@××××××.org> |
33 |
+Bug: http://genshi.edgewall.org/ticket/500 |
34 |
+ |
35 |
+Patch-Name: fix_tests_failure_with_python27.patch |
36 |
+--- |
37 |
+ genshi/filters/tests/test_html.py | 1 + |
38 |
+ 1 file changed, 1 insertion(+) |
39 |
+ |
40 |
+diff --git a/genshi/filters/tests/test_html.py b/genshi/filters/tests/test_html.py |
41 |
+index 0c6cfe1..a8cfa04 100644 |
42 |
+--- a/genshi/filters/tests/test_html.py |
43 |
++++ b/genshi/filters/tests/test_html.py |
44 |
+@@ -410,6 +410,7 @@ class HTMLSanitizerTestCase(unittest.TestCase): |
45 |
+ html = HTML(u'&junk;') |
46 |
+ self.assertEquals('&junk;', (html | HTMLSanitizer()).render()) |
47 |
+ |
48 |
++ @unittest.skip('http://genshi.edgewall.org/ticket/500#comment:3') |
49 |
+ def test_sanitize_remove_script_elem(self): |
50 |
+ html = HTML(u'<script>alert("Foo")</script>') |
51 |
+ self.assertEquals('', (html | HTMLSanitizer()).render()) |
52 |
|
53 |
diff --git a/dev-python/genshi/files/genshi-0.7-issue566.patch b/dev-python/genshi/files/genshi-0.7-issue566.patch |
54 |
new file mode 100644 |
55 |
index 00000000000..70fc8ea85e6 |
56 |
--- /dev/null |
57 |
+++ b/dev-python/genshi/files/genshi-0.7-issue566.patch |
58 |
@@ -0,0 +1,57 @@ |
59 |
+From fafbc4296902b2259c23d2ce55996b0127726b4f Mon Sep 17 00:00:00 2001 |
60 |
+From: SVN-Git Migration <python-modules-team@×××××××××××××××××××.org> |
61 |
+Date: Thu, 8 Oct 2015 09:13:49 -0700 |
62 |
+Subject: Fix an IndexError preventing Genshi for uploading attachments in |
63 |
+ |
64 |
+ Trac for users with non-English language settings. |
65 |
+Origin: http://genshi.edgewall.org/changeset/1243?format=diff&new=1243 |
66 |
+Bug: http://genshi.edgewall.org/ticket/566 |
67 |
+ |
68 |
+Patch-Name: issue566.patch |
69 |
+--- |
70 |
+ genshi/filters/i18n.py | 8 +++++++- |
71 |
+ genshi/filters/tests/i18n.py | 12 ++++++++++++ |
72 |
+ 2 files changed, 19 insertions(+), 1 deletion(-) |
73 |
+ |
74 |
+diff --git a/genshi/filters/i18n.py b/genshi/filters/i18n.py |
75 |
+index dfb52b8..8f2d25c 100644 |
76 |
+--- a/genshi/filters/i18n.py |
77 |
++++ b/genshi/filters/i18n.py |
78 |
+@@ -1048,7 +1048,13 @@ class MessageBuffer(object): |
79 |
+ |
80 |
+ while parts: |
81 |
+ order, string = parts.pop(0) |
82 |
+- events = self.events[order].pop(0) |
83 |
++ events = self.events[order] |
84 |
++ if events: |
85 |
++ events = events.pop(0) |
86 |
++ else: |
87 |
++ # create a dummy empty text event so any remaining |
88 |
++ # part of the translation can be processed. |
89 |
++ events = [(TEXT, "", (None, -1, -1))] |
90 |
+ parts_counter[order].pop() |
91 |
+ |
92 |
+ for event in events: |
93 |
+diff --git a/genshi/filters/tests/i18n.py b/genshi/filters/tests/i18n.py |
94 |
+index 212d5f6..b36a30b 100644 |
95 |
+--- a/genshi/filters/tests/i18n.py |
96 |
++++ b/genshi/filters/tests/i18n.py |
97 |
+@@ -928,6 +928,18 @@ class MsgDirectiveTestCase(unittest.TestCase): |
98 |
+ """</p></html>""", |
99 |
+ tmpl.generate(first="FIRST", second="SECOND").render()) |
100 |
+ |
101 |
++ def test_translate_i18n_msg_ticket_404_regression(self): |
102 |
++ tmpl = MarkupTemplate("""<html xmlns:py="http://genshi.edgewall.org/" |
103 |
++ xmlns:i18n="http://genshi.edgewall.org/i18n"> |
104 |
++ <h1 i18n:msg="name">text <a>$name</a></h1> |
105 |
++ </html>""") |
106 |
++ gettext = lambda s: u'head [1:%(name)s] tail' |
107 |
++ translator = Translator(gettext) |
108 |
++ translator.setup(tmpl) |
109 |
++ self.assertEqual("""<html> |
110 |
++ <h1>head <a>NAME</a> tail</h1> |
111 |
++ </html>""", tmpl.generate(name='NAME').render()) |
112 |
++ |
113 |
+ |
114 |
+ class ChooseDirectiveTestCase(unittest.TestCase): |
115 |
+ |
116 |
|
117 |
diff --git a/dev-python/genshi/files/genshi-0.7-issue582.patch b/dev-python/genshi/files/genshi-0.7-issue582.patch |
118 |
new file mode 100644 |
119 |
index 00000000000..fbcab626d6c |
120 |
--- /dev/null |
121 |
+++ b/dev-python/genshi/files/genshi-0.7-issue582.patch |
122 |
@@ -0,0 +1,364 @@ |
123 |
+From 554fa3428bea3039decfd9064b860c753b2637a1 Mon Sep 17 00:00:00 2001 |
124 |
+From: SVN-Git Migration <python-modules-team@×××××××××××××××××××.org> |
125 |
+Date: Thu, 8 Oct 2015 09:13:48 -0700 |
126 |
+Subject: Make genshi 0.7 compatible with Python 3.4. |
127 |
+ |
128 |
+Origin: http://genshi.edgewall.org/changeset/1252?format=diff&new=1252 |
129 |
+Bug: http://genshi.edgewall.org/ticket/582 |
130 |
+Forwarded: not-needed |
131 |
+ |
132 |
+Patch-Name: issue582.patch |
133 |
+--- |
134 |
+ doc/upgrade.txt | 8 ++--- |
135 |
+ genshi/compat.py | 10 +++++- |
136 |
+ genshi/filters/tests/test_html.py | 14 ++++++--- |
137 |
+ genshi/template/astutil.py | 66 ++++++++++++++++++++++++++++----------- |
138 |
+ genshi/template/eval.py | 37 +++++++++++++--------- |
139 |
+ genshi/template/tests/eval.py | 23 ++++++++++++++ |
140 |
+ run_benchmarks.sh | 31 ++++++++++++++++++ |
141 |
+ setup.py | 6 +++- |
142 |
+ 8 files changed, 151 insertions(+), 44 deletions(-) |
143 |
+ create mode 100644 run_benchmarks.sh |
144 |
+ |
145 |
+diff --git a/doc/upgrade.txt b/doc/upgrade.txt |
146 |
+index b240eda..ad4c080 100644 |
147 |
+--- a/doc/upgrade.txt |
148 |
++++ b/doc/upgrade.txt |
149 |
+@@ -7,11 +7,11 @@ Upgrading Genshi |
150 |
+ :depth: 2 |
151 |
+ .. sectnum:: |
152 |
+ |
153 |
+------------------------------------------------------- |
154 |
+-Upgrading from Genshi 0.6.x to the development version |
155 |
+------------------------------------------------------- |
156 |
++------------------------------------------- |
157 |
++Upgrading from Genshi 0.6.x to Genshi 0.7.x |
158 |
++------------------------------------------- |
159 |
+ |
160 |
+-The Genshi development version now supports both Python 2 and Python 3. |
161 |
++Genshi 0.7.x now supports both Python 2 and Python 3. |
162 |
+ |
163 |
+ The most noticable API change in the Genshi development version is that the |
164 |
+ default encoding in numerous places is now None (i.e. unicode) instead |
165 |
+diff --git a/genshi/compat.py b/genshi/compat.py |
166 |
+index 9787325..6574e39 100644 |
167 |
+--- a/genshi/compat.py |
168 |
++++ b/genshi/compat.py |
169 |
+@@ -35,6 +35,15 @@ else: |
170 |
+ 'Python 2 compatibility function. Not usable in Python 3.') |
171 |
+ |
172 |
+ |
173 |
++# We need to test if an object is an instance of a string type in places |
174 |
++ |
175 |
++if IS_PYTHON2: |
176 |
++ def isstring(obj): |
177 |
++ return isinstance(obj, basestring) |
178 |
++else: |
179 |
++ def isstring(obj): |
180 |
++ return isinstance(obj, str) |
181 |
++ |
182 |
+ # We need to differentiate between StringIO and BytesIO in places |
183 |
+ |
184 |
+ if IS_PYTHON2: |
185 |
+@@ -112,4 +121,3 @@ except NameError: |
186 |
+ if not x: |
187 |
+ return False |
188 |
+ return True |
189 |
+- |
190 |
+diff --git a/genshi/filters/tests/test_html.py b/genshi/filters/tests/test_html.py |
191 |
+index a8cfa04..7120988 100644 |
192 |
+--- a/genshi/filters/tests/test_html.py |
193 |
++++ b/genshi/filters/tests/test_html.py |
194 |
+@@ -368,12 +368,16 @@ def StyleSanitizer(): |
195 |
+ |
196 |
+ class HTMLSanitizerTestCase(unittest.TestCase): |
197 |
+ |
198 |
+- def assert_parse_error_or_equal(self, expected, exploit): |
199 |
++ def assert_parse_error_or_equal(self, expected, exploit, |
200 |
++ allow_strip=False): |
201 |
+ try: |
202 |
+ html = HTML(exploit) |
203 |
+ except ParseError: |
204 |
+ return |
205 |
+- self.assertEquals(expected, (html | HTMLSanitizer()).render()) |
206 |
++ sanitized_html = (html | HTMLSanitizer()).render() |
207 |
++ if not sanitized_html and allow_strip: |
208 |
++ return |
209 |
++ self.assertEquals(expected, sanitized_html) |
210 |
+ |
211 |
+ def test_sanitize_unchanged(self): |
212 |
+ html = HTML(u'<a href="#">fo<br />o</a>') |
213 |
+@@ -417,10 +421,12 @@ class HTMLSanitizerTestCase(unittest.TestCase): |
214 |
+ html = HTML(u'<SCRIPT SRC="http://example.com/"></SCRIPT>') |
215 |
+ self.assertEquals('', (html | HTMLSanitizer()).render()) |
216 |
+ src = u'<SCR\0IPT>alert("foo")</SCR\0IPT>' |
217 |
+- self.assert_parse_error_or_equal('<SCR\x00IPT>alert("foo")', src) |
218 |
++ self.assert_parse_error_or_equal('<SCR\x00IPT>alert("foo")', src, |
219 |
++ allow_strip=True) |
220 |
+ src = u'<SCRIPT&XYZ SRC="http://example.com/"></SCRIPT>' |
221 |
+ self.assert_parse_error_or_equal('<SCRIPT&XYZ; ' |
222 |
+- 'SRC="http://example.com/">', src) |
223 |
++ 'SRC="http://example.com/">', src, |
224 |
++ allow_strip=True) |
225 |
+ |
226 |
+ def test_sanitize_remove_onclick_attr(self): |
227 |
+ html = HTML(u'<div onclick=\'alert("foo")\' />') |
228 |
+diff --git a/genshi/template/astutil.py b/genshi/template/astutil.py |
229 |
+index b24f728..e561846 100644 |
230 |
+--- a/genshi/template/astutil.py |
231 |
++++ b/genshi/template/astutil.py |
232 |
+@@ -21,7 +21,7 @@ else: |
233 |
+ def parse(source, mode): |
234 |
+ return compile(source, '', mode, _ast.PyCF_ONLY_AST) |
235 |
+ |
236 |
+-from genshi.compat import IS_PYTHON2 |
237 |
++from genshi.compat import IS_PYTHON2, isstring |
238 |
+ |
239 |
+ __docformat__ = 'restructuredtext en' |
240 |
+ |
241 |
+@@ -103,32 +103,48 @@ class ASTCodeGenerator(object): |
242 |
+ self._new_line() |
243 |
+ return self.visit(node.body) |
244 |
+ |
245 |
++ # Python < 3.4 |
246 |
+ # arguments = (expr* args, identifier? vararg, |
247 |
+ # identifier? kwarg, expr* defaults) |
248 |
++ # |
249 |
++ # Python >= 3.4 |
250 |
++ # arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, |
251 |
++ # arg? kwarg, expr* defaults) |
252 |
+ def visit_arguments(self, node): |
253 |
+- first = True |
254 |
+- no_default_count = len(node.args) - len(node.defaults) |
255 |
+- for i, arg in enumerate(node.args): |
256 |
+- if not first: |
257 |
+- self._write(', ') |
258 |
++ def write_possible_comma(): |
259 |
++ if _first[0]: |
260 |
++ _first[0] = False |
261 |
+ else: |
262 |
+- first = False |
263 |
+- self.visit(arg) |
264 |
+- if i >= no_default_count: |
265 |
+- self._write('=') |
266 |
+- self.visit(node.defaults[i - no_default_count]) |
267 |
+- if getattr(node, 'vararg', None): |
268 |
+- if not first: |
269 |
+ self._write(', ') |
270 |
++ _first = [True] |
271 |
++ |
272 |
++ def write_args(args, defaults): |
273 |
++ no_default_count = len(args) - len(defaults) |
274 |
++ for i, arg in enumerate(args): |
275 |
++ write_possible_comma() |
276 |
++ self.visit(arg) |
277 |
++ default_idx = i - no_default_count |
278 |
++ if default_idx >= 0 and defaults[default_idx] is not None: |
279 |
++ self._write('=') |
280 |
++ self.visit(defaults[i - no_default_count]) |
281 |
++ |
282 |
++ write_args(node.args, node.defaults) |
283 |
++ if getattr(node, 'vararg', None): |
284 |
++ write_possible_comma() |
285 |
++ self._write('*') |
286 |
++ if isstring(node.vararg): |
287 |
++ self._write(node.vararg) |
288 |
+ else: |
289 |
+- first = False |
290 |
+- self._write('*' + node.vararg) |
291 |
++ self.visit(node.vararg) |
292 |
++ if getattr(node, 'kwonlyargs', None): |
293 |
++ write_args(node.kwonlyargs, node.kw_defaults) |
294 |
+ if getattr(node, 'kwarg', None): |
295 |
+- if not first: |
296 |
+- self._write(', ') |
297 |
++ write_possible_comma() |
298 |
++ self._write('**') |
299 |
++ if isstring(node.kwarg): |
300 |
++ self._write(node.kwarg) |
301 |
+ else: |
302 |
+- first = False |
303 |
+- self._write('**' + node.kwarg) |
304 |
++ self.visit(node.kwarg) |
305 |
+ |
306 |
+ if not IS_PYTHON2: |
307 |
+ # In Python 3 arguments get a special node |
308 |
+@@ -732,6 +748,17 @@ class ASTCodeGenerator(object): |
309 |
+ def visit_Name(self, node): |
310 |
+ self._write(node.id) |
311 |
+ |
312 |
++ # NameConstant(singleton value) |
313 |
++ def visit_NameConstant(self, node): |
314 |
++ if node.value is None: |
315 |
++ self._write('None') |
316 |
++ elif node.value is True: |
317 |
++ self._write('True') |
318 |
++ elif node.value is False: |
319 |
++ self._write('False') |
320 |
++ else: |
321 |
++ raise Exception("Unknown NameConstant %r" % (node.value,)) |
322 |
++ |
323 |
+ # List(expr* elts, expr_context ctx) |
324 |
+ def visit_List(self, node): |
325 |
+ self._write('[') |
326 |
+@@ -837,6 +864,7 @@ class ASTTransformer(object): |
327 |
+ visit_Attribute = _clone |
328 |
+ visit_Subscript = _clone |
329 |
+ visit_Name = _clone |
330 |
++ visit_NameConstant = _clone |
331 |
+ visit_List = _clone |
332 |
+ visit_Tuple = _clone |
333 |
+ |
334 |
+diff --git a/genshi/template/eval.py b/genshi/template/eval.py |
335 |
+index c00cfcb..81644a7 100644 |
336 |
+--- a/genshi/template/eval.py |
337 |
++++ b/genshi/template/eval.py |
338 |
+@@ -24,7 +24,8 @@ from genshi.template.astutil import ASTTransformer, ASTCodeGenerator, \ |
339 |
+ from genshi.template.base import TemplateRuntimeError |
340 |
+ from genshi.util import flatten |
341 |
+ |
342 |
+-from genshi.compat import get_code_params, build_code_chunk, IS_PYTHON2 |
343 |
++from genshi.compat import get_code_params, build_code_chunk, isstring, \ |
344 |
++ IS_PYTHON2 |
345 |
+ |
346 |
+ __all__ = ['Code', 'Expression', 'Suite', 'LenientLookup', 'StrictLookup', |
347 |
+ 'Undefined', 'UndefinedError'] |
348 |
+@@ -495,28 +496,34 @@ class TemplateASTTransformer(ASTTransformer): |
349 |
+ def __init__(self): |
350 |
+ self.locals = [CONSTANTS] |
351 |
+ |
352 |
++ def _process(self, names, node): |
353 |
++ if not IS_PYTHON2 and isinstance(node, _ast.arg): |
354 |
++ names.add(node.arg) |
355 |
++ elif isstring(node): |
356 |
++ names.add(node) |
357 |
++ elif isinstance(node, _ast.Name): |
358 |
++ names.add(node.id) |
359 |
++ elif isinstance(node, _ast.alias): |
360 |
++ names.add(node.asname or node.name) |
361 |
++ elif isinstance(node, _ast.Tuple): |
362 |
++ for elt in node.elts: |
363 |
++ self._process(names, elt) |
364 |
++ |
365 |
+ def _extract_names(self, node): |
366 |
+ names = set() |
367 |
+- def _process(node): |
368 |
+- if not IS_PYTHON2 and isinstance(node, _ast.arg): |
369 |
+- names.add(node.arg) |
370 |
+- if isinstance(node, _ast.Name): |
371 |
+- names.add(node.id) |
372 |
+- elif isinstance(node, _ast.alias): |
373 |
+- names.add(node.asname or node.name) |
374 |
+- elif isinstance(node, _ast.Tuple): |
375 |
+- for elt in node.elts: |
376 |
+- _process(elt) |
377 |
+ if hasattr(node, 'args'): |
378 |
+ for arg in node.args: |
379 |
+- _process(arg) |
380 |
++ self._process(names, arg) |
381 |
++ if hasattr(node, 'kwonlyargs'): |
382 |
++ for arg in node.kwonlyargs: |
383 |
++ self._process(names, arg) |
384 |
+ if hasattr(node, 'vararg'): |
385 |
+- names.add(node.vararg) |
386 |
++ self._process(names, node.vararg) |
387 |
+ if hasattr(node, 'kwarg'): |
388 |
+- names.add(node.kwarg) |
389 |
++ self._process(names, node.kwarg) |
390 |
+ elif hasattr(node, 'names'): |
391 |
+ for elt in node.names: |
392 |
+- _process(elt) |
393 |
++ self._process(names, elt) |
394 |
+ return names |
395 |
+ |
396 |
+ def visit_Str(self, node): |
397 |
+diff --git a/genshi/template/tests/eval.py b/genshi/template/tests/eval.py |
398 |
+index 7722571..c44a0e3 100644 |
399 |
+--- a/genshi/template/tests/eval.py |
400 |
++++ b/genshi/template/tests/eval.py |
401 |
+@@ -590,6 +590,29 @@ x = smash(foo='abc', bar='def') |
402 |
+ suite.execute(data) |
403 |
+ self.assertEqual(['bardef', 'fooabc'], sorted(data['x'])) |
404 |
+ |
405 |
++ if not IS_PYTHON2: |
406 |
++ def test_def_kwonlyarg(self): |
407 |
++ suite = Suite(""" |
408 |
++def kwonly(*args, k): |
409 |
++ return k |
410 |
++x = kwonly(k="foo") |
411 |
++""") |
412 |
++ data = {} |
413 |
++ suite.execute(data) |
414 |
++ self.assertEqual("foo", data['x']) |
415 |
++ |
416 |
++ def test_def_kwonlyarg_with_default(self): |
417 |
++ suite = Suite(""" |
418 |
++def kwonly(*args, k="bar"): |
419 |
++ return k |
420 |
++x = kwonly(k="foo") |
421 |
++y = kwonly() |
422 |
++""") |
423 |
++ data = {} |
424 |
++ suite.execute(data) |
425 |
++ self.assertEqual("foo", data['x']) |
426 |
++ self.assertEqual("bar", data['y']) |
427 |
++ |
428 |
+ def test_def_nested(self): |
429 |
+ suite = Suite(""" |
430 |
+ def doit(): |
431 |
+diff --git a/run_benchmarks.sh b/run_benchmarks.sh |
432 |
+new file mode 100644 |
433 |
+index 0000000..0c64cc8 |
434 |
+--- /dev/null |
435 |
++++ b/run_benchmarks.sh |
436 |
+@@ -0,0 +1,31 @@ |
437 |
++#!/bin/sh |
438 |
++# |
439 |
++# 1. Run the tests with `tox` (this will set up all the tox envs). |
440 |
++# 2. ./run_benchmarks.sh <env-name> | tee results-<env-name>.out |
441 |
++ |
442 |
++NAME="$1" |
443 |
++PYTHON="./.tox/$NAME/bin/python" |
444 |
++BENCH_DIR="bench_build/$1" |
445 |
++BENCH_BIN_DIR="$BENCH_DIR/bin" |
446 |
++mkdir -p "bench_build" |
447 |
++ |
448 |
++rm -rf "$BENCH_DIR" |
449 |
++cp -R "examples/bench" "$BENCH_DIR" |
450 |
++ |
451 |
++case "$NAME" in |
452 |
++ py32|py33) |
453 |
++ 2to3 -w --no-diffs "$BENCH_DIR" |
454 |
++ ;; |
455 |
++esac |
456 |
++ |
457 |
++echo "-- basic --" |
458 |
++"$PYTHON" "$BENCH_DIR/basic.py" |
459 |
++echo |
460 |
++ |
461 |
++echo "-- bigtable --" |
462 |
++"$PYTHON" "$BENCH_DIR/bigtable.py" |
463 |
++echo |
464 |
++ |
465 |
++echo "-- xpath --" |
466 |
++"$PYTHON" "$BENCH_DIR/xpath.py" |
467 |
++echo |
468 |
+diff --git a/setup.py b/setup.py |
469 |
+index 294ba9b..45099b5 100755 |
470 |
+--- a/setup.py |
471 |
++++ b/setup.py |
472 |
+@@ -65,9 +65,13 @@ available.""") |
473 |
+ |
474 |
+ |
475 |
+ if Feature: |
476 |
++ # Optional C extension module for speeding up Genshi: |
477 |
++ # Not activated by default on: |
478 |
++ # - PyPy (where it harms performance) |
479 |
++ # - CPython >= 3.3 (the new Unicode C API is not supported yet) |
480 |
+ speedups = Feature( |
481 |
+ "optional C speed-enhancements", |
482 |
+- standard = not is_pypy, |
483 |
++ standard = not is_pypy and sys.version_info < (3, 3), |
484 |
+ ext_modules = [ |
485 |
+ Extension('genshi._speedups', ['genshi/_speedups.c']), |
486 |
+ ], |
487 |
|
488 |
diff --git a/dev-python/genshi/files/genshi-0.7-issue602.patch b/dev-python/genshi/files/genshi-0.7-issue602.patch |
489 |
new file mode 100644 |
490 |
index 00000000000..d7f0b77fa92 |
491 |
--- /dev/null |
492 |
+++ b/dev-python/genshi/files/genshi-0.7-issue602.patch |
493 |
@@ -0,0 +1,114 @@ |
494 |
+From 1acbd00b4961164edc8a185458ba4a433bedbceb Mon Sep 17 00:00:00 2001 |
495 |
+From: SVN-Git Migration <python-modules-team@×××××××××××××××××××.org> |
496 |
+Date: Thu, 8 Oct 2015 09:13:46 -0700 |
497 |
+Subject: Fix Python 3.5 compatibility issues. |
498 |
+ |
499 |
+Origin: http://genshi.edgewall.org/attachment/ticket/602/t602.diff |
500 |
+Bug: http://genshi.edgewall.org/ticket/602 |
501 |
+Forwarded: not-needed |
502 |
+ |
503 |
+Patch-Name: issue602.patch |
504 |
+--- |
505 |
+ genshi/filters/i18n.py | 6 ++++-- |
506 |
+ genshi/template/astutil.py | 14 +++++++++++--- |
507 |
+ genshi/template/directives.py | 20 ++++++++++++++------ |
508 |
+ genshi/template/eval.py | 5 +++++ |
509 |
+ 4 files changed, 34 insertions(+), 11 deletions(-) |
510 |
+ |
511 |
+diff --git a/genshi/filters/i18n.py b/genshi/filters/i18n.py |
512 |
+index b724956..dfb52b8 100644 |
513 |
+--- a/genshi/filters/i18n.py |
514 |
++++ b/genshi/filters/i18n.py |
515 |
+@@ -1187,8 +1187,10 @@ def extract_from_code(code, gettext_functions): |
516 |
+ elif arg: |
517 |
+ strings.append(None) |
518 |
+ [_add(arg) for arg in node.args] |
519 |
+- _add(node.starargs) |
520 |
+- _add(node.kwargs) |
521 |
++ if hasattr(node, 'starargs'): |
522 |
++ _add(node.starargs) |
523 |
++ if hasattr(node, 'kwargs'): |
524 |
++ _add(node.kwargs) |
525 |
+ if len(strings) == 1: |
526 |
+ strings = strings[0] |
527 |
+ else: |
528 |
+diff --git a/genshi/template/astutil.py b/genshi/template/astutil.py |
529 |
+index a4c21c8..b24f728 100644 |
530 |
+--- a/genshi/template/astutil.py |
531 |
++++ b/genshi/template/astutil.py |
532 |
+@@ -135,6 +135,10 @@ class ASTCodeGenerator(object): |
533 |
+ def visit_arg(self, node): |
534 |
+ self._write(node.arg) |
535 |
+ |
536 |
++ def visit_Starred(self, node): |
537 |
++ self._write('*') |
538 |
++ self.visit(node.value) |
539 |
++ |
540 |
+ # FunctionDef(identifier name, arguments args, |
541 |
+ # stmt* body, expr* decorator_list) |
542 |
+ def visit_FunctionDef(self, node): |
543 |
+@@ -648,9 +652,13 @@ class ASTCodeGenerator(object): |
544 |
+ if not first: |
545 |
+ self._write(', ') |
546 |
+ first = False |
547 |
+- # keyword = (identifier arg, expr value) |
548 |
+- self._write(keyword.arg) |
549 |
+- self._write('=') |
550 |
++ if not keyword.arg: |
551 |
++ # Python 3.5+ star-star args |
552 |
++ self._write('**') |
553 |
++ else: |
554 |
++ # keyword = (identifier arg, expr value) |
555 |
++ self._write(keyword.arg) |
556 |
++ self._write('=') |
557 |
+ self.visit(keyword.value) |
558 |
+ if getattr(node, 'starargs', None): |
559 |
+ if not first: |
560 |
+diff --git a/genshi/template/directives.py b/genshi/template/directives.py |
561 |
+index 7301c2d..1f70ef6 100644 |
562 |
+--- a/genshi/template/directives.py |
563 |
++++ b/genshi/template/directives.py |
564 |
+@@ -266,13 +266,21 @@ class DefDirective(Directive): |
565 |
+ if isinstance(ast, _ast.Call): |
566 |
+ self.name = ast.func.id |
567 |
+ for arg in ast.args: |
568 |
+- # only names |
569 |
+- self.args.append(arg.id) |
570 |
++ if hasattr(_ast, 'Starred') and isinstance(arg, _ast.Starred): |
571 |
++ # Python 3.5+ |
572 |
++ self.star_args = arg.value.id |
573 |
++ else: |
574 |
++ # only names |
575 |
++ self.args.append(arg.id) |
576 |
+ for kwd in ast.keywords: |
577 |
+- self.args.append(kwd.arg) |
578 |
+- exp = Expression(kwd.value, template.filepath, |
579 |
+- lineno, lookup=template.lookup) |
580 |
+- self.defaults[kwd.arg] = exp |
581 |
++ if kwd.arg is None: |
582 |
++ # Python 3.5+ |
583 |
++ self.dstar_args = kwd.value.id |
584 |
++ else: |
585 |
++ self.args.append(kwd.arg) |
586 |
++ exp = Expression(kwd.value, template.filepath, |
587 |
++ lineno, lookup=template.lookup) |
588 |
++ self.defaults[kwd.arg] = exp |
589 |
+ if getattr(ast, 'starargs', None): |
590 |
+ self.star_args = ast.starargs.id |
591 |
+ if getattr(ast, 'kwargs', None): |
592 |
+diff --git a/genshi/template/eval.py b/genshi/template/eval.py |
593 |
+index 89aec49..c00cfcb 100644 |
594 |
+--- a/genshi/template/eval.py |
595 |
++++ b/genshi/template/eval.py |
596 |
+@@ -593,6 +593,11 @@ class TemplateASTTransformer(ASTTransformer): |
597 |
+ finally: |
598 |
+ self.locals.pop() |
599 |
+ |
600 |
++ # Only used in Python 3.5+ |
601 |
++ def visit_Starred(self, node): |
602 |
++ node.value = self.visit(node.value) |
603 |
++ return node |
604 |
++ |
605 |
+ def visit_Name(self, node): |
606 |
+ # If the name refers to a local inside a lambda, list comprehension, or |
607 |
+ # generator expression, leave it alone |
608 |
|
609 |
diff --git a/dev-python/genshi/genshi-0.7-r1.ebuild b/dev-python/genshi/genshi-0.7-r1.ebuild |
610 |
new file mode 100644 |
611 |
index 00000000000..65360402e2c |
612 |
--- /dev/null |
613 |
+++ b/dev-python/genshi/genshi-0.7-r1.ebuild |
614 |
@@ -0,0 +1,46 @@ |
615 |
+# Copyright 1999-2017 Gentoo Foundation |
616 |
+# Distributed under the terms of the GNU General Public License v2 |
617 |
+ |
618 |
+EAPI=5 |
619 |
+PYTHON_COMPAT=( python{2_7,3_{4,5,6}} pypy ) |
620 |
+ |
621 |
+inherit distutils-r1 |
622 |
+ |
623 |
+MY_P="Genshi-${PV}" |
624 |
+ |
625 |
+DESCRIPTION="Python toolkit for stream-based generation of output for the web" |
626 |
+HOMEPAGE="http://genshi.edgewall.org/ https://pypi.python.org/pypi/Genshi" |
627 |
+SRC_URI="http://ftp.edgewall.com/pub/genshi/${MY_P}.tar.gz" |
628 |
+ |
629 |
+LICENSE="BSD" |
630 |
+SLOT="0" |
631 |
+KEYWORDS="~amd64 ~ppc ~ppc64 ~sparc ~x86 ~x86-fbsd ~amd64-linux ~x86-linux ~x64-macos ~x86-macos" |
632 |
+IUSE="doc examples" |
633 |
+ |
634 |
+DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]" |
635 |
+RDEPEND="${DEPEND}" |
636 |
+ |
637 |
+S="${WORKDIR}/${MY_P}" |
638 |
+ |
639 |
+src_prepare() { |
640 |
+ epatch "${FILESDIR}/${P}-issue566.patch" |
641 |
+ epatch "${FILESDIR}/${P}-issue582.patch" |
642 |
+ epatch "${FILESDIR}/${P}-fix_tests_failure_with_python27.patch" |
643 |
+ epatch "${FILESDIR}/${P}-issue602.patch" |
644 |
+} |
645 |
+ |
646 |
+python_test() { |
647 |
+ esetup.py test |
648 |
+} |
649 |
+ |
650 |
+python_install_all() { |
651 |
+ if use doc; then |
652 |
+ dodoc doc/*.txt |
653 |
+ dohtml -r doc/* |
654 |
+ fi |
655 |
+ if use examples; then |
656 |
+ insinto /usr/share/doc/${PF} |
657 |
+ doins -r examples |
658 |
+ fi |
659 |
+ distutils-r1_python_install_all |
660 |
+} |