summaryrefslogtreecommitdiff
path: root/babel
diff options
context:
space:
mode:
authorAarni Koskela <akx@iki.fi>2016-07-09 12:51:11 +0300
committerGitHub <noreply@github.com>2016-07-09 12:51:11 +0300
commitd6ed8963a407355be0c03733270f2ba1a1dc7af9 (patch)
tree8b2aa73468075443af8596e1feb6c37530df8ef7 /babel
parent9a3ce80bffc0b9d6e76c0321a34509a9ef4243d9 (diff)
parent60d13b090a3a6a6989e520e08bcf86fb70073c72 (diff)
downloadbabel-d6ed8963a407355be0c03733270f2ba1a1dc7af9.tar.gz
Merge pull request #427 from sublee/issue-426
Python message extractor respects unicode_literals in __future__
Diffstat (limited to 'babel')
-rw-r--r--babel/messages/extract.py8
-rw-r--r--babel/util.py23
2 files changed, 28 insertions, 3 deletions
diff --git a/babel/messages/extract.py b/babel/messages/extract.py
index 4dc56a4..db17848 100644
--- a/babel/messages/extract.py
+++ b/babel/messages/extract.py
@@ -22,7 +22,7 @@ from os.path import relpath
import sys
from tokenize import generate_tokens, COMMENT, NAME, OP, STRING
-from babel.util import parse_encoding, pathmatch
+from babel.util import parse_encoding, parse_future_flags, pathmatch
from babel._compat import PY2, text_type
from textwrap import dedent
@@ -399,6 +399,7 @@ def extract_python(fileobj, keywords, comment_tags, options):
comment_tag = None
encoding = parse_encoding(fileobj) or options.get('encoding', 'UTF-8')
+ future_flags = parse_future_flags(fileobj, encoding)
if PY2:
next_line = fileobj.readline
@@ -470,8 +471,9 @@ def extract_python(fileobj, keywords, comment_tags, options):
# encoding
# https://sourceforge.net/tracker/?func=detail&atid=355470&
# aid=617979&group_id=5470
- value = eval('# coding=%s\n%s' % (str(encoding), value),
- {'__builtins__': {}}, {})
+ code = compile('# coding=%s\n%s' % (str(encoding), value),
+ '<string>', 'eval', future_flags)
+ value = eval(code, {'__builtins__': {}}, {})
if PY2 and not isinstance(value, text_type):
value = value.decode(encoding)
buf.append(value)
diff --git a/babel/util.py b/babel/util.py
index aeb9a5f..996f902 100644
--- a/babel/util.py
+++ b/babel/util.py
@@ -95,6 +95,29 @@ def parse_encoding(fp):
fp.seek(pos)
+PYTHON_FUTURE_IMPORT_re = re.compile(
+ r'from\s+__future__\s+import\s+\(*(.+)\)*')
+
+
+def parse_future_flags(fp, encoding='latin-1'):
+ """Parse the compiler flags by :mod:`__future__` from the given Python
+ code.
+ """
+ import __future__
+ pos = fp.tell()
+ fp.seek(0)
+ flags = 0
+ try:
+ body = fp.read().decode(encoding)
+ for m in PYTHON_FUTURE_IMPORT_re.finditer(body):
+ names = [x.strip() for x in m.group(1).split(',')]
+ for name in names:
+ flags |= getattr(__future__, name).compiler_flag
+ finally:
+ fp.seek(pos)
+ return flags
+
+
def pathmatch(pattern, filename):
"""Extended pathname pattern matching.