aboutsummaryrefslogtreecommitdiff
path: root/setuptools/sandbox.py
diff options
context:
space:
mode:
Diffstat (limited to 'setuptools/sandbox.py')
-rw-r--r--[-rwxr-xr-x]setuptools/sandbox.py129
1 files changed, 84 insertions, 45 deletions
diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py
index 685f3f7..034fc80 100755..100644
--- a/setuptools/sandbox.py
+++ b/setuptools/sandbox.py
@@ -8,11 +8,11 @@ import re
import contextlib
import pickle
import textwrap
+import builtins
-from setuptools.extern import six
-from setuptools.extern.six.moves import builtins, map
-
-import pkg_resources.py31compat
+import pkg_resources
+from distutils.errors import DistutilsError
+from pkg_resources import working_set
if sys.platform.startswith('java'):
import org.python.modules.posix.PosixModule as _os
@@ -23,12 +23,13 @@ try:
except NameError:
_file = None
_open = open
-from distutils.errors import DistutilsError
-from pkg_resources import working_set
__all__ = [
- "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup",
+ "AbstractSandbox",
+ "DirectorySandbox",
+ "SandboxViolation",
+ "run_setup",
]
@@ -70,7 +71,7 @@ def override_temp(replacement):
"""
Monkey-patch tempfile.tempdir with replacement, ensuring it exists
"""
- pkg_resources.py31compat.makedirs(replacement, exist_ok=True)
+ os.makedirs(replacement, exist_ok=True)
saved = tempfile.tempdir
@@ -108,6 +109,7 @@ class UnpickleableException(Exception):
except Exception:
# get UnpickleableException inside the sandbox
from setuptools.sandbox import UnpickleableException as cls
+
return cls.dump(cls, cls(repr(exc)))
@@ -138,7 +140,7 @@ class ExceptionSaver:
return
type, exc = map(pickle.loads, self._saved)
- six.reraise(type, exc, self._tb)
+ raise exc.with_traceback(self._tb)
@contextlib.contextmanager
@@ -156,7 +158,8 @@ def save_modules():
sys.modules.update(saved)
# remove any modules imported since
del_modules = (
- mod_name for mod_name in sys.modules
+ mod_name
+ for mod_name in sys.modules
if mod_name not in saved
# exclude any encodings modules. See #285
and not mod_name.startswith('encodings.')
@@ -185,8 +188,8 @@ def setup_context(setup_dir):
temp_dir = os.path.join(setup_dir, 'temp')
with save_pkg_resources_state():
with save_modules():
- hide_setuptools()
with save_path():
+ hide_setuptools()
with save_argv():
with override_temp(temp_dir):
with pushd(setup_dir):
@@ -195,6 +198,15 @@ def setup_context(setup_dir):
yield
+_MODULES_TO_HIDE = {
+ 'setuptools',
+ 'distutils',
+ 'pkg_resources',
+ 'Cython',
+ '_distutils_hack',
+}
+
+
def _needs_hiding(mod_name):
"""
>>> _needs_hiding('setuptools')
@@ -212,8 +224,8 @@ def _needs_hiding(mod_name):
>>> _needs_hiding('Cython')
True
"""
- pattern = re.compile(r'(setuptools|pkg_resources|distutils|Cython)(\.|$)')
- return bool(pattern.match(mod_name))
+ base_module = mod_name.split('.', 1)[0]
+ return base_module in _MODULES_TO_HIDE
def hide_setuptools():
@@ -223,6 +235,10 @@ def hide_setuptools():
necessary to avoid issues such as #315 where setuptools upgrading itself
would fail to find a function declared in the metadata.
"""
+ _distutils_hack = sys.modules.get('_distutils_hack', None)
+ if _distutils_hack is not None:
+ _distutils_hack.remove_shim()
+
modules = filter(_needs_hiding, sys.modules)
_clear_modules(modules)
@@ -238,15 +254,8 @@ def run_setup(setup_script, args):
working_set.__init__()
working_set.callbacks.append(lambda dist: dist.activate())
- # __file__ should be a byte string on Python 2 (#712)
- dunder_file = (
- setup_script
- if isinstance(setup_script, str) else
- setup_script.encode(sys.getfilesystemencoding())
- )
-
with DirectorySandbox(setup_dir):
- ns = dict(__file__=dunder_file, __name__='__main__')
+ ns = dict(__file__=setup_script, __name__='__main__')
_execfile(setup_script, ns)
except SystemExit as v:
if v.args and v.args[0]:
@@ -261,7 +270,8 @@ class AbstractSandbox:
def __init__(self):
self._attrs = [
- name for name in dir(_os)
+ name
+ for name in dir(_os)
if not name.startswith('_') and hasattr(self, name)
]
@@ -316,9 +326,25 @@ class AbstractSandbox:
_file = _mk_single_path_wrapper('file', _file)
_open = _mk_single_path_wrapper('open', _open)
for name in [
- "stat", "listdir", "chdir", "open", "chmod", "chown", "mkdir",
- "remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat",
- "startfile", "mkfifo", "mknod", "pathconf", "access"
+ "stat",
+ "listdir",
+ "chdir",
+ "open",
+ "chmod",
+ "chown",
+ "mkdir",
+ "remove",
+ "unlink",
+ "rmdir",
+ "utime",
+ "lchown",
+ "chroot",
+ "lstat",
+ "startfile",
+ "mkfifo",
+ "mknod",
+ "pathconf",
+ "access",
]:
if hasattr(_os, name):
locals()[name] = _mk_single_path_wrapper(name)
@@ -369,12 +395,12 @@ class AbstractSandbox:
"""Called for path pairs like rename, link, and symlink operations"""
return (
self._remap_input(operation + '-from', src, *args, **kw),
- self._remap_input(operation + '-to', dst, *args, **kw)
+ self._remap_input(operation + '-to', dst, *args, **kw),
)
if hasattr(os, 'devnull'):
- _EXCEPTIONS = [os.devnull,]
+ _EXCEPTIONS = [os.devnull]
else:
_EXCEPTIONS = []
@@ -382,28 +408,38 @@ else:
class DirectorySandbox(AbstractSandbox):
"""Restrict operations to a single subdirectory - pseudo-chroot"""
- write_ops = dict.fromkeys([
- "open", "chmod", "chown", "mkdir", "remove", "unlink", "rmdir",
- "utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam",
- ])
+ write_ops = dict.fromkeys(
+ [
+ "open",
+ "chmod",
+ "chown",
+ "mkdir",
+ "remove",
+ "unlink",
+ "rmdir",
+ "utime",
+ "lchown",
+ "chroot",
+ "mkfifo",
+ "mknod",
+ "tempnam",
+ ]
+ )
- _exception_patterns = [
- # Allow lib2to3 to attempt to save a pickled grammar object (#121)
- r'.*lib2to3.*\.pickle$',
- ]
+ _exception_patterns = []
"exempt writing to paths that match the pattern"
def __init__(self, sandbox, exceptions=_EXCEPTIONS):
self._sandbox = os.path.normcase(os.path.realpath(sandbox))
self._prefix = os.path.join(self._sandbox, '')
self._exceptions = [
- os.path.normcase(os.path.realpath(path))
- for path in exceptions
+ os.path.normcase(os.path.realpath(path)) for path in exceptions
]
AbstractSandbox.__init__(self)
def _violation(self, operation, *args, **kw):
from setuptools.sandbox import SandboxViolation
+
raise SandboxViolation(operation, args, kw)
if _file:
@@ -436,12 +472,10 @@ class DirectorySandbox(AbstractSandbox):
def _exempted(self, filepath):
start_matches = (
- filepath.startswith(exception)
- for exception in self._exceptions
+ filepath.startswith(exception) for exception in self._exceptions
)
pattern_matches = (
- re.match(pattern, filepath)
- for pattern in self._exception_patterns
+ re.match(pattern, filepath) for pattern in self._exception_patterns
)
candidates = itertools.chain(start_matches, pattern_matches)
return any(candidates)
@@ -466,15 +500,19 @@ class DirectorySandbox(AbstractSandbox):
WRITE_FLAGS = functools.reduce(
- operator.or_, [getattr(_os, a, 0) for a in
- "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()]
+ operator.or_,
+ [
+ getattr(_os, a, 0)
+ for a in "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()
+ ],
)
class SandboxViolation(DistutilsError):
"""A setup script attempted to modify the filesystem outside the sandbox"""
- tmpl = textwrap.dedent("""
+ tmpl = textwrap.dedent(
+ """
SandboxViolation: {cmd}{args!r} {kwargs}
The package setup script has attempted to modify files on your system
@@ -484,7 +522,8 @@ class SandboxViolation(DistutilsError):
support alternate installation locations even if you run its setup
script by hand. Please inform the package's author and the EasyInstall
maintainers to find out if a fix or workaround is available.
- """).lstrip()
+ """
+ ).lstrip()
def __str__(self):
cmd, args, kwargs = self.args