From 43e707381ef328a5e7cb251463edb391aec5fd32 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sun, 12 Jun 2005 01:12:34 +0000 Subject: Split setup-running and archive-extraction utilities into separate modules, for easy use by tools other than EasyInstall. --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041049 --- setuptools/sandbox.py | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100755 setuptools/sandbox.py (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py new file mode 100755 index 00000000..6407947c --- /dev/null +++ b/setuptools/sandbox.py @@ -0,0 +1,205 @@ +import os, sys, __builtin__ +_os = sys.modules[os.name] +_open = open + + +__all__ = [ + "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", +] + + +def run_setup(setup_script, *args): + """Run a distutils setup script, sandboxed in its directory""" + + old_dir = os.getcwd() + save_argv = sys.argv[:] + save_path = sys.path[:] + setup_dir = os.path.abspath(os.path.dirname(setup_script)) + + try: + os.chdir(setup_dir) + try: + sys.argv[:] = [setup_script]+list(args) + sys.path.insert(0, setup_dir) + DirectorySandbox(setup_dir).run( + lambda: execfile( + "setup.py", + {'__file__':setup_script, '__name__':'__main__'} + ) + ) + except SystemExit, v: + if v.args and v.args[0]: + raise + # Normal exit, just return + finally: + os.chdir(old_dir) + sys.path[:] = save_path + sys.argv[:] = save_argv + + + + +class AbstractSandbox: + """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" + + _active = False + + def __init__(self): + self._attrs = [ + name for name in dir(_os) + if not name.startswith('_') and hasattr(self,name) + ] + + def _copy(self, source): + for name in self._attrs: + setattr(os, name, getattr(source,name)) + + def run(self, func): + """Run 'func' under os sandboxing""" + try: + self._copy(self) + __builtin__.open = __builtin__.file = self._open + self._active = True + return func() + finally: + self._active = False + __builtin__.open = __builtin__.file = _open + self._copy(_os) + + + def _mk_dual_path_wrapper(name): + original = getattr(_os,name) + def wrap(self,src,dst,*args,**kw): + if self._active: + src,dst = self._remap_pair(name,src,dst,*args,**kw) + return original(src,dst,*args,**kw) + return wrap + + + for name in ["rename", "link", "symlink"]: + if hasattr(_os,name): locals()[name] = _mk_dual_path_wrapper(name) + + + def _mk_single_path_wrapper(name, original=None): + original = original or getattr(_os,name) + def wrap(self,path,*args,**kw): + if self._active: + path = self._remap_input(name,path,*args,**kw) + return original(path,*args,**kw) + return wrap + + _open = _mk_single_path_wrapper('file', _open) + for name in [ + "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) + + + def _mk_single_with_return(name): + original = getattr(_os,name) + def wrap(self,path,*args,**kw): + if self._active: + path = self._remap_input(name,path,*args,**kw) + return self._remap_output(name, original(path,*args,**kw)) + return original(path,*args,**kw) + return wrap + + for name in ['readlink', 'tempnam']: + if hasattr(_os,name): locals()[name] = _mk_single_with_return(name) + + def _mk_query(name): + original = getattr(_os,name) + def wrap(self,*args,**kw): + retval = original(*args,**kw) + if self._active: + return self._remap_output(name, retval) + return retval + return wrap + + for name in ['getcwd', 'tmpnam']: + if hasattr(_os,name): locals()[name] = _mk_query(name) + + def _validate_path(self,path): + """Called to remap or validate any path, whether input or output""" + return path + + def _remap_input(self,operation,path,*args,**kw): + """Called for path inputs""" + return self._validate_path(path) + + def _remap_output(self,operation,path): + """Called for path outputs""" + return self._validate_path(path) + + def _remap_pair(self,operation,src,dst,*args,**kw): + """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) + ) + + +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", + ]) + + def __init__(self,sandbox): + self._sandbox = os.path.realpath(sandbox) + self._prefix = os.path.join(self._sandbox,'') + AbstractSandbox.__init__(self) + + def _violation(self, operation, *args, **kw): + raise SandboxViolation(operation, args, kw) + + def _open(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU') and not self._ok(path): + self._violation("open", path, mode, *args, **kw) + return _open(path,mode,*args,**kw) + + def tmpnam(self): + self._violation("tmpnam") + + def _ok(self,path): + active = self._active + try: + self._active = False + realpath = os.path.realpath(path) + if realpath==self._sandbox or realpath.startswith(self._prefix): + return True + finally: + self._active = active + + def _remap_input(self,operation,path,*args,**kw): + """Called for path inputs""" + if operation in self.write_ops and not self._ok(path): + self._violation(operation, os.path.realpath(path), *args, **kw) + return path + + def _remap_pair(self,operation,src,dst,*args,**kw): + """Called for path pairs like rename, link, and symlink operations""" + if not self._ok(src) or not self._ok(dst): + self._violation(operation, src, dst, *args, **kw) + return (src,dst) + + +class SandboxViolation(RuntimeError): + """A setup script attempted to modify the filesystem outside the sandbox""" + + def __str__(self): + return """SandboxViolation: %s%r %s + +The package setup script has attempted to modify files on your system +that are not within the EasyInstall build area, and has been aborted. + +This package cannot be safely installed by EasyInstall, and may not +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.""" % self.args + + -- cgit v1.2.1 From 449f35743f5d0bc97ebfdba00bb8e7acc79465af Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sun, 12 Jun 2005 03:07:53 +0000 Subject: Rebalance responsibilities between PackageIndex, Installer, and main() so that PackageIndex handles all downloading of any kind, Installers can be reused for multiple packages, and main() manages temporary directories and all communication between PackageIndex and Installer. Also, change run_setup to take an argument sequence, because later we will probably need other arguments to control other aspects of run_setup's behavior. --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041050 --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 6407947c..0e6f5964 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -8,7 +8,7 @@ __all__ = [ ] -def run_setup(setup_script, *args): +def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" old_dir = os.getcwd() -- cgit v1.2.1 From 5ed7f988bca676d52388b7d0db6e540bfd1476f7 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sat, 25 Jun 2005 19:33:06 +0000 Subject: 0.5a3 bugfix release --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041072 --- setuptools/sandbox.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 0e6f5964..8aa58f8d 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,13 +1,11 @@ -import os, sys, __builtin__ +import os, sys, __builtin__, tempfile _os = sys.modules[os.name] _open = open - __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] - def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" @@ -15,8 +13,12 @@ def run_setup(setup_script, args): save_argv = sys.argv[:] save_path = sys.path[:] setup_dir = os.path.abspath(os.path.dirname(setup_script)) + temp_dir = os.path.join(setup_dir,'temp') + if not os.path.isdir(temp_dir): os.makedirs(temp_dir) + save_tmp = tempfile.tempdir try: + tempfile.tempdir = temp_dir os.chdir(setup_dir) try: sys.argv[:] = [setup_script]+list(args) @@ -35,9 +37,7 @@ def run_setup(setup_script, args): os.chdir(old_dir) sys.path[:] = save_path sys.argv[:] = save_argv - - - + tempfile.tempdir = save_tmp class AbstractSandbox: """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" -- cgit v1.2.1 From 451377d0e877fc610d1bdf8181ba70a90e4c14cc Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sun, 10 Jul 2005 04:49:31 +0000 Subject: Detect and handle conflicts with "unmanaged" packages when installing packages managed by EasyInstall. Also, add an option to exclude source files from .egg distributions. --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041109 --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 8aa58f8d..f124289a 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,7 +1,7 @@ import os, sys, __builtin__, tempfile _os = sys.modules[os.name] _open = open - +from distutils.errors import DistutilsError __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] @@ -188,7 +188,7 @@ class DirectorySandbox(AbstractSandbox): return (src,dst) -class SandboxViolation(RuntimeError): +class SandboxViolation(DistutilsError): """A setup script attempted to modify the filesystem outside the sandbox""" def __str__(self): -- cgit v1.2.1 From 20851ca9363b0fded18d42c3bd0f2dd2105f5093 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sun, 24 Jul 2005 02:38:20 +0000 Subject: Fixed the setup script sandbox facility not recognizing certain paths as valid on case-insensitive platforms. --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041146 --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index f124289a..dbc24ede 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -150,7 +150,7 @@ class DirectorySandbox(AbstractSandbox): ]) def __init__(self,sandbox): - self._sandbox = os.path.realpath(sandbox) + self._sandbox = os.path.normcase(os.path.realpath(sandbox)) self._prefix = os.path.join(self._sandbox,'') AbstractSandbox.__init__(self) @@ -169,7 +169,7 @@ class DirectorySandbox(AbstractSandbox): active = self._active try: self._active = False - realpath = os.path.realpath(path) + realpath = os.path.normcase(os.path.realpath(path)) if realpath==self._sandbox or realpath.startswith(self._prefix): return True finally: -- cgit v1.2.1 From 3f6ffbc76c79adac2905221aef8f03bef28999f7 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Fri, 21 Apr 2006 17:40:38 +0000 Subject: Recognize 'U' as a valid read-only mode for open() --HG-- branch : setuptools-0.6 extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/branches/setuptools-0.6%4045629 --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index dbc24ede..d4131e62 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -158,7 +158,7 @@ class DirectorySandbox(AbstractSandbox): raise SandboxViolation(operation, args, kw) def _open(self, path, mode='r', *args, **kw): - if mode not in ('r', 'rt', 'rb', 'rU') and not self._ok(path): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): self._violation("open", path, mode, *args, **kw) return _open(path,mode,*args,**kw) -- cgit v1.2.1 From 3abf8f8b8c886bdbcb28261ced7010f6cc88256f Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Tue, 24 Oct 2006 18:37:04 +0000 Subject: Fixed not allowing ``os.open()`` of paths outside the sandbox, even if they are opened read-only (e.g. reading ``/dev/urandom`` for random numbers, as is done by ``os.urandom()`` on some platforms). (backport from trunk) --HG-- branch : setuptools-0.6 extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/branches/setuptools-0.6%4052438 --- setuptools/sandbox.py | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index d4131e62..3874a4f9 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,4 +1,4 @@ -import os, sys, __builtin__, tempfile +import os, sys, __builtin__, tempfile, operator _os = sys.modules[os.name] _open = open from distutils.errors import DistutilsError @@ -187,6 +187,21 @@ class DirectorySandbox(AbstractSandbox): self._violation(operation, src, dst, *args, **kw) return (src,dst) + def open(self, file, flags, mode=0777): + """Called for low-level os.open()""" + if flags & WRITE_FLAGS: + self._violation("open", file, flags, mode) + return _os.open(file,flags,mode) + + +WRITE_FLAGS = reduce( + 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""" @@ -203,3 +218,29 @@ script by hand. Please inform the package's author and the EasyInstall maintainers to find out if a fix or workaround is available.""" % self.args + + + + + + + + + + + + + + + + + + + + + + + + + +# -- cgit v1.2.1 From 981bc8e3da37dda70f06d59b81b4dc694f1c48df Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sat, 30 Dec 2006 03:06:57 +0000 Subject: Fix os.open() sandboxing code that refused anything but read-only access. (backport from trunk) --HG-- branch : setuptools-0.6 extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/branches/setuptools-0.6%4053199 --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 3874a4f9..4db0dbdb 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -189,8 +189,8 @@ class DirectorySandbox(AbstractSandbox): def open(self, file, flags, mode=0777): """Called for low-level os.open()""" - if flags & WRITE_FLAGS: - self._violation("open", file, flags, mode) + if flags & WRITE_FLAGS and not self._ok(file): + self._violation("os.open", file, flags, mode) return _os.open(file,flags,mode) -- cgit v1.2.1 From 457f95783acaed3c59668b6c6bf93414c4f1967b Mon Sep 17 00:00:00 2001 From: Hanno Schlichting Date: Thu, 16 Jul 2009 17:39:16 +0200 Subject: Applied patch from pjenvey. This closes #6. --HG-- branch : distribute extra : rebase_source : 96ce51b3a70155a8b87de8ed0f72de8e12a7a27c --- setuptools/sandbox.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 4db0dbdb..97865dd9 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,5 +1,6 @@ import os, sys, __builtin__, tempfile, operator _os = sys.modules[os.name] +_file = file _open = open from distutils.errors import DistutilsError __all__ = [ @@ -58,12 +59,14 @@ class AbstractSandbox: """Run 'func' under os sandboxing""" try: self._copy(self) - __builtin__.open = __builtin__.file = self._open + __builtin__.file = self._file + __builtin__.open = self._open self._active = True return func() finally: self._active = False - __builtin__.open = __builtin__.file = _open + __builtin__.file = _file + __builtin__.open = _open self._copy(_os) @@ -88,7 +91,8 @@ class AbstractSandbox: return original(path,*args,**kw) return wrap - _open = _mk_single_path_wrapper('file', _open) + _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", -- cgit v1.2.1 From d7db8bf8f402130e3ce49603ead50de5f7a4d6b2 Mon Sep 17 00:00:00 2001 From: Hanno Schlichting Date: Fri, 17 Jul 2009 14:49:13 +0200 Subject: Packages required at build time where not fully present at install time. This closes #12. --HG-- branch : distribute extra : rebase_source : 178f508c83ecab9244064108d55ce840111a0e34 --- setuptools/sandbox.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 97865dd9..11c14938 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -6,10 +6,8 @@ from distutils.errors import DistutilsError __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] - def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" - old_dir = os.getcwd() save_argv = sys.argv[:] save_path = sys.path[:] @@ -17,7 +15,7 @@ def run_setup(setup_script, args): temp_dir = os.path.join(setup_dir,'temp') if not os.path.isdir(temp_dir): os.makedirs(temp_dir) save_tmp = tempfile.tempdir - + save_modules = sys.modules.copy() try: tempfile.tempdir = temp_dir os.chdir(setup_dir) @@ -35,6 +33,9 @@ def run_setup(setup_script, args): raise # Normal exit, just return finally: + sys.modules.update(save_modules) + for key in list(sys.modules): + if key not in save_modules: del sys.modules[key] os.chdir(old_dir) sys.path[:] = save_path sys.argv[:] = save_argv -- cgit v1.2.1 From 96c97c7b38ffe815a6f1cc6e76fea1d627610d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 11 Sep 2009 23:50:28 +0200 Subject: Conditionalize _file processing. --HG-- branch : distribute extra : rebase_source : fd07ce0e0541a269a88596e985884f688c86185e --- setuptools/sandbox.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 11c14938..67cedde6 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,6 +1,9 @@ import os, sys, __builtin__, tempfile, operator _os = sys.modules[os.name] -_file = file +try: + _file = file +except NameError: + _file = None _open = open from distutils.errors import DistutilsError __all__ = [ @@ -60,13 +63,15 @@ class AbstractSandbox: """Run 'func' under os sandboxing""" try: self._copy(self) - __builtin__.file = self._file + if _file: + __builtin__.file = self._file __builtin__.open = self._open self._active = True return func() finally: self._active = False - __builtin__.file = _file + if _file: + __builtin__.file = _file __builtin__.open = _open self._copy(_os) @@ -92,7 +97,8 @@ class AbstractSandbox: return original(path,*args,**kw) return wrap - _file = _mk_single_path_wrapper('file', _file) + if _file: + _file = _mk_single_path_wrapper('file', _file) _open = _mk_single_path_wrapper('open', _open) for name in [ "stat", "listdir", "chdir", "open", "chmod", "chown", "mkdir", -- cgit v1.2.1 From 7ed4be906cc7195c4d15bdd7a8b2bfa8474cc6be Mon Sep 17 00:00:00 2001 From: Philip Jenvey Date: Mon, 12 Oct 2009 14:47:40 -0700 Subject: fix a hole in sandboxing allowing builtin file to write outside of the sandbox --HG-- branch : distribute extra : rebase_source : 5ff181b30f41080ec0e0628c96abf270ffe1a730 --- setuptools/sandbox.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 67cedde6..7b487833 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -168,6 +168,12 @@ class DirectorySandbox(AbstractSandbox): def _violation(self, operation, *args, **kw): raise SandboxViolation(operation, args, kw) + if _file: + def _file(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): + self._violation("file", path, mode, *args, **kw) + return _file(path,mode,*args,**kw) + def _open(self, path, mode='r', *args, **kw): if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): self._violation("open", path, mode, *args, **kw) -- cgit v1.2.1 From f7279ede282b895e789b05ababb65ba4f6436160 Mon Sep 17 00:00:00 2001 From: tarek Date: Fri, 4 Dec 2009 11:20:36 +0100 Subject: Allowing 'os.devnull' in Sandbox, fixes #101 --HG-- branch : distribute extra : rebase_source : d6f63794621874eb637139f353314256e02e02df --- setuptools/sandbox.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 7b487833..502598ca 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -152,6 +152,8 @@ class AbstractSandbox: ) +_EXCEPTIONS = [os.devnull,] + class DirectorySandbox(AbstractSandbox): """Restrict operations to a single subdirectory - pseudo-chroot""" @@ -160,9 +162,10 @@ class DirectorySandbox(AbstractSandbox): "utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam", ]) - def __init__(self,sandbox): + def __init__(self, sandbox, exceptions=_EXCEPTIONS): self._sandbox = os.path.normcase(os.path.realpath(sandbox)) self._prefix = os.path.join(self._sandbox,'') + self._exceptions = exceptions AbstractSandbox.__init__(self) def _violation(self, operation, *args, **kw): @@ -187,7 +190,8 @@ class DirectorySandbox(AbstractSandbox): try: self._active = False realpath = os.path.normcase(os.path.realpath(path)) - if realpath==self._sandbox or realpath.startswith(self._prefix): + if (realpath in self._exceptions or realpath == self._sandbox + or realpath.startswith(self._prefix)): return True finally: self._active = active -- cgit v1.2.1 From 2cb36ad98366b3cad72f2be6b7a55fb51b43677c Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 2 Mar 2010 18:02:00 -0500 Subject: Worked out a fix for failing sandbox errors in Windows. Fixes #118. --HG-- branch : distribute extra : rebase_source : 69c8e59604f9d711cd29bb55e9edd3caab2b36a0 --- setuptools/sandbox.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 502598ca..630d5792 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -154,6 +154,12 @@ class AbstractSandbox: _EXCEPTIONS = [os.devnull,] +try: + gen_py = os.path.dirname(__import__('win32com.gen_py', fromlist=['__name__']).__file__) + _EXCEPTIONS.append(gen_py) +except ImportError: + pass + class DirectorySandbox(AbstractSandbox): """Restrict operations to a single subdirectory - pseudo-chroot""" @@ -165,7 +171,7 @@ class DirectorySandbox(AbstractSandbox): def __init__(self, sandbox, exceptions=_EXCEPTIONS): self._sandbox = os.path.normcase(os.path.realpath(sandbox)) self._prefix = os.path.join(self._sandbox,'') - self._exceptions = exceptions + self._exceptions = [os.path.normcase(os.path.realpath(path)) for path in exceptions] AbstractSandbox.__init__(self) def _violation(self, operation, *args, **kw): @@ -190,12 +196,16 @@ class DirectorySandbox(AbstractSandbox): try: self._active = False realpath = os.path.normcase(os.path.realpath(path)) - if (realpath in self._exceptions or realpath == self._sandbox + if (self._exempted(realpath) or realpath == self._sandbox or realpath.startswith(self._prefix)): return True finally: self._active = active + def _exempted(self, filepath): + exception_matches = map(filepath.startswith, self._exceptions) + return any(exception_matches) + def _remap_input(self,operation,path,*args,**kw): """Called for path inputs""" if operation in self.write_ops and not self._ok(path): -- cgit v1.2.1 From 6a6a261fa50522d77fba6d6345fb71ba9f00c311 Mon Sep 17 00:00:00 2001 From: Tarek Ziade Date: Thu, 6 May 2010 18:10:32 +0200 Subject: make sure all tests passes on all python versions fixes #149 --HG-- branch : distribute extra : rebase_source : 6288f4fcf65083b9d4ffb0ea8b35af44e699b4d5 --- setuptools/sandbox.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 630d5792..13cbe109 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -152,13 +152,18 @@ class AbstractSandbox: ) -_EXCEPTIONS = [os.devnull,] +if hasattr(os, 'devnull'): + _EXCEPTIONS = [os.devnull,] +else: + _EXCEPTIONS = [] -try: - gen_py = os.path.dirname(__import__('win32com.gen_py', fromlist=['__name__']).__file__) - _EXCEPTIONS.append(gen_py) -except ImportError: - pass +if not sys.version < '2.5': + try: + gen_py = os.path.dirname(__import__('win32com.gen_py', + fromlist=['__name__']).__file__) + _EXCEPTIONS.append(gen_py) + except ImportError: + pass class DirectorySandbox(AbstractSandbox): """Restrict operations to a single subdirectory - pseudo-chroot""" @@ -204,7 +209,7 @@ class DirectorySandbox(AbstractSandbox): def _exempted(self, filepath): exception_matches = map(filepath.startswith, self._exceptions) - return any(exception_matches) + return False not in exception_matches def _remap_input(self,operation,path,*args,**kw): """Called for path inputs""" -- cgit v1.2.1 From 6695e537c69743d1ef1b0e2c62b7bc7734e66446 Mon Sep 17 00:00:00 2001 From: Tarek Ziade Date: Thu, 6 May 2010 18:14:53 +0200 Subject: we want any(), not all() --HG-- branch : distribute extra : rebase_source : c740917424bbc5efdfb91360399f1f17a09ea3a1 --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 13cbe109..c2f14e7f 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -209,7 +209,7 @@ class DirectorySandbox(AbstractSandbox): def _exempted(self, filepath): exception_matches = map(filepath.startswith, self._exceptions) - return False not in exception_matches + return True in exception_matches def _remap_input(self,operation,path,*args,**kw): """Called for path inputs""" -- cgit v1.2.1 From 4353f3f6eaabc04859bcbd592c58df985bd2ad3b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 15 May 2010 07:24:02 -1000 Subject: Fix for #151 - attribute error when gen_py doesn't have __init__ module --HG-- branch : distribute extra : rebase_source : 6d42ed6e7f4d1ab4500aa8a695ee64af6a3f63f8 --- setuptools/sandbox.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 630d5792..b2ae991f 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -155,9 +155,14 @@ class AbstractSandbox: _EXCEPTIONS = [os.devnull,] try: - gen_py = os.path.dirname(__import__('win32com.gen_py', fromlist=['__name__']).__file__) - _EXCEPTIONS.append(gen_py) + win32com_pkg = os.path.dirname(__import__('win32com').__file__) + gen_py_pkg = os.path.join(win32com_pkg, 'gen_py') + _EXCEPTIONS.append(gen_py_pkg) except ImportError: + # it appears pywin32 is not installed, so no need to exclude. + pass +except AttributeError: + # unexpected error getting __file__ from win32com pass class DirectorySandbox(AbstractSandbox): -- cgit v1.2.1 From 50900e7b3129467091d7fb03a716755fcf0b0c52 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 15 May 2010 11:01:24 -1000 Subject: Updated gen_py exception to use attribute of win32com rather than infer the location of gen_py --HG-- branch : distribute extra : rebase_source : 55f1f3c23dc20edf9c91ea223fc5762fda22f5b2 --- setuptools/sandbox.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 37fc60af..0d6724d1 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -158,14 +158,13 @@ else: _EXCEPTIONS = [] try: - win32com_pkg = os.path.dirname(__import__('win32com').__file__) - gen_py_pkg = os.path.join(win32com_pkg, 'gen_py') - _EXCEPTIONS.append(gen_py_pkg) + import win32com + _EXCEPTIONS.append(win32com.__gen_path__) except ImportError: # it appears pywin32 is not installed, so no need to exclude. pass except AttributeError: - # unexpected error getting __file__ from win32com + # it appears __gen_path__ is not available, so fail silently pass class DirectorySandbox(AbstractSandbox): -- cgit v1.2.1 From 1569d2e22e7e7aa897eaa3ff1c9f2d7a2d5f581a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 15 May 2010 11:23:22 -1000 Subject: Found a public API method which is preferable to using the private attribute for ascertaining the location of the gen_py cache --HG-- branch : distribute extra : rebase_source : 6feed4430505ad2d2680b141d41dccb95d9e80af --- setuptools/sandbox.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 0d6724d1..a06d4483 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -158,14 +158,12 @@ else: _EXCEPTIONS = [] try: - import win32com - _EXCEPTIONS.append(win32com.__gen_path__) + from win32com.client.gencache import GetGeneratePath + _EXCEPTIONS.append(GetGeneratePath()) + del GetGeneratePath except ImportError: # it appears pywin32 is not installed, so no need to exclude. pass -except AttributeError: - # it appears __gen_path__ is not available, so fail silently - pass class DirectorySandbox(AbstractSandbox): """Restrict operations to a single subdirectory - pseudo-chroot""" -- cgit v1.2.1 From 38ac54038c96d339f55a66af6ad8da20320ff411 Mon Sep 17 00:00:00 2001 From: Erik Bray Date: Fri, 20 May 2011 16:08:26 -0400 Subject: Adds some missing bits to the sandbox fix--need to actually save/restore the pkg_resources state. --HG-- branch : distribute extra : rebase_source : 961ca56f30a6aabb5d24eff3cabb527d1be93ae4 --- setuptools/sandbox.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index a06d4483..8e0c09b5 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,4 +1,4 @@ -import os, sys, __builtin__, tempfile, operator +import os, sys, __builtin__, tempfile, operator, pkg_resources _os = sys.modules[os.name] try: _file = file @@ -19,6 +19,7 @@ def run_setup(setup_script, args): if not os.path.isdir(temp_dir): os.makedirs(temp_dir) save_tmp = tempfile.tempdir save_modules = sys.modules.copy() + pr_state = pkg_resources.__getstate__() try: tempfile.tempdir = temp_dir os.chdir(setup_dir) @@ -36,6 +37,7 @@ def run_setup(setup_script, args): raise # Normal exit, just return finally: + pkg_resources.__setstate__(pr_state) sys.modules.update(save_modules) for key in list(sys.modules): if key not in save_modules: del sys.modules[key] -- cgit v1.2.1 From 58a658b26d1c95b31d02050dcccd648d2e4ce27b Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Mon, 20 Jun 2011 22:55:16 +0100 Subject: Changes to support 2.x and 3.x in the same codebase. --HG-- branch : distribute extra : rebase_source : 7d3608edee54a43789f0574d702fb839628b5071 --- setuptools/sandbox.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 8e0c09b5..41f1119b 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,4 +1,4 @@ -import os, sys, __builtin__, tempfile, operator, pkg_resources +import os, sys, tempfile, operator, pkg_resources _os = sys.modules[os.name] try: _file = file @@ -6,6 +6,8 @@ except NameError: _file = None _open = open from distutils.errors import DistutilsError +from setuptools.compat import builtins, execfile, reduce + __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] @@ -32,7 +34,8 @@ def run_setup(setup_script, args): {'__file__':setup_script, '__name__':'__main__'} ) ) - except SystemExit, v: + except SystemExit: + v = sys.exc_info()[1] if v.args and v.args[0]: raise # Normal exit, just return @@ -66,15 +69,15 @@ class AbstractSandbox: try: self._copy(self) if _file: - __builtin__.file = self._file - __builtin__.open = self._open + builtins.file = self._file + builtins.open = self._open self._active = True return func() finally: self._active = False if _file: - __builtin__.file = _file - __builtin__.open = _open + builtins.file = _file + builtins.open = _open self._copy(_os) @@ -225,7 +228,7 @@ class DirectorySandbox(AbstractSandbox): self._violation(operation, src, dst, *args, **kw) return (src,dst) - def open(self, file, flags, mode=0777): + def open(self, file, flags, mode=0x1FF): # 0777 """Called for low-level os.open()""" if flags & WRITE_FLAGS and not self._ok(file): self._violation("os.open", file, flags, mode) -- cgit v1.2.1 From f568de0c10f5d67ef9a91b8609997dbdf4ecce3d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 18 May 2012 15:03:48 -0400 Subject: Exclude 'encodings' modules when removing modules from sys.modules. Workaround for #285. (Fixes #285) --HG-- branch : distribute extra : rebase_source : 913eaebbb0971a044d6087dc4faa2fdb4220def2 --- setuptools/sandbox.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 8e0c09b5..ab2543d9 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -39,8 +39,14 @@ def run_setup(setup_script, args): finally: pkg_resources.__setstate__(pr_state) sys.modules.update(save_modules) - for key in list(sys.modules): - if key not in save_modules: del sys.modules[key] + # remove any modules imported within the sandbox + del_modules = [ + mod_name for mod_name in sys.modules + if mod_name not in save_modules + # exclude any encodings modules. See #285 + and not mod_name.startswith('encodings.') + ] + map(sys.modules.__delitem__, del_modules) os.chdir(old_dir) sys.path[:] = save_path sys.argv[:] = save_argv -- cgit v1.2.1 From d847dbfeee2b2c85d7bc0a66813c33836a9850fa Mon Sep 17 00:00:00 2001 From: Erik Bray Date: Thu, 6 Sep 2012 15:51:09 -0400 Subject: Adds a fix for issue #318, including a regression test. This also fixes another test that was passing trivially due to *bug* in yet another test, ugh --HG-- branch : distribute extra : rebase_source : 476550766b7b756dced040ad4356b7685d6f062a --- setuptools/sandbox.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index ab2543d9..64f725e7 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -166,12 +166,12 @@ else: _EXCEPTIONS = [] try: - from win32com.client.gencache import GetGeneratePath - _EXCEPTIONS.append(GetGeneratePath()) - del GetGeneratePath + from win32com.client.gencache import GetGeneratePath + _EXCEPTIONS.append(GetGeneratePath()) + del GetGeneratePath except ImportError: - # it appears pywin32 is not installed, so no need to exclude. - pass + # it appears pywin32 is not installed, so no need to exclude. + pass class DirectorySandbox(AbstractSandbox): """Restrict operations to a single subdirectory - pseudo-chroot""" -- cgit v1.2.1 From 3b6b1d147dae6ba825d0597d88abfda4cc3d295a Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Mon, 26 Nov 2012 22:24:45 +0100 Subject: Fix 2 errors with Jython 2.5. (Now there remain 1 failure and 2 errors with Jython 2.5 and 1 failure and 5 errors with Jython 2.7.) --HG-- branch : distribute extra : rebase_source : c245820df5090ac5d005ebb7d6c4419145afce53 --- setuptools/sandbox.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 64f725e7..1583b81f 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,5 +1,8 @@ import os, sys, __builtin__, tempfile, operator, pkg_resources -_os = sys.modules[os.name] +if os.name == "java": + import org.python.modules.posix.PosixModule as _os +else: + _os = sys.modules[os.name] try: _file = file except NameError: -- cgit v1.2.1 From 6b9f1df35359a8a7b43975b32ee79d8f7259d8c8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 20 Mar 2013 11:01:29 -0700 Subject: Update sandbox.py to latest from setuptools-0.6 --HG-- branch : Setuptools-Distribute merge extra : source : 7f4dd650af5779b69ae13fe6a1b4adce386b5489 --- setuptools/sandbox.py | 79 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 19 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 4db0dbdb..4c5e7129 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,14 +1,46 @@ -import os, sys, __builtin__, tempfile, operator +import os, sys, __builtin__, tempfile, operator, pkg_resources _os = sys.modules[os.name] _open = open +_file = file + from distutils.errors import DistutilsError +from pkg_resources import working_set + __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" - old_dir = os.getcwd() save_argv = sys.argv[:] save_path = sys.path[:] @@ -16,13 +48,16 @@ def run_setup(setup_script, args): temp_dir = os.path.join(setup_dir,'temp') if not os.path.isdir(temp_dir): os.makedirs(temp_dir) save_tmp = tempfile.tempdir - + save_modules = sys.modules.copy() + pr_state = pkg_resources.__getstate__() try: - tempfile.tempdir = temp_dir - os.chdir(setup_dir) + tempfile.tempdir = temp_dir; os.chdir(setup_dir) try: sys.argv[:] = [setup_script]+list(args) sys.path.insert(0, setup_dir) + # reset to include setup dir, w/clean callback list + working_set.__init__() + working_set.callbacks.append(lambda dist:dist.activate()) DirectorySandbox(setup_dir).run( lambda: execfile( "setup.py", @@ -34,11 +69,17 @@ def run_setup(setup_script, args): raise # Normal exit, just return finally: + pkg_resources.__setstate__(pr_state) + sys.modules.update(save_modules) + for key in list(sys.modules): + if key not in save_modules: del sys.modules[key] os.chdir(old_dir) sys.path[:] = save_path sys.argv[:] = save_argv tempfile.tempdir = save_tmp + + class AbstractSandbox: """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" @@ -58,15 +99,16 @@ class AbstractSandbox: """Run 'func' under os sandboxing""" try: self._copy(self) - __builtin__.open = __builtin__.file = self._open + __builtin__.file = self._file + __builtin__.open = self._open self._active = True return func() finally: self._active = False - __builtin__.open = __builtin__.file = _open + __builtin__.open = _open + __builtin__.file = _file self._copy(_os) - def _mk_dual_path_wrapper(name): original = getattr(_os,name) def wrap(self,src,dst,*args,**kw): @@ -75,7 +117,6 @@ class AbstractSandbox: return original(src,dst,*args,**kw) return wrap - for name in ["rename", "link", "symlink"]: if hasattr(_os,name): locals()[name] = _mk_dual_path_wrapper(name) @@ -88,7 +129,8 @@ class AbstractSandbox: return original(path,*args,**kw) return wrap - _open = _mk_single_path_wrapper('file', _open) + _open = _mk_single_path_wrapper('open', _open) + _file = _mk_single_path_wrapper('file', _file) for name in [ "stat", "listdir", "chdir", "open", "chmod", "chown", "mkdir", "remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat", @@ -96,7 +138,6 @@ class AbstractSandbox: ]: if hasattr(_os,name): locals()[name] = _mk_single_path_wrapper(name) - def _mk_single_with_return(name): original = getattr(_os,name) def wrap(self,path,*args,**kw): @@ -162,10 +203,10 @@ class DirectorySandbox(AbstractSandbox): self._violation("open", path, mode, *args, **kw) return _open(path,mode,*args,**kw) - def tmpnam(self): - self._violation("tmpnam") + def tmpnam(self): self._violation("tmpnam") def _ok(self,path): + if hasattr(_os,'devnull') and path==_os.devnull: return True active = self._active try: self._active = False @@ -187,22 +228,22 @@ class DirectorySandbox(AbstractSandbox): self._violation(operation, src, dst, *args, **kw) return (src,dst) + def _file(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): + self._violation("file", path, mode, *args, **kw) + return _file(path,mode,*args,**kw) + def open(self, file, flags, mode=0777): """Called for low-level os.open()""" if flags & WRITE_FLAGS and not self._ok(file): self._violation("os.open", file, flags, mode) return _os.open(file,flags,mode) - WRITE_FLAGS = reduce( - operator.or_, - [getattr(_os, a, 0) for a in + 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""" -- cgit v1.2.1 From ac16aa2d54815d3e805c60a38afa5f4c9f3d282f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 16 May 2013 08:17:22 -0400 Subject: Remove redundant exception for os.devnull --HG-- branch : Setuptools-Distribute merge --- setuptools/sandbox.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index e026ff13..f3095125 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -61,7 +61,7 @@ def run_setup(setup_script, args): sys.argv[:] = [setup_script]+list(args) sys.path.insert(0, setup_dir) # reset to include setup dir, w/clean callback list - working_set.__init__() + working_set.__init__() working_set.callbacks.append(lambda dist:dist.activate()) DirectorySandbox(setup_dir).run( lambda: execfile( @@ -241,7 +241,6 @@ class DirectorySandbox(AbstractSandbox): self._violation("tmpnam") def _ok(self,path): - if hasattr(_os,'devnull') and path==_os.devnull: return True active = self._active try: self._active = False -- cgit v1.2.1 From 8e657eac1ef02faedca99df319fff6b63f4a4305 Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Sat, 15 Jun 2013 15:34:53 +0100 Subject: Initial commit. All tests pass on 2.7, 3.2 and 3.3, though there are some atexit errors in the multiprocessing module in 2.7/3.2 (seemingly unrelated to setuptools). --HG-- branch : single-codebase --- setuptools/sandbox.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index f3095125..090cb34c 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,4 +1,4 @@ -import os, sys, __builtin__, tempfile, operator, pkg_resources +import os, sys, tempfile, operator, pkg_resources if os.name == "java": import org.python.modules.posix.PosixModule as _os else: @@ -9,6 +9,7 @@ except NameError: _file = None _open = open from distutils.errors import DistutilsError +from setuptools.compat import builtins, execfile, reduce from pkg_resources import working_set __all__ = [ @@ -69,7 +70,8 @@ def run_setup(setup_script, args): {'__file__':setup_script, '__name__':'__main__'} ) ) - except SystemExit, v: + except SystemExit: + v = sys.exc_info()[1] if v.args and v.args[0]: raise # Normal exit, just return @@ -111,15 +113,15 @@ class AbstractSandbox: try: self._copy(self) if _file: - __builtin__.file = self._file - __builtin__.open = self._open + builtins.file = self._file + builtins.open = self._open self._active = True return func() finally: self._active = False if _file: - __builtin__.file = _file - __builtin__.open = _open + builtins.file = _file + builtins.open = _open self._copy(_os) def _mk_dual_path_wrapper(name): @@ -267,7 +269,7 @@ class DirectorySandbox(AbstractSandbox): self._violation(operation, src, dst, *args, **kw) return (src,dst) - def open(self, file, flags, mode=0777): + def open(self, file, flags, mode=0x1FF): # 0777 """Called for low-level os.open()""" if flags & WRITE_FLAGS and not self._ok(file): self._violation("os.open", file, flags, mode) -- cgit v1.2.1 From 744a61f18bbfcbf7dfaa08886185b4595d8b7bcb Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Mon, 17 Jun 2013 19:23:33 +0100 Subject: Misc. updates following 2to3 checks. --HG-- branch : single-codebase --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 090cb34c..a5a01a46 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -85,7 +85,7 @@ def run_setup(setup_script, args): # exclude any encodings modules. See #285 and not mod_name.startswith('encodings.') ] - map(sys.modules.__delitem__, del_modules) + list(map(sys.modules.__delitem__, del_modules)) os.chdir(old_dir) sys.path[:] = save_path sys.argv[:] = save_argv -- cgit v1.2.1 From 7161829fd5e4515903ce56b711e551bc75c35ba7 Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Wed, 19 Jun 2013 12:07:26 +0100 Subject: More post-merge fixes. --HG-- branch : single-codebase --- setuptools/sandbox.py | 1 - 1 file changed, 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 91dfc519..4e527446 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -9,7 +9,6 @@ except NameError: _file = None _open = open from distutils.errors import DistutilsError -from setuptools.compat import builtins, execfile, reduce from pkg_resources import working_set from setuptools.compat import builtins, execfile, reduce -- cgit v1.2.1 From 0be93889e5c04b7573736d312dc4f904c23f6a2e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 13 Jul 2013 16:14:20 -0400 Subject: Allow other arguments and kwargs to os.open when in the sandbox. Fixes Distribute #386. --- setuptools/sandbox.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 4e527446..29fc07b8 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -270,11 +270,11 @@ class DirectorySandbox(AbstractSandbox): self._violation(operation, src, dst, *args, **kw) return (src,dst) - def open(self, file, flags, mode=0x1FF): # 0777 + def open(self, file, flags, mode=0x1FF, *args, **kw): # 0777 """Called for low-level os.open()""" if flags & WRITE_FLAGS and not self._ok(file): - self._violation("os.open", file, flags, mode) - return _os.open(file,flags,mode) + self._violation("os.open", file, flags, mode, *args, **kw) + return _os.open(file,flags,mode, *args, **kw) WRITE_FLAGS = reduce( operator.or_, [getattr(_os, a, 0) for a in -- cgit v1.2.1 From 715085069e4882ee67d6898f12b975c05dd6b769 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 24 Nov 2013 16:42:28 -0500 Subject: Remove compatibility around reduce. --- setuptools/sandbox.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 29fc07b8..27914f2e 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,4 +1,5 @@ import os, sys, tempfile, operator, pkg_resources +import functools if os.name == "java": import org.python.modules.posix.PosixModule as _os else: @@ -11,7 +12,7 @@ _open = open from distutils.errors import DistutilsError from pkg_resources import working_set -from setuptools.compat import builtins, execfile, reduce +from setuptools.compat import builtins, execfile __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", @@ -276,7 +277,7 @@ class DirectorySandbox(AbstractSandbox): self._violation("os.open", file, flags, mode, *args, **kw) return _os.open(file,flags,mode, *args, **kw) -WRITE_FLAGS = reduce( +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()] ) -- cgit v1.2.1 From ecb026c64b97e1675ab830c4474331a6e03361a8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 24 Nov 2013 16:48:27 -0500 Subject: Modernize style on sandbox.py --- setuptools/sandbox.py | 40 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 27914f2e..6dd1ca07 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -1,5 +1,11 @@ -import os, sys, tempfile, operator, pkg_resources +import os +import sys +import tempfile +import operator import functools + +import pkg_resources + if os.name == "java": import org.python.modules.posix.PosixModule as _os else: @@ -18,34 +24,6 @@ __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" old_dir = os.getcwd() @@ -94,7 +72,6 @@ def run_setup(setup_script, args): tempfile.tempdir = save_tmp - class AbstractSandbox: """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" @@ -137,7 +114,6 @@ class AbstractSandbox: for name in ["rename", "link", "symlink"]: if hasattr(_os,name): locals()[name] = _mk_dual_path_wrapper(name) - def _mk_single_path_wrapper(name, original=None): original = original or getattr(_os,name) def wrap(self,path,*args,**kw): @@ -250,7 +226,7 @@ class DirectorySandbox(AbstractSandbox): self._active = False realpath = os.path.normcase(os.path.realpath(path)) if (self._exempted(realpath) or realpath == self._sandbox - or realpath.startswith(self._prefix)): + or realpath.startswith(self._prefix)): return True finally: self._active = active -- cgit v1.2.1 From 7a8e4a536be8c6cc8f313e6f0e6b907ffc55b205 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 7 Dec 2013 11:44:40 -0500 Subject: Normalize whitespace in function signatures --HG-- extra : histedit_source : 471b9c3fbde309c39492f2a567a26993c1dc94de --- setuptools/sandbox.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 6dd1ca07..7354e46a 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -220,7 +220,7 @@ class DirectorySandbox(AbstractSandbox): def tmpnam(self): self._violation("tmpnam") - def _ok(self,path): + def _ok(self, path): active = self._active try: self._active = False @@ -235,13 +235,13 @@ class DirectorySandbox(AbstractSandbox): exception_matches = map(filepath.startswith, self._exceptions) return True in exception_matches - def _remap_input(self,operation,path,*args,**kw): + def _remap_input(self, operation, path, *args, **kw): """Called for path inputs""" if operation in self.write_ops and not self._ok(path): self._violation(operation, os.path.realpath(path), *args, **kw) return path - def _remap_pair(self,operation,src,dst,*args,**kw): + def _remap_pair(self, operation, src, dst, *args, **kw): """Called for path pairs like rename, link, and symlink operations""" if not self._ok(src) or not self._ok(dst): self._violation(operation, src, dst, *args, **kw) -- cgit v1.2.1 From 47a464565e66612086c02d35c470ad20909e3931 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 7 Dec 2013 11:55:44 -0500 Subject: Always return a boolean in DirectorySandbox._ok --HG-- extra : histedit_source : b0072af02db4ba170105a4eb3f8a033dce678869 --- setuptools/sandbox.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 7354e46a..49c4ea93 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -200,7 +200,10 @@ class DirectorySandbox(AbstractSandbox): 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] + self._exceptions = [ + os.path.normcase(os.path.realpath(path)) + for path in exceptions + ] AbstractSandbox.__init__(self) def _violation(self, operation, *args, **kw): @@ -225,9 +228,11 @@ class DirectorySandbox(AbstractSandbox): try: self._active = False realpath = os.path.normcase(os.path.realpath(path)) - if (self._exempted(realpath) or realpath == self._sandbox - or realpath.startswith(self._prefix)): - return True + return ( + self._exempted(realpath) + or realpath == self._sandbox + or realpath.startswith(self._prefix) + ) finally: self._active = active -- cgit v1.2.1 From f196854eeb75ecd5b3e676e29b0f29137af25826 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 7 Dec 2013 12:14:52 -0500 Subject: Use any for matching exceptions in DirectorySandbox. --HG-- extra : histedit_source : 9a99f28235a96543a3ca2da4ec691da0e1cd880c --- setuptools/sandbox.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 49c4ea93..d50f1f66 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -237,8 +237,11 @@ class DirectorySandbox(AbstractSandbox): self._active = active def _exempted(self, filepath): - exception_matches = map(filepath.startswith, self._exceptions) - return True in exception_matches + exception_matches = any( + filepath.startswith(exception) + for exception in self._exceptions + ) + return exception_matches def _remap_input(self, operation, path, *args, **kw): """Called for path inputs""" -- cgit v1.2.1 From 3915375e6b94d7f41be271aec3c3e37efcba8c27 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 7 Dec 2013 12:15:25 -0500 Subject: Use any on a generator instead --HG-- extra : histedit_source : 7924e09d06d2f6db58371735314caeee77aa2d3d --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index d50f1f66..50fb02a3 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -237,11 +237,11 @@ class DirectorySandbox(AbstractSandbox): self._active = active def _exempted(self, filepath): - exception_matches = any( + exception_matches = ( filepath.startswith(exception) for exception in self._exceptions ) - return exception_matches + return any(exception_matches) def _remap_input(self, operation, path, *args, **kw): """Called for path inputs""" -- cgit v1.2.1 From ef565f9ddd20ca66d1c1ff57da4ceb91038010e0 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 7 Dec 2013 12:28:15 -0500 Subject: Add support for exempting a path based on a regular expression. --HG-- extra : histedit_source : 2f1f4146ec1d5196cb65602302185a12060cfa17 --- setuptools/sandbox.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 50fb02a3..26960846 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -3,6 +3,8 @@ import sys import tempfile import operator import functools +import itertools +import re import pkg_resources @@ -197,6 +199,9 @@ class DirectorySandbox(AbstractSandbox): "utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam", ]) + _exception_patterns = [] + "allow 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,'') @@ -237,11 +242,16 @@ class DirectorySandbox(AbstractSandbox): self._active = active def _exempted(self, filepath): - exception_matches = ( + start_matches = ( filepath.startswith(exception) for exception in self._exceptions ) - return any(exception_matches) + pattern_matches = ( + re.match(pattern, filepath) + for pattern in self._exception_patterns + ) + candidates = itertools.chain(start_matches, pattern_matches) + return any(candidates) def _remap_input(self, operation, path, *args, **kw): """Called for path inputs""" -- cgit v1.2.1 From d30d526eb40a4855a3589d895aac75900aedfc44 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 7 Dec 2013 12:36:45 -0500 Subject: Exempt lib2to3 pickled grammars from the DirectorySandboxing. Fixes #121. --HG-- extra : histedit_source : 6cd9a3c6003d3f6de2f8e676b61589db4dffafb0 --- setuptools/sandbox.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 26960846..042c5958 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -199,8 +199,11 @@ class DirectorySandbox(AbstractSandbox): "utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam", ]) - _exception_patterns = [] - "allow writing to paths that match the pattern" + _exception_patterns = [ + # Allow lib2to3 to attempt to save a pickled grammar object (#121) + '.*lib2to3.*\.pickle$', + ] + "exempt writing to paths that match the pattern" def __init__(self, sandbox, exceptions=_EXCEPTIONS): self._sandbox = os.path.normcase(os.path.realpath(sandbox)) -- cgit v1.2.1 From 3fdbb8f7fa5c84dca9a7ff309d71ae3aeff60009 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 5 May 2014 03:50:59 -0400 Subject: Use modern syntax for octal values --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 042c5958..dc6e54bf 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -268,7 +268,7 @@ class DirectorySandbox(AbstractSandbox): self._violation(operation, src, dst, *args, **kw) return (src,dst) - def open(self, file, flags, mode=0x1FF, *args, **kw): # 0777 + def open(self, file, flags, mode=0o777, *args, **kw): """Called for low-level os.open()""" if flags & WRITE_FLAGS and not self._ok(file): self._violation("os.open", file, flags, mode, *args, **kw) -- cgit v1.2.1 From c4ecbd1e58a3384a5ab730450fa5487e48b68721 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 5 Jul 2014 14:42:49 -0400 Subject: Since Python 3 will always need the _execfile functionality (to fulfill the test in test_sandbox), this functionality should become part of the core implementation. --- setuptools/sandbox.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index dc6e54bf..7985e9ee 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -20,12 +20,23 @@ _open = open from distutils.errors import DistutilsError from pkg_resources import working_set -from setuptools.compat import builtins, execfile +from setuptools.compat import builtins __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] +def _execfile(filename, globals, locals=None): + """ + Python 3 implementation of execfile. + """ + with open(filename, 'rb') as stream: + script = stream.read() + if locals is None: + locals = globals + code = compile(script, filename, 'exec') + exec(code, globals, locals) + def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" old_dir = os.getcwd() @@ -46,12 +57,10 @@ def run_setup(setup_script, args): # reset to include setup dir, w/clean callback list working_set.__init__() working_set.callbacks.append(lambda dist:dist.activate()) - DirectorySandbox(setup_dir).run( - lambda: execfile( - "setup.py", - {'__file__':setup_script, '__name__':'__main__'} - ) - ) + def runner(): + ns = dict(__file__=setup_script, __name__='__main__') + _execfile(setup_script, ns) + DirectorySandbox(setup_dir).run(runner) except SystemExit: v = sys.exc_info()[1] if v.args and v.args[0]: -- cgit v1.2.1 From b49435397a5094f94678adf3549cc8941aa469b7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 5 Jul 2014 15:06:51 -0400 Subject: Use six for Python 2 compatibility --HG-- branch : feature/issue-229 extra : source : 7b1997ececc5772798ce33a0f8e77387cb55a977 --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 7985e9ee..185f2573 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -6,6 +6,8 @@ import functools import itertools import re +from six.moves import builtins + import pkg_resources if os.name == "java": @@ -20,8 +22,6 @@ _open = open from distutils.errors import DistutilsError from pkg_resources import working_set -from setuptools.compat import builtins - __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] -- cgit v1.2.1 From 249e5853496ec108dc78e58c003bf46315b50ffc Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 1 Aug 2014 15:31:47 -0400 Subject: Extract variable --- setuptools/sandbox.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 7985e9ee..a0d3dc61 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -30,7 +30,8 @@ def _execfile(filename, globals, locals=None): """ Python 3 implementation of execfile. """ - with open(filename, 'rb') as stream: + mode = 'rb' + with open(filename, mode) as stream: script = stream.read() if locals is None: locals = globals -- cgit v1.2.1 From 59e3528c710363e167e0860aab4fd1a611cc058b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 1 Aug 2014 15:36:08 -0400 Subject: Correct execfile implementation for Python 2.6. Fixes #236. --- setuptools/sandbox.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index a0d3dc61..e79a13a8 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -31,6 +31,10 @@ def _execfile(filename, globals, locals=None): Python 3 implementation of execfile. """ mode = 'rb' + # Python 2.6 compile requires LF for newlines, so use deprecated + # Universal newlines support. + if sys.version_info < (2, 7): + mode += 'U' with open(filename, mode) as stream: script = stream.read() if locals is None: -- cgit v1.2.1 From 8aa6480a1242aaa658d4bd521ff04efd1663a459 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 27 Dec 2014 11:07:39 -0500 Subject: Extract sandboxing context as a series of encapsulated contexts. --- setuptools/sandbox.py | 113 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 26 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index e79a13a8..131b7048 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -5,6 +5,7 @@ import operator import functools import itertools import re +import contextlib import pkg_resources @@ -42,20 +43,95 @@ def _execfile(filename, globals, locals=None): code = compile(script, filename, 'exec') exec(code, globals, locals) + +@contextlib.contextmanager +def save_argv(): + saved = sys.argv[:] + try: + yield saved + finally: + sys.argv[:] = saved + + +@contextlib.contextmanager +def save_path(): + saved = sys.path[:] + try: + yield saved + finally: + sys.path[:] = saved + + +@contextlib.contextmanager +def override_temp(replacement): + """ + Monkey-patch tempfile.tempdir with replacement, ensuring it exists + """ + if not os.path.isdir(replacement): + os.makedirs(replacement) + + saved = tempfile.tempdir + + tempfile.tempdir = replacement + + try: + yield + finally: + tempfile.tempdir = saved + + +@contextlib.contextmanager +def pushd(target): + saved = os.getcwd() + os.chdir(target) + try: + yield saved + finally: + os.chdir(saved) + + +@contextlib.contextmanager +def save_modules(): + saved = sys.modules.copy() + try: + yield saved + finally: + sys.modules.update(saved) + # remove any modules imported since + del_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.') + ] + list(map(sys.modules.__delitem__, del_modules)) + + +@contextlib.contextmanager +def save_pkg_resources_state(): + saved = pkg_resources.__getstate__() + try: + yield saved + finally: + pkg_resources.__setstate__(saved) + + +@contextlib.contextmanager +def setup_context(setup_dir): + temp_dir = os.path.join(setup_dir, 'temp') + with save_pkg_resources_state(): + with save_modules(): + with save_path(): + with save_argv(): + with override_temp(temp_dir): + with pushd(setup_dir): + yield + + def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" - old_dir = os.getcwd() - save_argv = sys.argv[:] - save_path = sys.path[:] setup_dir = os.path.abspath(os.path.dirname(setup_script)) - temp_dir = os.path.join(setup_dir,'temp') - if not os.path.isdir(temp_dir): os.makedirs(temp_dir) - save_tmp = tempfile.tempdir - save_modules = sys.modules.copy() - pr_state = pkg_resources.__getstate__() - try: - tempfile.tempdir = temp_dir - os.chdir(setup_dir) + with setup_context(setup_dir): try: sys.argv[:] = [setup_script]+list(args) sys.path.insert(0, setup_dir) @@ -71,21 +147,6 @@ def run_setup(setup_script, args): if v.args and v.args[0]: raise # Normal exit, just return - finally: - pkg_resources.__setstate__(pr_state) - sys.modules.update(save_modules) - # remove any modules imported within the sandbox - del_modules = [ - mod_name for mod_name in sys.modules - if mod_name not in save_modules - # exclude any encodings modules. See #285 - and not mod_name.startswith('encodings.') - ] - list(map(sys.modules.__delitem__, del_modules)) - os.chdir(old_dir) - sys.path[:] = save_path - sys.argv[:] = save_argv - tempfile.tempdir = save_tmp class AbstractSandbox: -- cgit v1.2.1 From 824cfa0bc32d500da6fd045147f752e8bf02f7b3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 28 Dec 2014 15:39:46 -0500 Subject: Remove setuptools modules from sys.modules before invoking setup script. Fixes #315. --- setuptools/sandbox.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 131b7048..e958f912 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -121,6 +121,7 @@ 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(): with save_argv(): with override_temp(temp_dir): @@ -128,6 +129,32 @@ def setup_context(setup_dir): yield +def _is_setuptools_module(mod_name): + """ + >>> is_setuptools_module('setuptools') + True + >>> is_setuptools_module('pkg_resources') + True + >>> is_setuptools_module('setuptools_plugin') + False + >>> is_setuptools_module('setuptools.__init__') + True + """ + pattern = re.compile('(setuptools|pkg_resources)(\.|$)') + return bool(pattern.match(mod_name)) + + +def hide_setuptools(): + """ + Remove references to setuptools' modules from sys.modules to allow the + invocation to import the most appropriate setuptools. This technique is + necessary to avoid issues such as #315 where setuptools upgrading itself + would fail to find a function declared in the metadata. + """ + modules = list(filter(_is_setuptools_module, sys.modules)) + list(map(sys.modules.__delitem__, modules)) + + def run_setup(setup_script, args): """Run a distutils setup script, sandboxed in its directory""" setup_dir = os.path.abspath(os.path.dirname(setup_script)) -- cgit v1.2.1 From eb2fdc6f488d1a1d4b0cf02e9a8cf03ab33f9d23 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 28 Dec 2014 15:42:40 -0500 Subject: Extract function for _clear_modules, encapsulating the need for the module names to be greedily evaluated before removing them. --- setuptools/sandbox.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index e958f912..f4f9dfec 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -98,13 +98,18 @@ def save_modules(): finally: sys.modules.update(saved) # remove any modules imported since - del_modules = [ + del_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.') - ] - list(map(sys.modules.__delitem__, del_modules)) + ) + _clear_modules(del_modules) + + +def _clear_modules(module_names): + for mod_name in list(module_names): + del sys.modules[mod_name] @contextlib.contextmanager @@ -151,8 +156,8 @@ def hide_setuptools(): necessary to avoid issues such as #315 where setuptools upgrading itself would fail to find a function declared in the metadata. """ - modules = list(filter(_is_setuptools_module, sys.modules)) - list(map(sys.modules.__delitem__, modules)) + modules = filter(_is_setuptools_module, sys.modules) + _clear_modules(modules) def run_setup(setup_script, args): -- cgit v1.2.1 From 15d7d87013e9c95f1e343ab7fee3d7f2bbd1d607 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 28 Dec 2014 16:01:33 -0500 Subject: Include distutils in modules hidden --- setuptools/sandbox.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index f4f9dfec..2216e9a6 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -144,8 +144,10 @@ def _is_setuptools_module(mod_name): False >>> is_setuptools_module('setuptools.__init__') True + >>> is_setuptools_module('distutils') + True """ - pattern = re.compile('(setuptools|pkg_resources)(\.|$)') + pattern = re.compile('(setuptools|pkg_resources|distutils)(\.|$)') return bool(pattern.match(mod_name)) -- cgit v1.2.1 From b239a5f2ec3ef076bfe825db1a694f02351b281f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 28 Dec 2014 16:01:43 -0500 Subject: Correct docstring --- setuptools/sandbox.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 2216e9a6..63760df4 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -136,15 +136,15 @@ def setup_context(setup_dir): def _is_setuptools_module(mod_name): """ - >>> is_setuptools_module('setuptools') + >>> _is_setuptools_module('setuptools') True - >>> is_setuptools_module('pkg_resources') + >>> _is_setuptools_module('pkg_resources') True - >>> is_setuptools_module('setuptools_plugin') + >>> _is_setuptools_module('setuptools_plugin') False - >>> is_setuptools_module('setuptools.__init__') + >>> _is_setuptools_module('setuptools.__init__') True - >>> is_setuptools_module('distutils') + >>> _is_setuptools_module('distutils') True """ pattern = re.compile('(setuptools|pkg_resources|distutils)(\.|$)') -- cgit v1.2.1 From ee14a898847efe9d53f7dc57b872805753463eb5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 28 Dec 2014 16:02:14 -0500 Subject: Rename function to match intention. --- setuptools/sandbox.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 63760df4..f1b60cc0 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -134,17 +134,17 @@ def setup_context(setup_dir): yield -def _is_setuptools_module(mod_name): +def _needs_hiding(mod_name): """ - >>> _is_setuptools_module('setuptools') + >>> _needs_hiding('setuptools') True - >>> _is_setuptools_module('pkg_resources') + >>> _needs_hiding('pkg_resources') True - >>> _is_setuptools_module('setuptools_plugin') + >>> _needs_hiding('setuptools_plugin') False - >>> _is_setuptools_module('setuptools.__init__') + >>> _needs_hiding('setuptools.__init__') True - >>> _is_setuptools_module('distutils') + >>> _needs_hiding('distutils') True """ pattern = re.compile('(setuptools|pkg_resources|distutils)(\.|$)') @@ -158,7 +158,7 @@ def hide_setuptools(): necessary to avoid issues such as #315 where setuptools upgrading itself would fail to find a function declared in the metadata. """ - modules = filter(_is_setuptools_module, sys.modules) + modules = filter(_needs_hiding, sys.modules) _clear_modules(modules) -- cgit v1.2.1 From 22715bcc472ac5b41cfcd94fa7ca26a5cef01eb9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 28 Dec 2014 20:54:46 -0500 Subject: Disable purging of distutils/setuptools during sandbox operations. Ref #315. --- setuptools/sandbox.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index f1b60cc0..e3c18e39 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -126,7 +126,9 @@ def setup_context(setup_dir): temp_dir = os.path.join(setup_dir, 'temp') with save_pkg_resources_state(): with save_modules(): - hide_setuptools() + # Disabled per + # https://bitbucket.org/pypa/setuptools/issue/315/setuptools-should-always-use-its-own#comment-14512075 + # hide_setuptools() with save_path(): with save_argv(): with override_temp(temp_dir): -- cgit v1.2.1 From 1e6095429693886831747050b38bad979eaaf966 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 29 Dec 2014 22:17:26 -0500 Subject: Backed out changeset: 40cc1fbecb1c Restores purging of distutils/setuptools during sandbox operations. Ref #315. --- setuptools/sandbox.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index e3c18e39..f1b60cc0 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -126,9 +126,7 @@ def setup_context(setup_dir): temp_dir = os.path.join(setup_dir, 'temp') with save_pkg_resources_state(): with save_modules(): - # Disabled per - # https://bitbucket.org/pypa/setuptools/issue/315/setuptools-should-always-use-its-own#comment-14512075 - # hide_setuptools() + hide_setuptools() with save_path(): with save_argv(): with override_temp(temp_dir): -- cgit v1.2.1 From 12169497ccb2303474016e01933f52d7e4eab93a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 29 Dec 2014 22:48:19 -0500 Subject: Catch, save, and restore any exceptions across the save_modules context. This corrects the latter of the two test failures. Ref #315. --- setuptools/sandbox.py | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index f1b60cc0..c6840ce4 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -6,6 +6,7 @@ import functools import itertools import re import contextlib +import pickle import pkg_resources @@ -21,6 +22,7 @@ _open = open from distutils.errors import DistutilsError from pkg_resources import working_set +from setuptools import compat from setuptools.compat import builtins __all__ = [ @@ -92,19 +94,38 @@ def pushd(target): @contextlib.contextmanager def save_modules(): + """ + Context in which imported modules are saved. + + Translates exceptions internal to the context into the equivalent exception + outside the context. + """ saved = sys.modules.copy() try: - yield saved - finally: - sys.modules.update(saved) - # remove any modules imported since - del_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.') - ) - _clear_modules(del_modules) + try: + yield saved + except: + # dump any exception + class_, exc, tb = sys.exc_info() + saved_cls = pickle.dumps(class_) + saved_exc = pickle.dumps(exc) + raise + finally: + sys.modules.update(saved) + # remove any modules imported since + del_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.') + ) + _clear_modules(del_modules) + except: + # reload and re-raise any exception, using restored modules + class_, exc, tb = sys.exc_info() + new_cls = pickle.loads(saved_cls) + new_exc = pickle.loads(saved_exc) + compat.reraise(new_cls, new_exc, tb) def _clear_modules(module_names): -- cgit v1.2.1 From fddd230b60c17ca2100e41962de7b9e16ee85408 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 30 Dec 2014 12:37:02 -0500 Subject: Ensure setuptools is present in the environment before invoking setup.py from easy_install. Fixes #319. --- setuptools/sandbox.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index c6840ce4..b90d1e1b 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -152,6 +152,8 @@ def setup_context(setup_dir): with save_argv(): with override_temp(temp_dir): with pushd(setup_dir): + # ensure setuptools commands are available + __import__('setuptools') yield -- cgit v1.2.1 From 9d6a6e5927ae0e67164383e419f3145fc154467e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 4 Jan 2015 11:35:16 -0500 Subject: Use except/as, now supported by Python 2.6 --- setuptools/sandbox.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index b90d1e1b..7971f42c 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -199,8 +199,7 @@ def run_setup(setup_script, args): ns = dict(__file__=setup_script, __name__='__main__') _execfile(setup_script, ns) DirectorySandbox(setup_dir).run(runner) - except SystemExit: - v = sys.exc_info()[1] + except SystemExit as v: if v.args and v.args[0]: raise # Normal exit, just return -- cgit v1.2.1 From 74637dd638a30c153d9af60688078c7e12d810d3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 21:23:57 -0500 Subject: Extract Exception saving behavior. --- setuptools/sandbox.py | 70 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 25 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 7971f42c..37d89a2a 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -92,6 +92,37 @@ def pushd(target): os.chdir(saved) +class ExceptionSaver: + """ + A Context Manager that will save an exception, serialized, and restore it + later. + """ + def __enter__(self): + return self + + def __exit__(self, type, exc, tb): + if not exc: + return + + # dump the exception + self.saved_type = pickle.dumps(type) + self.saved_exc = pickle.dumps(exc) + self.tb = tb + + # suppress the exception + return True + + def resume(self): + "restore and re-raise any exception" + + if 'saved_exc' not in vars(self): + return + + type = pickle.loads(self.saved_type) + exc = pickle.loads(self.saved_exc) + compat.reraise(type, exc, self.tb) + + @contextlib.contextmanager def save_modules(): """ @@ -101,31 +132,20 @@ def save_modules(): outside the context. """ saved = sys.modules.copy() - try: - try: - yield saved - except: - # dump any exception - class_, exc, tb = sys.exc_info() - saved_cls = pickle.dumps(class_) - saved_exc = pickle.dumps(exc) - raise - finally: - sys.modules.update(saved) - # remove any modules imported since - del_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.') - ) - _clear_modules(del_modules) - except: - # reload and re-raise any exception, using restored modules - class_, exc, tb = sys.exc_info() - new_cls = pickle.loads(saved_cls) - new_exc = pickle.loads(saved_exc) - compat.reraise(new_cls, new_exc, tb) + with ExceptionSaver() as saved_exc: + yield saved + + sys.modules.update(saved) + # remove any modules imported since + del_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.') + ) + _clear_modules(del_modules) + + saved_exc.resume() def _clear_modules(module_names): -- cgit v1.2.1 From 9948d3c8a7880cbc13012e8a3fedda130614601d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 21:40:02 -0500 Subject: Make attributes private and remove redundant naming. --- setuptools/sandbox.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 37d89a2a..0847ef41 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -105,9 +105,9 @@ class ExceptionSaver: return # dump the exception - self.saved_type = pickle.dumps(type) - self.saved_exc = pickle.dumps(exc) - self.tb = tb + self._type = pickle.dumps(type) + self._exc = pickle.dumps(exc) + self._tb = tb # suppress the exception return True @@ -115,12 +115,12 @@ class ExceptionSaver: def resume(self): "restore and re-raise any exception" - if 'saved_exc' not in vars(self): + if '_exc' not in vars(self): return - type = pickle.loads(self.saved_type) - exc = pickle.loads(self.saved_exc) - compat.reraise(type, exc, self.tb) + type = pickle.loads(self._type) + exc = pickle.loads(self._exc) + compat.reraise(type, exc, self._tb) @contextlib.contextmanager -- cgit v1.2.1 From 9cf04f13f2ff72a7befa15f8f4835d2c662508e6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 14 Jan 2015 22:06:09 -0500 Subject: Wrap unpickleable exceptions in another class. Fixes #329. --- setuptools/sandbox.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 0847ef41..83283ca3 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -92,6 +92,22 @@ def pushd(target): os.chdir(saved) +class UnpickleableException(Exception): + """ + An exception representing another Exception that could not be pickled. + """ + @classmethod + def dump(cls, type, exc): + """ + Always return a dumped (pickled) type and exc. If exc can't be pickled, + wrap it in UnpickleableException first. + """ + try: + return pickle.dumps(type), pickle.dumps(exc) + except Exception: + return cls.dump(cls, cls(repr(exc))) + + class ExceptionSaver: """ A Context Manager that will save an exception, serialized, and restore it @@ -105,8 +121,7 @@ class ExceptionSaver: return # dump the exception - self._type = pickle.dumps(type) - self._exc = pickle.dumps(exc) + self._saved = UnpickleableException.dump(type, exc) self._tb = tb # suppress the exception @@ -115,11 +130,10 @@ class ExceptionSaver: def resume(self): "restore and re-raise any exception" - if '_exc' not in vars(self): + if '_saved' not in vars(self): return - type = pickle.loads(self._type) - exc = pickle.loads(self._exc) + type, exc = map(pickle.loads, self._saved) compat.reraise(type, exc, self._tb) -- cgit v1.2.1 From 492758aff46622fb93845f96b9062dab029064f4 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 3 Feb 2015 22:28:29 +0400 Subject: Re-use context available in sandbox. --- setuptools/sandbox.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 83283ca3..67255123 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -47,8 +47,10 @@ def _execfile(filename, globals, locals=None): @contextlib.contextmanager -def save_argv(): +def save_argv(repl=None): saved = sys.argv[:] + if repl is not None: + sys.argv[:] = repl try: yield saved finally: -- cgit v1.2.1 From 8fe7605a2787648a23c28741e20ba403e95a357b Mon Sep 17 00:00:00 2001 From: Arfrever Frehtes Taifersar Arahesis Date: Mon, 30 Mar 2015 04:26:56 +0200 Subject: Fix setuptools.sandbox._execfile() with Python 3.1. It fixes failure of setuptools.tests.test_sandbox.TestSandbox.test_setup_py_with_CRLF() with Python 3.1. --- setuptools/sandbox.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 67255123..31e3eb2d 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -34,12 +34,12 @@ def _execfile(filename, globals, locals=None): Python 3 implementation of execfile. """ mode = 'rb' - # Python 2.6 compile requires LF for newlines, so use deprecated - # Universal newlines support. - if sys.version_info < (2, 7): - mode += 'U' with open(filename, mode) as stream: script = stream.read() + # compile() function in Python 2.6 and 3.1 requires LF line endings. + if sys.version_info[:2] < (2, 7) or sys.version_info[:2] >= (3, 0) and sys.version_info[:2] < (3, 2): + script = script.replace(b'\r\n', b'\n') + script = script.replace(b'\r', b'\n') if locals is None: locals = globals code = compile(script, filename, 'exec') -- cgit v1.2.1 From 2039b2aeba48685275bd2b341bf69d3f3f63786b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Tue, 21 Apr 2015 22:24:09 +0300 Subject: Check for Jython using sys.platform, not os.name --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 31e3eb2d..213cebff 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -10,7 +10,7 @@ import pickle import pkg_resources -if os.name == "java": +if sys.platform.startswith('java'): import org.python.modules.posix.PosixModule as _os else: _os = sys.modules[os.name] -- cgit v1.2.1 From 264b5dc6b9cf48b22bd2263d426026d7b8f45608 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 10:48:20 -0500 Subject: Prevent infinite recursion when UnpickleableException occurs in a sandbox context. Fixes #440. --- setuptools/sandbox.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 213cebff..b8b1bac1 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -98,8 +98,8 @@ class UnpickleableException(Exception): """ An exception representing another Exception that could not be pickled. """ - @classmethod - def dump(cls, type, exc): + @staticmethod + def dump(type, exc): """ Always return a dumped (pickled) type and exc. If exc can't be pickled, wrap it in UnpickleableException first. @@ -107,6 +107,8 @@ class UnpickleableException(Exception): try: return pickle.dumps(type), pickle.dumps(exc) except Exception: + # get UnpickleableException inside the sandbox + from setuptools.sandbox import UnpickleableException as cls return cls.dump(cls, cls(repr(exc))) -- cgit v1.2.1 From 1d74aaab3372b6727158802c610043ca036ce5d3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 13 Dec 2015 11:29:01 -0500 Subject: Always import for SandboxViolation so it's pickleable. Ref #440. --- setuptools/sandbox.py | 1 + 1 file changed, 1 insertion(+) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index b8b1bac1..85de85ff 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -384,6 +384,7 @@ class DirectorySandbox(AbstractSandbox): AbstractSandbox.__init__(self) def _violation(self, operation, *args, **kw): + from setuptools.sandbox import SandboxViolation raise SandboxViolation(operation, args, kw) if _file: -- cgit v1.2.1 From 06872bb0bbbeb953e90bd0941444b0d499056557 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 31 Dec 2015 11:51:01 -0500 Subject: Update vendoring technique to match that used for packaging. Ref #229. --HG-- branch : feature/issue-229 --- setuptools/sandbox.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 43b84791..47d7f40c 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -8,8 +8,14 @@ import re import contextlib import pickle -import six -from six.moves import builtins +try: + from setuptools._vendor import six + from setuptools._vendor.six.moves import builtins +except ImportError: + # fallback to naturally-installed version; allows system packagers to + # omit vendored packages. + import six + from six.moves import builtins import pkg_resources -- cgit v1.2.1 From 952c1bafda1929c74c737646aa025e6ffad6632e Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 31 Dec 2015 16:30:47 -0500 Subject: Modeling after Astropy's technique for bundling libraries, the imports are now much cleaner. Thanks @embray. Ref #229. --HG-- branch : feature/issue-229 --- setuptools/sandbox.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 47d7f40c..37035f37 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -8,14 +8,8 @@ import re import contextlib import pickle -try: - from setuptools._vendor import six - from setuptools._vendor.six.moves import builtins -except ImportError: - # fallback to naturally-installed version; allows system packagers to - # omit vendored packages. - import six - from six.moves import builtins +from setuptools.extern import six +from setuptools.extern.six.moves import builtins import pkg_resources -- cgit v1.2.1 From 8af3b6ef5b4173a0d0d6735147c98c882ae98344 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 16 Jan 2016 06:54:00 -0500 Subject: Always use Python 3 version of map --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 37035f37..668bcac7 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -9,7 +9,7 @@ import contextlib import pickle from setuptools.extern import six -from setuptools.extern.six.moves import builtins +from setuptools.extern.six.moves import builtins, map import pkg_resources -- cgit v1.2.1 From 57d450a4e0485c8c9db04a5b6d02615c3798f418 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 24 Jan 2016 11:49:11 -0500 Subject: Also hide Cython when hiding setuptools, as setuptools will have imported Cython and Cython references the distutils.Extension. Fixes #488. --- setuptools/sandbox.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 668bcac7..23e296b1 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -207,8 +207,12 @@ def _needs_hiding(mod_name): True >>> _needs_hiding('distutils') True + >>> _needs_hiding('os') + False + >>> _needs_hiding('Cython') + True """ - pattern = re.compile('(setuptools|pkg_resources|distutils)(\.|$)') + pattern = re.compile('(setuptools|pkg_resources|distutils|Cython)(\.|$)') return bool(pattern.match(mod_name)) -- cgit v1.2.1 From 6d11e88f938f09ef16db4c6064b6e74acba4db1d Mon Sep 17 00:00:00 2001 From: stepshal Date: Tue, 12 Jul 2016 22:00:43 +0700 Subject: Fix quantity of blank lines after code object. --- setuptools/sandbox.py | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 23e296b1..83c3afdb 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -29,6 +29,7 @@ __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] + def _execfile(filename, globals, locals=None): """ Python 3 implementation of execfile. @@ -117,6 +118,7 @@ class ExceptionSaver: A Context Manager that will save an exception, serialized, and restore it later. """ + def __enter__(self): return self @@ -237,6 +239,7 @@ def run_setup(setup_script, args): # reset to include setup dir, w/clean callback list working_set.__init__() working_set.callbacks.append(lambda dist:dist.activate()) + def runner(): ns = dict(__file__=setup_script, __name__='__main__') _execfile(setup_script, ns) @@ -280,6 +283,7 @@ class AbstractSandbox: def _mk_dual_path_wrapper(name): original = getattr(_os,name) + def wrap(self,src,dst,*args,**kw): if self._active: src,dst = self._remap_pair(name,src,dst,*args,**kw) @@ -291,6 +295,7 @@ class AbstractSandbox: def _mk_single_path_wrapper(name, original=None): original = original or getattr(_os,name) + def wrap(self,path,*args,**kw): if self._active: path = self._remap_input(name,path,*args,**kw) @@ -309,6 +314,7 @@ class AbstractSandbox: def _mk_single_with_return(name): original = getattr(_os,name) + def wrap(self,path,*args,**kw): if self._active: path = self._remap_input(name,path,*args,**kw) @@ -321,6 +327,7 @@ class AbstractSandbox: def _mk_query(name): original = getattr(_os,name) + def wrap(self,*args,**kw): retval = original(*args,**kw) if self._active: @@ -364,6 +371,7 @@ except ImportError: # it appears pywin32 is not installed, so no need to exclude. pass + class DirectorySandbox(AbstractSandbox): """Restrict operations to a single subdirectory - pseudo-chroot""" @@ -453,6 +461,7 @@ WRITE_FLAGS = functools.reduce( "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""" @@ -468,29 +477,4 @@ script by hand. Please inform the package's author and the EasyInstall maintainers to find out if a fix or workaround is available.""" % self.args - - - - - - - - - - - - - - - - - - - - - - - - - # -- cgit v1.2.1 From f749ccab1e55723848946c9aba5c3eddebe0b24e Mon Sep 17 00:00:00 2001 From: stepshal Date: Thu, 14 Jul 2016 09:26:06 +0700 Subject: Add missing whitespace. --- setuptools/sandbox.py | 68 +++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 83c3afdb..c6bab096 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -238,7 +238,7 @@ def run_setup(setup_script, args): sys.path.insert(0, setup_dir) # reset to include setup dir, w/clean callback list working_set.__init__() - working_set.callbacks.append(lambda dist:dist.activate()) + working_set.callbacks.append(lambda dist: dist.activate()) def runner(): ns = dict(__file__=setup_script, __name__='__main__') @@ -258,12 +258,12 @@ class AbstractSandbox: def __init__(self): self._attrs = [ name for name in dir(_os) - if not name.startswith('_') and hasattr(self,name) + if not name.startswith('_') and hasattr(self, name) ] def _copy(self, source): for name in self._attrs: - setattr(os, name, getattr(source,name)) + setattr(os, name, getattr(source, name)) def run(self, func): """Run 'func' under os sandboxing""" @@ -282,24 +282,24 @@ class AbstractSandbox: self._copy(_os) def _mk_dual_path_wrapper(name): - original = getattr(_os,name) + original = getattr(_os, name) - def wrap(self,src,dst,*args,**kw): + def wrap(self, src, dst, *args, **kw): if self._active: - src,dst = self._remap_pair(name,src,dst,*args,**kw) - return original(src,dst,*args,**kw) + src, dst = self._remap_pair(name, src, dst, *args, **kw) + return original(src, dst, *args, **kw) return wrap for name in ["rename", "link", "symlink"]: - if hasattr(_os,name): locals()[name] = _mk_dual_path_wrapper(name) + if hasattr(_os, name): locals()[name] = _mk_dual_path_wrapper(name) def _mk_single_path_wrapper(name, original=None): - original = original or getattr(_os,name) + original = original or getattr(_os, name) - def wrap(self,path,*args,**kw): + def wrap(self, path, *args, **kw): if self._active: - path = self._remap_input(name,path,*args,**kw) - return original(path,*args,**kw) + path = self._remap_input(name, path, *args, **kw) + return original(path, *args, **kw) return wrap if _file: @@ -310,51 +310,51 @@ class AbstractSandbox: "remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat", "startfile", "mkfifo", "mknod", "pathconf", "access" ]: - if hasattr(_os,name): locals()[name] = _mk_single_path_wrapper(name) + if hasattr(_os, name): locals()[name] = _mk_single_path_wrapper(name) def _mk_single_with_return(name): - original = getattr(_os,name) + original = getattr(_os, name) - def wrap(self,path,*args,**kw): + def wrap(self, path, *args, **kw): if self._active: - path = self._remap_input(name,path,*args,**kw) - return self._remap_output(name, original(path,*args,**kw)) - return original(path,*args,**kw) + path = self._remap_input(name, path, *args, **kw) + return self._remap_output(name, original(path, *args, **kw)) + return original(path, *args, **kw) return wrap for name in ['readlink', 'tempnam']: - if hasattr(_os,name): locals()[name] = _mk_single_with_return(name) + if hasattr(_os, name): locals()[name] = _mk_single_with_return(name) def _mk_query(name): - original = getattr(_os,name) + original = getattr(_os, name) - def wrap(self,*args,**kw): - retval = original(*args,**kw) + def wrap(self, *args, **kw): + retval = original(*args, **kw) if self._active: return self._remap_output(name, retval) return retval return wrap for name in ['getcwd', 'tmpnam']: - if hasattr(_os,name): locals()[name] = _mk_query(name) + if hasattr(_os, name): locals()[name] = _mk_query(name) - def _validate_path(self,path): + def _validate_path(self, path): """Called to remap or validate any path, whether input or output""" return path - def _remap_input(self,operation,path,*args,**kw): + def _remap_input(self, operation, path, *args, **kw): """Called for path inputs""" return self._validate_path(path) - def _remap_output(self,operation,path): + def _remap_output(self, operation, path): """Called for path outputs""" return self._validate_path(path) - def _remap_pair(self,operation,src,dst,*args,**kw): + def _remap_pair(self, operation, src, dst, *args, **kw): """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+'-from', src, *args, **kw), + self._remap_input(operation+'-to', dst, *args, **kw) ) @@ -388,7 +388,7 @@ class DirectorySandbox(AbstractSandbox): def __init__(self, sandbox, exceptions=_EXCEPTIONS): self._sandbox = os.path.normcase(os.path.realpath(sandbox)) - self._prefix = os.path.join(self._sandbox,'') + self._prefix = os.path.join(self._sandbox, '') self._exceptions = [ os.path.normcase(os.path.realpath(path)) for path in exceptions @@ -403,12 +403,12 @@ class DirectorySandbox(AbstractSandbox): def _file(self, path, mode='r', *args, **kw): if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): self._violation("file", path, mode, *args, **kw) - return _file(path,mode,*args,**kw) + return _file(path, mode, *args, **kw) def _open(self, path, mode='r', *args, **kw): if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): self._violation("open", path, mode, *args, **kw) - return _open(path,mode,*args,**kw) + return _open(path, mode, *args, **kw) def tmpnam(self): self._violation("tmpnam") @@ -448,13 +448,13 @@ class DirectorySandbox(AbstractSandbox): """Called for path pairs like rename, link, and symlink operations""" if not self._ok(src) or not self._ok(dst): self._violation(operation, src, dst, *args, **kw) - return (src,dst) + return (src, dst) def open(self, file, flags, mode=0o777, *args, **kw): """Called for low-level os.open()""" if flags & WRITE_FLAGS and not self._ok(file): self._violation("os.open", file, flags, mode, *args, **kw) - return _os.open(file,flags,mode, *args, **kw) + return _os.open(file, flags, mode, *args, **kw) WRITE_FLAGS = functools.reduce( operator.or_, [getattr(_os, a, 0) for a in -- cgit v1.2.1 From dc2d1dc249bec8e3a864e2aa6002a8e27adc4b7c Mon Sep 17 00:00:00 2001 From: stepshal Date: Thu, 14 Jul 2016 12:11:49 +0700 Subject: Fix missing whitespace around operator. --- setuptools/sandbox.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index c6bab096..5ed45f84 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -234,7 +234,7 @@ def run_setup(setup_script, args): setup_dir = os.path.abspath(os.path.dirname(setup_script)) with setup_context(setup_dir): try: - sys.argv[:] = [setup_script]+list(args) + sys.argv[:] = [setup_script] + list(args) sys.path.insert(0, setup_dir) # reset to include setup dir, w/clean callback list working_set.__init__() @@ -353,8 +353,8 @@ class AbstractSandbox: def _remap_pair(self, operation, src, dst, *args, **kw): """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 + '-from', src, *args, **kw), + self._remap_input(operation + '-to', dst, *args, **kw) ) -- cgit v1.2.1 From 64335b63f9e03e71d0acd885b8bfd0b4b7a60aa8 Mon Sep 17 00:00:00 2001 From: stepshal Date: Thu, 21 Jul 2016 04:13:28 +0700 Subject: Put colon-separated compound statement on separate lines. --- setuptools/sandbox.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 5ed45f84..c89593b1 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -291,7 +291,8 @@ class AbstractSandbox: return wrap for name in ["rename", "link", "symlink"]: - if hasattr(_os, name): locals()[name] = _mk_dual_path_wrapper(name) + if hasattr(_os, name): + locals()[name] = _mk_dual_path_wrapper(name) def _mk_single_path_wrapper(name, original=None): original = original or getattr(_os, name) @@ -310,7 +311,8 @@ class AbstractSandbox: "remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat", "startfile", "mkfifo", "mknod", "pathconf", "access" ]: - if hasattr(_os, name): locals()[name] = _mk_single_path_wrapper(name) + if hasattr(_os, name): + locals()[name] = _mk_single_path_wrapper(name) def _mk_single_with_return(name): original = getattr(_os, name) @@ -323,7 +325,8 @@ class AbstractSandbox: return wrap for name in ['readlink', 'tempnam']: - if hasattr(_os, name): locals()[name] = _mk_single_with_return(name) + if hasattr(_os, name): + locals()[name] = _mk_single_with_return(name) def _mk_query(name): original = getattr(_os, name) @@ -336,7 +339,8 @@ class AbstractSandbox: return wrap for name in ['getcwd', 'tmpnam']: - if hasattr(_os, name): locals()[name] = _mk_query(name) + if hasattr(_os, name): + locals()[name] = _mk_query(name) def _validate_path(self, path): """Called to remap or validate any path, whether input or output""" -- cgit v1.2.1 From 39bf3155d47c0024240be414a611dcb6d549f53c Mon Sep 17 00:00:00 2001 From: stepshal Date: Thu, 21 Jul 2016 09:37:34 +0700 Subject: Add missing blank lines after class or function definition. --- setuptools/sandbox.py | 1 + 1 file changed, 1 insertion(+) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index c89593b1..df630d3e 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -460,6 +460,7 @@ class DirectorySandbox(AbstractSandbox): self._violation("os.open", file, flags, mode, *args, **kw) return _os.open(file, flags, mode, *args, **kw) + 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()] -- cgit v1.2.1 From 7f118aaae6a49171a91248cc413dc78eb497a054 Mon Sep 17 00:00:00 2001 From: stepshal Date: Thu, 21 Jul 2016 10:17:11 +0700 Subject: Fix continuation line unaligned for hanging indent. --- setuptools/sandbox.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index df630d3e..2babb636 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -258,7 +258,7 @@ class AbstractSandbox: def __init__(self): self._attrs = [ name for name in dir(_os) - if not name.startswith('_') and hasattr(self, name) + if not name.startswith('_') and hasattr(self, name) ] def _copy(self, source): -- cgit v1.2.1 From 31bd37c6ac8de9e8c1bacebc2d8e1215df91eb96 Mon Sep 17 00:00:00 2001 From: stepshal Date: Tue, 18 Oct 2016 20:24:35 +0700 Subject: Fix quantity of blank lines. --- setuptools/sandbox.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 2babb636..53ce1551 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -99,6 +99,7 @@ class UnpickleableException(Exception): """ An exception representing another Exception that could not be pickled. """ + @staticmethod def dump(type, exc): """ @@ -243,6 +244,7 @@ def run_setup(setup_script, args): def runner(): ns = dict(__file__=setup_script, __name__='__main__') _execfile(setup_script, ns) + DirectorySandbox(setup_dir).run(runner) except SystemExit as v: if v.args and v.args[0]: @@ -301,6 +303,7 @@ class AbstractSandbox: if self._active: path = self._remap_input(name, path, *args, **kw) return original(path, *args, **kw) + return wrap if _file: @@ -322,6 +325,7 @@ class AbstractSandbox: path = self._remap_input(name, path, *args, **kw) return self._remap_output(name, original(path, *args, **kw)) return original(path, *args, **kw) + return wrap for name in ['readlink', 'tempnam']: @@ -336,6 +340,7 @@ class AbstractSandbox: if self._active: return self._remap_output(name, retval) return retval + return wrap for name in ['getcwd', 'tmpnam']: @@ -404,6 +409,7 @@ class DirectorySandbox(AbstractSandbox): raise SandboxViolation(operation, args, kw) if _file: + def _file(self, path, mode='r', *args, **kw): if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): self._violation("file", path, mode, *args, **kw) -- cgit v1.2.1 From ed3fac3741f01ce05c139216e5af58c238c63f29 Mon Sep 17 00:00:00 2001 From: stepshal Date: Wed, 19 Oct 2016 00:23:56 +0700 Subject: Fix quantity of blank lines. --- setuptools/sandbox.py | 1 + 1 file changed, 1 insertion(+) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 53ce1551..39afd57e 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -290,6 +290,7 @@ class AbstractSandbox: if self._active: src, dst = self._remap_pair(name, src, dst, *args, **kw) return original(src, dst, *args, **kw) + return wrap for name in ["rename", "link", "symlink"]: -- cgit v1.2.1 From 7daf18ff0aaa6e9c9f5078ed1880512dbf8e497a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 18 Nov 2016 15:19:12 -0500 Subject: Drop exception support for packages triggering win32com cache generation during build/install. Fixes #841 --- setuptools/sandbox.py | 8 -------- 1 file changed, 8 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 39afd57e..d882d715 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -373,14 +373,6 @@ if hasattr(os, 'devnull'): else: _EXCEPTIONS = [] -try: - from win32com.client.gencache import GetGeneratePath - _EXCEPTIONS.append(GetGeneratePath()) - del GetGeneratePath -except ImportError: - # it appears pywin32 is not installed, so no need to exclude. - pass - class DirectorySandbox(AbstractSandbox): """Restrict operations to a single subdirectory - pseudo-chroot""" -- cgit v1.2.1 From f14930e66601b462699c44384c482cd966f53b8f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 9 Dec 2016 08:16:33 -0500 Subject: Drop support for Python 2.6, removing lots of compatibility code for a leaner, cleaner codebase. Fixes #878. --- setuptools/sandbox.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index d882d715..640691d8 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -37,10 +37,6 @@ def _execfile(filename, globals, locals=None): mode = 'rb' with open(filename, mode) as stream: script = stream.read() - # compile() function in Python 2.6 and 3.1 requires LF line endings. - if sys.version_info[:2] < (2, 7) or sys.version_info[:2] >= (3, 0) and sys.version_info[:2] < (3, 2): - script = script.replace(b'\r\n', b'\n') - script = script.replace(b'\r', b'\n') if locals is None: locals = globals code = compile(script, filename, 'exec') -- cgit v1.2.1 From cd2a519c6592d90e8658a5e90d8b0342d08b9ae9 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 18 Dec 2016 11:51:19 -0500 Subject: In sandbox.run_setup, always ensure that __file__ is str. Fixes #712. --- setuptools/sandbox.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index d882d715..817a3afa 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -241,8 +241,15 @@ 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()) + ) + def runner(): - ns = dict(__file__=setup_script, __name__='__main__') + ns = dict(__file__=dunder_file, __name__='__main__') _execfile(setup_script, ns) DirectorySandbox(setup_dir).run(runner) -- cgit v1.2.1 From ff371f18f0076bc63da05334f7e551c1cc29e10d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 1 Jan 2017 22:34:28 -0500 Subject: Strip out vendored packages and require them instead. Ref #581. --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 817a3afa..0ddd2332 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -8,8 +8,8 @@ import re import contextlib import pickle -from setuptools.extern import six -from setuptools.extern.six.moves import builtins, map +import six +from six.moves import builtins, map import pkg_resources -- cgit v1.2.1 From 3d0cc355fb5e8012cb8c72f0e25042a5a44f31d6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 24 Feb 2017 11:49:51 -0500 Subject: Revert "Merge pull request #933 from pypa/feature/581-depend-not-bundle" This reverts commit 089cdeb489a0fa94d11b7307b54210ef9aa40511, reversing changes made to aaec654d804cb78dbb6391afff721a63f26a71cd. --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 0ddd2332..817a3afa 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -8,8 +8,8 @@ import re import contextlib import pickle -import six -from six.moves import builtins, map +from setuptools.extern import six +from setuptools.extern.six.moves import builtins, map import pkg_resources -- cgit v1.2.1 From e753cb42481783ac858ceb518aaac1472075063c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Fri, 24 Feb 2017 10:55:44 +0200 Subject: Python 3.6 invalid escape sequence deprecation fixes --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 0ddd2332..41c1c3b1 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -215,7 +215,7 @@ def _needs_hiding(mod_name): >>> _needs_hiding('Cython') True """ - pattern = re.compile('(setuptools|pkg_resources|distutils|Cython)(\.|$)') + pattern = re.compile(r'(setuptools|pkg_resources|distutils|Cython)(\.|$)') return bool(pattern.match(mod_name)) @@ -391,7 +391,7 @@ class DirectorySandbox(AbstractSandbox): _exception_patterns = [ # Allow lib2to3 to attempt to save a pickled grammar object (#121) - '.*lib2to3.*\.pickle$', + r'.*lib2to3.*\.pickle$', ] "exempt writing to paths that match the pattern" -- cgit v1.2.1 From 7474f891cd5f62b0ef2af286096b47f8497e5d0d Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 May 2017 11:08:53 -0400 Subject: Remove extraneous whitespace and empty comment --- setuptools/sandbox.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 41c1c3b1..9c4ff336 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -486,6 +486,3 @@ This package cannot be safely installed by EasyInstall, and may not 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.""" % self.args - - -# -- cgit v1.2.1 From d6959fca54137c47abb9c3f7a0cbd1d0fd3704d3 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 May 2017 11:12:01 -0400 Subject: Use dedent and left strip to store the template inside the class. --- setuptools/sandbox.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 9c4ff336..4711fec2 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -7,6 +7,7 @@ import itertools import re import contextlib import pickle +import textwrap import six from six.moves import builtins, map @@ -476,13 +477,17 @@ WRITE_FLAGS = functools.reduce( class SandboxViolation(DistutilsError): """A setup script attempted to modify the filesystem outside the sandbox""" - def __str__(self): - return """SandboxViolation: %s%r %s + tmpl = textwrap.dedent(""" + SandboxViolation: %s%r %s + + The package setup script has attempted to modify files on your system + that are not within the EasyInstall build area, and has been aborted. -The package setup script has attempted to modify files on your system -that are not within the EasyInstall build area, and has been aborted. + This package cannot be safely installed by EasyInstall, and may not + 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() -This package cannot be safely installed by EasyInstall, and may not -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.""" % self.args + def __str__(self): + return self.tmpl % self.args -- cgit v1.2.1 From d48cb39b4666477da1d954d3604023095c233869 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 May 2017 11:31:55 -0400 Subject: Use new style format strings and expand args to variables for better clarity of purpose. --- setuptools/sandbox.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 4711fec2..53964f4b 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -478,7 +478,7 @@ class SandboxViolation(DistutilsError): """A setup script attempted to modify the filesystem outside the sandbox""" tmpl = textwrap.dedent(""" - SandboxViolation: %s%r %s + SandboxViolation: {cmd}{args!r} {kwargs} The package setup script has attempted to modify files on your system that are not within the EasyInstall build area, and has been aborted. @@ -490,4 +490,5 @@ class SandboxViolation(DistutilsError): """).lstrip() def __str__(self): - return self.tmpl % self.args + cmd, args, kwargs = self.args + return self.tmpl.format(**locals()) -- cgit v1.2.1 From 20567bef2a36b259d2209cc76fd11a61ad288853 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 21 May 2017 11:42:04 -0400 Subject: Implement AbstractSandbox as a context manager. --- setuptools/sandbox.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 53964f4b..14f18d74 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -249,11 +249,9 @@ def run_setup(setup_script, args): setup_script.encode(sys.getfilesystemencoding()) ) - def runner(): + with DirectorySandbox(setup_dir): ns = dict(__file__=dunder_file, __name__='__main__') _execfile(setup_script, ns) - - DirectorySandbox(setup_dir).run(runner) except SystemExit as v: if v.args and v.args[0]: raise @@ -275,21 +273,24 @@ class AbstractSandbox: for name in self._attrs: setattr(os, name, getattr(source, name)) + def __enter__(self): + self._copy(self) + if _file: + builtins.file = self._file + builtins.open = self._open + self._active = True + + def __exit__(self, exc_type, exc_value, traceback): + self._active = False + if _file: + builtins.file = _file + builtins.open = _open + self._copy(_os) + def run(self, func): """Run 'func' under os sandboxing""" - try: - self._copy(self) - if _file: - builtins.file = self._file - builtins.open = self._open - self._active = True + with self: return func() - finally: - self._active = False - if _file: - builtins.file = _file - builtins.open = _open - self._copy(_os) def _mk_dual_path_wrapper(name): original = getattr(_os, name) -- cgit v1.2.1 From 04a306fa080e8a71f94ea5198b507c501c621cb6 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Thu, 13 Jul 2017 14:13:54 -0400 Subject: Use makedirs with future compatibility throughout setuptools. Ref #1083. --- setuptools/sandbox.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index f99c13c4..1d981f49 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -12,7 +12,7 @@ import textwrap from setuptools.extern import six from setuptools.extern.six.moves import builtins, map -import pkg_resources +import pkg_resources.py31compat if sys.platform.startswith('java'): import org.python.modules.posix.PosixModule as _os @@ -26,6 +26,7 @@ _open = open from distutils.errors import DistutilsError from pkg_resources import working_set + __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] @@ -73,8 +74,7 @@ def override_temp(replacement): """ Monkey-patch tempfile.tempdir with replacement, ensuring it exists """ - if not os.path.isdir(replacement): - os.makedirs(replacement) + pkg_resources.py31compat.makedirs(replacement, exist_ok=True) saved = tempfile.tempdir -- cgit v1.2.1 From 760e2e1df9c9c9d1fc072e7b6ad9df4c32bfc835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Fri, 27 Jul 2018 14:36:34 +0200 Subject: Remove spurious executable permissions --- setuptools/sandbox.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 setuptools/sandbox.py (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py old mode 100755 new mode 100644 -- cgit v1.2.1 From 3d4d8b9dde61b87271861b8c7ebeb168ac4fa72b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 19 Jan 2020 12:46:30 -0500 Subject: =?UTF-8?q?=F0=9F=91=B9=20Feed=20the=20hobgoblins=20(delint).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setuptools/sandbox.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 685f3f72..e46dfc8d 100644 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -13,6 +13,8 @@ from setuptools.extern import six from setuptools.extern.six.moves import builtins, map import pkg_resources.py31compat +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,8 +25,6 @@ try: except NameError: _file = None _open = open -from distutils.errors import DistutilsError -from pkg_resources import working_set __all__ = [ @@ -374,7 +374,7 @@ class AbstractSandbox: if hasattr(os, 'devnull'): - _EXCEPTIONS = [os.devnull,] + _EXCEPTIONS = [os.devnull] else: _EXCEPTIONS = [] @@ -466,7 +466,8 @@ class DirectorySandbox(AbstractSandbox): WRITE_FLAGS = functools.reduce( - operator.or_, [getattr(_os, a, 0) for a in + operator.or_, [ + getattr(_os, a, 0) for a in "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()] ) -- cgit v1.2.1 From b3de7989665740cd4218d7d814e719d90e75de73 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 18 Jan 2020 08:13:23 -0800 Subject: Remove pkg_resources.py31compat.makedirs() in favor of the stdlib As setuptools is now python 3.5+, this compatibility shim is no longer necessary. --- setuptools/sandbox.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index e46dfc8d..93ae8eb4 100644 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -12,7 +12,7 @@ import textwrap 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 @@ -70,7 +70,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 -- cgit v1.2.1 From 89e9d3c8910c3f419eb9f1c2758a748c6938655b Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Mon, 13 Jul 2020 14:43:23 -0400 Subject: Adjust distutils shim when removing _distutils_importer --- setuptools/sandbox.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 93ae8eb4..342a713f 100644 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -185,8 +185,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 +195,15 @@ def setup_context(setup_dir): yield +_MODULES_TO_HIDE = { + 'setuptools', + 'distutils', + 'pkg_resources', + 'Cython', + '_distutils_importer', +} + + def _needs_hiding(mod_name): """ >>> _needs_hiding('setuptools') @@ -212,8 +221,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 +232,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_importer = sys.modules.get('_distutils_importer', None) + if _distutils_importer is not None: + _distutils_importer.remove_shim() + modules = filter(_needs_hiding, sys.modules) _clear_modules(modules) -- cgit v1.2.1 From dcc71f773576c19a3658735879893515b056ece5 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 26 Jul 2020 10:35:02 -0400 Subject: Rename _distutils_importer to _distutils_hack, as it supplies more than just an importer. --- setuptools/sandbox.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 342a713f..24a36080 100644 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -200,7 +200,7 @@ _MODULES_TO_HIDE = { 'distutils', 'pkg_resources', 'Cython', - '_distutils_importer', + '_distutils_hack', } @@ -232,9 +232,9 @@ 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_importer = sys.modules.get('_distutils_importer', None) - if _distutils_importer is not None: - _distutils_importer.remove_shim() + _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) -- cgit v1.2.1 From fb7ab81a3d080422687bad71f9ae9d36eeefbee2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 16 Aug 2020 00:29:24 -0400 Subject: Remove Python 2 compatibility --- setuptools/sandbox.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 24a36080..91b960d8 100644 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -8,9 +8,7 @@ import re import contextlib import pickle import textwrap - -from setuptools.extern import six -from setuptools.extern.six.moves import builtins, map +import builtins import pkg_resources from distutils.errors import DistutilsError @@ -138,7 +136,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 @@ -251,15 +249,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]: -- cgit v1.2.1 From ca296ca8663a376f3c36c9f8fd86b10ba81366c2 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sun, 18 Jul 2021 09:27:21 +0100 Subject: remove lib2to3 usage --- setuptools/sandbox.py | 86 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 26 deletions(-) (limited to 'setuptools/sandbox.py') diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 91b960d8..034fc80d 100644 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -26,7 +26,10 @@ _open = open __all__ = [ - "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", + "AbstractSandbox", + "DirectorySandbox", + "SandboxViolation", + "run_setup", ] @@ -106,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))) @@ -154,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.') @@ -265,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) ] @@ -320,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) @@ -373,7 +395,7 @@ 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), ) @@ -386,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: @@ -440,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) @@ -470,16 +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 @@ -489,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 -- cgit v1.2.1