[pypy-commit] pypy default: Port @with_unicode_literals from the py3k branch
amauryfa
noreply at buildbot.pypy.org
Mon Jan 28 09:18:14 CET 2013
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch:
Changeset: r60576:ef2d35b92279
Date: 2013-01-27 20:50 +0100
http://bitbucket.org/pypy/pypy/changeset/ef2d35b92279/
Log: Port @with_unicode_literals from the py3k branch
diff --git a/rpython/tool/sourcetools.py b/rpython/tool/sourcetools.py
--- a/rpython/tool/sourcetools.py
+++ b/rpython/tool/sourcetools.py
@@ -6,6 +6,7 @@
# XXX We should try to generalize and single out one approach to dynamic
# XXX code compilation.
+import types
import sys, os, inspect, new
import py
@@ -295,3 +296,40 @@
result.func_defaults = f.func_defaults
result.func_dict.update(f.func_dict)
return result
+
+
+def _convert_const_maybe(x, encoding):
+ if isinstance(x, str):
+ return x.decode(encoding)
+ elif isinstance(x, tuple):
+ items = [_convert_const_maybe(item, encoding) for item in x]
+ return tuple(items)
+ return x
+
+def with_unicode_literals(fn=None, **kwds):
+ """Decorator that replace all string literals with unicode literals.
+ Similar to 'from __future__ import string literals' at function level.
+ Useful to limit changes in the py3k branch.
+ """
+ encoding = kwds.pop('encoding', 'ascii')
+ if kwds:
+ raise TypeError("Unexpected keyword argument(s): %s" % ', '.join(kwds.keys()))
+ def decorator(fn):
+ co = fn.func_code
+ new_consts = []
+ for const in co.co_consts:
+ new_consts.append(_convert_const_maybe(const, encoding))
+ new_consts = tuple(new_consts)
+ new_code = types.CodeType(co.co_argcount, co.co_nlocals, co.co_stacksize,
+ co.co_flags, co.co_code, new_consts, co.co_names,
+ co.co_varnames, co.co_filename, co.co_name,
+ co.co_firstlineno, co.co_lnotab)
+ fn.func_code = new_code
+ return fn
+ #
+ # support the usage of @with_unicode_literals instead of @with_unicode_literals()
+ if fn is not None:
+ assert type(fn) is types.FunctionType
+ return decorator(fn)
+ else:
+ return decorator
diff --git a/rpython/tool/test/test_sourcetools.py b/rpython/tool/test/test_sourcetools.py
--- a/rpython/tool/test/test_sourcetools.py
+++ b/rpython/tool/test/test_sourcetools.py
@@ -1,4 +1,7 @@
-from rpython.tool.sourcetools import func_with_new_name, func_renamer, rpython_wrapper
+# -*- encoding: utf-8 -*-
+import py
+from rpython.tool.sourcetools import (
+ func_with_new_name, func_renamer, rpython_wrapper, with_unicode_literals)
def test_rename():
def f(x, y=5):
@@ -56,3 +59,28 @@
]
+def test_with_unicode_literals():
+ @with_unicode_literals()
+ def foo():
+ return 'hello'
+ assert type(foo()) is unicode
+ #
+ @with_unicode_literals
+ def foo():
+ return 'hello'
+ assert type(foo()) is unicode
+ #
+ def foo():
+ return 'hello àèì'
+ py.test.raises(UnicodeDecodeError, "with_unicode_literals(foo)")
+ #
+ @with_unicode_literals(encoding='utf-8')
+ def foo():
+ return 'hello àèì'
+ assert foo() == u'hello àèì'
+ #
+ @with_unicode_literals
+ def foo():
+ return ('a', 'b')
+ assert type(foo()[0]) is unicode
+
More information about the pypy-commit
mailing list