diff --git a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_constants.py b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_constants.py index 77cf2f054ac3..415d07239a82 100644 --- a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_constants.py +++ b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_constants.py @@ -1,3 +1,5 @@ +import sys + try: xrange = xrange except: @@ -6,3 +8,105 @@ except: NUMPY_NUMERIC_TYPES = "biufc" NUMPY_FLOATING_POINT_TYPES = "fc" +IS_PYCHARM = True + +#======================================================================================================================= +# Python 3? +#======================================================================================================================= +IS_PY3K = False +IS_PY34_OR_GREATER = False +IS_PY36_OR_GREATER = False +IS_PY37_OR_GREATER = False +IS_PY36_OR_LESSER = False +IS_PY38_OR_GREATER = False +IS_PY38 = False +IS_PY39 = False +IS_PY39_OR_GREATER = False +IS_PY310 = False +IS_PY310_OR_GREATER = False +IS_PY311 = False +IS_PY311_OR_GREATER = False +IS_PY312_OR_GREATER = False +IS_PY312_OR_LESSER = False +IS_PY313 = False +IS_PY313_OR_GREATER = False +IS_PY313_OR_LESSER = False +IS_PY314 = False +IS_PY2 = True +IS_PY27 = False +IS_PY24 = False +try: + if sys.version_info[0] >= 3: + IS_PY3K = True + IS_PY2 = False + IS_PY34_OR_GREATER = sys.version_info >= (3, 4) + IS_PY36_OR_GREATER = sys.version_info >= (3, 6) + IS_PY37_OR_GREATER = sys.version_info >= (3, 7) + IS_PY36_OR_LESSER = sys.version_info[:2] <= (3, 6) + IS_PY38 = sys.version_info[0] == 3 and sys.version_info[1] == 8 + IS_PY38_OR_GREATER = sys.version_info >= (3, 8) + IS_PY39 = sys.version_info[0] == 3 and sys.version_info[1] == 9 + IS_PY39_OR_GREATER = sys.version_info >= (3, 9) + IS_PY310 = sys.version_info[0] == 3 and sys.version_info[1] == 10 + IS_PY310_OR_GREATER = sys.version_info >= (3, 10) + IS_PY311 = sys.version_info[0] == 3 and sys.version_info[1] == 11 + IS_PY311_OR_GREATER = sys.version_info >= (3, 11) + IS_PY312_OR_GREATER = sys.version_info >= (3, 12) + IS_PY312_OR_LESSER = sys.version_info[:2] <= (3, 12) + IS_PY313 = sys.version_info[0] == 3 and sys.version_info[1] == 13 + IS_PY313_OR_GREATER = sys.version_info >= (3, 13) + IS_PY313_OR_LESSER = sys.version_info[:2] <= (3, 13) + IS_PY314 = sys.version_info[0] == 3 and sys.version_info[1] == 14 + elif sys.version_info[0] == 2 and sys.version_info[1] == 7: + IS_PY27 = True + elif sys.version_info[0] == 2 and sys.version_info[1] == 4: + IS_PY24 = True +except AttributeError: + pass # Not all versions have sys.version_info + + +if IS_PY3K: + + def dict_keys(d): + return list(d.keys()) + + def dict_values(d): + return list(d.values()) + + dict_iter_values = dict.values + + def dict_iter_items(d): + return d.items() + + def dict_items(d): + return list(d.items()) + +else: + def dict_keys(d): + return d.keys() + + try: + dict_iter_values = dict.itervalues + except: + try: + dict_iter_values = dict.values # Older versions don't have the itervalues + except: + + def dict_iter_values(d): + return d.values() + + try: + dict_values = dict.values + except: + + def dict_values(d): + return d.values() + + def dict_iter_items(d): + try: + return d.iteritems() + except: + return d.items() + + def dict_items(d): + return d.items() \ No newline at end of file diff --git a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_repr_utils.py b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_repr_utils.py new file mode 100644 index 000000000000..49e78f2d755c --- /dev/null +++ b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_repr_utils.py @@ -0,0 +1,283 @@ +# Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +from array import array +from collections import deque + +from _pydev_bundle import pydev_log +from _pydevd_bundle.custom.pydevd_constants import IS_PY3K +from _pydevd_bundle.custom.pydevd_utils import take_first_n_coll_elements + +# Maximum final result string length +MAX_REPR_LENGTH = 1000 +# Maximum number of value elements +MAX_REPR_ITEM_SIZE = 256 +DEFAULT_FORMAT = '%s' + + +def _get_ndarray_variable_repr(num_array, max_items=MAX_REPR_ITEM_SIZE): + # ndarray.__str__() is already optimised and works fast enough + if num_array.ndim == 0: + return str(num_array).replace('\n', ',').strip() + else: + return str(num_array[:max_items]).replace('\n', ',').strip() + + +def _get_series_variable_repr(series, max_items=MAX_REPR_ITEM_SIZE): + res = [] + total_length = 0 + series = series.iloc[:max_items] + for item in series.items(): + # item: (index, value) + item_repr = str(item) + res.append(item_repr) + total_length += len(item_repr) + if total_length > MAX_REPR_LENGTH: + break + return ' '.join(res) + + +def _get_df_variable_repr(data_frame): + # Avoid using df.iteritems() or df.values[i], because it works very slow for + # large data frames. df.__str__() is already optimised and works fast enough. + data_preview = [] + column_row = 0 + shape_rows, shape_cols = data_frame.shape + if shape_cols > 1000 or shape_rows > 10000: + head_number = 1 + else: + head_number = 3 + rows = str(data_frame.head(head_number)).split('\n') + for (i, r) in enumerate(rows): + if i != column_row: + data_preview.append("[%s]" % r) + + if r == '': + column_row = i + 1 + + # The string provided is used for column name completion + # by JupyterVarsFrameExecutor.parseFrameVars + return '%s %s' % (list(data_frame.columns), ' '.join(data_preview)) + + +def _trim_string_repr_if_needed(value, do_trim=True, max_length=MAX_REPR_LENGTH): + if len(value) > max_length and do_trim: + value = value[:max_length] + value += '...' + return value + + +def _get_external_collection_repr(collection, raise_exception=False): + typename = type(collection).__name__ + typename_with_package = type(collection) + + # pandas var + try: + if typename == "Series" or typename == "GeoSeries": + return _get_series_variable_repr(collection) + if typename == "DataFrame" or typename == "GeoDataFrame": + return _get_df_variable_repr(collection) + except Exception as e: + pydev_log.warn("Failed to format pandas variable: " + str(e)) + if raise_exception: + raise e + # ndarray and other numpy types + try: + if typename == 'ndarray' or "numpy." in str(typename_with_package): + return _get_ndarray_variable_repr(collection) + except Exception as e: + pydev_log.warn("Failed to format numpy ndarray: " + str(e)) + if raise_exception: + raise e + return None + + +pydevd_repr_function_python2 = None + + +if IS_PY3K: + from reprlib import Repr + from itertools import islice + + + def _possibly_sorted(x): + # Since not all sequences of items can be sorted and comparison + # functions may raise arbitrary exceptions, return an unsorted + # sequence in that case. + try: + return sorted(x) + except Exception: + return list(x) + + + class PydevdRepr(Repr): + def __init__(self, do_trim): + super(PydevdRepr, self).__init__() + self.fillvalue = '...' + self.maxdict = MAX_REPR_ITEM_SIZE + self.maxlist = MAX_REPR_ITEM_SIZE + self.maxtuple = MAX_REPR_ITEM_SIZE + self.maxset = MAX_REPR_ITEM_SIZE + self.maxfrozenset = MAX_REPR_ITEM_SIZE + self.maxdeque = MAX_REPR_ITEM_SIZE + self.maxarray = MAX_REPR_ITEM_SIZE + self.maxlong = MAX_REPR_ITEM_SIZE + self.maxstring = MAX_REPR_ITEM_SIZE + self.maxother = MAX_REPR_ITEM_SIZE + self.do_trim = do_trim + + def _repr_iterable(self, x, level, left, right, maxiter, trail=''): + n = len(x) + if level <= 0 and n: + s = self.fillvalue + else: + newlevel = level - 1 + repr1 = self.repr1 + pieces = [] + curr_length = 0 + max_elements = maxiter if self.do_trim else n + for elem in islice(x, max_elements): + elem_repr = repr1(elem, newlevel) + curr_length += len(elem_repr) + pieces.append(elem_repr) + if curr_length >= MAX_REPR_LENGTH and self.do_trim: + break + + if (n > maxiter or curr_length >= MAX_REPR_LENGTH) and self.do_trim: + pieces.append(self.fillvalue) + s = ', '.join(pieces) + if n == 1 and trail: + right = trail + right + return '%s%s%s' % (left, s, right) + + def repr_str(self, x, level): + if level == self.maxlevel: + if self.do_trim: + return x[:self.maxstring] + else: + return x + else: + if self.do_trim: + return super().repr_str(x, level) + else: + return "'{x}'".format(x=x) + + def repr_dict(self, x, level): + n = len(x) + if n == 0: return '{}' + if level <= 0: return '{...}' + newlevel = level - 1 + repr1 = self.repr1 + pieces = [] + curr_length = 0 + max_elements = self.maxdict if self.do_trim else n + for key in islice(_possibly_sorted(x), max_elements): + keyrepr = repr1(key, newlevel) + valrepr = repr1(x[key], newlevel) + elem_repr = '%s: %s' % (keyrepr, valrepr) + pieces.append(elem_repr) + curr_length += len(elem_repr) + if curr_length >= MAX_REPR_LENGTH and self.do_trim: + break + + if (n > self.maxdict or curr_length >= MAX_REPR_LENGTH) and self.do_trim: + pieces.append(self.fillvalue) + s = ', '.join(pieces) + return '{%s}' % (s,) + + def repr_instance(self, x, level): + # pandas series, ds | ndarray + result = _get_external_collection_repr(x) + if result is not None: + return result + + # if `__repr__` is overridden, then use `reprlib` + if x.__class__.__repr__ != object.__repr__: + if self.do_trim: + return super().repr_instance(x, level) + + return repr(x) + + # if `__str__` is overridden, then return str(x) + if x.__class__.__str__ != object.__str__: + return str(x) + + if self.do_trim: + return super().repr_instance(x, level) + + return '%s' % x + + +else: + def pydevd_repr_function(value, do_trim=True): + # pandas series, ds | ndarray + result = _get_external_collection_repr(value, True) + if result is not None: + return result + + limited_size_collection_classes = [ + list, tuple, set, frozenset, dict, array, deque, str, + ] + + if IS_PY3K: + limited_size_collection_classes.append(bytes) + else: + limited_size_collection_classes.append(unicode) + + if hasattr(value, '__class__'): + if value.__class__ in limited_size_collection_classes: + if len(value) > MAX_REPR_ITEM_SIZE and do_trim: + return ('%s' % take_first_n_coll_elements(value, MAX_REPR_ITEM_SIZE)).rstrip(')]}') + '...' + return None + + # if `__repr__` is overridden, then return repr(value) + if hasattr(value.__class__, "__repr__"): + if do_trim: + return repr(value)[:MAX_REPR_LENGTH] + else: + return repr(value) + + # else + if do_trim: + return str(value)[:MAX_REPR_LENGTH] + else: + return str(value) + + pydevd_repr_function_python2 = pydevd_repr_function + + +def get_value_repr(value, do_trim=True, format=DEFAULT_FORMAT): + """ + Returns string representation of any value + + :param value: target value + :param bool do_trim: is truncated representation + :param str format: formatting string (format % value) + :return: string representation of target value + :rtype: str + """ + value_representation = None + try: + try: + if format != DEFAULT_FORMAT: + value_representation = format % value + else: + if IS_PY3K: + pydevd_repr_fun = PydevdRepr(do_trim).repr + value_representation = pydevd_repr_fun(value) + else: + value_representation = pydevd_repr_function_python2(value, do_trim) + + except Exception as e: + pydev_log.warn("Failed to get repr for a value: " + str(e)) + + if value_representation is None: + value_representation = format % value + + if do_trim: + return _trim_string_repr_if_needed(value_representation, do_trim) + else: + return value_representation + except: + try: + return _trim_string_repr_if_needed(repr(value), do_trim) + except: + return 'Unable to get repr for %s' % value.__class__ diff --git a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_utils.py b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_utils.py index 283d6c7a2d1a..e0568d639249 100644 --- a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_utils.py +++ b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/custom/pydevd_utils.py @@ -1,3 +1,14 @@ +from array import array +from collections import deque + +from _pydevd_bundle.custom.pydevd_asyncio_provider import \ + get_eval_async_expression_in_context +from _pydevd_bundle.custom.pydevd_constants import dict_iter_items +try: + from collections import OrderedDict +except: + OrderedDict = dict + class VariableWithOffset(object): def __init__(self, data, offset): self.data, self.offset = data, offset @@ -9,3 +20,28 @@ def eval_expression(expression, globals, locals): return eval_func(expression, globals, locals, False) return eval(expression, globals, locals) + +def get_var_and_offset(var): + if isinstance(var, VariableWithOffset): + return var.data, var.offset + return var, 0 + +def take_first_n_coll_elements(coll, n): + if coll.__class__ in (list, tuple, array, str): + return coll[:n] + elif coll.__class__ in (set, frozenset, deque): + buf = [] + for i, x in enumerate(coll): + if i >= n: + break + buf.append(x) + return type(coll)(buf) + elif coll.__class__ in (dict, OrderedDict): + ret = type(coll)() + for i, (k, v) in enumerate(dict_iter_items(coll)): + if i >= n: + break + ret[k] = v + return ret + else: + raise TypeError("Unsupported collection type: '%s'" % str(coll.__class__)) diff --git a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py index 20a7351a91d2..0fc7d3fa26d2 100644 --- a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py +++ b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_resolver.py @@ -810,7 +810,7 @@ def get_var_scope(attr_name, attr_value, evaluate_name, handle_return_values): elif attr_name == GENERATED_LEN_ATTR_NAME: return "" - if attr_name.startswith("__") and attr_name.endswith("__"): + if (attr_name.startswith("__") and attr_name.endswith("__")) or inspect.ismodule(attr_value): return DAPGrouper.SCOPE_SPECIAL_VARS if attr_name.startswith("_") or attr_name.endswith("__"): @@ -818,10 +818,10 @@ def get_var_scope(attr_name, attr_value, evaluate_name, handle_return_values): try: if inspect.isroutine(attr_value) or isinstance(attr_value, MethodWrapperType): - return DAPGrouper.SCOPE_FUNCTION_VARS + return DAPGrouper.SCOPE_SPECIAL_VARS # note: we changed the scope here to correspond the scopes of pycharm's pydevd elif inspect.isclass(attr_value): - return DAPGrouper.SCOPE_CLASS_VARS + return DAPGrouper.SCOPE_SPECIAL_VARS # note: we changed the scope here to correspond the scopes of pycharm's pydevd except: # It's possible that isinstance throws an exception when dealing with user-code. if DebugInfoHolder.DEBUG_TRACE_LEVEL > 0: diff --git a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_utils.py b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_utils.py index 05549bc19fa2..d402b0405275 100644 --- a/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_utils.py +++ b/python/helpers/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_utils.py @@ -330,10 +330,10 @@ class DAPGrouper(object): the xml protocol the type is just added to each variable and the UI can group/hide it as needed. """ - SCOPE_SPECIAL_VARS = "special variables" - SCOPE_PROTECTED_VARS = "protected variables" - SCOPE_FUNCTION_VARS = "function variables" - SCOPE_CLASS_VARS = "class variables" + SCOPE_SPECIAL_VARS = "Special Variables" + SCOPE_PROTECTED_VARS = "Protected Attributes" + SCOPE_FUNCTION_VARS = "Function Variables" + SCOPE_CLASS_VARS = "Class Variables" SCOPES_SORTED = [ SCOPE_SPECIAL_VARS, diff --git a/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_numpy_types.py b/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_numpy_types.py index 57ed2b4f9b14..7ae0f7e60a02 100644 --- a/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_numpy_types.py +++ b/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_numpy_types.py @@ -1,10 +1,23 @@ -from _pydevd_bundle.pydevd_extension_api import TypeResolveProvider +from _pydevd_bundle.custom.pydevd_utils import get_var_and_offset +from _pydevd_bundle.pydevd_extension_api import TypeResolveProvider, \ + StrPresentationProvider from _pydevd_bundle.pydevd_resolver import defaultResolver from .pydevd_helpers import find_mod_attr -from _pydevd_bundle import pydevd_constants +from _pydevd_bundle.custom.pydevd_repr_utils import get_value_repr + +import inspect + +try: + from collections import OrderedDict +except: + OrderedDict = dict + TOO_LARGE_MSG = "Maximum number of items (%s) reached. To show more items customize the value of the PYDEVD_CONTAINER_NUMPY_MAX_ITEMS environment variable." TOO_LARGE_ATTR = "Unable to handle:" +IS_PYCHARM = True +MAX_ITEMS_TO_HANDLE = 300 if not IS_PYCHARM else 100 +DEFAULT_PRECISION = 5 class NdArrayItemsContainer(object): @@ -17,74 +30,135 @@ class NDArrayTypeResolveProvider(object): """ def can_provide(self, type_object, type_name): - nd_array = find_mod_attr("numpy", "ndarray") - return nd_array is not None and issubclass(type_object, nd_array) + nd_array = find_mod_attr('numpy', 'ndarray') + return nd_array is not None and inspect.isclass(type_object) and issubclass(type_object, nd_array) + + ''' + This resolves a numpy ndarray returning some metadata about the NDArray + ''' def is_numeric(self, obj): - if not hasattr(obj, "dtype"): + if not hasattr(obj, 'dtype'): return False - return obj.dtype.kind in "biufc" + return obj.dtype.kind in 'biufc' + + def round_if_possible(self, obj): + try: + return obj.round(DEFAULT_PRECISION) + except TypeError: + return obj def resolve(self, obj, attribute): - if attribute == "__internals__": - return defaultResolver.get_dictionary(obj) - if attribute == "min": - if self.is_numeric(obj) and obj.size > 0: + if attribute == '__internals__': + if not IS_PYCHARM: + return defaultResolver.get_dictionary(obj) + if attribute == 'min': + if self.is_numeric(obj): return obj.min() else: return None - if attribute == "max": - if self.is_numeric(obj) and obj.size > 0: + if attribute == 'max': + if self.is_numeric(obj): return obj.max() else: return None - if attribute == "shape": + if attribute == 'shape': return obj.shape - if attribute == "dtype": + if attribute == 'dtype': return obj.dtype - if attribute == "size": + if attribute == 'size': return obj.size - if attribute.startswith("["): + if attribute.startswith('['): container = NdArrayItemsContainer() i = 0 - format_str = "%0" + str(int(len(str(len(obj))))) + "d" + format_str = '%0' + str(int(len(str(len(obj))))) + 'd' for item in obj: setattr(container, format_str % i, item) i += 1 - if i >= pydevd_constants.PYDEVD_CONTAINER_NUMPY_MAX_ITEMS: - setattr(container, TOO_LARGE_ATTR, TOO_LARGE_MSG % (pydevd_constants.PYDEVD_CONTAINER_NUMPY_MAX_ITEMS,)) + if i > MAX_ITEMS_TO_HANDLE: + setattr(container, TOO_LARGE_ATTR, TOO_LARGE_MSG) break return container + if IS_PYCHARM and attribute == 'array': + container = NdArrayItemsContainer() + container.items = obj + return container return None def get_dictionary(self, obj): ret = dict() - ret["__internals__"] = defaultResolver.get_dictionary(obj) + if not IS_PYCHARM: + ret['__internals__'] = defaultResolver.get_dictionary(obj) if obj.size > 1024 * 1024: - ret["min"] = "ndarray too big, calculating min would slow down debugging" - ret["max"] = "ndarray too big, calculating max would slow down debugging" - elif obj.size == 0: - ret["min"] = "array is empty" - ret["max"] = "array is empty" + ret['min'] = 'ndarray too big, calculating min would slow down debugging' + ret['max'] = 'ndarray too big, calculating max would slow down debugging' else: if self.is_numeric(obj): - ret["min"] = obj.min() - ret["max"] = obj.max() + ret['min'] = obj.min() + ret['max'] = obj.max() else: - ret["min"] = "not a numeric object" - ret["max"] = "not a numeric object" - ret["shape"] = obj.shape - ret["dtype"] = obj.dtype - ret["size"] = obj.size - try: - ret["[0:%s] " % (len(obj))] = list(obj[0 : pydevd_constants.PYDEVD_CONTAINER_NUMPY_MAX_ITEMS]) - except: - # This may not work depending on the array shape. - pass + ret['min'] = 'not a numeric object' + ret['max'] = 'not a numeric object' + ret['shape'] = obj.shape + ret['dtype'] = obj.dtype + ret['size'] = obj.size + if IS_PYCHARM: + container = NdArrayItemsContainer() + container.items = obj + ret['array'] = container + else: + ret['[0:%s] ' % (len(obj))] = list(obj[0:MAX_ITEMS_TO_HANDLE]) return ret +class NDArrayStrProvider(StrPresentationProvider): + def can_provide(self, type_object, type_name): + nd_array = find_mod_attr('numpy', 'ndarray') + return nd_array is not None and inspect.isclass(type_object) and issubclass(type_object, nd_array) + + def _to_str_no_trim(self, val): + return str(val.tolist()).replace('\n', ',').strip() + + def get_str(self, val, do_trim=True): + if do_trim: + return get_value_repr(val) + try: + import numpy as np + with np.printoptions(threshold=sys.maxsize): + return self._to_str_no_trim(val) + except: + return self._to_str_no_trim(val) + +class NdArrayItemsContainerProvider(object): + def can_provide(self, type_object, type_name): + return inspect.isclass(type_object) and issubclass(type_object, NdArrayItemsContainer) + + def resolve(self, obj, attribute): + if attribute == '__len__': + return None + return obj.items[int(attribute)] + + def get_dictionary(self, obj): + obj, offset = get_var_and_offset(obj) + + l = len(obj.items) + d = OrderedDict() + + format_str = '%0' + str(int(len(str(l)))) + 'd' + + i = offset + for item in obj.items[offset:offset + MAX_ITEMS_TO_HANDLE]: + d[format_str % i] = item + i += 1 + + if i > MAX_ITEMS_TO_HANDLE + offset: + break + d['__len__'] = l + return d import sys if not sys.platform.startswith("java"): TypeResolveProvider.register(NDArrayTypeResolveProvider) + if IS_PYCHARM: + TypeResolveProvider.register(NdArrayItemsContainerProvider) + StrPresentationProvider.register(NDArrayStrProvider) diff --git a/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_pandas_types.py b/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_pandas_types.py index 631691ef3d3a..668fb49d3d63 100644 --- a/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_pandas_types.py +++ b/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_pandas_types.py @@ -1,5 +1,6 @@ import sys +from _pydevd_bundle.custom.pydevd_repr_utils import get_value_repr from _pydevd_bundle.pydevd_constants import PANDAS_MAX_ROWS, PANDAS_MAX_COLS, PANDAS_MAX_COLWIDTH from _pydevd_bundle.pydevd_extension_api import TypeResolveProvider, StrPresentationProvider from _pydevd_bundle.pydevd_resolver import inspect, MethodWrapperType @@ -88,7 +89,7 @@ class PandasDataFrameTypeResolveProvider(object): replacements = { # This actually calls: DataFrame.transpose(), which can be expensive, so, # let's just add some string representation for it. - "T": "", + # "T": "", # This creates a whole new dict{index: Series) for each column. Doing a # subsequent repr() from this dict can be very slow, so, don't return it. "_series": "", @@ -109,9 +110,18 @@ class PandasDataFrameTypeResolveProvider(object): return repr(df) return self.get_str(df) - def get_str(self, df): - with customize_pandas_options(): - return repr(df) + def _to_str_no_trim(self, val): + return str(val.tolist()).replace('\n', ',').strip() + + def get_str(self, val, do_trim=True): + if do_trim: + return get_value_repr(val) + try: + import numpy as np + with np.printoptions(threshold=sys.maxsize): + return self._to_str_no_trim(val) + except: + return self._to_str_no_trim(val) class PandasSeriesTypeResolveProvider(object): @@ -126,7 +136,7 @@ class PandasSeriesTypeResolveProvider(object): replacements = { # This actually calls: DataFrame.transpose(), which can be expensive, so, # let's just add some string representation for it. - "T": "", + # "T": "", # This creates a whole new dict{index: Series) for each column. Doing a # subsequent repr() from this dict can be very slow, so, don't return it. "_series": "", @@ -147,9 +157,18 @@ class PandasSeriesTypeResolveProvider(object): return repr(df) return self.get_str(df) - def get_str(self, series): - with customize_pandas_options(): - return repr(series) + def _to_str_no_trim(self, val): + return str(val.tolist()).replace('\n', ',').strip() + + def get_str(self, val, do_trim=True): + if do_trim: + return get_value_repr(val) + try: + import numpy as np + with np.printoptions(threshold=sys.maxsize): + return self._to_str_no_trim(val) + except: + return self._to_str_no_trim(val) class PandasStylerTypeResolveProvider(object): diff --git a/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_repr_lib.py b/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_repr_lib.py new file mode 100644 index 000000000000..cba96f8d89d5 --- /dev/null +++ b/python/helpers/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/pydevd_plugin_repr_lib.py @@ -0,0 +1,21 @@ +from typing import Any + +from _pydevd_bundle.custom.pydevd_repr_utils import get_value_repr +from _pydevd_bundle.pydevd_extension_api import StrPresentationProvider +from pydevd_plugins.extensions.types.pydevd_plugin_numpy_types import NDArrayStrProvider +from pydevd_plugins.extensions.types.pydevd_plugins_django_form_str import DjangoFormStr + + +class PydevdReprStrProvider(StrPresentationProvider): + def can_provide(self, type_object, type_name): + # this provider can resolve anything that is not otherwise custom handled by our + # other custom resolvers, such as NDArrayStrProvider + return (not NDArrayStrProvider.can_provide(self, type_object, type_name) + and not DjangoFormStr.can_provide(self, type_object, type_name)) + + def get_str_in_context(self, val: Any, context: str): + return self.get_str(val) + + def get_str(self, val, do_trim=True): + return get_value_repr(val) +