Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/executing/_utils.py: 21%

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

82 statements  

1 

2import ast 

3import sys 

4import dis 

5from typing import cast, Any,Iterator 

6import types 

7 

8 

9 

10def assert_(condition, message=""): 

11 # type: (Any, str) -> None 

12 """ 

13 Like an assert statement, but unaffected by -O 

14 :param condition: value that is expected to be truthy 

15 :type message: Any 

16 """ 

17 if not condition: 

18 raise AssertionError(str(message)) 

19 

20 

21if sys.version_info >= (3, 4): 

22 # noinspection PyUnresolvedReferences 

23 _get_instructions = dis.get_instructions 

24 from dis import Instruction as _Instruction 

25 

26 class Instruction(_Instruction): 

27 lineno = None # type: int 

28else: 

29 from collections import namedtuple 

30 

31 class Instruction(namedtuple('Instruction', 'offset argval opname starts_line')): 

32 lineno = None # type: int 

33 

34 from dis import HAVE_ARGUMENT, EXTENDED_ARG, hasconst, opname, findlinestarts, hasname 

35 

36 # Based on dis.disassemble from 2.7 

37 # Left as similar as possible for easy diff 

38 

39 def _get_instructions(co): 

40 # type: (types.CodeType) -> Iterator[Instruction] 

41 code = co.co_code 

42 linestarts = dict(findlinestarts(co)) 

43 n = len(code) 

44 i = 0 

45 extended_arg = 0 

46 while i < n: 

47 offset = i 

48 c = code[i] 

49 op = ord(c) 

50 lineno = linestarts.get(i) 

51 argval = None 

52 i = i + 1 

53 if op >= HAVE_ARGUMENT: 

54 oparg = ord(code[i]) + ord(code[i + 1]) * 256 + extended_arg 

55 extended_arg = 0 

56 i = i + 2 

57 if op == EXTENDED_ARG: 

58 extended_arg = oparg * 65536 

59 

60 if op in hasconst: 

61 argval = co.co_consts[oparg] 

62 elif op in hasname: 

63 argval = co.co_names[oparg] 

64 elif opname[op] == 'LOAD_FAST': 

65 argval = co.co_varnames[oparg] 

66 yield Instruction(offset, argval, opname[op], lineno) 

67 

68def get_instructions(co): 

69 # type: (types.CodeType) -> Iterator[EnhancedInstruction] 

70 lineno = co.co_firstlineno 

71 for inst in _get_instructions(co): 

72 inst = cast(EnhancedInstruction, inst) 

73 lineno = inst.starts_line or lineno 

74 assert_(lineno) 

75 inst.lineno = lineno 

76 yield inst 

77 

78 

79# Type class used to expand out the definition of AST to include fields added by this library 

80# It's not actually used for anything other than type checking though! 

81class EnhancedAST(ast.AST): 

82 parent = None # type: EnhancedAST 

83 

84# Type class used to expand out the definition of AST to include fields added by this library 

85# It's not actually used for anything other than type checking though! 

86class EnhancedInstruction(Instruction): 

87 _copied = None # type: bool 

88 

89 

90 

91 

92 

93def mangled_name(node): 

94 # type: (EnhancedAST) -> str 

95 """ 

96 

97 Parameters: 

98 node: the node which should be mangled 

99 name: the name of the node 

100 

101 Returns: 

102 The mangled name of `node` 

103 """ 

104 

105 function_class_types=(ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef) 

106 

107 if isinstance(node, ast.Attribute): 

108 name = node.attr 

109 elif isinstance(node, ast.Name): 

110 name = node.id 

111 elif isinstance(node, (ast.alias)): 

112 name = node.asname or node.name.split(".")[0] 

113 elif isinstance(node, function_class_types): 

114 name = node.name 

115 elif isinstance(node, ast.ExceptHandler): 

116 assert node.name 

117 name = node.name 

118 elif sys.version_info >= (3,12) and isinstance(node,ast.TypeVar): 

119 name=node.name 

120 else: 

121 raise TypeError("no node to mangle") 

122 

123 if name.startswith("__") and not name.endswith("__"): 

124 

125 parent,child=node.parent,node 

126 

127 while not (isinstance(parent,ast.ClassDef) and child not in parent.bases): 

128 if not hasattr(parent,"parent"): 

129 break # pragma: no mutate 

130 

131 parent,child=parent.parent,parent 

132 else: 

133 class_name=parent.name.lstrip("_") 

134 if class_name!="" and child not in parent.decorator_list: 

135 return "_" + class_name + name 

136 

137 

138 

139 return name