Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pure_eval/my_getattr_static.py: 22%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

86 statements  

1import types 

2 

3from pure_eval.utils import of_type, CannotEval 

4 

5_sentinel = object() 

6 

7 

8def _static_getmro(klass): 

9 return type.__dict__['__mro__'].__get__(klass) 

10 

11 

12def _check_instance(obj, attr): 

13 instance_dict = {} 

14 try: 

15 instance_dict = object.__getattribute__(obj, "__dict__") 

16 except AttributeError: 

17 pass 

18 return dict.get(instance_dict, attr, _sentinel) 

19 

20 

21def _check_class(klass, attr): 

22 for entry in _static_getmro(klass): 

23 if _shadowed_dict(type(entry)) is _sentinel: 

24 try: 

25 return entry.__dict__[attr] 

26 except KeyError: 

27 pass 

28 else: 

29 break 

30 return _sentinel 

31 

32 

33def _is_type(obj): 

34 try: 

35 _static_getmro(obj) 

36 except TypeError: 

37 return False 

38 return True 

39 

40 

41def _shadowed_dict(klass): 

42 dict_attr = type.__dict__["__dict__"] 

43 for entry in _static_getmro(klass): 

44 try: 

45 class_dict = dict_attr.__get__(entry)["__dict__"] 

46 except KeyError: 

47 pass 

48 else: 

49 if not (type(class_dict) is types.GetSetDescriptorType and 

50 class_dict.__name__ == "__dict__" and 

51 class_dict.__objclass__ is entry): 

52 return class_dict 

53 return _sentinel 

54 

55 

56def getattr_static(obj, attr): 

57 """Retrieve attributes without triggering dynamic lookup via the 

58 descriptor protocol, __getattr__ or __getattribute__. 

59 

60 Note: this function may not be able to retrieve all attributes 

61 that getattr can fetch (like dynamically created attributes) 

62 and may find attributes that getattr can't (like descriptors 

63 that raise AttributeError). It can also return descriptor objects 

64 instead of instance members in some cases. See the 

65 documentation for details. 

66 """ 

67 instance_result = _sentinel 

68 if not _is_type(obj): 

69 klass = type(obj) 

70 dict_attr = _shadowed_dict(klass) 

71 if (dict_attr is _sentinel or 

72 type(dict_attr) is types.MemberDescriptorType): 

73 instance_result = _check_instance(obj, attr) 

74 else: 

75 raise CannotEval 

76 else: 

77 klass = obj 

78 

79 klass_result = _check_class(klass, attr) 

80 

81 if instance_result is not _sentinel and klass_result is not _sentinel: 

82 if _check_class(type(klass_result), "__get__") is not _sentinel and ( 

83 _check_class(type(klass_result), "__set__") is not _sentinel 

84 or _check_class(type(klass_result), "__delete__") is not _sentinel 

85 ): 

86 return _resolve_descriptor(klass_result, obj, klass) 

87 

88 if instance_result is not _sentinel: 

89 return instance_result 

90 if klass_result is not _sentinel: 

91 get = _check_class(type(klass_result), '__get__') 

92 if get is _sentinel: 

93 return klass_result 

94 else: 

95 if obj is klass: 

96 instance = None 

97 else: 

98 instance = obj 

99 return _resolve_descriptor(klass_result, instance, klass) 

100 

101 if obj is klass: 

102 # for types we check the metaclass too 

103 for entry in _static_getmro(type(klass)): 

104 if _shadowed_dict(type(entry)) is _sentinel: 

105 try: 

106 result = entry.__dict__[attr] 

107 get = _check_class(type(result), '__get__') 

108 if get is not _sentinel: 

109 raise CannotEval 

110 return result 

111 except KeyError: 

112 pass 

113 raise CannotEval 

114 

115 

116class _foo: 

117 __slots__ = ['foo'] 

118 method = lambda: 0 

119 

120 

121slot_descriptor = _foo.foo 

122wrapper_descriptor = str.__dict__['__add__'] 

123method_descriptor = str.__dict__['startswith'] 

124user_method_descriptor = _foo.__dict__['method'] 

125 

126safe_descriptors_raw = [ 

127 slot_descriptor, 

128 wrapper_descriptor, 

129 method_descriptor, 

130 user_method_descriptor, 

131] 

132 

133safe_descriptor_types = list(map(type, safe_descriptors_raw)) 

134 

135 

136def _resolve_descriptor(d, instance, owner): 

137 try: 

138 return type(of_type(d, *safe_descriptor_types)).__get__(d, instance, owner) 

139 except AttributeError as e: 

140 raise CannotEval from e