-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcheck_noarg_deco.py
77 lines (74 loc) · 2.57 KB
/
check_noarg_deco.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from sys import _getframe, version_info as PYVER
from opcode import (_inline_cache_entries as ICE, EXTENDED_ARG, opmap,
stack_effect, HAVE_ARGUMENT)
CACHE = opmap['CACHE']
if NO_312 := PYVER < (3, 12):
PRECALL = opmap['PRECALL']
LEN_PRECALL = ICE[PRECALL] * 2 + 2
else:
LEN_PRECALL = 0
CALL = opmap['CALL']
ICE_CALL = ICE[CALL]
LENICE_CALL = ICE_CALL * 2
MAKE_FUNCTION = opmap['MAKE_FUNCTION']
LOAD_CONST = opmap['LOAD_CONST']
LOAD_BUILD_CLASS = opmap['LOAD_BUILD_CLASS']
def check_noarg_deco():
try:
f = _getframe(2)
except ValueError:
return False
code = f.f_code.co_code
op = f.f_lasti - LENICE_CALL
if code[op] is not CALL or code[op + 1]:
return False
op -= LEN_PRECALL + 2
if code[op] is CACHE:
ncaches = 0
while op >= 0:
while op >= 0 and code[op] is CACHE:
ncaches += 1
op -= 2
if ncaches is ICE_CALL and code[op] is CALL:
if not code[op + 1]:
ncaches = 0
op -= LEN_PRECALL + 2
continue
break
if (op >= 0 and ncaches is ICE_CALL and code[op] is CALL
and code[op + 1] >= 2):
stacklevel = -code[op + 1]
op -= LEN_PRECALL + 2
while op >= 0:
pos = op - 2
if code[op] >= HAVE_ARGUMENT:
shift = 1
oparg = code[op + 1]
if pos >= 0 and code[pos] is EXTENDED_ARG:
while pos >= 0 and code[pos] is EXTENDED_ARG:
oparg += code[pos + 1] << shift
shift += 1
pos -= 2
else:
oparg = None
stacklevel += stack_effect(code[op], oparg, jump=False)
if not stacklevel:
break
op = pos
else:
return False
if (code[op] is LOAD_CONST and code[op + 2] is MAKE_FUNCTION
and op - 2 >= 0 and code[op - 2] is LOAD_BUILD_CLASS):
return True
elif code[op] is MAKE_FUNCTION:
pos = op - 4
shift = 1
oparg = code[op - 1]
if pos >= 0 and code[pos] is EXTENDED_ARG:
while pos >= 0 and code[pos] is EXTENDED_ARG:
oparg += code[pos + 1] << shift
shift += 1
pos -= 2
codeobj = f.f_code.co_consts[oparg]
return codeobj is not _getframe(1).f_code
return False