Bug 1264831 - Work around issues with the exec statement in older python 2.7 versions. r?gps
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -23,20 +23,22 @@ from mozbuild.configure.options import (
PositiveOptionValue,
)
from mozbuild.configure.help import HelpFormatter
from mozbuild.configure.util import (
ConfigureOutputHandler,
LineIO,
)
from mozbuild.util import (
+ exec_,
memoize,
ReadOnlyDict,
ReadOnlyNamespace,
)
+
import mozpack.path as mozpath
class ConfigureError(Exception):
pass
class DependsFunction(object):
@@ -195,17 +197,17 @@ class ConfigureSandbox(dict):
'Cannot include `%s` because it was included already.' % path)
self._paths.append(path)
self._all_paths.add(path)
source = open(path, 'rb').read()
code = compile(source, path, 'exec')
- exec(code, self)
+ exec_(code, self)
self._paths.pop(-1)
def run(self, path=None):
'''Executes the given file within the sandbox, as well as everything
pending from any other included file, and ensure the overall
consistency of the executed script(s).'''
if path:
@@ -565,20 +567,17 @@ class ConfigureSandbox(dict):
# Until this proves to be a performance problem, just construct an
# import statement and execute it.
import_line = ''
if _from:
import_line += 'from %s ' % _from
import_line += 'import %s' % _import
if _as:
import_line += ' as %s' % _as
- # Some versions of python fail with "SyntaxError: unqualified exec
- # is not allowed in function '_apply_imports' it contains a nested
- # function with free variable" when using the exec function.
- exec import_line in {}, glob
+ exec_(import_line, {}, glob)
def _resolve_and_set(self, data, name, value):
# Don't set anything when --help was on the command line
if self._help:
return
name = self._resolve(name, need_help_dependency=False)
if name is None:
return
--- a/python/mozbuild/mozbuild/frontend/sandbox.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox.py
@@ -18,17 +18,20 @@ user-friendly error messages in the case
"""
from __future__ import absolute_import, unicode_literals
import os
import sys
import weakref
-from mozbuild.util import ReadOnlyDict
+from mozbuild.util import (
+ exec_,
+ ReadOnlyDict,
+)
from .context import Context
from mozpack.files import FileFinder
default_finder = FileFinder('/', find_executables=False)
def alphabetical_sorted(iterable, cmp=None, key=lambda x: x.lower(),
@@ -169,21 +172,17 @@ class Sandbox(dict):
# do want Unicode literals.
code = compile(source, path, 'exec')
# We use ourself as the global namespace for the execution. There
# is no need for a separate local namespace as moz.build execution
# is flat, namespace-wise.
old_source = self._current_source
self._current_source = source
try:
- # Ideally, we'd use exec(code, self), but that yield the
- # following error:
- # SyntaxError: unqualified exec is not allowed in function
- # 'execute' it is a nested function.
- exec code in self
+ exec_(code, self)
finally:
self._current_source = old_source
self.exec_function(execute, path=path)
def exec_function(self, func, args=(), kwargs={}, path='',
becomes_current_path=True):
"""Execute function with the given arguments in the sandbox.
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -1,16 +1,16 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
# This file contains miscellaneous utility functions that don't belong anywhere
# in particular.
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, unicode_literals, print_function
import argparse
import collections
import ctypes
import difflib
import errno
import functools
import hashlib
@@ -37,16 +37,32 @@ if sys.version_info[0] == 3:
else:
str_type = basestring
if sys.platform == 'win32':
_kernel32 = ctypes.windll.kernel32
_FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
+def exec_(object, globals=None, locals=None):
+ """Wrapper around the exec statement to avoid bogus errors like:
+
+ SyntaxError: unqualified exec is not allowed in function ...
+ it is a nested function.
+
+ or
+
+ SyntaxError: unqualified exec is not allowed in function ...
+ it contains a nested function with free variable
+
+ which happen with older versions of python 2.7.
+ """
+ exec(object, globals, locals)
+
+
def hash_file(path, hasher=None):
"""Hashes a file specified by the path given and returns the hex digest."""
# If the default hashing function changes, this may invalidate
# lots of cached data. Don't change it lightly.
h = hasher or hashlib.sha1()
with open(path, 'rb') as fh: