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
|
"""
Python introspection helpers.
"""
from types import CodeType as code, FunctionType as function
def copycode(template, changes):
if hasattr(code, "replace"):
return template.replace(**{"co_" + k: v for k, v in changes.items()})
names = [
"argcount",
"nlocals",
"stacksize",
"flags",
"code",
"consts",
"names",
"varnames",
"filename",
"name",
"firstlineno",
"lnotab",
"freevars",
"cellvars",
]
if hasattr(code, "co_kwonlyargcount"):
names.insert(1, "kwonlyargcount")
if hasattr(code, "co_posonlyargcount"):
# PEP 570 added "positional only arguments"
names.insert(1, "posonlyargcount")
values = [changes.get(name, getattr(template, "co_" + name)) for name in names]
return code(*values)
def copyfunction(template, funcchanges, codechanges):
names = [
"globals",
"name",
"defaults",
"closure",
]
values = [
funcchanges.get(name, getattr(template, "__" + name + "__")) for name in names
]
return function(copycode(template.__code__, codechanges), *values)
def preserveName(f):
"""
Preserve the name of the given function on the decorated function.
"""
def decorator(decorated):
return copyfunction(decorated, dict(name=f.__name__), dict(name=f.__name__))
return decorator
|