This commit is contained in:
lz_db
2026-10-16 22:48:30 +08:00
parent 190de72571
commit 0b36fd3383
3161 changed files with 12787 additions and 77274 deletions
@@ -1,36 +1,30 @@
from __future__ import annotations
import builtins
import contextlib
import functools
import itertools
import operator
import os
import pickle
import re
import sys
import tempfile
import operator
import functools
import itertools
import re
import contextlib
import pickle
import textwrap
from types import TracebackType
from typing import TYPE_CHECKING, Any, ClassVar
import builtins
import pkg_resources
from distutils.errors import DistutilsError
from pkg_resources import working_set
from distutils.errors import DistutilsError
if TYPE_CHECKING:
import os as _os
elif sys.platform.startswith('java'):
import org.python.modules.posix.PosixModule as _os # pyright: ignore[reportMissingImports]
if sys.platform.startswith('java'):
import org.python.modules.posix.PosixModule as _os
else:
_os = sys.modules[os.name]
try:
_file = file
except NameError:
_file = None
_open = open
if TYPE_CHECKING:
from typing_extensions import Self
__all__ = [
"AbstractSandbox",
"DirectorySandbox",
@@ -121,21 +115,16 @@ class UnpickleableException(Exception):
class ExceptionSaver:
"""
A Context Manager that will save an exception, serialize, and restore it
A Context Manager that will save an exception, serialized, and restore it
later.
"""
def __enter__(self) -> Self:
def __enter__(self):
return self
def __exit__(
self,
type: type[BaseException] | None,
exc: BaseException | None,
tb: TracebackType | None,
) -> bool:
def __exit__(self, type, exc, tb):
if not exc:
return False
return
# dump the exception
self._saved = UnpickleableException.dump(type, exc)
@@ -150,7 +139,7 @@ class ExceptionSaver:
if '_saved' not in vars(self):
return
_type, exc = map(pickle.loads, self._saved)
type, exc = map(pickle.loads, self._saved)
raise exc.with_traceback(self._tb)
@@ -248,7 +237,7 @@ def hide_setuptools():
"""
_distutils_hack = sys.modules.get('_distutils_hack', None)
if _distutils_hack is not None:
_distutils_hack._remove_shim()
_distutils_hack.remove_shim()
modules = filter(_needs_hiding, sys.modules)
_clear_modules(modules)
@@ -279,7 +268,7 @@ class AbstractSandbox:
_active = False
def __init__(self) -> None:
def __init__(self):
self._attrs = [
name
for name in dir(_os)
@@ -290,18 +279,17 @@ class AbstractSandbox:
for name in self._attrs:
setattr(os, name, getattr(source, name))
def __enter__(self) -> None:
def __enter__(self):
self._copy(self)
if _file:
builtins.file = self._file
builtins.open = self._open
self._active = True
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_value: BaseException | None,
traceback: TracebackType | None,
):
def __exit__(self, exc_type, exc_value, traceback):
self._active = False
if _file:
builtins.file = _file
builtins.open = _open
self._copy(_os)
@@ -310,7 +298,7 @@ class AbstractSandbox:
with self:
return func()
def _mk_dual_path_wrapper(name: str): # type: ignore[misc] # https://github.com/pypa/setuptools/pull/4099
def _mk_dual_path_wrapper(name):
original = getattr(_os, name)
def wrap(self, src, dst, *args, **kw):
@@ -320,11 +308,11 @@ class AbstractSandbox:
return wrap
for __name in ["rename", "link", "symlink"]:
if hasattr(_os, __name):
locals()[__name] = _mk_dual_path_wrapper(__name)
for name in ["rename", "link", "symlink"]:
if hasattr(_os, name):
locals()[name] = _mk_dual_path_wrapper(name)
def _mk_single_path_wrapper(name: str, original=None): # type: ignore[misc] # https://github.com/pypa/setuptools/pull/4099
def _mk_single_path_wrapper(name, original=None):
original = original or getattr(_os, name)
def wrap(self, path, *args, **kw):
@@ -334,8 +322,10 @@ class AbstractSandbox:
return wrap
if _file:
_file = _mk_single_path_wrapper('file', _file)
_open = _mk_single_path_wrapper('open', _open)
for __name in [
for name in [
"stat",
"listdir",
"chdir",
@@ -356,10 +346,10 @@ class AbstractSandbox:
"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: str): # type: ignore[misc] # https://github.com/pypa/setuptools/pull/4099
def _mk_single_with_return(name):
original = getattr(_os, name)
def wrap(self, path, *args, **kw):
@@ -370,11 +360,11 @@ class AbstractSandbox:
return wrap
for __name in ['readlink', 'tempnam']:
if hasattr(_os, __name):
locals()[__name] = _mk_single_with_return(__name)
for name in ['readlink', 'tempnam']:
if hasattr(_os, name):
locals()[name] = _mk_single_with_return(name)
def _mk_query(name: str): # type: ignore[misc] # https://github.com/pypa/setuptools/pull/4099
def _mk_query(name):
original = getattr(_os, name)
def wrap(self, *args, **kw):
@@ -385,9 +375,9 @@ class AbstractSandbox:
return wrap
for __name in ['getcwd', 'tmpnam']:
if hasattr(_os, __name):
locals()[__name] = _mk_query(__name)
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"""
@@ -408,11 +398,6 @@ class AbstractSandbox:
self._remap_input(operation + '-to', dst, *args, **kw),
)
if TYPE_CHECKING:
# This is a catch-all for all the dynamically created attributes.
# This isn't public API anyway
def __getattribute__(self, name: str) -> Any: ...
if hasattr(os, 'devnull'):
_EXCEPTIONS = [os.devnull]
@@ -423,26 +408,28 @@ else:
class DirectorySandbox(AbstractSandbox):
"""Restrict operations to a single subdirectory - pseudo-chroot"""
write_ops: ClassVar[dict[str, None]] = 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: list[str | re.Pattern] = []
_exception_patterns = []
"exempt writing to paths that match the pattern"
def __init__(self, sandbox, exceptions=_EXCEPTIONS) -> None:
def __init__(self, sandbox, exceptions=_EXCEPTIONS):
self._sandbox = os.path.normcase(os.path.realpath(sandbox))
self._prefix = os.path.join(self._sandbox, '')
self._exceptions = [
@@ -455,12 +442,19 @@ 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)
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)
def tmpnam(self) -> None:
def tmpnam(self):
self._violation("tmpnam")
def _ok(self, path):
@@ -498,7 +492,7 @@ class DirectorySandbox(AbstractSandbox):
self._violation(operation, src, dst, *args, **kw)
return (src, dst)
def open(self, file, flags, mode: int = 0o777, *args, **kw) -> int:
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)
@@ -531,6 +525,6 @@ class SandboxViolation(DistutilsError):
"""
).lstrip()
def __str__(self) -> str:
def __str__(self):
cmd, args, kwargs = self.args
return self.tmpl.format(**locals())