[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/microsoft/vscode-python/main/python_files/get_variable_info.py [Back]  [Original]

# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE in the project root
# for license information.

import locale
import sys
from typing import ClassVar


# this class is from in ptvsd/debugpy tools
class SafeRepr(object):  # noqa: UP004
    # Can be used to override the encoding from locale.getpreferredencoding()
    locale_preferred_encoding = None

    # Can be used to override the encoding used for sys.stdout.encoding
    sys_stdout_encoding = None

    # String types are truncated to maxstring_outer when at the outer-
    # most level, and truncated to maxstring_inner characters inside
    # collections.
    maxstring_outer = 2**16
    maxstring_inner = 128
    string_types = (str, bytes)
    bytes = bytes
    set_info = (set, "{", "}", False)
    frozenset_info = (frozenset, "frozenset({", "})", False)
    int_types = (int,)
    long_iter_types = (list, tuple, bytearray, range, dict, set, frozenset)

    # Collection types are recursively iterated for each limit in
    # maxcollection.
    maxcollection = (60, 20)

    # Specifies type, prefix string, suffix string, and whether to include a
    # comma if there is only one element. (Using a sequence rather than a
    # mapping because we use isinstance() to determine the matching type.)
    collection_types = [  # noqa: RUF012
        (tuple, "(", ")", True),
        (list, "[", "]", False),
        frozenset_info,
        set_info,
    ]
    try:
        from collections import deque

        collection_types.append((deque, "deque([", "])", False))
    except Exception:
        pass

    # type, prefix string, suffix string, item prefix string,
    # item key/value separator, item suffix string
    dict_types: ClassVar[list] = [(dict, "{", "}", "", ": ", "")]
    try:
        from collections import OrderedDict

        dict_types.append((OrderedDict, "OrderedDict([", "])", "(", ", ", ")"))
    except Exception:
        pass

    # All other types are treated identically to strings, but using
    # different limits.
    maxother_outer = 2**16
    maxother_inner = 128

    convert_to_hex = False
    raw_value = False

    def __call__(self, obj):
        """
        :param object obj:
            The object for which we want a representation.

        :return str:
            Returns bytes encoded as utf-8 on py2 and str on py3.
        """  # noqa: D205
        try:
            return "".join(self._repr(obj, 0))
        except Exception:
            try:
                return f"An exception was raised: {sys.exc_info()[1]!r}"
            except Exception:
                return "An exception was raised"

    def _repr(self, obj, level):
        """Returns an iterable of the parts in the final repr string."""
        try:
            obj_repr = type(obj).__repr__
        except Exception:
            obj_repr = None

        def has_obj_repr(t):
            r = t.__repr__
            try:
                return obj_repr == r
            except Exception:
                return obj_repr is r

        for t, prefix, suffix, comma in self.collection_types:
            if isinstance(obj, t) and has_obj_repr(t):
                return self._repr_iter(obj, level, prefix, suffix, comma)

        for (
            t,
            prefix,
            suffix,
            item_prefix,
            item_sep,
            item_suffix,
        ) in self.dict_types:
            if isinstance(obj, t) and has_obj_repr(t):
                return self._repr_dict(
                    obj, level, prefix, suffix, item_prefix, item_sep, item_suffix
                )

        for t in self.string_types:
            if isinstance(obj, t) and has_obj_repr(t):
                return self._repr_str(obj, level)

        if self._is_long_iter(obj):
            return self._repr_long_iter(obj)

        return self._repr_other(obj, level)

    # Determines whether an iterable exceeds the limits set in
    # maxlimits, and is therefore unsafe to repr().
    def _is_long_iter(self, obj, level=0):
        try:
            # Strings have their own limits (and do not nest). Because
            # they don't have __iter__ in 2.x, this check goes before
            # the next one.
            if isinstance(obj, self.string_types):
                return len(obj) > self.maxstring_inner

            # If it's not an iterable (and not a string), it's fine.
            if not hasattr(obj, "__iter__"):
                return False

            # If it's not an instance of these collection types then it
            # is fine. Note: this is a fix for
            # https://github.com/Microsoft/ptvsd/issues/406
            if not isinstance(obj, self.long_iter_types):
                return False

            # Iterable is its own iterator - this is a one-off iterable
            # like generator or enumerate(). We can't really count that,
            # but repr() for these should not include any elements anyway,
            # so we can treat it the same as non-iterables.
            if obj is iter(obj):
                return False

            # range reprs fine regardless of length.
            if isinstance(obj, range):
                return False

            # numpy and scipy collections (ndarray etc) have
            # self-truncating repr, so they're always safe.
            try:
                module = type(obj).__module__.partition(".")[0]
                if module in ("numpy", "scipy"):
                    return False
            except Exception:
                pass

            # Iterables that nest too deep are considered long.
            if level >= len(self.maxcollection):
                return True

            # It is too long if the length exceeds the limit, or any
            # of its elements are long iterables.
            if hasattr(obj, "__len__"):
                try:
                    size = len(obj)
                except Exception:
                    size = None
                if size is not None and size > self.maxcollection[level]:
                    return True
                return any(self._is_long_iter(item, level + 1) for item in obj)
            return any(
                i > self.maxcollection[level] or self._is_long_iter(item, level + 1)
                for i, item in enumerate(obj)
            )

        except Exception:
            # If anything breaks, assume the worst case.
            return True

    def _repr_iter(self, obj, level, prefix, suffix, comma_after_single_element=False):  # noqa: FBT002
        yield prefix

        if level >= len(self.maxcollection):
            yield "..."
        else:
            count = self.maxcollection[level]
            yield_comma = False
            for item in obj:
                if yield_comma:
                    yield ", "
                yield_comma = True

                count -= 1
                if count = len(self.maxcollection):
            yield prefix + "..." + suffix
            return

        yield prefix

        count = self.maxcollection[level]
        yield_comma = False

        obj_keys = list(obj)

        for key in obj_keys:
            if yield_comma:
                yield ", "
            yield_comma = True

            count -= 1
            if count 

Web Proxy Viewer  |  New URL  |  Original Page