Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/setuptools/sandbox.py
7763 views
1
import os
2
import sys
3
import tempfile
4
import operator
5
import functools
6
import itertools
7
import re
8
import contextlib
9
import pickle
10
import textwrap
11
12
from setuptools.extern import six
13
from setuptools.extern.six.moves import builtins, map
14
15
import pkg_resources
16
from distutils.errors import DistutilsError
17
from pkg_resources import working_set
18
19
if sys.platform.startswith('java'):
20
import org.python.modules.posix.PosixModule as _os
21
else:
22
_os = sys.modules[os.name]
23
try:
24
_file = file
25
except NameError:
26
_file = None
27
_open = open
28
29
30
__all__ = [
31
"AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup",
32
]
33
34
35
def _execfile(filename, globals, locals=None):
36
"""
37
Python 3 implementation of execfile.
38
"""
39
mode = 'rb'
40
with open(filename, mode) as stream:
41
script = stream.read()
42
if locals is None:
43
locals = globals
44
code = compile(script, filename, 'exec')
45
exec(code, globals, locals)
46
47
48
@contextlib.contextmanager
49
def save_argv(repl=None):
50
saved = sys.argv[:]
51
if repl is not None:
52
sys.argv[:] = repl
53
try:
54
yield saved
55
finally:
56
sys.argv[:] = saved
57
58
59
@contextlib.contextmanager
60
def save_path():
61
saved = sys.path[:]
62
try:
63
yield saved
64
finally:
65
sys.path[:] = saved
66
67
68
@contextlib.contextmanager
69
def override_temp(replacement):
70
"""
71
Monkey-patch tempfile.tempdir with replacement, ensuring it exists
72
"""
73
os.makedirs(replacement, exist_ok=True)
74
75
saved = tempfile.tempdir
76
77
tempfile.tempdir = replacement
78
79
try:
80
yield
81
finally:
82
tempfile.tempdir = saved
83
84
85
@contextlib.contextmanager
86
def pushd(target):
87
saved = os.getcwd()
88
os.chdir(target)
89
try:
90
yield saved
91
finally:
92
os.chdir(saved)
93
94
95
class UnpickleableException(Exception):
96
"""
97
An exception representing another Exception that could not be pickled.
98
"""
99
100
@staticmethod
101
def dump(type, exc):
102
"""
103
Always return a dumped (pickled) type and exc. If exc can't be pickled,
104
wrap it in UnpickleableException first.
105
"""
106
try:
107
return pickle.dumps(type), pickle.dumps(exc)
108
except Exception:
109
# get UnpickleableException inside the sandbox
110
from setuptools.sandbox import UnpickleableException as cls
111
return cls.dump(cls, cls(repr(exc)))
112
113
114
class ExceptionSaver:
115
"""
116
A Context Manager that will save an exception, serialized, and restore it
117
later.
118
"""
119
120
def __enter__(self):
121
return self
122
123
def __exit__(self, type, exc, tb):
124
if not exc:
125
return
126
127
# dump the exception
128
self._saved = UnpickleableException.dump(type, exc)
129
self._tb = tb
130
131
# suppress the exception
132
return True
133
134
def resume(self):
135
"restore and re-raise any exception"
136
137
if '_saved' not in vars(self):
138
return
139
140
type, exc = map(pickle.loads, self._saved)
141
six.reraise(type, exc, self._tb)
142
143
144
@contextlib.contextmanager
145
def save_modules():
146
"""
147
Context in which imported modules are saved.
148
149
Translates exceptions internal to the context into the equivalent exception
150
outside the context.
151
"""
152
saved = sys.modules.copy()
153
with ExceptionSaver() as saved_exc:
154
yield saved
155
156
sys.modules.update(saved)
157
# remove any modules imported since
158
del_modules = (
159
mod_name for mod_name in sys.modules
160
if mod_name not in saved
161
# exclude any encodings modules. See #285
162
and not mod_name.startswith('encodings.')
163
)
164
_clear_modules(del_modules)
165
166
saved_exc.resume()
167
168
169
def _clear_modules(module_names):
170
for mod_name in list(module_names):
171
del sys.modules[mod_name]
172
173
174
@contextlib.contextmanager
175
def save_pkg_resources_state():
176
saved = pkg_resources.__getstate__()
177
try:
178
yield saved
179
finally:
180
pkg_resources.__setstate__(saved)
181
182
183
@contextlib.contextmanager
184
def setup_context(setup_dir):
185
temp_dir = os.path.join(setup_dir, 'temp')
186
with save_pkg_resources_state():
187
with save_modules():
188
hide_setuptools()
189
with save_path():
190
with save_argv():
191
with override_temp(temp_dir):
192
with pushd(setup_dir):
193
# ensure setuptools commands are available
194
__import__('setuptools')
195
yield
196
197
198
def _needs_hiding(mod_name):
199
"""
200
>>> _needs_hiding('setuptools')
201
True
202
>>> _needs_hiding('pkg_resources')
203
True
204
>>> _needs_hiding('setuptools_plugin')
205
False
206
>>> _needs_hiding('setuptools.__init__')
207
True
208
>>> _needs_hiding('distutils')
209
True
210
>>> _needs_hiding('os')
211
False
212
>>> _needs_hiding('Cython')
213
True
214
"""
215
pattern = re.compile(r'(setuptools|pkg_resources|distutils|Cython)(\.|$)')
216
return bool(pattern.match(mod_name))
217
218
219
def hide_setuptools():
220
"""
221
Remove references to setuptools' modules from sys.modules to allow the
222
invocation to import the most appropriate setuptools. This technique is
223
necessary to avoid issues such as #315 where setuptools upgrading itself
224
would fail to find a function declared in the metadata.
225
"""
226
modules = filter(_needs_hiding, sys.modules)
227
_clear_modules(modules)
228
229
230
def run_setup(setup_script, args):
231
"""Run a distutils setup script, sandboxed in its directory"""
232
setup_dir = os.path.abspath(os.path.dirname(setup_script))
233
with setup_context(setup_dir):
234
try:
235
sys.argv[:] = [setup_script] + list(args)
236
sys.path.insert(0, setup_dir)
237
# reset to include setup dir, w/clean callback list
238
working_set.__init__()
239
working_set.callbacks.append(lambda dist: dist.activate())
240
241
# __file__ should be a byte string on Python 2 (#712)
242
dunder_file = (
243
setup_script
244
if isinstance(setup_script, str) else
245
setup_script.encode(sys.getfilesystemencoding())
246
)
247
248
with DirectorySandbox(setup_dir):
249
ns = dict(__file__=dunder_file, __name__='__main__')
250
_execfile(setup_script, ns)
251
except SystemExit as v:
252
if v.args and v.args[0]:
253
raise
254
# Normal exit, just return
255
256
257
class AbstractSandbox:
258
"""Wrap 'os' module and 'open()' builtin for virtualizing setup scripts"""
259
260
_active = False
261
262
def __init__(self):
263
self._attrs = [
264
name for name in dir(_os)
265
if not name.startswith('_') and hasattr(self, name)
266
]
267
268
def _copy(self, source):
269
for name in self._attrs:
270
setattr(os, name, getattr(source, name))
271
272
def __enter__(self):
273
self._copy(self)
274
if _file:
275
builtins.file = self._file
276
builtins.open = self._open
277
self._active = True
278
279
def __exit__(self, exc_type, exc_value, traceback):
280
self._active = False
281
if _file:
282
builtins.file = _file
283
builtins.open = _open
284
self._copy(_os)
285
286
def run(self, func):
287
"""Run 'func' under os sandboxing"""
288
with self:
289
return func()
290
291
def _mk_dual_path_wrapper(name):
292
original = getattr(_os, name)
293
294
def wrap(self, src, dst, *args, **kw):
295
if self._active:
296
src, dst = self._remap_pair(name, src, dst, *args, **kw)
297
return original(src, dst, *args, **kw)
298
299
return wrap
300
301
for name in ["rename", "link", "symlink"]:
302
if hasattr(_os, name):
303
locals()[name] = _mk_dual_path_wrapper(name)
304
305
def _mk_single_path_wrapper(name, original=None):
306
original = original or getattr(_os, name)
307
308
def wrap(self, path, *args, **kw):
309
if self._active:
310
path = self._remap_input(name, path, *args, **kw)
311
return original(path, *args, **kw)
312
313
return wrap
314
315
if _file:
316
_file = _mk_single_path_wrapper('file', _file)
317
_open = _mk_single_path_wrapper('open', _open)
318
for name in [
319
"stat", "listdir", "chdir", "open", "chmod", "chown", "mkdir",
320
"remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat",
321
"startfile", "mkfifo", "mknod", "pathconf", "access"
322
]:
323
if hasattr(_os, name):
324
locals()[name] = _mk_single_path_wrapper(name)
325
326
def _mk_single_with_return(name):
327
original = getattr(_os, name)
328
329
def wrap(self, path, *args, **kw):
330
if self._active:
331
path = self._remap_input(name, path, *args, **kw)
332
return self._remap_output(name, original(path, *args, **kw))
333
return original(path, *args, **kw)
334
335
return wrap
336
337
for name in ['readlink', 'tempnam']:
338
if hasattr(_os, name):
339
locals()[name] = _mk_single_with_return(name)
340
341
def _mk_query(name):
342
original = getattr(_os, name)
343
344
def wrap(self, *args, **kw):
345
retval = original(*args, **kw)
346
if self._active:
347
return self._remap_output(name, retval)
348
return retval
349
350
return wrap
351
352
for name in ['getcwd', 'tmpnam']:
353
if hasattr(_os, name):
354
locals()[name] = _mk_query(name)
355
356
def _validate_path(self, path):
357
"""Called to remap or validate any path, whether input or output"""
358
return path
359
360
def _remap_input(self, operation, path, *args, **kw):
361
"""Called for path inputs"""
362
return self._validate_path(path)
363
364
def _remap_output(self, operation, path):
365
"""Called for path outputs"""
366
return self._validate_path(path)
367
368
def _remap_pair(self, operation, src, dst, *args, **kw):
369
"""Called for path pairs like rename, link, and symlink operations"""
370
return (
371
self._remap_input(operation + '-from', src, *args, **kw),
372
self._remap_input(operation + '-to', dst, *args, **kw)
373
)
374
375
376
if hasattr(os, 'devnull'):
377
_EXCEPTIONS = [os.devnull]
378
else:
379
_EXCEPTIONS = []
380
381
382
class DirectorySandbox(AbstractSandbox):
383
"""Restrict operations to a single subdirectory - pseudo-chroot"""
384
385
write_ops = dict.fromkeys([
386
"open", "chmod", "chown", "mkdir", "remove", "unlink", "rmdir",
387
"utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam",
388
])
389
390
_exception_patterns = [
391
# Allow lib2to3 to attempt to save a pickled grammar object (#121)
392
r'.*lib2to3.*\.pickle$',
393
]
394
"exempt writing to paths that match the pattern"
395
396
def __init__(self, sandbox, exceptions=_EXCEPTIONS):
397
self._sandbox = os.path.normcase(os.path.realpath(sandbox))
398
self._prefix = os.path.join(self._sandbox, '')
399
self._exceptions = [
400
os.path.normcase(os.path.realpath(path))
401
for path in exceptions
402
]
403
AbstractSandbox.__init__(self)
404
405
def _violation(self, operation, *args, **kw):
406
from setuptools.sandbox import SandboxViolation
407
raise SandboxViolation(operation, args, kw)
408
409
if _file:
410
411
def _file(self, path, mode='r', *args, **kw):
412
if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path):
413
self._violation("file", path, mode, *args, **kw)
414
return _file(path, mode, *args, **kw)
415
416
def _open(self, path, mode='r', *args, **kw):
417
if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path):
418
self._violation("open", path, mode, *args, **kw)
419
return _open(path, mode, *args, **kw)
420
421
def tmpnam(self):
422
self._violation("tmpnam")
423
424
def _ok(self, path):
425
active = self._active
426
try:
427
self._active = False
428
realpath = os.path.normcase(os.path.realpath(path))
429
return (
430
self._exempted(realpath)
431
or realpath == self._sandbox
432
or realpath.startswith(self._prefix)
433
)
434
finally:
435
self._active = active
436
437
def _exempted(self, filepath):
438
start_matches = (
439
filepath.startswith(exception)
440
for exception in self._exceptions
441
)
442
pattern_matches = (
443
re.match(pattern, filepath)
444
for pattern in self._exception_patterns
445
)
446
candidates = itertools.chain(start_matches, pattern_matches)
447
return any(candidates)
448
449
def _remap_input(self, operation, path, *args, **kw):
450
"""Called for path inputs"""
451
if operation in self.write_ops and not self._ok(path):
452
self._violation(operation, os.path.realpath(path), *args, **kw)
453
return path
454
455
def _remap_pair(self, operation, src, dst, *args, **kw):
456
"""Called for path pairs like rename, link, and symlink operations"""
457
if not self._ok(src) or not self._ok(dst):
458
self._violation(operation, src, dst, *args, **kw)
459
return (src, dst)
460
461
def open(self, file, flags, mode=0o777, *args, **kw):
462
"""Called for low-level os.open()"""
463
if flags & WRITE_FLAGS and not self._ok(file):
464
self._violation("os.open", file, flags, mode, *args, **kw)
465
return _os.open(file, flags, mode, *args, **kw)
466
467
468
WRITE_FLAGS = functools.reduce(
469
operator.or_, [
470
getattr(_os, a, 0) for a in
471
"O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()]
472
)
473
474
475
class SandboxViolation(DistutilsError):
476
"""A setup script attempted to modify the filesystem outside the sandbox"""
477
478
tmpl = textwrap.dedent("""
479
SandboxViolation: {cmd}{args!r} {kwargs}
480
481
The package setup script has attempted to modify files on your system
482
that are not within the EasyInstall build area, and has been aborted.
483
484
This package cannot be safely installed by EasyInstall, and may not
485
support alternate installation locations even if you run its setup
486
script by hand. Please inform the package's author and the EasyInstall
487
maintainers to find out if a fix or workaround is available.
488
""").lstrip()
489
490
def __str__(self):
491
cmd, args, kwargs = self.args
492
return self.tmpl.format(**locals())
493
494