diff env/lib/python3.7/site-packages/jinja2/sandbox.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
line wrap: on
line diff
--- a/env/lib/python3.7/site-packages/jinja2/sandbox.py	Thu May 14 16:47:39 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,510 +0,0 @@
-# -*- coding: utf-8 -*-
-"""A sandbox layer that ensures unsafe operations cannot be performed.
-Useful when the template itself comes from an untrusted source.
-"""
-import operator
-import types
-import warnings
-from collections import deque
-from string import Formatter
-
-from markupsafe import EscapeFormatter
-from markupsafe import Markup
-
-from ._compat import abc
-from ._compat import PY2
-from ._compat import range_type
-from ._compat import string_types
-from .environment import Environment
-from .exceptions import SecurityError
-
-#: maximum number of items a range may produce
-MAX_RANGE = 100000
-
-#: attributes of function objects that are considered unsafe.
-if PY2:
-    UNSAFE_FUNCTION_ATTRIBUTES = {
-        "func_closure",
-        "func_code",
-        "func_dict",
-        "func_defaults",
-        "func_globals",
-    }
-else:
-    # On versions > python 2 the special attributes on functions are gone,
-    # but they remain on methods and generators for whatever reason.
-    UNSAFE_FUNCTION_ATTRIBUTES = set()
-
-#: unsafe method attributes.  function attributes are unsafe for methods too
-UNSAFE_METHOD_ATTRIBUTES = {"im_class", "im_func", "im_self"}
-
-#: unsafe generator attributes.
-UNSAFE_GENERATOR_ATTRIBUTES = {"gi_frame", "gi_code"}
-
-#: unsafe attributes on coroutines
-UNSAFE_COROUTINE_ATTRIBUTES = {"cr_frame", "cr_code"}
-
-#: unsafe attributes on async generators
-UNSAFE_ASYNC_GENERATOR_ATTRIBUTES = {"ag_code", "ag_frame"}
-
-# make sure we don't warn in python 2.6 about stuff we don't care about
-warnings.filterwarnings(
-    "ignore", "the sets module", DeprecationWarning, module=__name__
-)
-
-_mutable_set_types = (set,)
-_mutable_mapping_types = (dict,)
-_mutable_sequence_types = (list,)
-
-# on python 2.x we can register the user collection types
-try:
-    from UserDict import UserDict, DictMixin
-    from UserList import UserList
-
-    _mutable_mapping_types += (UserDict, DictMixin)
-    _mutable_set_types += (UserList,)
-except ImportError:
-    pass
-
-# if sets is still available, register the mutable set from there as well
-try:
-    from sets import Set
-
-    _mutable_set_types += (Set,)
-except ImportError:
-    pass
-
-#: register Python 2.6 abstract base classes
-_mutable_set_types += (abc.MutableSet,)
-_mutable_mapping_types += (abc.MutableMapping,)
-_mutable_sequence_types += (abc.MutableSequence,)
-
-_mutable_spec = (
-    (
-        _mutable_set_types,
-        frozenset(
-            [
-                "add",
-                "clear",
-                "difference_update",
-                "discard",
-                "pop",
-                "remove",
-                "symmetric_difference_update",
-                "update",
-            ]
-        ),
-    ),
-    (
-        _mutable_mapping_types,
-        frozenset(["clear", "pop", "popitem", "setdefault", "update"]),
-    ),
-    (
-        _mutable_sequence_types,
-        frozenset(["append", "reverse", "insert", "sort", "extend", "remove"]),
-    ),
-    (
-        deque,
-        frozenset(
-            [
-                "append",
-                "appendleft",
-                "clear",
-                "extend",
-                "extendleft",
-                "pop",
-                "popleft",
-                "remove",
-                "rotate",
-            ]
-        ),
-    ),
-)
-
-
-class _MagicFormatMapping(abc.Mapping):
-    """This class implements a dummy wrapper to fix a bug in the Python
-    standard library for string formatting.
-
-    See https://bugs.python.org/issue13598 for information about why
-    this is necessary.
-    """
-
-    def __init__(self, args, kwargs):
-        self._args = args
-        self._kwargs = kwargs
-        self._last_index = 0
-
-    def __getitem__(self, key):
-        if key == "":
-            idx = self._last_index
-            self._last_index += 1
-            try:
-                return self._args[idx]
-            except LookupError:
-                pass
-            key = str(idx)
-        return self._kwargs[key]
-
-    def __iter__(self):
-        return iter(self._kwargs)
-
-    def __len__(self):
-        return len(self._kwargs)
-
-
-def inspect_format_method(callable):
-    if not isinstance(
-        callable, (types.MethodType, types.BuiltinMethodType)
-    ) or callable.__name__ not in ("format", "format_map"):
-        return None
-    obj = callable.__self__
-    if isinstance(obj, string_types):
-        return obj
-
-
-def safe_range(*args):
-    """A range that can't generate ranges with a length of more than
-    MAX_RANGE items.
-    """
-    rng = range_type(*args)
-
-    if len(rng) > MAX_RANGE:
-        raise OverflowError(
-            "Range too big. The sandbox blocks ranges larger than"
-            " MAX_RANGE (%d)." % MAX_RANGE
-        )
-
-    return rng
-
-
-def unsafe(f):
-    """Marks a function or method as unsafe.
-
-    ::
-
-        @unsafe
-        def delete(self):
-            pass
-    """
-    f.unsafe_callable = True
-    return f
-
-
-def is_internal_attribute(obj, attr):
-    """Test if the attribute given is an internal python attribute.  For
-    example this function returns `True` for the `func_code` attribute of
-    python objects.  This is useful if the environment method
-    :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden.
-
-    >>> from jinja2.sandbox import is_internal_attribute
-    >>> is_internal_attribute(str, "mro")
-    True
-    >>> is_internal_attribute(str, "upper")
-    False
-    """
-    if isinstance(obj, types.FunctionType):
-        if attr in UNSAFE_FUNCTION_ATTRIBUTES:
-            return True
-    elif isinstance(obj, types.MethodType):
-        if attr in UNSAFE_FUNCTION_ATTRIBUTES or attr in UNSAFE_METHOD_ATTRIBUTES:
-            return True
-    elif isinstance(obj, type):
-        if attr == "mro":
-            return True
-    elif isinstance(obj, (types.CodeType, types.TracebackType, types.FrameType)):
-        return True
-    elif isinstance(obj, types.GeneratorType):
-        if attr in UNSAFE_GENERATOR_ATTRIBUTES:
-            return True
-    elif hasattr(types, "CoroutineType") and isinstance(obj, types.CoroutineType):
-        if attr in UNSAFE_COROUTINE_ATTRIBUTES:
-            return True
-    elif hasattr(types, "AsyncGeneratorType") and isinstance(
-        obj, types.AsyncGeneratorType
-    ):
-        if attr in UNSAFE_ASYNC_GENERATOR_ATTRIBUTES:
-            return True
-    return attr.startswith("__")
-
-
-def modifies_known_mutable(obj, attr):
-    """This function checks if an attribute on a builtin mutable object
-    (list, dict, set or deque) would modify it if called.  It also supports
-    the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
-    with Python 2.6 onwards the abstract base classes `MutableSet`,
-    `MutableMapping`, and `MutableSequence`.
-
-    >>> modifies_known_mutable({}, "clear")
-    True
-    >>> modifies_known_mutable({}, "keys")
-    False
-    >>> modifies_known_mutable([], "append")
-    True
-    >>> modifies_known_mutable([], "index")
-    False
-
-    If called with an unsupported object (such as unicode) `False` is
-    returned.
-
-    >>> modifies_known_mutable("foo", "upper")
-    False
-    """
-    for typespec, unsafe in _mutable_spec:
-        if isinstance(obj, typespec):
-            return attr in unsafe
-    return False
-
-
-class SandboxedEnvironment(Environment):
-    """The sandboxed environment.  It works like the regular environment but
-    tells the compiler to generate sandboxed code.  Additionally subclasses of
-    this environment may override the methods that tell the runtime what
-    attributes or functions are safe to access.
-
-    If the template tries to access insecure code a :exc:`SecurityError` is
-    raised.  However also other exceptions may occur during the rendering so
-    the caller has to ensure that all exceptions are caught.
-    """
-
-    sandboxed = True
-
-    #: default callback table for the binary operators.  A copy of this is
-    #: available on each instance of a sandboxed environment as
-    #: :attr:`binop_table`
-    default_binop_table = {
-        "+": operator.add,
-        "-": operator.sub,
-        "*": operator.mul,
-        "/": operator.truediv,
-        "//": operator.floordiv,
-        "**": operator.pow,
-        "%": operator.mod,
-    }
-
-    #: default callback table for the unary operators.  A copy of this is
-    #: available on each instance of a sandboxed environment as
-    #: :attr:`unop_table`
-    default_unop_table = {"+": operator.pos, "-": operator.neg}
-
-    #: a set of binary operators that should be intercepted.  Each operator
-    #: that is added to this set (empty by default) is delegated to the
-    #: :meth:`call_binop` method that will perform the operator.  The default
-    #: operator callback is specified by :attr:`binop_table`.
-    #:
-    #: The following binary operators are interceptable:
-    #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**``
-    #:
-    #: The default operation form the operator table corresponds to the
-    #: builtin function.  Intercepted calls are always slower than the native
-    #: operator call, so make sure only to intercept the ones you are
-    #: interested in.
-    #:
-    #: .. versionadded:: 2.6
-    intercepted_binops = frozenset()
-
-    #: a set of unary operators that should be intercepted.  Each operator
-    #: that is added to this set (empty by default) is delegated to the
-    #: :meth:`call_unop` method that will perform the operator.  The default
-    #: operator callback is specified by :attr:`unop_table`.
-    #:
-    #: The following unary operators are interceptable: ``+``, ``-``
-    #:
-    #: The default operation form the operator table corresponds to the
-    #: builtin function.  Intercepted calls are always slower than the native
-    #: operator call, so make sure only to intercept the ones you are
-    #: interested in.
-    #:
-    #: .. versionadded:: 2.6
-    intercepted_unops = frozenset()
-
-    def intercept_unop(self, operator):
-        """Called during template compilation with the name of a unary
-        operator to check if it should be intercepted at runtime.  If this
-        method returns `True`, :meth:`call_unop` is executed for this unary
-        operator.  The default implementation of :meth:`call_unop` will use
-        the :attr:`unop_table` dictionary to perform the operator with the
-        same logic as the builtin one.
-
-        The following unary operators are interceptable: ``+`` and ``-``
-
-        Intercepted calls are always slower than the native operator call,
-        so make sure only to intercept the ones you are interested in.
-
-        .. versionadded:: 2.6
-        """
-        return False
-
-    def __init__(self, *args, **kwargs):
-        Environment.__init__(self, *args, **kwargs)
-        self.globals["range"] = safe_range
-        self.binop_table = self.default_binop_table.copy()
-        self.unop_table = self.default_unop_table.copy()
-
-    def is_safe_attribute(self, obj, attr, value):
-        """The sandboxed environment will call this method to check if the
-        attribute of an object is safe to access.  Per default all attributes
-        starting with an underscore are considered private as well as the
-        special attributes of internal python objects as returned by the
-        :func:`is_internal_attribute` function.
-        """
-        return not (attr.startswith("_") or is_internal_attribute(obj, attr))
-
-    def is_safe_callable(self, obj):
-        """Check if an object is safely callable.  Per default a function is
-        considered safe unless the `unsafe_callable` attribute exists and is
-        True.  Override this method to alter the behavior, but this won't
-        affect the `unsafe` decorator from this module.
-        """
-        return not (
-            getattr(obj, "unsafe_callable", False) or getattr(obj, "alters_data", False)
-        )
-
-    def call_binop(self, context, operator, left, right):
-        """For intercepted binary operator calls (:meth:`intercepted_binops`)
-        this function is executed instead of the builtin operator.  This can
-        be used to fine tune the behavior of certain operators.
-
-        .. versionadded:: 2.6
-        """
-        return self.binop_table[operator](left, right)
-
-    def call_unop(self, context, operator, arg):
-        """For intercepted unary operator calls (:meth:`intercepted_unops`)
-        this function is executed instead of the builtin operator.  This can
-        be used to fine tune the behavior of certain operators.
-
-        .. versionadded:: 2.6
-        """
-        return self.unop_table[operator](arg)
-
-    def getitem(self, obj, argument):
-        """Subscribe an object from sandboxed code."""
-        try:
-            return obj[argument]
-        except (TypeError, LookupError):
-            if isinstance(argument, string_types):
-                try:
-                    attr = str(argument)
-                except Exception:
-                    pass
-                else:
-                    try:
-                        value = getattr(obj, attr)
-                    except AttributeError:
-                        pass
-                    else:
-                        if self.is_safe_attribute(obj, argument, value):
-                            return value
-                        return self.unsafe_undefined(obj, argument)
-        return self.undefined(obj=obj, name=argument)
-
-    def getattr(self, obj, attribute):
-        """Subscribe an object from sandboxed code and prefer the
-        attribute.  The attribute passed *must* be a bytestring.
-        """
-        try:
-            value = getattr(obj, attribute)
-        except AttributeError:
-            try:
-                return obj[attribute]
-            except (TypeError, LookupError):
-                pass
-        else:
-            if self.is_safe_attribute(obj, attribute, value):
-                return value
-            return self.unsafe_undefined(obj, attribute)
-        return self.undefined(obj=obj, name=attribute)
-
-    def unsafe_undefined(self, obj, attribute):
-        """Return an undefined object for unsafe attributes."""
-        return self.undefined(
-            "access to attribute %r of %r "
-            "object is unsafe." % (attribute, obj.__class__.__name__),
-            name=attribute,
-            obj=obj,
-            exc=SecurityError,
-        )
-
-    def format_string(self, s, args, kwargs, format_func=None):
-        """If a format call is detected, then this is routed through this
-        method so that our safety sandbox can be used for it.
-        """
-        if isinstance(s, Markup):
-            formatter = SandboxedEscapeFormatter(self, s.escape)
-        else:
-            formatter = SandboxedFormatter(self)
-
-        if format_func is not None and format_func.__name__ == "format_map":
-            if len(args) != 1 or kwargs:
-                raise TypeError(
-                    "format_map() takes exactly one argument %d given"
-                    % (len(args) + (kwargs is not None))
-                )
-
-            kwargs = args[0]
-            args = None
-
-        kwargs = _MagicFormatMapping(args, kwargs)
-        rv = formatter.vformat(s, args, kwargs)
-        return type(s)(rv)
-
-    def call(__self, __context, __obj, *args, **kwargs):  # noqa: B902
-        """Call an object from sandboxed code."""
-        fmt = inspect_format_method(__obj)
-        if fmt is not None:
-            return __self.format_string(fmt, args, kwargs, __obj)
-
-        # the double prefixes are to avoid double keyword argument
-        # errors when proxying the call.
-        if not __self.is_safe_callable(__obj):
-            raise SecurityError("%r is not safely callable" % (__obj,))
-        return __context.call(__obj, *args, **kwargs)
-
-
-class ImmutableSandboxedEnvironment(SandboxedEnvironment):
-    """Works exactly like the regular `SandboxedEnvironment` but does not
-    permit modifications on the builtin mutable objects `list`, `set`, and
-    `dict` by using the :func:`modifies_known_mutable` function.
-    """
-
-    def is_safe_attribute(self, obj, attr, value):
-        if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
-            return False
-        return not modifies_known_mutable(obj, attr)
-
-
-# This really is not a public API apparently.
-try:
-    from _string import formatter_field_name_split
-except ImportError:
-
-    def formatter_field_name_split(field_name):
-        return field_name._formatter_field_name_split()
-
-
-class SandboxedFormatterMixin(object):
-    def __init__(self, env):
-        self._env = env
-
-    def get_field(self, field_name, args, kwargs):
-        first, rest = formatter_field_name_split(field_name)
-        obj = self.get_value(first, args, kwargs)
-        for is_attr, i in rest:
-            if is_attr:
-                obj = self._env.getattr(obj, i)
-            else:
-                obj = self._env.getitem(obj, i)
-        return obj, first
-
-
-class SandboxedFormatter(SandboxedFormatterMixin, Formatter):
-    def __init__(self, env):
-        SandboxedFormatterMixin.__init__(self, env)
-        Formatter.__init__(self)
-
-
-class SandboxedEscapeFormatter(SandboxedFormatterMixin, EscapeFormatter):
-    def __init__(self, env, escape):
-        SandboxedFormatterMixin.__init__(self, env)
-        EscapeFormatter.__init__(self, escape)