def resolve_compound_var_object_fields(var, attrs, user_type_renderers={}): """ Resolve compound variable by its object and attributes :param var: an object of variable :param attrs: a sequence of variable's attributes separated by \t (i.e.: obj\tattr1\tattr2) :param user_type_renderers: a dictionary with user type renderers :return: a dictionary of variables's fields """ namespace = var offset = get_offset(attrs) attrs = attrs.split('\t', 1)[1] if offset else attrs attr_list = attrs.split('\t') var_expr = ".".join(attr_list) for k in attr_list: type, _typeName, resolver = get_type(var) var = resolver.resolve(var, k) try: type, _typeName, resolver = get_type(var) type_renderer = try_get_type_renderer_for_var(var, user_type_renderers) if type_renderer is not None and offset == 0: return _resolve_custom_variable_fields(var, var_expr, resolver, offset, type_renderer) return _resolve_default_variable_fields(var, resolver, offset) except: traceback.print_exc()
def resolve_compound_variable_fields(thread_id, frame_id, scope, attrs, user_type_renderers={}): """ Resolve compound variable in debugger scopes by its name and attributes :param thread_id: id of the variable's thread :param frame_id: id of the variable's frame :param scope: can be BY_ID, EXPRESSION, GLOBAL, LOCAL, FRAME :param attrs: after reaching the proper scope, we have to get the attributes until we find the proper location (i.e.: obj\tattr1\tattr2) :param user_type_renderers: a dictionary with user type renderers :return: a dictionary of variables's fields :note: PyCharm supports progressive loading of large collections and uses the `attrs` parameter to pass the offset, e.g. 300\t\\obj\tattr1\tattr2 should return the value of attr2 starting from the 300th element. This hack makes it possible to add the support of progressive loading without extending of the protocol. """ offset = get_offset(attrs) orig_attrs, attrs = attrs, attrs.split('\t', 1)[1] if offset else attrs var = getVariable(thread_id, frame_id, scope, attrs) var_expr = ".".join(attrs.split('\t')) try: _type, _typeName, resolver = get_type(var) type_renderer = try_get_type_renderer_for_var(var, user_type_renderers) if type_renderer is not None and offset == 0: frame_info = (thread_id, frame_id) return _typeName, _resolve_custom_variable_fields( var, var_expr, resolver, offset, type_renderer, frame_info) return _typeName, _resolve_default_variable_fields( var, resolver, offset) except: sys.stderr.write( 'Error evaluating: thread_id: %s\nframe_id: %s\nscope: %s\nattrs: %s\n' % ( thread_id, frame_id, scope, orig_attrs, )) traceback.print_exc()
def var_to_struct(val, name, format='%s', do_trim=True, evaluate_full_value=True, user_type_renderers=None): """ single variable or dictionary to Thrift struct representation """ debug_value = DebugValue() try: # This should be faster than isinstance (but we have to protect against not having a '__class__' attribute). is_exception_on_eval = val.__class__ == ExceptionOnEvaluate except: is_exception_on_eval = False if is_exception_on_eval: v = val.result else: v = val if name in DO_NOT_PROCESS_VARS: debug_value.name = name debug_value.value = val return debug_value _type, typeName, resolver = get_type(v) type_qualifier = getattr(_type, "__module__", "") type_renderer = None if user_type_renderers is not None: type_renderer = try_get_type_renderer_for_var(v, user_type_renderers) var_custom_string_repr = None value = None if not evaluate_full_value: value = DEFAULT_VALUES_DICT[LOAD_VALUES_POLICY] elif type_renderer is not None: var_custom_string_repr = type_renderer.evaluate_var_string_repr(v) value = var_custom_string_repr if value is None: value = _get_default_var_string_representation(v, _type, typeName, format) debug_value.name = name debug_value.type = typeName if type_qualifier: debug_value.qualifier = type_qualifier # cannot be too big... communication may not handle it. if len(value) > MAXIMUM_VARIABLE_REPRESENTATION_SIZE and do_trim: value = value[0:MAXIMUM_VARIABLE_REPRESENTATION_SIZE] value += '...' # fix to work with unicode values try: if not IS_PY3K: if value.__class__ == unicode: # @UndefinedVariable value = value.encode('utf-8') else: if value.__class__ == bytes: value = value.encode('utf-8') except TypeError: # in java, unicode is a function pass if is_pandas_container(type_qualifier, typeName, v) and var_custom_string_repr is None: value = pandas_to_str(v, typeName, value, pydevd_resolver.MAX_ITEMS_TO_HANDLE) debug_value.value = value try: if should_evaluate_shape(): if hasattr(v, 'shape') and not callable(v.shape): debug_value.shape = str(tuple(v.shape)) elif hasattr(v, '__len__') and not is_string(v): debug_value.shape = str(len(v)) except: pass if is_exception_on_eval: debug_value.isErrorOnEval = True else: if resolver is not None: debug_value.isContainer = True else: pass if type_renderer is not None: debug_value.typeRendererId = type_renderer.to_type return debug_value
def var_to_xml(val, name, doTrim=True, additional_in_xml='', evaluate_full_value=True, format='%s', user_type_renderers=None): """ single variable or dictionary to xml representation """ if name in DO_NOT_PROCESS_VARS: xml = '<var name="%s" ' % (make_valid_xml_value(name)) return ''.join((xml, ' />\n')) try: # This should be faster than isinstance (but we have to protect against not having a '__class__' attribute). is_exception_on_eval = val.__class__ == ExceptionOnEvaluate except: is_exception_on_eval = False if is_exception_on_eval: v = val.result else: v = val _type, typeName, resolver = get_type(v) type_qualifier = getattr(_type, "__module__", "") type_renderer = None if user_type_renderers is not None: type_renderer = try_get_type_renderer_for_var(v, user_type_renderers) var_custom_string_repr = None value = None if not evaluate_full_value: value = DEFAULT_VALUES_DICT[LOAD_VALUES_POLICY] elif type_renderer is not None: var_custom_string_repr = type_renderer.evaluate_var_string_repr(v) value = var_custom_string_repr if value is None: value = _get_default_var_string_representation(v, _type, typeName, format) try: name = _do_quote(name) # TODO: Fix PY-5834 without using quote except: pass xml = '<var name="%s" type="%s" ' % (make_valid_xml_value(name), make_valid_xml_value(typeName)) if type_qualifier: xml_qualifier = 'qualifier="%s"' % make_valid_xml_value(type_qualifier) else: xml_qualifier = '' # cannot be too big... communication may not handle it. if len(value) > MAXIMUM_VARIABLE_REPRESENTATION_SIZE and doTrim: value = value[0:MAXIMUM_VARIABLE_REPRESENTATION_SIZE] value += '...' if is_pandas_container(type_qualifier, typeName, v) and var_custom_string_repr is None: value = pandas_to_str(v, typeName, value, pydevd_resolver.MAX_ITEMS_TO_HANDLE) xml_value = ' value="%s"' % (make_valid_xml_value(_do_quote(value))) xml_shape = '' try: if should_evaluate_shape(): if hasattr(v, 'shape') and not callable(v.shape): xml_shape = ' shape="%s"' % make_valid_xml_value( str(tuple(v.shape))) elif hasattr(v, '__len__') and not is_string(v): xml_shape = ' shape="%s"' % make_valid_xml_value( "%s" % str(len(v))) except: pass if is_exception_on_eval: xml_container = ' isErrorOnEval="True"' else: if resolver is not None: xml_container = ' isContainer="True"' else: xml_container = '' if type_renderer is not None: xml_type_renderer_id = 'typeRendererId="%s"' % make_valid_xml_value( type_renderer.to_type) else: xml_type_renderer_id = '' return ''.join((xml, xml_qualifier, xml_value, xml_container, xml_shape, xml_type_renderer_id, additional_in_xml, ' />\n'))