]>
crepu.dev Git - config.git/blob - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/sandbox.py
14 from distutils
.errors
import DistutilsError
15 from pkg_resources
import working_set
17 if sys
.platform
.startswith('java'):
18 import org
.python
.modules
.posix
.PosixModule
as _os
20 _os
= sys
.modules
[os
.name
]
36 def _execfile(filename
, globals, locals=None):
38 Python 3 implementation of execfile.
41 with
open(filename
, mode
) as stream
:
42 script
= stream
.read()
45 code
= compile(script
, filename
, 'exec')
46 exec(code
, globals, locals)
49 @contextlib.contextmanager
50 def save_argv(repl
=None):
60 @contextlib.contextmanager
69 @contextlib.contextmanager
70 def override_temp(replacement
):
72 Monkey-patch tempfile.tempdir with replacement, ensuring it exists
74 os
.makedirs(replacement
, exist_ok
=True)
76 saved
= tempfile
.tempdir
78 tempfile
.tempdir
= replacement
83 tempfile
.tempdir
= saved
86 @contextlib.contextmanager
96 class UnpickleableException(Exception):
98 An exception representing another Exception that could not be pickled.
104 Always return a dumped (pickled) type and exc. If exc can't be pickled,
105 wrap it in UnpickleableException first.
108 return pickle
.dumps(type), pickle
.dumps(exc
)
110 # get UnpickleableException inside the sandbox
111 from setuptools
.sandbox
import UnpickleableException
as cls
113 return cls
.dump(cls
, cls(repr(exc
)))
116 class ExceptionSaver
:
118 A Context Manager that will save an exception, serialized, and restore it
125 def __exit__(self
, type, exc
, tb
):
130 self
._saved
= UnpickleableException
.dump(type, exc
)
133 # suppress the exception
137 "restore and re-raise any exception"
139 if '_saved' not in vars(self
):
142 type, exc
= map(pickle
.loads
, self
._saved
)
143 raise exc
.with_traceback(self
._tb
)
146 @contextlib.contextmanager
149 Context in which imported modules are saved.
151 Translates exceptions internal to the context into the equivalent exception
154 saved
= sys
.modules
.copy()
155 with
ExceptionSaver() as saved_exc
:
158 sys
.modules
.update(saved
)
159 # remove any modules imported since
162 for mod_name
in sys
.modules
163 if mod_name
not in saved
164 # exclude any encodings modules. See #285
165 and not mod_name
.startswith('encodings.')
167 _clear_modules(del_modules
)
172 def _clear_modules(module_names
):
173 for mod_name
in list(module_names
):
174 del sys
.modules
[mod_name
]
177 @contextlib.contextmanager
178 def save_pkg_resources_state():
179 saved
= pkg_resources
.__getstate
__()
183 pkg_resources
.__setstate
__(saved
)
186 @contextlib.contextmanager
187 def setup_context(setup_dir
):
188 temp_dir
= os
.path
.join(setup_dir
, 'temp')
189 with
save_pkg_resources_state():
194 with
override_temp(temp_dir
):
195 with
pushd(setup_dir
):
196 # ensure setuptools commands are available
197 __import__('setuptools')
210 def _needs_hiding(mod_name
):
212 >>> _needs_hiding('setuptools')
214 >>> _needs_hiding('pkg_resources')
216 >>> _needs_hiding('setuptools_plugin')
218 >>> _needs_hiding('setuptools.__init__')
220 >>> _needs_hiding('distutils')
222 >>> _needs_hiding('os')
224 >>> _needs_hiding('Cython')
227 base_module
= mod_name
.split('.', 1)[0]
228 return base_module
in _MODULES_TO_HIDE
231 def hide_setuptools():
233 Remove references to setuptools' modules from sys.modules to allow the
234 invocation to import the most appropriate setuptools. This technique is
235 necessary to avoid issues such as #315 where setuptools upgrading itself
236 would fail to find a function declared in the metadata.
238 _distutils_hack
= sys
.modules
.get('_distutils_hack', None)
239 if _distutils_hack
is not None:
240 _distutils_hack
.remove_shim()
242 modules
= filter(_needs_hiding
, sys
.modules
)
243 _clear_modules(modules
)
246 def run_setup(setup_script
, args
):
247 """Run a distutils setup script, sandboxed in its directory"""
248 setup_dir
= os
.path
.abspath(os
.path
.dirname(setup_script
))
249 with
setup_context(setup_dir
):
251 sys
.argv
[:] = [setup_script
] + list(args
)
252 sys
.path
.insert(0, setup_dir
)
253 # reset to include setup dir, w/clean callback list
254 working_set
.__init
__()
255 working_set
.callbacks
.append(lambda dist
: dist
.activate())
257 with
DirectorySandbox(setup_dir
):
258 ns
= dict(__file__
=setup_script
, __name__
='__main__')
259 _execfile(setup_script
, ns
)
260 except SystemExit as v
:
261 if v
.args
and v
.args
[0]:
263 # Normal exit, just return
266 class AbstractSandbox
:
267 """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts"""
275 if not name
.startswith('_') and hasattr(self
, name
)
278 def _copy(self
, source
):
279 for name
in self
._attrs
:
280 setattr(os
, name
, getattr(source
, name
))
285 builtins
.file = self
._file
286 builtins
.open = self
._open
289 def __exit__(self
, exc_type
, exc_value
, traceback
):
292 builtins
.file = _file
293 builtins
.open = _open
297 """Run 'func' under os sandboxing"""
301 def _mk_dual_path_wrapper(name
):
302 original
= getattr(_os
, name
)
304 def wrap(self
, src
, dst
, *args
, **kw
):
306 src
, dst
= self
._remap
_pair
(name
, src
, dst
, *args
, **kw
)
307 return original(src
, dst
, *args
, **kw
)
311 for name
in ["rename", "link", "symlink"]:
312 if hasattr(_os
, name
):
313 locals()[name
] = _mk_dual_path_wrapper(name
)
315 def _mk_single_path_wrapper(name
, original
=None):
316 original
= original
or getattr(_os
, name
)
318 def wrap(self
, path
, *args
, **kw
):
320 path
= self
._remap
_input
(name
, path
, *args
, **kw
)
321 return original(path
, *args
, **kw
)
326 _file
= _mk_single_path_wrapper('file', _file
)
327 _open
= _mk_single_path_wrapper('open', _open
)
349 if hasattr(_os
, name
):
350 locals()[name
] = _mk_single_path_wrapper(name
)
352 def _mk_single_with_return(name
):
353 original
= getattr(_os
, name
)
355 def wrap(self
, path
, *args
, **kw
):
357 path
= self
._remap
_input
(name
, path
, *args
, **kw
)
358 return self
._remap
_output
(name
, original(path
, *args
, **kw
))
359 return original(path
, *args
, **kw
)
363 for name
in ['readlink', 'tempnam']:
364 if hasattr(_os
, name
):
365 locals()[name
] = _mk_single_with_return(name
)
368 original
= getattr(_os
, name
)
370 def wrap(self
, *args
, **kw
):
371 retval
= original(*args
, **kw
)
373 return self
._remap
_output
(name
, retval
)
378 for name
in ['getcwd', 'tmpnam']:
379 if hasattr(_os
, name
):
380 locals()[name
] = _mk_query(name
)
382 def _validate_path(self
, path
):
383 """Called to remap or validate any path, whether input or output"""
386 def _remap_input(self
, operation
, path
, *args
, **kw
):
387 """Called for path inputs"""
388 return self
._validate
_path
(path
)
390 def _remap_output(self
, operation
, path
):
391 """Called for path outputs"""
392 return self
._validate
_path
(path
)
394 def _remap_pair(self
, operation
, src
, dst
, *args
, **kw
):
395 """Called for path pairs like rename, link, and symlink operations"""
397 self
._remap
_input
(operation
+ '-from', src
, *args
, **kw
),
398 self
._remap
_input
(operation
+ '-to', dst
, *args
, **kw
),
402 if hasattr(os
, 'devnull'):
403 _EXCEPTIONS
= [os
.devnull
]
408 class DirectorySandbox(AbstractSandbox
):
409 """Restrict operations to a single subdirectory - pseudo-chroot"""
411 write_ops
= dict.fromkeys(
429 _exception_patterns
= []
430 "exempt writing to paths that match the pattern"
432 def __init__(self
, sandbox
, exceptions
=_EXCEPTIONS
):
433 self
._sandbox
= os
.path
.normcase(os
.path
.realpath(sandbox
))
434 self
._prefix
= os
.path
.join(self
._sandbox
, '')
436 os
.path
.normcase(os
.path
.realpath(path
)) for path
in exceptions
438 AbstractSandbox
.__init
__(self
)
440 def _violation(self
, operation
, *args
, **kw
):
441 from setuptools
.sandbox
import SandboxViolation
443 raise SandboxViolation(operation
, args
, kw
)
447 def _file(self
, path
, mode
='r', *args
, **kw
):
448 if mode
not in ('r', 'rt', 'rb', 'rU', 'U') and not self
._ok
(path
):
449 self
._violation
("file", path
, mode
, *args
, **kw
)
450 return _file(path
, mode
, *args
, **kw
)
452 def _open(self
, path
, mode
='r', *args
, **kw
):
453 if mode
not in ('r', 'rt', 'rb', 'rU', 'U') and not self
._ok
(path
):
454 self
._violation
("open", path
, mode
, *args
, **kw
)
455 return _open(path
, mode
, *args
, **kw
)
458 self
._violation
("tmpnam")
461 active
= self
._active
464 realpath
= os
.path
.normcase(os
.path
.realpath(path
))
466 self
._exempted
(realpath
)
467 or realpath
== self
._sandbox
468 or realpath
.startswith(self
._prefix
)
471 self
._active
= active
473 def _exempted(self
, filepath
):
475 filepath
.startswith(exception
) for exception
in self
._exceptions
478 re
.match(pattern
, filepath
) for pattern
in self
._exception
_patterns
480 candidates
= itertools
.chain(start_matches
, pattern_matches
)
481 return any(candidates
)
483 def _remap_input(self
, operation
, path
, *args
, **kw
):
484 """Called for path inputs"""
485 if operation
in self
.write_ops
and not self
._ok
(path
):
486 self
._violation
(operation
, os
.path
.realpath(path
), *args
, **kw
)
489 def _remap_pair(self
, operation
, src
, dst
, *args
, **kw
):
490 """Called for path pairs like rename, link, and symlink operations"""
491 if not self
._ok
(src
) or not self
._ok
(dst
):
492 self
._violation
(operation
, src
, dst
, *args
, **kw
)
495 def open(self
, file, flags
, mode
=0o777, *args
, **kw
):
496 """Called for low-level os.open()"""
497 if flags
& WRITE_FLAGS
and not self
._ok
(file):
498 self
._violation
("os.open", file, flags
, mode
, *args
, **kw
)
499 return _os
.open(file, flags
, mode
, *args
, **kw
)
502 WRITE_FLAGS
= functools
.reduce(
506 for a
in "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()
511 class SandboxViolation(DistutilsError
):
512 """A setup script attempted to modify the filesystem outside the sandbox"""
514 tmpl
= textwrap
.dedent(
516 SandboxViolation: {cmd}{args!r} {kwargs}
518 The package setup script has attempted to modify files on your system
519 that are not within the EasyInstall build area, and has been aborted.
521 This package cannot be safely installed by EasyInstall, and may not
522 support alternate installation locations even if you run its setup
523 script by hand. Please inform the package's author and the EasyInstall
524 maintainers to find out if a fix or workaround is available.
529 cmd
, args
, kwargs
= self
.args
530 return self
.tmpl
.format(**locals())