Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/setuptools/sandbox.py
7763 views
import os1import sys2import tempfile3import operator4import functools5import itertools6import re7import contextlib8import pickle9import textwrap1011from setuptools.extern import six12from setuptools.extern.six.moves import builtins, map1314import pkg_resources15from distutils.errors import DistutilsError16from pkg_resources import working_set1718if sys.platform.startswith('java'):19import org.python.modules.posix.PosixModule as _os20else:21_os = sys.modules[os.name]22try:23_file = file24except NameError:25_file = None26_open = open272829__all__ = [30"AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup",31]323334def _execfile(filename, globals, locals=None):35"""36Python 3 implementation of execfile.37"""38mode = 'rb'39with open(filename, mode) as stream:40script = stream.read()41if locals is None:42locals = globals43code = compile(script, filename, 'exec')44exec(code, globals, locals)454647@contextlib.contextmanager48def save_argv(repl=None):49saved = sys.argv[:]50if repl is not None:51sys.argv[:] = repl52try:53yield saved54finally:55sys.argv[:] = saved565758@contextlib.contextmanager59def save_path():60saved = sys.path[:]61try:62yield saved63finally:64sys.path[:] = saved656667@contextlib.contextmanager68def override_temp(replacement):69"""70Monkey-patch tempfile.tempdir with replacement, ensuring it exists71"""72os.makedirs(replacement, exist_ok=True)7374saved = tempfile.tempdir7576tempfile.tempdir = replacement7778try:79yield80finally:81tempfile.tempdir = saved828384@contextlib.contextmanager85def pushd(target):86saved = os.getcwd()87os.chdir(target)88try:89yield saved90finally:91os.chdir(saved)929394class UnpickleableException(Exception):95"""96An exception representing another Exception that could not be pickled.97"""9899@staticmethod100def dump(type, exc):101"""102Always return a dumped (pickled) type and exc. If exc can't be pickled,103wrap it in UnpickleableException first.104"""105try:106return pickle.dumps(type), pickle.dumps(exc)107except Exception:108# get UnpickleableException inside the sandbox109from setuptools.sandbox import UnpickleableException as cls110return cls.dump(cls, cls(repr(exc)))111112113class ExceptionSaver:114"""115A Context Manager that will save an exception, serialized, and restore it116later.117"""118119def __enter__(self):120return self121122def __exit__(self, type, exc, tb):123if not exc:124return125126# dump the exception127self._saved = UnpickleableException.dump(type, exc)128self._tb = tb129130# suppress the exception131return True132133def resume(self):134"restore and re-raise any exception"135136if '_saved' not in vars(self):137return138139type, exc = map(pickle.loads, self._saved)140six.reraise(type, exc, self._tb)141142143@contextlib.contextmanager144def save_modules():145"""146Context in which imported modules are saved.147148Translates exceptions internal to the context into the equivalent exception149outside the context.150"""151saved = sys.modules.copy()152with ExceptionSaver() as saved_exc:153yield saved154155sys.modules.update(saved)156# remove any modules imported since157del_modules = (158mod_name for mod_name in sys.modules159if mod_name not in saved160# exclude any encodings modules. See #285161and not mod_name.startswith('encodings.')162)163_clear_modules(del_modules)164165saved_exc.resume()166167168def _clear_modules(module_names):169for mod_name in list(module_names):170del sys.modules[mod_name]171172173@contextlib.contextmanager174def save_pkg_resources_state():175saved = pkg_resources.__getstate__()176try:177yield saved178finally:179pkg_resources.__setstate__(saved)180181182@contextlib.contextmanager183def setup_context(setup_dir):184temp_dir = os.path.join(setup_dir, 'temp')185with save_pkg_resources_state():186with save_modules():187hide_setuptools()188with save_path():189with save_argv():190with override_temp(temp_dir):191with pushd(setup_dir):192# ensure setuptools commands are available193__import__('setuptools')194yield195196197def _needs_hiding(mod_name):198"""199>>> _needs_hiding('setuptools')200True201>>> _needs_hiding('pkg_resources')202True203>>> _needs_hiding('setuptools_plugin')204False205>>> _needs_hiding('setuptools.__init__')206True207>>> _needs_hiding('distutils')208True209>>> _needs_hiding('os')210False211>>> _needs_hiding('Cython')212True213"""214pattern = re.compile(r'(setuptools|pkg_resources|distutils|Cython)(\.|$)')215return bool(pattern.match(mod_name))216217218def hide_setuptools():219"""220Remove references to setuptools' modules from sys.modules to allow the221invocation to import the most appropriate setuptools. This technique is222necessary to avoid issues such as #315 where setuptools upgrading itself223would fail to find a function declared in the metadata.224"""225modules = filter(_needs_hiding, sys.modules)226_clear_modules(modules)227228229def run_setup(setup_script, args):230"""Run a distutils setup script, sandboxed in its directory"""231setup_dir = os.path.abspath(os.path.dirname(setup_script))232with setup_context(setup_dir):233try:234sys.argv[:] = [setup_script] + list(args)235sys.path.insert(0, setup_dir)236# reset to include setup dir, w/clean callback list237working_set.__init__()238working_set.callbacks.append(lambda dist: dist.activate())239240# __file__ should be a byte string on Python 2 (#712)241dunder_file = (242setup_script243if isinstance(setup_script, str) else244setup_script.encode(sys.getfilesystemencoding())245)246247with DirectorySandbox(setup_dir):248ns = dict(__file__=dunder_file, __name__='__main__')249_execfile(setup_script, ns)250except SystemExit as v:251if v.args and v.args[0]:252raise253# Normal exit, just return254255256class AbstractSandbox:257"""Wrap 'os' module and 'open()' builtin for virtualizing setup scripts"""258259_active = False260261def __init__(self):262self._attrs = [263name for name in dir(_os)264if not name.startswith('_') and hasattr(self, name)265]266267def _copy(self, source):268for name in self._attrs:269setattr(os, name, getattr(source, name))270271def __enter__(self):272self._copy(self)273if _file:274builtins.file = self._file275builtins.open = self._open276self._active = True277278def __exit__(self, exc_type, exc_value, traceback):279self._active = False280if _file:281builtins.file = _file282builtins.open = _open283self._copy(_os)284285def run(self, func):286"""Run 'func' under os sandboxing"""287with self:288return func()289290def _mk_dual_path_wrapper(name):291original = getattr(_os, name)292293def wrap(self, src, dst, *args, **kw):294if self._active:295src, dst = self._remap_pair(name, src, dst, *args, **kw)296return original(src, dst, *args, **kw)297298return wrap299300for name in ["rename", "link", "symlink"]:301if hasattr(_os, name):302locals()[name] = _mk_dual_path_wrapper(name)303304def _mk_single_path_wrapper(name, original=None):305original = original or getattr(_os, name)306307def wrap(self, path, *args, **kw):308if self._active:309path = self._remap_input(name, path, *args, **kw)310return original(path, *args, **kw)311312return wrap313314if _file:315_file = _mk_single_path_wrapper('file', _file)316_open = _mk_single_path_wrapper('open', _open)317for name in [318"stat", "listdir", "chdir", "open", "chmod", "chown", "mkdir",319"remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat",320"startfile", "mkfifo", "mknod", "pathconf", "access"321]:322if hasattr(_os, name):323locals()[name] = _mk_single_path_wrapper(name)324325def _mk_single_with_return(name):326original = getattr(_os, name)327328def wrap(self, path, *args, **kw):329if self._active:330path = self._remap_input(name, path, *args, **kw)331return self._remap_output(name, original(path, *args, **kw))332return original(path, *args, **kw)333334return wrap335336for name in ['readlink', 'tempnam']:337if hasattr(_os, name):338locals()[name] = _mk_single_with_return(name)339340def _mk_query(name):341original = getattr(_os, name)342343def wrap(self, *args, **kw):344retval = original(*args, **kw)345if self._active:346return self._remap_output(name, retval)347return retval348349return wrap350351for name in ['getcwd', 'tmpnam']:352if hasattr(_os, name):353locals()[name] = _mk_query(name)354355def _validate_path(self, path):356"""Called to remap or validate any path, whether input or output"""357return path358359def _remap_input(self, operation, path, *args, **kw):360"""Called for path inputs"""361return self._validate_path(path)362363def _remap_output(self, operation, path):364"""Called for path outputs"""365return self._validate_path(path)366367def _remap_pair(self, operation, src, dst, *args, **kw):368"""Called for path pairs like rename, link, and symlink operations"""369return (370self._remap_input(operation + '-from', src, *args, **kw),371self._remap_input(operation + '-to', dst, *args, **kw)372)373374375if hasattr(os, 'devnull'):376_EXCEPTIONS = [os.devnull]377else:378_EXCEPTIONS = []379380381class DirectorySandbox(AbstractSandbox):382"""Restrict operations to a single subdirectory - pseudo-chroot"""383384write_ops = dict.fromkeys([385"open", "chmod", "chown", "mkdir", "remove", "unlink", "rmdir",386"utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam",387])388389_exception_patterns = [390# Allow lib2to3 to attempt to save a pickled grammar object (#121)391r'.*lib2to3.*\.pickle$',392]393"exempt writing to paths that match the pattern"394395def __init__(self, sandbox, exceptions=_EXCEPTIONS):396self._sandbox = os.path.normcase(os.path.realpath(sandbox))397self._prefix = os.path.join(self._sandbox, '')398self._exceptions = [399os.path.normcase(os.path.realpath(path))400for path in exceptions401]402AbstractSandbox.__init__(self)403404def _violation(self, operation, *args, **kw):405from setuptools.sandbox import SandboxViolation406raise SandboxViolation(operation, args, kw)407408if _file:409410def _file(self, path, mode='r', *args, **kw):411if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path):412self._violation("file", path, mode, *args, **kw)413return _file(path, mode, *args, **kw)414415def _open(self, path, mode='r', *args, **kw):416if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path):417self._violation("open", path, mode, *args, **kw)418return _open(path, mode, *args, **kw)419420def tmpnam(self):421self._violation("tmpnam")422423def _ok(self, path):424active = self._active425try:426self._active = False427realpath = os.path.normcase(os.path.realpath(path))428return (429self._exempted(realpath)430or realpath == self._sandbox431or realpath.startswith(self._prefix)432)433finally:434self._active = active435436def _exempted(self, filepath):437start_matches = (438filepath.startswith(exception)439for exception in self._exceptions440)441pattern_matches = (442re.match(pattern, filepath)443for pattern in self._exception_patterns444)445candidates = itertools.chain(start_matches, pattern_matches)446return any(candidates)447448def _remap_input(self, operation, path, *args, **kw):449"""Called for path inputs"""450if operation in self.write_ops and not self._ok(path):451self._violation(operation, os.path.realpath(path), *args, **kw)452return path453454def _remap_pair(self, operation, src, dst, *args, **kw):455"""Called for path pairs like rename, link, and symlink operations"""456if not self._ok(src) or not self._ok(dst):457self._violation(operation, src, dst, *args, **kw)458return (src, dst)459460def open(self, file, flags, mode=0o777, *args, **kw):461"""Called for low-level os.open()"""462if flags & WRITE_FLAGS and not self._ok(file):463self._violation("os.open", file, flags, mode, *args, **kw)464return _os.open(file, flags, mode, *args, **kw)465466467WRITE_FLAGS = functools.reduce(468operator.or_, [469getattr(_os, a, 0) for a in470"O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()]471)472473474class SandboxViolation(DistutilsError):475"""A setup script attempted to modify the filesystem outside the sandbox"""476477tmpl = textwrap.dedent("""478SandboxViolation: {cmd}{args!r} {kwargs}479480The package setup script has attempted to modify files on your system481that are not within the EasyInstall build area, and has been aborted.482483This package cannot be safely installed by EasyInstall, and may not484support alternate installation locations even if you run its setup485script by hand. Please inform the package's author and the EasyInstall486maintainers to find out if a fix or workaround is available.487""").lstrip()488489def __str__(self):490cmd, args, kwargs = self.args491return self.tmpl.format(**locals())492493494