Change __len__ to len().

This commit is contained in:
Fabio Zadrozny 2020-04-19 13:42:27 -03:00
parent d2014babd6
commit 011810aa42
9 changed files with 64 additions and 66 deletions

View file

@ -71,6 +71,7 @@ except AttributeError:
MAXIMUM_VARIABLE_REPRESENTATION_SIZE = 1000
# Prefix for saving functions return values in locals
RETURN_VALUES_DICT = '__pydevd_ret_val_dict'
GENERATED_LEN_ATTR_NAME = 'len()'
import os

View file

@ -9,7 +9,7 @@ from os.path import basename
from functools import partial
from _pydevd_bundle.pydevd_constants import dict_iter_items, dict_keys, xrange, IS_PY36_OR_GREATER, \
MethodWrapperType, RETURN_VALUES_DICT, DebugInfoHolder, IS_PYPY
MethodWrapperType, RETURN_VALUES_DICT, DebugInfoHolder, IS_PYPY, GENERATED_LEN_ATTR_NAME
from _pydevd_bundle.pydevd_safe_repr import SafeRepr
# Note: 300 is already a lot to see in the outline (after that the user should really use the shell to get things)
@ -223,7 +223,7 @@ class DictResolver:
sort_keys = not IS_PY36_OR_GREATER
def resolve(self, dict, key):
if key in ('__len__', TOO_LARGE_ATTR):
if key in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR):
return None
if '(' not in key:
@ -276,17 +276,17 @@ class DictResolver:
ret.append((TOO_LARGE_ATTR, TOO_LARGE_MSG, None))
break
ret.append(('__len__', len(dct), partial(_apply_evaluate_name, evaluate_name='len(%s)')))
# in case the class extends built-in type and has some additional fields
from_default_resolver = defaultResolver.get_contents_debug_adapter_protocol(dct, fmt)
if from_default_resolver:
ret = from_default_resolver + ret
if not self.sort_keys:
return ret
if self.sort_keys:
ret = sorted(ret, key=lambda tup: sorted_attributes_key(tup[0]))
return sorted(ret, key=lambda tup: sorted_attributes_key(tup[0]))
ret.append((GENERATED_LEN_ATTR_NAME, len(dct), partial(_apply_evaluate_name, evaluate_name='len(%s)')))
return ret
def get_dictionary(self, dict):
ret = self.init_dict()
@ -304,7 +304,7 @@ class DictResolver:
# in case if the class extends built-in type and has some additional fields
additional_fields = defaultResolver.get_dictionary(dict)
ret.update(additional_fields)
ret['__len__'] = len(dict)
ret[GENERATED_LEN_ATTR_NAME] = len(dict)
return ret
@ -322,7 +322,7 @@ class TupleResolver: # to enumerate tuples and lists
@param var: that's the original attribute
@param attribute: that's the key passed in the dict (as a string)
'''
if attribute in ('__len__', TOO_LARGE_ATTR):
if attribute in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR):
return None
try:
return var[int(attribute)]
@ -353,11 +353,12 @@ class TupleResolver: # to enumerate tuples and lists
ret.append((TOO_LARGE_ATTR, TOO_LARGE_MSG, None))
break
ret.append(('__len__', len(lst), partial(_apply_evaluate_name, evaluate_name='len(%s)')))
# Needed in case the class extends the built-in type and has some additional fields.
from_default_resolver = defaultResolver.get_contents_debug_adapter_protocol(lst, fmt=fmt)
if from_default_resolver:
ret = from_default_resolver + ret
ret.append((GENERATED_LEN_ATTR_NAME, len(lst), partial(_apply_evaluate_name, evaluate_name='len(%s)')))
return ret
def get_dictionary(self, var, fmt={}):
@ -378,7 +379,7 @@ class TupleResolver: # to enumerate tuples and lists
# in case if the class extends built-in type and has some additional fields
additional_fields = defaultResolver.get_dictionary(var)
d.update(additional_fields)
d['__len__'] = len(var)
d[GENERATED_LEN_ATTR_NAME] = len(var)
return d
@ -400,15 +401,15 @@ class SetResolver:
ret.append((TOO_LARGE_ATTR, TOO_LARGE_MSG, None))
break
ret.append(('__len__', len(obj), partial(_apply_evaluate_name, evaluate_name='len(%s)')))
# Needed in case the class extends the built-in type and has some additional fields.
from_default_resolver = defaultResolver.get_contents_debug_adapter_protocol(obj, fmt=fmt)
if from_default_resolver:
ret = from_default_resolver + ret
ret.append((GENERATED_LEN_ATTR_NAME, len(obj), partial(_apply_evaluate_name, evaluate_name='len(%s)')))
return ret
def resolve(self, var, attribute):
if attribute in ('__len__', TOO_LARGE_ATTR):
if attribute in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR):
return None
try:
@ -434,7 +435,7 @@ class SetResolver:
# in case if the class extends built-in type and has some additional fields
additional_fields = defaultResolver.get_dictionary(var)
d.update(additional_fields)
d['__len__'] = len(var)
d[GENERATED_LEN_ATTR_NAME] = len(var)
return d
def change_var_from_name(self, container, name, new_value):
@ -490,7 +491,7 @@ class JyArrayResolver:
'''
def resolve(self, var, attribute):
if attribute == '__len__':
if attribute == GENERATED_LEN_ATTR_NAME:
return None
return var[int(attribute)]
@ -500,7 +501,7 @@ class JyArrayResolver:
for i in xrange(len(obj)):
ret[ i ] = obj[i]
ret['__len__'] = len(obj)
ret[GENERATED_LEN_ATTR_NAME] = len(obj)
return ret
@ -510,7 +511,7 @@ class JyArrayResolver:
class MultiValueDictResolver(DictResolver):
def resolve(self, dict, key):
if key in ('__len__', TOO_LARGE_ATTR):
if key in (GENERATED_LEN_ATTR_NAME, TOO_LARGE_ATTR):
return None
# ok, we have to iterate over the items to find the one that matches the id, because that's the only way
@ -660,8 +661,7 @@ def get_var_scope(attr_name, attr_value, evaluate_name, handle_return_values):
if handle_return_values and attr_name == RETURN_VALUES_DICT:
return ''
elif attr_name == '__len__' and evaluate_name != '.__len__':
# Treat the __len__ we generate internally separate from the __len__ function
elif attr_name == GENERATED_LEN_ATTR_NAME:
return ''
if attr_name.startswith('__') and attr_name.endswith('__'):

View file

@ -2,7 +2,7 @@ from contextlib import contextmanager
import sys
from _pydevd_bundle.pydevd_constants import get_frame, dict_items, RETURN_VALUES_DICT, \
dict_iter_items, ForkSafeLock
dict_iter_items, ForkSafeLock, GENERATED_LEN_ATTR_NAME
from _pydevd_bundle.pydevd_xml import get_variable_details, get_type
from _pydev_bundle.pydev_override import overrides
from _pydevd_bundle.pydevd_resolver import sorted_attributes_key, TOO_LARGE_ATTR, get_var_scope
@ -61,7 +61,7 @@ class _AbstractVariable(object):
attributes.append('readOnly')
name = '(return) %s' % (name,)
elif name in (TOO_LARGE_ATTR, '__len__'):
elif name in (TOO_LARGE_ATTR, GENERATED_LEN_ATTR_NAME):
attributes.append('readOnly')
var_data = {

View file

@ -11,7 +11,7 @@ except:
import inspect
import sys
from _pydevd_bundle.pydevd_constants import IS_PY3K, USE_CUSTOM_SYS_CURRENT_FRAMES, IS_PYPY, SUPPORT_GEVENT, \
GEVENT_SUPPORT_NOT_SET_MSG
GEVENT_SUPPORT_NOT_SET_MSG, GENERATED_LEN_ATTR_NAME
from _pydev_imps._pydev_saved_modules import threading
@ -76,11 +76,11 @@ def to_number(x):
def compare_object_attrs_key(x):
if '__len__' == x:
if GENERATED_LEN_ATTR_NAME == x:
as_number = to_number(x)
if as_number is None:
as_number = 99999999
# __len__ should appear after other attributes in a list.
# len() should appear after other attributes in a list.
return (1, as_number)
else:
return (-1, to_string(x))

View file

@ -17,7 +17,7 @@ from _pydevd_bundle._debug_adapter.pydevd_schema import (ThreadEvent, ModuleEven
from _pydevd_bundle.pydevd_comm_constants import file_system_encoding
from _pydevd_bundle.pydevd_constants import (int_types, IS_64BIT_PROCESS,
PY_VERSION_STR, PY_IMPL_VERSION_STR, PY_IMPL_NAME, IS_PY36_OR_GREATER, IS_PY39_OR_GREATER,
IS_PY37_OR_GREATER, IS_PYPY)
IS_PY37_OR_GREATER, IS_PYPY, GENERATED_LEN_ATTR_NAME)
from tests_python import debugger_unittest
from tests_python.debug_constants import TEST_CHERRYPY, IS_PY2, TEST_DJANGO, TEST_FLASK, IS_PY26, \
IS_PY27, IS_CPYTHON, TEST_GEVENT
@ -1223,7 +1223,7 @@ def test_dict_ordered(case_setup):
variables_response = json_facade.get_variables_response(ref)
assert [(d['name'], d['value']) for d in variables_response.body.variables if (not d['name'].startswith('_OrderedDict')) and (d['name'] not in DAPGrouper.SCOPES_SORTED)] == [
('4', "'first'"), ('3', "'second'"), ('2', "'last'"), ('__len__', '3')]
('4', "'first'"), ('3', "'second'"), ('2', "'last'"), (GENERATED_LEN_ATTR_NAME, '3')]
json_facade.write_continue()
writer.finished_ok = True
@ -1276,7 +1276,7 @@ def test_stack_and_variables_dict(case_setup):
assert check == [
{'name': "'a'", 'value': '30', 'type': 'int', 'evaluateName': "variable_for_test_3['a']", 'variablesReference': 0 },
{'name': "'b'", 'value': '20', 'type': 'int', 'evaluateName': "variable_for_test_3['b']", 'variablesReference': 0},
{'name': '__len__', 'value': '2', 'type': 'int', 'evaluateName': 'len(variable_for_test_3)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}}
{'name': GENERATED_LEN_ATTR_NAME, 'value': '2', 'type': 'int', 'evaluateName': 'len(variable_for_test_3)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}}
]
json_facade.write_continue()
@ -1480,7 +1480,7 @@ def test_stack_and_variables_set_and_list(case_setup):
u'variablesReference': 0,
},
{
u'name': u'__len__',
u'name': GENERATED_LEN_ATTR_NAME,
u'type': u'int',
u'value': u'2',
u'evaluateName': u'len(variable_for_test_1)',
@ -1683,7 +1683,7 @@ def test_evaluate_variable_references(case_setup):
'variablesReference': 0,
},
{
'name': '__len__',
'name': GENERATED_LEN_ATTR_NAME,
'type': 'int',
'value': '1',
'presentationHint': {'attributes': ['readOnly']},

View file

@ -1,5 +1,5 @@
from tests_python.debug_constants import IS_PY2
from _pydevd_bundle.pydevd_constants import IS_PY36_OR_GREATER
from _pydevd_bundle.pydevd_constants import IS_PY36_OR_GREATER, GENERATED_LEN_ATTR_NAME
def check_len_entry(len_entry, first_2_params):
@ -14,7 +14,7 @@ def test_dict_resolver():
dct = {(1, 2): 2, u'22': 22}
contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(dict_resolver.get_contents_debug_adapter_protocol(dct))
len_entry = contents_debug_adapter_protocol.pop(-1)
check_len_entry(len_entry, ('__len__', 2))
check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 2))
if IS_PY36_OR_GREATER:
assert contents_debug_adapter_protocol == [
('(1, 2)', 2, '[(1, 2)]'), ("'22'", 22, "['22']")]
@ -34,7 +34,7 @@ def test_dict_resolver_hex():
contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(
dict_resolver.get_contents_debug_adapter_protocol(dct, fmt={'hex': True}))
len_entry = contents_debug_adapter_protocol.pop(-1)
check_len_entry(len_entry, ('__len__', 1))
check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 1))
assert contents_debug_adapter_protocol == [
('(0x1, 0xa, 0x64)', (10000, 100000, 100000), '[(1, 10, 100)]'), ]
@ -166,12 +166,6 @@ def test_django_forms_resolver():
def clear_contents_debug_adapter_protocol(contents_debug_adapter_protocol):
lst = []
for x in contents_debug_adapter_protocol:
if x[0] == '__len__':
if x[2] == '.__len__':
# i.e.: remove a builtin __len__ method, but not the __len__ we add with the length.
continue
lst.append(x)
if not x[0].startswith('__'):
if '<built-in method' in str(x[1]) or '<method-wrapper' in str(x[1]) or '<bound method' in str(x[1]):
@ -185,8 +179,6 @@ def clear_contents_debug_adapter_protocol(contents_debug_adapter_protocol):
def clear_contents_dictionary(dictionary):
dictionary = dictionary.copy()
for key in list(dictionary):
if key == '__len__':
continue
if key.startswith('__') or key in ('count', 'index'):
del dictionary[key]
return dictionary
@ -213,7 +205,7 @@ def test_tuple_resolver():
('09', 9, '[9]'),
('10', 10, '[10]'),
]
check_len_entry(len_entry, ('__len__', 11))
check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 11))
assert clear_contents_dictionary(tuple_resolver.get_dictionary(lst)) == {
'00': 0,
@ -227,7 +219,7 @@ def test_tuple_resolver():
'08': 8,
'09': 9,
'10': 10,
'__len__': 11
GENERATED_LEN_ATTR_NAME: 11
}
lst = tuple(range(17))
@ -253,7 +245,7 @@ def test_tuple_resolver():
('0x0f', 15, '[15]'),
('0x10', 16, '[16]'),
]
check_len_entry(len_entry, ('__len__', 17))
check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 17))
assert clear_contents_dictionary(tuple_resolver.get_dictionary(lst, fmt=fmt)) == {
'0x00': 0,
@ -273,7 +265,7 @@ def test_tuple_resolver():
'0x0e': 14,
'0x0f': 15,
'0x10': 16,
'__len__': 17
GENERATED_LEN_ATTR_NAME: 17
}
lst = tuple(range(10))
@ -291,7 +283,7 @@ def test_tuple_resolver():
('8', 8, '[8]'),
('9', 9, '[9]'),
]
check_len_entry(len_entry, ('__len__', 10))
check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 10))
assert clear_contents_dictionary(tuple_resolver.get_dictionary(lst)) == {
'0': 0,
@ -304,7 +296,7 @@ def test_tuple_resolver():
'7': 7,
'8': 8,
'9': 9,
'__len__': 10
GENERATED_LEN_ATTR_NAME: 10
}
contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(tuple_resolver.get_contents_debug_adapter_protocol(lst, fmt=fmt))
@ -321,7 +313,7 @@ def test_tuple_resolver():
('0x8', 8, '[8]'),
('0x9', 9, '[9]'),
]
check_len_entry(len_entry, ('__len__', 10))
check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 10))
assert clear_contents_dictionary(tuple_resolver.get_dictionary(lst, fmt=fmt)) == {
'0x0': 0,
@ -334,7 +326,7 @@ def test_tuple_resolver():
'0x7': 7,
'0x8': 8,
'0x9': 9,
'__len__': 10
GENERATED_LEN_ATTR_NAME: 10
}
@ -349,6 +341,6 @@ def test_tuple_resolver_mixed():
my_tuple.some_value = 10
contents_debug_adapter_protocol = clear_contents_debug_adapter_protocol(tuple_resolver.get_contents_debug_adapter_protocol(my_tuple))
len_entry = contents_debug_adapter_protocol.pop(-1)
check_len_entry(len_entry, ('__len__', 2))
check_len_entry(len_entry, (GENERATED_LEN_ATTR_NAME, 2))
assert contents_debug_adapter_protocol == [
('some_value', 10, '.some_value'), ('0', 1, '[0]'), ('1', 2, '[1]'), ]

View file

@ -1,5 +1,5 @@
import sys
from _pydevd_bundle.pydevd_constants import int_types
from _pydevd_bundle.pydevd_constants import int_types, GENERATED_LEN_ATTR_NAME
from _pydevd_bundle.pydevd_resolver import MAX_ITEMS_TO_HANDLE, TOO_LARGE_ATTR
from _pydevd_bundle import pydevd_frame_utils
@ -68,7 +68,7 @@ def test_suspended_frames_manager():
as_dict = (dict([x.get_name(), x.get_var_data()] for x in children_vars if x.get_name() not in DAPGrouper.SCOPES_SORTED))
assert as_dict == {
'0': {'name': '0', 'value': '1', 'type': 'int', 'evaluateName': 'var2[0]', 'variablesReference': 0 },
'__len__': {'name': '__len__', 'value': '1', 'type': 'int', 'evaluateName': 'len(var2)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}, },
GENERATED_LEN_ATTR_NAME: {'name': GENERATED_LEN_ATTR_NAME, 'value': '1', 'type': 'int', 'evaluateName': 'len(var2)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}, },
}
var3 = dict((x.get_name(), x) for x in variable.get_children_variables())['var3']
@ -78,7 +78,7 @@ def test_suspended_frames_manager():
check_vars_dict_expected(as_dict, {
'33': {'name': '33', 'value': "[1]", 'type': 'list', 'evaluateName': 'var3[33]'},
'__len__': {'name': '__len__', 'value': '1', 'type': 'int', 'evaluateName': 'len(var3)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}, }
GENERATED_LEN_ATTR_NAME: {'name': GENERATED_LEN_ATTR_NAME, 'value': '1', 'type': 'int', 'evaluateName': 'len(var3)', 'variablesReference': 0, 'presentationHint': {'attributes': ['readOnly']}, }
})
@ -132,11 +132,11 @@ def test_get_child_variables():
var_data = x.get_var_data()
assert 'readOnly' in var_data['presentationHint']['attributes']
found_too_large = True
elif x.name == '__len__':
elif x.name == GENERATED_LEN_ATTR_NAME:
found_len = True
if not found_too_large:
raise AssertionError('Expected to find variable named: %s' % (TOO_LARGE_ATTR,))
if not found_len:
raise AssertionError('Expected to find variable named: __len__')
raise AssertionError('Expected to find variable named: len()')

View file

@ -69,7 +69,12 @@ class DebugConfig(collections.MutableMapping):
"connect": (),
# Attach by PID
"processId": (),
"variablePresentation": {},
"variablePresentation": {
"special": "group",
"function": "group",
"class_": "group",
"protected": "inline",
},
}
def __init__(self, *args, **kwargs):

View file

@ -102,7 +102,7 @@ def test_variables(pyfile, target, run):
{
"type": "int",
"value": "2",
"name": "__len__",
"name": "len()",
"evaluateName": "len(b)",
"variablesReference": 0,
"presentationHint": {"attributes": ["readOnly"]},
@ -162,7 +162,7 @@ def test_variable_sort(pyfile, target, run):
"__c_test",
]
special_vars_entry = [v for v in vars if v["name"] == "special variables"][0]
special_vars_entry, = (v for v in vars if v["name"] == "special variables")
special_vars_variables = session.request(
"variables",
{"variablesReference": special_vars_entry["variablesReference"]},
@ -179,14 +179,14 @@ def test_variable_sort(pyfile, target, run):
)["variables"]
var_names = [v["name"] for v in b_test_vars]
if sys.version_info[:2] >= (3, 6):
# Note that the special __len__ we manually create is not added to special variables.
# Note that the special len() we manually create is not added to special variables.
expected = [
"special variables",
"function variables",
"'spam'",
"'eggs'",
"'abcd'",
"__len__",
"len()",
]
else:
expected = [
@ -195,7 +195,7 @@ def test_variable_sort(pyfile, target, run):
"'abcd'",
"'eggs'",
"'spam'",
"__len__",
"len()",
]
assert var_names == expected
@ -207,8 +207,8 @@ def test_variable_sort(pyfile, target, run):
"variables", {"variablesReference": c_test["variablesReference"]}
)["variables"]
var_names = [v["name"] for v in c_test_vars]
# Note that the special __len__ we manually create is not added to special variables.
expected = ["1", "2", "10", "__len__"]
# Note that the special len() we manually create is not added to special variables.
expected = ["1", "2", "10", "len()"]
assert var_names == expected
@ -417,7 +417,7 @@ def test_hex_numbers(pyfile, target, run):
),
some.dict.containing(
{
"name": "__len__",
"name": "len()",
"value": "0x3",
"type": "int",
"evaluateName": "len(b)",
@ -463,7 +463,7 @@ def test_hex_numbers(pyfile, target, run):
),
some.dict.containing(
{
"name": "__len__",
"name": "len()",
"value": "0x3",
"type": "int",
"evaluateName": "len(c)",
@ -504,7 +504,7 @@ def test_hex_numbers(pyfile, target, run):
),
some.dict.containing(
{
"name": "__len__",
"name": "len()",
"value": "0x3",
"type": "int",
"evaluateName": "len(c)",
@ -530,7 +530,7 @@ def test_hex_numbers(pyfile, target, run):
),
some.dict.containing(
{
"name": "__len__",
"name": "len()",
"value": "0x1",
"type": "int",
"evaluateName": "len(d)",
@ -578,7 +578,7 @@ def test_hex_numbers(pyfile, target, run):
),
some.dict.containing(
{
"name": "__len__",
"name": "len()",
"value": "0x3",
"type": "int",
"evaluateName": "len(d[(1, 10, 100)])",